diff options
Diffstat (limited to 'nss/lib/ssl/sslnonce.c')
-rw-r--r-- | nss/lib/ssl/sslnonce.c | 331 |
1 files changed, 157 insertions, 174 deletions
diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c index 2e861f1..91cc870 100644 --- a/nss/lib/ssl/sslnonce.c +++ b/nss/lib/ssl/sslnonce.c @@ -1,5 +1,5 @@ -/* - * This file implements the CLIENT Session ID cache. +/* + * This file implements the CLIENT Session ID cache. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -22,18 +22,18 @@ PRUint32 ssl_sid_timeout = 100; PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */ static sslSessionID *cache = NULL; -static PZLock * cacheLock = NULL; +static PZLock *cacheLock = NULL; /* sids can be in one of 4 states: * - * never_cached, created, but not yet put into cache. - * 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. + * never_cached, created, but not yet put into cache. + * 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) +#define LOCK_CACHE lock_cache() +#define UNLOCK_CACHE PZ_Unlock(cacheLock) static SECStatus ssl_InitClientSessionCacheLock(void) @@ -62,7 +62,7 @@ FreeSessionCacheLocks() SECStatus rv1, rv2; rv1 = ssl_FreeSymWrapKeysLock(); rv2 = ssl_FreeClientSessionCacheLock(); - if ( (SECSuccess == rv1) && (SECSuccess == rv2) ) { + if ((SECSuccess == rv1) && (SECSuccess == rv2)) { return SECSuccess; } return SECFailure; @@ -75,7 +75,7 @@ InitSessionCacheLocks(void) PRErrorCode rc; rv1 = ssl_InitSymWrapKeysLock(); rv2 = ssl_InitClientSessionCacheLock(); - if ( (SECSuccess == rv1) && (SECSuccess == rv2) ) { + if ((SECSuccess == rv1) && (SECSuccess == rv2)) { return SECSuccess; } rc = PORT_GetError(); @@ -101,7 +101,8 @@ ssl_FreeSessionCacheLocks() static PRCallOnceType lockOnce; /* free the session cache locks if they were initialized lazily */ -static SECStatus ssl_ShutdownLocks(void* appData, void* nssData) +static SECStatus +ssl_ShutdownLocks(void *appData, void *nssData) { PORT_Assert(PR_FALSE == LocksInitializedEarly); if (LocksInitializedEarly) { @@ -113,7 +114,8 @@ static SECStatus ssl_ShutdownLocks(void* appData, void* nssData) return SECSuccess; } -static PRStatus initSessionCacheLocksLazily(void) +static PRStatus +initSessionCacheLocksLazily(void) { SECStatus rv = InitSessionCacheLocks(); if (SECSuccess != rv) { @@ -139,10 +141,11 @@ ssl_InitSessionCacheLocks(PRBool lazyInit) if (lazyInit) { return (PR_SUCCESS == - PR_CallOnce(&lockOnce, initSessionCacheLocksLazily)) ? - SECSuccess : SECFailure; + PR_CallOnce(&lockOnce, initSessionCacheLocksLazily)) + ? SECSuccess + : SECFailure; } - + if (SECSuccess == InitSessionCacheLocks()) { LocksInitializedEarly = PR_TRUE; return SECSuccess; @@ -151,7 +154,7 @@ ssl_InitSessionCacheLocks(PRBool lazyInit) return SECFailure; } -static void +static void lock_cache(void) { ssl_InitSessionCacheLocks(PR_TRUE); @@ -168,63 +171,63 @@ ssl_DestroySID(sslSessionID *sid) PORT_Assert(sid->references == 0); PORT_Assert(sid->cached != in_client_cache); - if (sid->version < SSL_LIBRARY_VERSION_3_0) { - SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); - SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); - } else { - if (sid->u.ssl3.locked.sessionTicket.ticket.data) { - SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, - PR_FALSE); - } - if (sid->u.ssl3.srvName.data) { - SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); - } + if (sid->u.ssl3.locked.sessionTicket.ticket.data) { + SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, + PR_FALSE); + } + if (sid->u.ssl3.srvName.data) { + SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); + } + if (sid->u.ssl3.signedCertTimestamps.data) { + SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); + } - if (sid->u.ssl3.lock) { - PR_DestroyRWLock(sid->u.ssl3.lock); - } + if (sid->u.ssl3.lock) { + PR_DestroyRWLock(sid->u.ssl3.lock); } if (sid->peerID != NULL) - PORT_Free((void *)sid->peerID); /* CONST */ + PORT_Free((void *)sid->peerID); /* CONST */ if (sid->urlSvrName != NULL) - PORT_Free((void *)sid->urlSvrName); /* CONST */ + PORT_Free((void *)sid->urlSvrName); /* CONST */ - if ( sid->peerCert ) { - CERT_DestroyCertificate(sid->peerCert); + if (sid->peerCert) { + CERT_DestroyCertificate(sid->peerCert); } if (sid->peerCertStatus.items) { SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); } - if ( sid->localCert ) { - CERT_DestroyCertificate(sid->localCert); + if (sid->localCert) { + CERT_DestroyCertificate(sid->localCert); } - + + SECITEM_FreeItem(&sid->u.ssl3.alpnSelection, PR_FALSE); + PORT_ZFree(sid, sizeof(sslSessionID)); } /* BEWARE: This function gets called for both client and server SIDs !! - * Decrement reference count, and - * free sid if ref count is zero, and sid is not in the cache. - * Does NOT remove from the cache first. + * Decrement reference count, and + * free sid if ref count is zero, and sid is not in the cache. + * Does NOT remove from the cache first. * If the sid is still in the cache, it is left there until next time * the cache list is traversed. */ -static void +static void ssl_FreeLockedSID(sslSessionID *sid) { PORT_Assert(sid->references >= 1); if (--sid->references == 0) { - ssl_DestroySID(sid); + ssl_DestroySID(sid); } } /* BEWARE: This function gets called for both client and server SIDs !! - * Decrement reference count, and - * free sid if ref count is zero, and sid is not in the cache. - * Does NOT remove from the cache first. + * Decrement reference count, and + * free sid if ref count is zero, and sid is not in the cache. + * Does NOT remove from the cache first. * These locks are necessary because the sid _might_ be in the cache list. */ void @@ -244,57 +247,53 @@ ssl_FreeSID(sslSessionID *sid) */ sslSessionID * -ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, - const char * urlSvrName) +ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, + const char *urlSvrName) { sslSessionID **sidp; - sslSessionID * sid; - PRUint32 now; + sslSessionID *sid; + PRUint32 now; if (!urlSvrName) - return NULL; + return NULL; now = ssl_Time(); LOCK_CACHE; sidp = &cache; while ((sid = *sidp) != 0) { - PORT_Assert(sid->cached == in_client_cache); - PORT_Assert(sid->references >= 1); - - SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid)); - - if (sid->expirationTime < now) { - /* - ** This session-id timed out. - ** Don't even care who it belongs to, blow it out of our cache. - */ - SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d", - now - sid->creationTime, sid->references)); - - *sidp = sid->next; /* delink it from the list. */ - sid->cached = invalid_cache; /* mark not on list. */ - ssl_FreeLockedSID(sid); /* drop ref count, free. */ - } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */ - (sid->port == port) && /* server port matches */ - /* proxy (peerID) matches */ - (((peerID == NULL) && (sid->peerID == NULL)) || - ((peerID != NULL) && (sid->peerID != NULL) && - PORT_Strcmp(sid->peerID, peerID) == 0)) && - /* is cacheable */ - (sid->version < SSL_LIBRARY_VERSION_3_0 || - sid->u.ssl3.keys.resumable) && - /* server hostname matches. */ - (sid->urlSvrName != NULL) && - ((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) || - ((sid->peerCert != NULL) && (SECSuccess == - CERT_VerifyCertName(sid->peerCert, urlSvrName))) ) - ) { - /* Hit */ - sid->lastAccessTime = now; - sid->references++; - break; - } else { - sidp = &sid->next; - } + PORT_Assert(sid->cached == in_client_cache); + PORT_Assert(sid->references >= 1); + + SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid)); + + if (sid->expirationTime < now) { + /* + ** This session-id timed out. + ** Don't even care who it belongs to, blow it out of our cache. + */ + SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d", + now - sid->creationTime, sid->references)); + + *sidp = sid->next; /* delink it from the list. */ + sid->cached = invalid_cache; /* mark not on list. */ + ssl_FreeLockedSID(sid); /* drop ref count, free. */ + } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */ + (sid->port == port) && /* server port matches */ + /* proxy (peerID) matches */ + (((peerID == NULL) && (sid->peerID == NULL)) || + ((peerID != NULL) && (sid->peerID != NULL) && + PORT_Strcmp(sid->peerID, peerID) == 0)) && + /* is cacheable */ + (sid->u.ssl3.keys.resumable) && + /* server hostname matches. */ + (sid->urlSvrName != NULL) && + (0 == PORT_Strcmp(urlSvrName, sid->urlSvrName))) { + /* Hit */ + sid->lastAccessTime = now; + sid->references++; + break; + } else { + sidp = &sid->next; + } } UNLOCK_CACHE; return sid; @@ -304,62 +303,51 @@ ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, ** Add an sid to the cache or return a previously cached entry to the cache. ** Although this is static, it is called via ss->sec.cache(). */ -static void +static void CacheSID(sslSessionID *sid) { - PRUint32 expirationPeriod; + PRUint32 expirationPeriod; PORT_Assert(sid->cached == never_cached); SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x " - "time=%x cached=%d", - sid, sid->cached, sid->addr.pr_s6_addr32[0], - sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], - sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, - sid->cached)); + "time=%x cached=%d", + sid, sid->cached, sid->addr.pr_s6_addr32[0], + sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], + sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, + sid->cached)); if (!sid->urlSvrName) { /* don't cache this SID because it can never be matched */ return; } - /* XXX should be different trace for version 2 vs. version 3 */ - if (sid->version < SSL_LIBRARY_VERSION_3_0) { - expirationPeriod = ssl_sid_timeout; - PRINT_BUF(8, (0, "sessionID:", - sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); - PRINT_BUF(8, (0, "masterKey:", - sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); - PRINT_BUF(8, (0, "cipherArg:", - sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); - } else { - if (sid->u.ssl3.sessionIDLength == 0 && - sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) - return; - - /* Client generates the SessionID if this was a stateless resume. */ - if (sid->u.ssl3.sessionIDLength == 0) { - SECStatus rv; - rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, - SSL3_SESSIONID_BYTES); - if (rv != SECSuccess) - return; - sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; - } - expirationPeriod = ssl3_sid_timeout; - PRINT_BUF(8, (0, "sessionID:", - sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); - - sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL); - if (!sid->u.ssl3.lock) { - return; - } + if (sid->u.ssl3.sessionIDLength == 0 && + sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) + return; + + /* Client generates the SessionID if this was a stateless resume. */ + if (sid->u.ssl3.sessionIDLength == 0) { + SECStatus rv; + rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, + SSL3_SESSIONID_BYTES); + if (rv != SECSuccess) + return; + sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; + } + expirationPeriod = ssl3_sid_timeout; + PRINT_BUF(8, (0, "sessionID:", + sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); + + sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL); + if (!sid->u.ssl3.lock) { + return; } PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); if (!sid->creationTime) - sid->lastAccessTime = sid->creationTime = ssl_Time(); + sid->lastAccessTime = sid->creationTime = ssl_Time(); if (!sid->expirationTime) - sid->expirationTime = sid->creationTime + expirationPeriod; + sid->expirationTime = sid->creationTime + expirationPeriod; /* * Put sid into the cache. Bump reference count to indicate that @@ -369,12 +357,12 @@ CacheSID(sslSessionID *sid) LOCK_CACHE; sid->references++; sid->cached = in_client_cache; - sid->next = cache; - cache = sid; + sid->next = cache; + cache = sid; UNLOCK_CACHE; } -/* +/* * If sid "zap" is in the cache, * removes sid from cache, and decrements reference count. * Caller must hold cache lock. @@ -386,43 +374,35 @@ UncacheSID(sslSessionID *zap) sslSessionID *sid; if (zap->cached != in_client_cache) { - return; + return; } - SSL_TRC(8,("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x " - "time=%x cipher=%d", - zap, zap->cached, zap->addr.pr_s6_addr32[0], - zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2], - zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime, - zap->u.ssl2.cipherType)); - if (zap->version < SSL_LIBRARY_VERSION_3_0) { - PRINT_BUF(8, (0, "sessionID:", - zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID))); - PRINT_BUF(8, (0, "masterKey:", - zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len)); - PRINT_BUF(8, (0, "cipherArg:", - zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len)); - } + SSL_TRC(8, ("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x " + "time=%x cipherSuite=%d", + zap, zap->cached, zap->addr.pr_s6_addr32[0], + zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2], + zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime, + zap->u.ssl3.cipherSuite)); /* See if it's in the cache, if so nuke it */ while ((sid = *sidp) != 0) { - if (sid == zap) { - /* - ** Bingo. Reduce reference count by one so that when - ** everyone is done with the sid we can free it up. - */ - *sidp = zap->next; - zap->cached = invalid_cache; - ssl_FreeLockedSID(zap); - return; - } - sidp = &sid->next; + if (sid == zap) { + /* + ** Bingo. Reduce reference count by one so that when + ** everyone is done with the sid we can free it up. + */ + *sidp = zap->next; + zap->cached = invalid_cache; + ssl_FreeLockedSID(zap); + return; + } + sidp = &sid->next; } } /* If sid "zap" is in the cache, * removes sid from cache, and decrements reference count. - * Although this function is static, it is called externally via + * Although this function is static, it is called externally via * ss->sec.uncache(). */ static void @@ -431,19 +411,18 @@ LockAndUncacheSID(sslSessionID *zap) LOCK_CACHE; UncacheSID(zap); UNLOCK_CACHE; - } /* choose client or server cache functions for this sslsocket. */ -void +void ssl_ChooseSessionIDProcs(sslSecurityInfo *sec) { if (sec->isServer) { - sec->cache = ssl_sid_cache; - sec->uncache = ssl_sid_uncache; + sec->cache = ssl_sid_cache; + sec->uncache = ssl_sid_uncache; } else { - sec->cache = CacheSID; - sec->uncache = LockAndUncacheSID; + sec->cache = CacheSID; + sec->uncache = LockAndUncacheSID; } } @@ -452,8 +431,8 @@ void SSL_ClearSessionCache(void) { LOCK_CACHE; - while(cache != NULL) - UncacheSID(cache); + while (cache != NULL) + UncacheSID(cache); UNLOCK_CACHE; } @@ -461,9 +440,13 @@ SSL_ClearSessionCache(void) PRUint32 ssl_Time(void) { +#ifdef UNSAFE_FUZZER_MODE + return 1234; +#endif + PRUint32 myTime; #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) - myTime = time(NULL); /* accurate until the year 2038. */ + myTime = time(NULL); /* accurate until the year 2038. */ #else /* portable, but possibly slower */ PRTime now; @@ -492,11 +475,11 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid, * yet, so no locking is needed. */ if (sid->u.ssl3.lock) { - PR_RWLock_Wlock(sid->u.ssl3.lock); - if (sid->u.ssl3.locked.sessionTicket.ticket.data) { - SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, - PR_FALSE); - } + PR_RWLock_Wlock(sid->u.ssl3.lock); + if (sid->u.ssl3.locked.sessionTicket.ticket.data) { + SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, + PR_FALSE); + } } PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); @@ -507,6 +490,6 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid, newSessionTicket->ticket.len = 0; if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); + PR_RWLock_Unlock(sid->u.ssl3.lock); } } |