Bug 366553: libSSL leaks global array of trusted client auth CA names, r=wtc
--- a/security/nss/lib/ssl/sslsecur.c
+++ b/security/nss/lib/ssl/sslsecur.c
@@ -41,16 +41,17 @@
#include "cert.h"
#include "secitem.h"
#include "keyhi.h"
#include "ssl.h"
#include "sslimpl.h"
#include "sslproto.h"
#include "secoid.h" /* for SECOID_GetALgorithmTag */
#include "pk11func.h" /* for PK11_GenerateRandom */
+#include "nss.h" /* for NSS_RegisterShutdown */
#define MAX_BLOCK_CYPHER_SIZE 32
#define TEST_FOR_FAILURE /* reminder */
#define SET_ERROR_CODE /* reminder */
/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
*
@@ -639,16 +640,42 @@ ssl_FindCertKEAType(CERTCertificate * ce
}
loser:
return keaType;
}
+static const PRCallOnceType pristineCallOnce;
+static PRCallOnceType setupServerCAListOnce;
+
+static SECStatus serverCAListShutdown(void* appData, void* nssData)
+{
+ PORT_Assert(ssl3_server_ca_list);
+ if (ssl3_server_ca_list) {
+ CERT_FreeDistNames(ssl3_server_ca_list);
+ ssl3_server_ca_list = NULL;
+ }
+ setupServerCAListOnce = pristineCallOnce;
+ return SECSuccess;
+}
+
+static PRStatus serverCAListSetup(void *arg)
+{
+ CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
+ SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL);
+ PORT_Assert(SECSuccess == rv);
+ if (SECSuccess == rv) {
+ ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle);
+ return PR_SUCCESS;
+ }
+ return PR_FAILURE;
+}
+
/* XXX need to protect the data that gets changed here.!! */
SECStatus
SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
SECKEYPrivateKey *key, SSL3KEAType kea)
{
SECStatus rv;
@@ -758,20 +785,21 @@ SSL_ConfigSecureServer(PRFileDesc *fd, C
rv = ssl3_CreateRSAStepDownKeys(ss);
if (rv != SECSuccess) {
return SECFailure; /* err set by ssl3_CreateRSAStepDownKeys */
}
}
}
/* Only do this once because it's global. */
- if (ssl3_server_ca_list == NULL)
- ssl3_server_ca_list = CERT_GetSSLCACerts(ss->dbHandle);
-
- return SECSuccess;
+ if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce,
+ &serverCAListSetup,
+ (void *)(ss->dbHandle))) {
+ return SECSuccess;
+ }
loser:
if (pubKey) {
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
}
if (sc->serverCert != NULL) {
CERT_DestroyCertificate(sc->serverCert);