Bug 764646: Backed out changeset 4bb4712d7432 because selfserv calls
authorWan-Teh Chang <wtc@google.com>
Wed, 25 Sep 2013 17:05:03 -0700
changeset 10855 07dd289c5111272270bbb3b9067fc70ac0877827
parent 10854 4bb4712d7432c7457de28dd46436c67a1dd9600e
child 10856 574d0c70a2c73ba3c7bdf9007dbb230dcc5efbe1
push id161
push userwtc@google.com
push dateThu, 26 Sep 2013 00:05:36 +0000
bugs764646
Bug 764646: Backed out changeset 4bb4712d7432 because selfserv calls SSL_ConfigServerSessionIDCache, which ultimately calls NSS_RegisterShutdown, before calling NSS_Initialize.
lib/ssl/ssl3con.c
lib/ssl/sslimpl.h
lib/ssl/sslnonce.c
lib/ssl/sslsnce.c
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -5389,16 +5389,17 @@ SSL3_ShutdownServerCache(void)
 	    if (*pSymWrapKey) {
 		PK11_FreeSymKey(*pSymWrapKey);
 	    	*pSymWrapKey = NULL;
 	    }
 	}
     }
 
     PZ_Unlock(symWrapKeysLock);
+    ssl_FreeSessionCacheLocks();
     return SECSuccess;
 }
 
 SECStatus ssl_InitSymWrapKeysLock(void)
 {
     symWrapKeysLock = PZ_NewLock(nssILockOther);
     return symWrapKeysLock ? SECSuccess : SECFailure;
 }
@@ -5440,17 +5441,17 @@ getWrappingKey( sslSocket *       ss,
 
     symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech);
     PORT_Assert(symWrapMechIndex >= 0);
     if (symWrapMechIndex < 0)
     	return NULL;	/* invalid masterWrapMech. */
 
     pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType];
 
