Skip to content

Commit 4d072bf

Browse files
committed
Avoid corner-case memory leak in SSL parameter processing.
After reading the root cert list from the ssl_ca_file, immediately install it as client CA list of the new SSL context. That gives the SSL context ownership of the list, so that SSL_CTX_free will free it. This avoids a permanent memory leak if we fail further down in be_tls_init(), which could happen if bogus CRL data is offered. The leak could only amount to something if the CRL parameters get broken after server start (else we'd just quit) and then the server is SIGHUP'd many times without fixing the CRL data. That's rather unlikely perhaps, but it seems worth fixing, if only because the code is clearer this way. While we're here, add some comments about the memory management aspects of this logic. Noted by Jelte Fennema and independently by Andres Freund. Back-patch to v10; before commit de41869 it doesn't matter, since we'd not re-execute this code during SIGHUP. Discussion: https://postgr.es/m/16160-18367e56e9a28264@postgresql.org
1 parent 6ed0599 commit 4d072bf

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

src/backend/libpq/be-secure-openssl.c

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ static const char *ssl_protocol_version_to_string(int v);
8181
int
8282
be_tls_init(bool isServerStart)
8383
{
84-
STACK_OF(X509_NAME) * root_cert_list = NULL;
8584
SSL_CTX *context;
8685
int ssl_ver_min = -1;
8786
int ssl_ver_max = -1;
@@ -100,6 +99,10 @@ be_tls_init(bool isServerStart)
10099
}
101100

102101
/*
102+
* Create a new SSL context into which we'll load all the configuration
103+
* settings. If we fail partway through, we can avoid memory leakage by
104+
* freeing this context; we don't install it as active until the end.
105+
*
103106
* We use SSLv23_method() because it can negotiate use of the highest
104107
* mutually supported protocol version, while alternatives like
105108
* TLSv1_2_method() permit only one specific version. Note that we don't
@@ -269,6 +272,8 @@ be_tls_init(bool isServerStart)
269272
*/
270273
if (ssl_ca_file[0])
271274
{
275+
STACK_OF(X509_NAME) * root_cert_list;
276+
272277
if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 ||
273278
(root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
274279
{
@@ -278,6 +283,25 @@ be_tls_init(bool isServerStart)
278283
ssl_ca_file, SSLerrmessage(ERR_get_error()))));
279284
goto error;
280285
}
286+
287+
/*
288+
* Tell OpenSSL to send the list of root certs we trust to clients in
289+
* CertificateRequests. This lets a client with a keystore select the
290+
* appropriate client certificate to send to us. Also, this ensures
291+
* that the SSL context will "own" the root_cert_list and remember to
292+
* free it when no longer needed.
293+
*/
294+
SSL_CTX_set_client_CA_list(context, root_cert_list);
295+
296+
/*
297+
* Always ask for SSL client cert, but don't fail if it's not
298+
* presented. We might fail such connections later, depending on what
299+
* we find in pg_hba.conf.
300+
*/
301+
SSL_CTX_set_verify(context,
302+
(SSL_VERIFY_PEER |
303+
SSL_VERIFY_CLIENT_ONCE),
304+
verify_cb);
281305
}
282306

283307
/*----------
@@ -308,26 +332,6 @@ be_tls_init(bool isServerStart)
308332
}
309333
}
310334

311-
if (ssl_ca_file[0])
312-
{
313-
/*
314-
* Always ask for SSL client cert, but don't fail if it's not
315-
* presented. We might fail such connections later, depending on what
316-
* we find in pg_hba.conf.
317-
*/
318-
SSL_CTX_set_verify(context,
319-
(SSL_VERIFY_PEER |
320-
SSL_VERIFY_CLIENT_ONCE),
321-
verify_cb);
322-
323-
/*
324-
* Tell OpenSSL to send the list of root certs we trust to clients in
325-
* CertificateRequests. This lets a client with a keystore select the
326-
* appropriate client certificate to send to us.
327-
*/
328-
SSL_CTX_set_client_CA_list(context, root_cert_list);
329-
}
330-
331335
/*
332336
* Success! Replace any existing SSL_context.
333337
*/
@@ -346,6 +350,7 @@ be_tls_init(bool isServerStart)
346350

347351
return 0;
348352

353+
/* Clean up by releasing working context. */
349354
error:
350355
if (context)
351356
SSL_CTX_free(context);

0 commit comments

Comments
 (0)