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