-    ssl_InitSessionCacheLocks();
+    ssl_InitSessionCacheLocks(PR_TRUE);
 
     PZ_Lock(symWrapKeysLock);
 
     unwrappedWrappingKey = *pSymWrapKey;
     if (unwrappedWrappingKey != NULL) {
 	if (PK11_VerifyKeyOK(unwrappedWrappingKey)) {
 	    unwrappedWrappingKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
 	    goto done;
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -1778,17 +1778,19 @@ ssl_SetWrappingKey(SSLWrappedSymWrapping
 
 /* get rid of the symmetric wrapping key references. */
 extern SECStatus SSL3_ShutdownServerCache(void);
 
 extern SECStatus ssl_InitSymWrapKeysLock(void);
 
 extern SECStatus ssl_FreeSymWrapKeysLock(void);
 
-extern SECStatus ssl_InitSessionCacheLocks(void);
+extern SECStatus ssl_InitSessionCacheLocks(PRBool lazyInit);
+
+extern SECStatus ssl_FreeSessionCacheLocks(void);
 
 
 /**************** DTLS-specific functions **************/
 extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
 extern void dtls_FreeQueuedMessages(PRCList *lst);
 extern void dtls_FreeHandshakeMessages(PRCList *lst);
 
 extern SECStatus dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf);
--- a/lib/ssl/sslnonce.c
+++ b/lib/ssl/sslnonce.c
@@ -30,84 +30,136 @@ static PZLock *      cacheLock = NULL;
  * in_client_cache, 	in the client cache's linked list.
  * in_server_cache, 	entry came from the server's cache file.
  * invalid_cache	has been removed from the cache. 
  */
 
 #define LOCK_CACHE 	lock_cache()
 #define UNLOCK_CACHE	PZ_Unlock(cacheLock)
 
-static PRCallOnceType lockOnce;
+static SECStatus
+ssl_InitClientSessionCacheLock(void)
+{
+    cacheLock = PZ_NewLock(nssILockCache);
+    return cacheLock ? SECSuccess : SECFailure;
+}
 
-/* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys
- * the session cache locks on shutdown and resets them to their initial
- * state. */
+static SECStatus
+ssl_FreeClientSessionCacheLock(void)
+{
+    if (cacheLock) {
+        PZ_DestroyLock(cacheLock);
+        cacheLock = NULL;
+        return SECSuccess;
+    }
+    PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
+    return SECFailure;
+}
+
+static PRBool LocksInitializedEarly = PR_FALSE;
+
 static SECStatus
-FreeSessionCacheLocks(void* appData, void* nssData)
+FreeSessionCacheLocks()
+{
+    SECStatus rv1, rv2;
+    rv1 = ssl_FreeSymWrapKeysLock();
+    rv2 = ssl_FreeClientSessionCacheLock();
+    if ( (SECSuccess == rv1) && (SECSuccess == rv2) ) {
+        return SECSuccess;
+    }
+    return SECFailure;
+}
+
+static SECStatus
+InitSessionCacheLocks(void)
 {
-    static const PRCallOnceType pristineCallOnce;
-    SECStatus rv;
+    SECStatus rv1, rv2;
+    PRErrorCode rc;
+    rv1 = ssl_InitSymWrapKeysLock();
+    rv2 = ssl_InitClientSessionCacheLock();
+    if ( (SECSuccess == rv1) && (SECSuccess == rv2) ) {
+        return SECSuccess;
+    }
+    rc = PORT_GetError();
+    FreeSessionCacheLocks();
+    PORT_SetError(rc);
+    return SECFailure;
+}
 
-    if (!cacheLock) {
+/* free the session cache locks if they were initialized early */
+SECStatus
+ssl_FreeSessionCacheLocks()
+{
+    PORT_Assert(PR_TRUE == LocksInitializedEarly);
+    if (!LocksInitializedEarly) {
         PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
         return SECFailure;
     }
-
-    PZ_DestroyLock(cacheLock);
-    cacheLock = NULL;
-
-    rv = ssl_FreeSymWrapKeysLock();
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    lockOnce = pristineCallOnce;
+    FreeSessionCacheLocks();
+    LocksInitializedEarly = PR_FALSE;
     return SECSuccess;
 }
 
-/* InitSessionCacheLocks is called, protected by lockOnce, to create the
- * session cache locks. */
-static PRStatus
-InitSessionCacheLocks(void)
+static PRCallOnceType lockOnce;
+
+/* free the session cache locks if they were initialized lazily */
+static SECStatus ssl_ShutdownLocks(void* appData, void* nssData)
 {
-    SECStatus rv;
+    PORT_Assert(PR_FALSE == LocksInitializedEarly);
+    if (LocksInitializedEarly) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+    FreeSessionCacheLocks();
+    memset(&lockOnce, 0, sizeof(lockOnce));
+    return SECSuccess;
+}
 
-    cacheLock = PZ_NewLock(nssILockCache);
-    if (cacheLock == NULL) {
+static PRStatus initSessionCacheLocksLazily(void)
+{
+    SECStatus rv = InitSessionCacheLocks();
+    if (SECSuccess != rv) {
         return PR_FAILURE;
     }
-    rv = ssl_InitSymWrapKeysLock();
-    if (rv != SECSuccess) {
-        PRErrorCode error = PORT_GetError();
-        PZ_DestroyLock(cacheLock);
-        cacheLock = NULL;
-        PORT_SetError(error);
-        return PR_FAILURE;
-    }
-
-    rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL);
+    rv = NSS_RegisterShutdown(ssl_ShutdownLocks, NULL);
     PORT_Assert(SECSuccess == rv);
     if (SECSuccess != rv) {
         return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
+/* lazyInit means that the call is not happening during a 1-time
+ * initialization function, but rather during dynamic, lazy initialization
+ */
 SECStatus
-ssl_InitSessionCacheLocks(void)
+ssl_InitSessionCacheLocks(PRBool lazyInit)
 {
-    return (PR_SUCCESS ==
-            PR_CallOnce(&lockOnce, InitSessionCacheLocks)) ?
-           SECSuccess : SECFailure;
+    if (LocksInitializedEarly) {
+        return SECSuccess;
+    }
+
+    if (lazyInit) {
+        return (PR_SUCCESS ==
+                PR_CallOnce(&lockOnce, initSessionCacheLocksLazily)) ?
+               SECSuccess : SECFailure;
+    }
+     
+    if (SECSuccess == InitSessionCacheLocks()) {
+        LocksInitializedEarly = PR_TRUE;
+        return SECSuccess;
+    }
+
+    return SECFailure;
 }
 
-static void
+static void 
 lock_cache(void)
 {
-    ssl_InitSessionCacheLocks();
+    ssl_InitSessionCacheLocks(PR_TRUE);
     PZ_Lock(cacheLock);
 }
 
 /* BEWARE: This function gets called for both client and server SIDs !!
  * If the unreferenced sid is not in the cache, Free sid and its contents.
  */
 static void
 ssl_DestroySID(sslSessionID *sid)
--- a/lib/ssl/sslsnce.c
+++ b/lib/ssl/sslsnce.c
@@ -1348,17 +1348,17 @@ SSL_ConfigServerSessionIDCacheInstance(	
 }
 
 SECStatus
 SSL_ConfigServerSessionIDCache(	int      maxCacheEntries, 
 				PRUint32 ssl2_timeout,
 			       	PRUint32 ssl3_timeout, 
 			  const char *   directory)
 {
-    ssl_InitSessionCacheLocks();
+    ssl_InitSessionCacheLocks(PR_FALSE);
     return SSL_ConfigServerSessionIDCacheInstance(&globalCache, 
     		maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
 }
 
 SECStatus
 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
 {
     CloseCache(cache);
@@ -1462,17 +1462,17 @@ SSL_ConfigServerSessionIDCacheWithOpt(
 			       	PRUint32 ssl3_timeout, 
                                 const char *   directory,
                                 int maxCacheEntries,
                                 int maxCertCacheEntries,
                                 int maxSrvNameCacheEntries,
                                 PRBool enableMPCache)
 {
     if (!enableMPCache) {
-        ssl_InitSessionCacheLocks();
+        ssl_InitSessionCacheLocks(PR_FALSE);
         return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache, 
            ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
            maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
     } else {
         return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout, ssl3_timeout,
                 directory, maxCacheEntries, maxCertCacheEntries,
                                                  maxSrvNameCacheEntries);
     }
@@ -1507,17 +1507,17 @@ SSL_InheritMPServerSIDCacheInstance(cach
     */
     if (isMultiProcess) {
 	if (cache && cache->sharedCache) {
 	    cache->sharedCache->everInherited = PR_TRUE;
 	}
     	return SECSuccess;	/* already done. */
     }
 
-    ssl_InitSessionCacheLocks();
+    ssl_InitSessionCacheLocks(PR_FALSE);
 
     ssl_sid_lookup  = ServerSessionIDLookup;
     ssl_sid_cache   = ServerSessionIDCache;
     ssl_sid_uncache = ServerSessionIDUncache;
 
     if (!envString) {
     	envString  = getenv(envVarName);
 	if (!envString) {