@@ -8,12 +8,34 @@ import (
8
8
"os"
9
9
"os/user"
10
10
"path/filepath"
11
+ "sync"
11
12
)
12
13
13
- // ssl generates a function to upgrade a net.Conn based on the "sslmode" and
14
- // related settings. The function is nil when no upgrade should take place.
15
- func ssl (o values ) (func (net.Conn ) (net.Conn , error ), error ) {
14
+ // To avoid allocating the map if we never use ssl
15
+ var configMapOnce sync.Once
16
+ var configMapMu sync.Mutex
17
+ var configMap map [string ]* ssldata
18
+
19
+ type ssldata struct {
20
+ Conf * tls.Config
21
+ VerifyCAOnly bool
22
+ }
23
+
24
+ func getTLSConf (o values ) (* ssldata , error ) {
16
25
verifyCaOnly := false
26
+ configMapOnce .Do (func () {
27
+ configMap = make (map [string ]* ssldata )
28
+ })
29
+ // this function modifies o, so take the hash before any modifications are
30
+ // made
31
+ hash := string (o .Hash ())
32
+ // This pseudo-parameter is not recognized by the PostgreSQL server, so let's delete it after use.
33
+ configMapMu .Lock ()
34
+ conf , ok := configMap [hash ]
35
+ configMapMu .Unlock ()
36
+ if ok {
37
+ return conf , nil
38
+ }
17
39
tlsConf := tls.Config {}
18
40
switch mode := o ["sslmode" ]; mode {
19
41
// "require" is the default.
@@ -69,10 +91,27 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
69
91
// also initiates renegotiations and cannot be reconfigured.
70
92
tlsConf .Renegotiation = tls .RenegotiateFreelyAsClient
71
93
94
+ data := & ssldata {& tlsConf , verifyCaOnly }
95
+ configMapMu .Lock ()
96
+ configMap [hash ] = data
97
+ configMapMu .Unlock ()
98
+ return data , nil
99
+ }
100
+
101
+ // ssl generates a function to upgrade a net.Conn based on the "sslmode" and
102
+ // related settings. The function is nil when no upgrade should take place.
103
+ func ssl (o values ) (func (net.Conn ) (net.Conn , error ), error ) {
104
+ data , err := getTLSConf (o )
105
+ if data == nil && err == nil {
106
+ return nil , nil
107
+ }
108
+ if err != nil {
109
+ return nil , err
110
+ }
72
111
return func (conn net.Conn ) (net.Conn , error ) {
73
- client := tls .Client (conn , & tlsConf )
74
- if verifyCaOnly {
75
- err := sslVerifyCertificateAuthority (client , & tlsConf )
112
+ client := tls .Client (conn , data . Conf )
113
+ if data . VerifyCAOnly {
114
+ err := sslVerifyCertificateAuthority (client , data . Conf )
76
115
if err != nil {
77
116
return nil , err
78
117
}
@@ -86,8 +125,7 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
86
125
// in the user's home directory. The configured files must exist and have
87
126
// the correct permissions.
88
127
func sslClientCertificates (tlsConf * tls.Config , o values ) error {
89
- sslinline := o ["sslinline" ]
90
- if sslinline == "true" {
128
+ if o ["sslinline" ] == "true" {
91
129
cert , err := tls .X509KeyPair ([]byte (o ["sslcert" ]), []byte (o ["sslkey" ]))
92
130
// Clear out these params, in case they were to be sent to the PostgreSQL server by mistake
93
131
o ["sslcert" ] = ""
@@ -98,7 +136,6 @@ func sslClientCertificates(tlsConf *tls.Config, o values) error {
98
136
tlsConf .Certificates = []tls.Certificate {cert }
99
137
return nil
100
138
}
101
-
102
139
// user.Current() might fail when cross-compiling. We have to ignore the
103
140
// error and continue without home directory defaults, since we wouldn't
104
141
// know from where to load them.
0 commit comments