Bug 764646: Backed out changeset 4bb4712d7432 because selfserv calls
SSL_ConfigServerSessionIDCache, which ultimately calls
NSS_RegisterShutdown, before calling NSS_Initialize.
--- 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) {