* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
		
			
				
	
	
		
			194 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| 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
 | |
| }
 |