Bug 366553: libSSL leaks global array of trusted client auth CA names, r=wtc
authornelson%bolyard.com
Tue, 11 Sep 2007 00:21:09 +0000
changeset 8043 aba13990eb7e7bf50f82dd7a802edf7b4cbf3cdf
parent 8042 7d1e08ff702a3d657627cc2de4c051314353a8b2
child 8044 73c61492282565c38d0e3b7f108b9ef688d5b7bf
push idunknown
push userunknown
push dateunknown
reviewerswtc
bugs366553
Bug 366553: libSSL leaks global array of trusted client auth CA names, r=wtc
security/nss/lib/ssl/sslsecur.c
--- 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);