@@ -93,6 +93,12 @@ static void SSLerrfree(char *buf);
93
93
94
94
static bool pq_init_ssl_lib = true;
95
95
static bool pq_init_crypto_lib = true;
96
+
97
+ /*
98
+ * SSL_context is currently shared between threads and therefore we need to be
99
+ * careful to lock around any usage of it when providing thread safety.
100
+ * ssl_config_mutex is the mutex that we use to protect it.
101
+ */
96
102
static SSL_CTX * SSL_context = NULL ;
97
103
98
104
#ifdef ENABLE_THREAD_SAFETY
@@ -254,6 +260,10 @@ pqsecure_open_client(PGconn *conn)
254
260
/* We cannot use MSG_NOSIGNAL to block SIGPIPE when using SSL */
255
261
conn -> sigpipe_flag = false;
256
262
263
+ #ifdef ENABLE_THREAD_SAFETY
264
+ if (pthread_mutex_lock (& ssl_config_mutex ))
265
+ return -1 ;
266
+ #endif
257
267
/* Create a connection-specific SSL object */
258
268
if (!(conn -> ssl = SSL_new (SSL_context )) ||
259
269
!SSL_set_app_data (conn -> ssl , conn ) ||
@@ -266,9 +276,14 @@ pqsecure_open_client(PGconn *conn)
266
276
err );
267
277
SSLerrfree (err );
268
278
close_SSL (conn );
279
+ #ifdef ENABLE_THREAD_SAFETY
280
+ pthread_mutex_unlock (& ssl_config_mutex );
281
+ #endif
269
282
return PGRES_POLLING_FAILED ;
270
283
}
271
-
284
+ #ifdef ENABLE_THREAD_SAFETY
285
+ pthread_mutex_unlock (& ssl_config_mutex );
286
+ #endif
272
287
/*
273
288
* Load client certificate, private key, and trusted CA certs.
274
289
*/
@@ -1000,8 +1015,9 @@ destroy_ssl_system(void)
1000
1015
CRYPTO_set_id_callback (NULL );
1001
1016
1002
1017
/*
1003
- * We don't free the lock array. If we get another connection in this
1004
- * process, we will just re-use it with the existing mutexes.
1018
+ * We don't free the lock array or the SSL_context. If we get another
1019
+ * connection in this process, we will just re-use them with the
1020
+ * existing mutexes.
1005
1021
*
1006
1022
* This means we leak a little memory on repeated load/unload of the
1007
1023
* library.
@@ -1090,7 +1106,15 @@ initialize_SSL(PGconn *conn)
1090
1106
* understands which subject cert to present, in case different
1091
1107
* sslcert settings are used for different connections in the same
1092
1108
* process.
1109
+ *
1110
+ * NOTE: This function may also modify our SSL_context and therefore
1111
+ * we have to lock around this call and any places where we use the
1112
+ * SSL_context struct.
1093
1113
*/
1114
+ #ifdef ENABLE_THREAD_SAFETY
1115
+ if (pthread_mutex_lock (& ssl_config_mutex ))
1116
+ return -1 ;
1117
+ #endif
1094
1118
if (SSL_CTX_use_certificate_chain_file (SSL_context , fnbuf ) != 1 )
1095
1119
{
1096
1120
char * err = SSLerrmessage ();
@@ -1099,8 +1123,13 @@ initialize_SSL(PGconn *conn)
1099
1123
libpq_gettext ("could not read certificate file \"%s\": %s\n" ),
1100
1124
fnbuf , err );
1101
1125
SSLerrfree (err );
1126
+
1127
+ #ifdef ENABLE_THREAD_SAFETY
1128
+ pthread_mutex_unlock (& ssl_config_mutex );
1129
+ #endif
1102
1130
return -1 ;
1103
1131
}
1132
+
1104
1133
if (SSL_use_certificate_file (conn -> ssl , fnbuf , SSL_FILETYPE_PEM ) != 1 )
1105
1134
{
1106
1135
char * err = SSLerrmessage ();
@@ -1109,10 +1138,18 @@ initialize_SSL(PGconn *conn)
1109
1138
libpq_gettext ("could not read certificate file \"%s\": %s\n" ),
1110
1139
fnbuf , err );
1111
1140
SSLerrfree (err );
1141
+ #ifdef ENABLE_THREAD_SAFETY
1142
+ pthread_mutex_unlock (& ssl_config_mutex );
1143
+ #endif
1112
1144
return -1 ;
1113
1145
}
1146
+
1114
1147
/* need to load the associated private key, too */
1115
1148
have_cert = true;
1149
+
1150
+ #ifdef ENABLE_THREAD_SAFETY
1151
+ pthread_mutex_unlock (& ssl_config_mutex );
1152
+ #endif
1116
1153
}
1117
1154
1118
1155
/*
@@ -1288,6 +1325,10 @@ initialize_SSL(PGconn *conn)
1288
1325
{
1289
1326
X509_STORE * cvstore ;
1290
1327
1328
+ #ifdef ENABLE_THREAD_SAFETY
1329
+ if (pthread_mutex_lock (& ssl_config_mutex ))
1330
+ return -1 ;
1331
+ #endif
1291
1332
if (SSL_CTX_load_verify_locations (SSL_context , fnbuf , NULL ) != 1 )
1292
1333
{
1293
1334
char * err = SSLerrmessage ();
@@ -1296,6 +1337,9 @@ initialize_SSL(PGconn *conn)
1296
1337
libpq_gettext ("could not read root certificate file \"%s\": %s\n" ),
1297
1338
fnbuf , err );
1298
1339
SSLerrfree (err );
1340
+ #ifdef ENABLE_THREAD_SAFETY
1341
+ pthread_mutex_unlock (& ssl_config_mutex );
1342
+ #endif
1299
1343
return -1 ;
1300
1344
}
1301
1345
@@ -1323,11 +1367,17 @@ initialize_SSL(PGconn *conn)
1323
1367
libpq_gettext ("SSL library does not support CRL certificates (file \"%s\")\n" ),
1324
1368
fnbuf );
1325
1369
SSLerrfree (err );
1370
+ #ifdef ENABLE_THREAD_SAFETY
1371
+ pthread_mutex_unlock (& ssl_config_mutex );
1372
+ #endif
1326
1373
return -1 ;
1327
1374
#endif
1328
1375
}
1329
1376
/* if not found, silently ignore; we do not require CRL */
1330
1377
}
1378
+ #ifdef ENABLE_THREAD_SAFETY
1379
+ pthread_mutex_unlock (& ssl_config_mutex );
1380
+ #endif
1331
1381
1332
1382
SSL_set_verify (conn -> ssl , SSL_VERIFY_PEER , verify_cb );
1333
1383
}
0 commit comments