@@ -92,6 +92,12 @@ static void SSLerrfree(char *buf);
9292
9393static bool pq_init_ssl_lib = true;
9494static bool pq_init_crypto_lib = true;
95+
96+ /*
97+ * SSL_context is currently shared between threads and therefore we need to be
98+ * careful to lock around any usage of it when providing thread safety.
99+ * ssl_config_mutex is the mutex that we use to protect it.
100+ */
95101static SSL_CTX * SSL_context = NULL ;
96102
97103#ifdef ENABLE_THREAD_SAFETY
@@ -253,6 +259,10 @@ pqsecure_open_client(PGconn *conn)
253259 /* We cannot use MSG_NOSIGNAL to block SIGPIPE when using SSL */
254260 conn -> sigpipe_flag = false;
255261
262+ #ifdef ENABLE_THREAD_SAFETY
263+ if (pthread_mutex_lock (& ssl_config_mutex ))
264+ return -1 ;
265+ #endif
256266 /* Create a connection-specific SSL object */
257267 if (!(conn -> ssl = SSL_new (SSL_context )) ||
258268 !SSL_set_app_data (conn -> ssl , conn ) ||
@@ -265,9 +275,14 @@ pqsecure_open_client(PGconn *conn)
265275 err );
266276 SSLerrfree (err );
267277 close_SSL (conn );
278+ #ifdef ENABLE_THREAD_SAFETY
279+ pthread_mutex_unlock (& ssl_config_mutex );
280+ #endif
268281 return PGRES_POLLING_FAILED ;
269282 }
270-
283+ #ifdef ENABLE_THREAD_SAFETY
284+ pthread_mutex_unlock (& ssl_config_mutex );
285+ #endif
271286 /*
272287 * Load client certificate, private key, and trusted CA certs.
273288 */
@@ -999,8 +1014,9 @@ destroy_ssl_system(void)
9991014 CRYPTO_set_id_callback (NULL );
10001015
10011016 /*
1002- * We don't free the lock array. If we get another connection in this
1003- * process, we will just re-use it with the existing mutexes.
1017+ * We don't free the lock array or the SSL_context. If we get another
1018+ * connection in this process, we will just re-use them with the
1019+ * existing mutexes.
10041020 *
10051021 * This means we leak a little memory on repeated load/unload of the
10061022 * library.
@@ -1089,7 +1105,15 @@ initialize_SSL(PGconn *conn)
10891105 * understands which subject cert to present, in case different
10901106 * sslcert settings are used for different connections in the same
10911107 * process.
1108+ *
1109+ * NOTE: This function may also modify our SSL_context and therefore
1110+ * we have to lock around this call and any places where we use the
1111+ * SSL_context struct.
10921112 */
1113+ #ifdef ENABLE_THREAD_SAFETY
1114+ if (pthread_mutex_lock (& ssl_config_mutex ))
1115+ return -1 ;
1116+ #endif
10931117 if (SSL_CTX_use_certificate_chain_file (SSL_context , fnbuf ) != 1 )
10941118 {
10951119 char * err = SSLerrmessage ();
@@ -1098,8 +1122,13 @@ initialize_SSL(PGconn *conn)
10981122 libpq_gettext ("could not read certificate file \"%s\": %s\n" ),
10991123 fnbuf , err );
11001124 SSLerrfree (err );
1125+
1126+ #ifdef ENABLE_THREAD_SAFETY
1127+ pthread_mutex_unlock (& ssl_config_mutex );
1128+ #endif
11011129 return -1 ;
11021130 }
1131+
11031132 if (SSL_use_certificate_file (conn -> ssl , fnbuf , SSL_FILETYPE_PEM ) != 1 )
11041133 {
11051134 char * err = SSLerrmessage ();
@@ -1108,10 +1137,18 @@ initialize_SSL(PGconn *conn)
11081137 libpq_gettext ("could not read certificate file \"%s\": %s\n" ),
11091138 fnbuf , err );
11101139 SSLerrfree (err );
1140+ #ifdef ENABLE_THREAD_SAFETY
1141+ pthread_mutex_unlock (& ssl_config_mutex );
1142+ #endif
11111143 return -1 ;
11121144 }
1145+
11131146 /* need to load the associated private key, too */
11141147 have_cert = true;
1148+
1149+ #ifdef ENABLE_THREAD_SAFETY
1150+ pthread_mutex_unlock (& ssl_config_mutex );
1151+ #endif
11151152 }
11161153
11171154 /*
@@ -1287,6 +1324,10 @@ initialize_SSL(PGconn *conn)
12871324 {
12881325 X509_STORE * cvstore ;
12891326
1327+ #ifdef ENABLE_THREAD_SAFETY
1328+ if (pthread_mutex_lock (& ssl_config_mutex ))
1329+ return -1 ;
1330+ #endif
12901331 if (SSL_CTX_load_verify_locations (SSL_context , fnbuf , NULL ) != 1 )
12911332 {
12921333 char * err = SSLerrmessage ();
@@ -1295,6 +1336,9 @@ initialize_SSL(PGconn *conn)
12951336 libpq_gettext ("could not read root certificate file \"%s\": %s\n" ),
12961337 fnbuf , err );
12971338 SSLerrfree (err );
1339+ #ifdef ENABLE_THREAD_SAFETY
1340+ pthread_mutex_unlock (& ssl_config_mutex );
1341+ #endif
12981342 return -1 ;
12991343 }
13001344
@@ -1322,11 +1366,17 @@ initialize_SSL(PGconn *conn)
13221366 libpq_gettext ("SSL library does not support CRL certificates (file \"%s\")\n" ),
13231367 fnbuf );
13241368 SSLerrfree (err );
1369+ #ifdef ENABLE_THREAD_SAFETY
1370+ pthread_mutex_unlock (& ssl_config_mutex );
1371+ #endif
13251372 return -1 ;
13261373#endif
13271374 }
13281375 /* if not found, silently ignore; we do not require CRL */
13291376 }
1377+ #ifdef ENABLE_THREAD_SAFETY
1378+ pthread_mutex_unlock (& ssl_config_mutex );
1379+ #endif
13301380
13311381 SSL_set_verify (conn -> ssl , SSL_VERIFY_PEER , verify_cb );
13321382 }
0 commit comments