@@ -12,7 +12,7 @@ import (
12
12
13
13
// ssl generates a function to upgrade a net.Conn based on the "sslmode" and
14
14
// related settings. The function is nil when no upgrade should take place.
15
- func ssl (o values ) func (net.Conn ) net.Conn {
15
+ func ssl (o values ) ( f func (net.Conn ) ( net.Conn , error ), err error ) {
16
16
verifyCaOnly := false
17
17
tlsConf := tls.Config {}
18
18
switch mode := o ["sslmode" ]; mode {
@@ -31,7 +31,7 @@ func ssl(o values) func(net.Conn) net.Conn {
31
31
// behavior is discouraged, and applications that need certificate
32
32
// validation should always use verify-ca or verify-full.
33
33
if sslrootcert , ok := o ["sslrootcert" ]; ok {
34
- if _ , err : = os .Stat (sslrootcert ); err == nil {
34
+ if _ , err = os .Stat (sslrootcert ); err == nil {
35
35
verifyCaOnly = true
36
36
} else {
37
37
delete (o , "sslrootcert" )
@@ -45,29 +45,39 @@ func ssl(o values) func(net.Conn) net.Conn {
45
45
case "verify-full" :
46
46
tlsConf .ServerName = o ["host" ]
47
47
case "disable" :
48
- return nil
48
+ return nil , nil
49
49
default :
50
- errorf (`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported` , mode )
50
+ err = fmterrorf (`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported` , mode )
51
+ return nil , err
51
52
}
52
53
53
- sslClientCertificates (& tlsConf , o )
54
- sslCertificateAuthority (& tlsConf , o )
54
+ err = sslClientCertificates (& tlsConf , o )
55
+ if err != nil {
56
+ return nil , err
57
+ }
58
+ err = sslCertificateAuthority (& tlsConf , o )
59
+ if err != nil {
60
+ return nil , err
61
+ }
55
62
sslRenegotiation (& tlsConf )
56
63
57
- return func (conn net.Conn ) net.Conn {
64
+ return func (conn net.Conn ) ( net.Conn , error ) {
58
65
client := tls .Client (conn , & tlsConf )
59
66
if verifyCaOnly {
60
- sslVerifyCertificateAuthority (client , & tlsConf )
67
+ errVerify := sslVerifyCertificateAuthority (client , & tlsConf )
68
+ if errVerify != nil {
69
+ return nil , errVerify
70
+ }
61
71
}
62
- return client
63
- }
72
+ return client , nil
73
+ }, nil
64
74
}
65
75
66
76
// sslClientCertificates adds the certificate specified in the "sslcert" and
67
77
// "sslkey" settings, or if they aren't set, from the .postgresql directory
68
78
// in the user's home directory. The configured files must exist and have
69
79
// the correct permissions.
70
- func sslClientCertificates (tlsConf * tls.Config , o values ) {
80
+ func sslClientCertificates (tlsConf * tls.Config , o values ) ( err error ) {
71
81
// user.Current() might fail when cross-compiling. We have to ignore the
72
82
// error and continue without home directory defaults, since we wouldn't
73
83
// know from where to load them.
@@ -82,13 +92,13 @@ func sslClientCertificates(tlsConf *tls.Config, o values) {
82
92
}
83
93
// https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045
84
94
if len (sslcert ) == 0 {
85
- return
95
+ return nil
86
96
}
87
97
// https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054
88
- if _ , err : = os .Stat (sslcert ); os .IsNotExist (err ) {
89
- return
98
+ if _ , err = os .Stat (sslcert ); os .IsNotExist (err ) {
99
+ return nil
90
100
} else if err != nil {
91
- panic ( err )
101
+ return err
92
102
}
93
103
94
104
// In libpq, the ssl key is only loaded if the setting is not blank.
@@ -100,44 +110,49 @@ func sslClientCertificates(tlsConf *tls.Config, o values) {
100
110
}
101
111
102
112
if len (sslkey ) > 0 {
103
- if err : = sslKeyPermissions (sslkey ); err != nil {
104
- panic ( err )
113
+ if err = sslKeyPermissions (sslkey ); err != nil {
114
+ return err
105
115
}
106
116
}
107
117
108
118
cert , err := tls .LoadX509KeyPair (sslcert , sslkey )
109
119
if err != nil {
110
- panic ( err )
120
+ return err
111
121
}
122
+
112
123
tlsConf .Certificates = []tls.Certificate {cert }
124
+ return nil
113
125
}
114
126
115
127
// sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting.
116
- func sslCertificateAuthority (tlsConf * tls.Config , o values ) {
128
+ func sslCertificateAuthority (tlsConf * tls.Config , o values ) ( err error ) {
117
129
// In libpq, the root certificate is only loaded if the setting is not blank.
118
130
//
119
131
// https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951
120
132
if sslrootcert := o ["sslrootcert" ]; len (sslrootcert ) > 0 {
121
133
tlsConf .RootCAs = x509 .NewCertPool ()
122
134
123
- cert , err := ioutil .ReadFile (sslrootcert )
135
+ var cert []byte
136
+ cert , err = ioutil .ReadFile (sslrootcert )
124
137
if err != nil {
125
- panic ( err )
138
+ return err
126
139
}
127
140
128
141
if ! tlsConf .RootCAs .AppendCertsFromPEM (cert ) {
129
- errorf ("couldn't parse pem in sslrootcert" )
142
+ return fmterrorf ("couldn't parse pem in sslrootcert" )
130
143
}
131
144
}
145
+
146
+ return nil
132
147
}
133
148
134
149
// sslVerifyCertificateAuthority carries out a TLS handshake to the server and
135
150
// verifies the presented certificate against the CA, i.e. the one specified in
136
151
// sslrootcert or the system CA if sslrootcert was not specified.
137
- func sslVerifyCertificateAuthority (client * tls.Conn , tlsConf * tls.Config ) {
138
- err : = client .Handshake ()
152
+ func sslVerifyCertificateAuthority (client * tls.Conn , tlsConf * tls.Config ) ( err error ) {
153
+ err = client .Handshake ()
139
154
if err != nil {
140
- panic ( err )
155
+ return err
141
156
}
142
157
certs := client .ConnectionState ().PeerCertificates
143
158
opts := x509.VerifyOptions {
@@ -152,7 +167,5 @@ func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) {
152
167
opts .Intermediates .AddCert (cert )
153
168
}
154
169
_ , err = certs [0 ].Verify (opts )
155
- if err != nil {
156
- panic (err )
157
- }
170
+ return err
158
171
}
0 commit comments