123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- package pq
- import (
- "crypto/tls"
- "crypto/x509"
- "io/ioutil"
- "net"
- "os"
- "os/user"
- "path/filepath"
- )
- func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
- verifyCaOnly := false
- tlsConf := tls.Config{}
- switch mode := o["sslmode"]; mode {
-
- case "", "require":
-
-
- tlsConf.InsecureSkipVerify = true
-
-
-
-
-
-
-
-
- if sslrootcert, ok := o["sslrootcert"]; ok {
- if _, err := os.Stat(sslrootcert); err == nil {
- verifyCaOnly = true
- } else {
- delete(o, "sslrootcert")
- }
- }
- case "verify-ca":
-
-
- 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
- }
-
-
-
-
-
- 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
- }
- func sslClientCertificates(tlsConf *tls.Config, o values) error {
-
-
-
- user, _ := user.Current()
-
-
-
- sslcert := o["sslcert"]
- if len(sslcert) == 0 && user != nil {
- sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt")
- }
-
- if len(sslcert) == 0 {
- return nil
- }
-
- if _, err := os.Stat(sslcert); os.IsNotExist(err) {
- return nil
- } else if err != nil {
- return err
- }
-
-
-
- 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
- }
- func sslCertificateAuthority(tlsConf *tls.Config, o values) error {
-
-
-
- if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 {
- tlsConf.RootCAs = x509.NewCertPool()
- 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
- }
- 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
- }
|