aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/lib/pq/ssl.go
diff options
context:
space:
mode:
authorGibheer <gibheer+git@zero-knowledge.org>2021-12-02 17:54:14 +0100
committerGibheer <gibheer+git@zero-knowledge.org>2021-12-02 17:54:14 +0100
commitfa05045d31c05c8928020f05f1d281901d983b2b (patch)
tree2ed3bac60302bfb14535a169f4b3e10d18fc6120 /vendor/github.com/lib/pq/ssl.go
parent41d4805d584161ca16b8187194385e47c36422a6 (diff)
cmd/monfront - import monfront from separate repository
This is the import from the separate monfront repository. The history could not be imported, but this should suffice.
Diffstat (limited to 'vendor/github.com/lib/pq/ssl.go')
-rw-r--r--vendor/github.com/lib/pq/ssl.go193
1 files changed, 193 insertions, 0 deletions
diff --git a/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go
new file mode 100644
index 0000000..e5eb928
--- /dev/null
+++ b/vendor/github.com/lib/pq/ssl.go
@@ -0,0 +1,193 @@
+package pq
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/user"
+ "path/filepath"
+)
+
+// ssl generates a function to upgrade a net.Conn based on the "sslmode" and
+// related settings. The function is nil when no upgrade should take place.
+func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
+ verifyCaOnly := false
+ tlsConf := tls.Config{}
+ switch mode := o["sslmode"]; mode {
+ // "require" is the default.
+ case "", "require":
+ // We must skip TLS's own verification since it requires full
+ // verification since Go 1.3.
+ tlsConf.InsecureSkipVerify = true
+
+ // From http://www.postgresql.org/docs/current/static/libpq-ssl.html:
+ //
+ // Note: For backwards compatibility with earlier versions of
+ // PostgreSQL, if a root CA file exists, the behavior of
+ // sslmode=require will be the same as that of verify-ca, meaning the
+ // server certificate is validated against the CA. Relying on this
+ // behavior is discouraged, and applications that need certificate
+ // validation should always use verify-ca or verify-full.
+ if sslrootcert, ok := o["sslrootcert"]; ok {
+ if _, err := os.Stat(sslrootcert); err == nil {
+ verifyCaOnly = true
+ } else {
+ delete(o, "sslrootcert")
+ }
+ }
+ case "verify-ca":
+ // We must skip TLS's own verification since it requires full
+ // verification since Go 1.3.
+ tlsConf.InsecureSkipVerify = true
+ verifyCaOnly = true
+ case "verify-full":
+ tlsConf.ServerName = o["host"]
+ case "disable":
+ return nil, nil
+ default:
+ return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode)
+ }
+
+ err := sslClientCertificates(&tlsConf, o)
+ if err != nil {
+ return nil, err
+ }
+ err = sslCertificateAuthority(&tlsConf, o)
+ if err != nil {
+ return nil, err
+ }
+
+ // Accept renegotiation requests initiated by the backend.
+ //
+ // Renegotiation was deprecated then removed from PostgreSQL 9.5, but
+ // the default configuration of older versions has it enabled. Redshift
+ // also initiates renegotiations and cannot be reconfigured.
+ tlsConf.Renegotiation = tls.RenegotiateFreelyAsClient
+
+ return func(conn net.Conn) (net.Conn, error) {
+ client := tls.Client(conn, &tlsConf)
+ if verifyCaOnly {
+ err := sslVerifyCertificateAuthority(client, &tlsConf)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return client, nil
+ }, nil
+}
+
+// sslClientCertificates adds the certificate specified in the "sslcert" and
+// "sslkey" settings, or if they aren't set, from the .postgresql directory
+// in the user's home directory. The configured files must exist and have
+// the correct permissions.
+func sslClientCertificates(tlsConf *tls.Config, o values) error {
+ sslinline := o["sslinline"]
+ if sslinline == "true" {
+ cert, err := tls.X509KeyPair([]byte(o["sslcert"]), []byte(o["sslkey"]))
+ if err != nil {
+ return err
+ }
+ tlsConf.Certificates = []tls.Certificate{cert}
+ return nil
+ }
+
+ // user.Current() might fail when cross-compiling. We have to ignore the
+ // error and continue without home directory defaults, since we wouldn't
+ // know from where to load them.
+ user, _ := user.Current()
+
+ // In libpq, the client certificate is only loaded if the setting is not blank.
+ //
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1036-L1037
+ sslcert := o["sslcert"]
+ if len(sslcert) == 0 && user != nil {
+ sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt")
+ }
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045
+ if len(sslcert) == 0 {
+ return nil
+ }
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054
+ if _, err := os.Stat(sslcert); os.IsNotExist(err) {
+ return nil
+ } else if err != nil {
+ return err
+ }
+
+ // In libpq, the ssl key is only loaded if the setting is not blank.
+ //
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1123-L1222
+ sslkey := o["sslkey"]
+ if len(sslkey) == 0 && user != nil {
+ sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key")
+ }
+
+ if len(sslkey) > 0 {
+ if err := sslKeyPermissions(sslkey); err != nil {
+ return err
+ }
+ }
+
+ cert, err := tls.LoadX509KeyPair(sslcert, sslkey)
+ if err != nil {
+ return err
+ }
+
+ tlsConf.Certificates = []tls.Certificate{cert}
+ return nil
+}
+
+// sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting.
+func sslCertificateAuthority(tlsConf *tls.Config, o values) error {
+ // In libpq, the root certificate is only loaded if the setting is not blank.
+ //
+ // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951
+ if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 {
+ tlsConf.RootCAs = x509.NewCertPool()
+
+ sslinline := o["sslinline"]
+
+ var cert []byte
+ if sslinline == "true" {
+ cert = []byte(sslrootcert)
+ } else {
+ var err error
+ cert, err = ioutil.ReadFile(sslrootcert)
+ if err != nil {
+ return err
+ }
+ }
+
+ if !tlsConf.RootCAs.AppendCertsFromPEM(cert) {
+ return fmterrorf("couldn't parse pem in sslrootcert")
+ }
+ }
+
+ return nil
+}
+
+// sslVerifyCertificateAuthority carries out a TLS handshake to the server and
+// verifies the presented certificate against the CA, i.e. the one specified in
+// sslrootcert or the system CA if sslrootcert was not specified.
+func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) error {
+ err := client.Handshake()
+ if err != nil {
+ return err
+ }
+ certs := client.ConnectionState().PeerCertificates
+ opts := x509.VerifyOptions{
+ DNSName: client.ConnectionState().ServerName,
+ Intermediates: x509.NewCertPool(),
+ Roots: tlsConf.RootCAs,
+ }
+ for i, cert := range certs {
+ if i == 0 {
+ continue
+ }
+ opts.Intermediates.AddCert(cert)
+ }
+ _, err = certs[0].Verify(opts)
+ return err
+}