Bug 366553, libSSL leaks global array of trusted client auth CA names NSS_3_11_BRANCH
authornelson%bolyard.com
Wed, 26 Sep 2007 02:16:51 +0000
branchNSS_3_11_BRANCH
changeset 8074 c5d52e0d6033aade9f49ec9a33ef70b6c069b579
parent 8060 72d63ba6014f91ca49045455e239a2ed7c200eaf
child 8075 1ccd92e83267e829222243e5d7289bf4f3f6125c
push idunknown
push userunknown
push dateunknown
bugs366553
Bug 366553, libSSL leaks global array of trusted client auth CA names r=wtc,rrelyea
security/nss/lib/ssl/sslsecur.c
--- a/security/nss/lib/ssl/sslsecur.c
+++ b/security/nss/lib/ssl/sslsecur.c
@@ -639,16 +639,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 +784,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);