| OLD | NEW |
| 1 /* | 1 /* |
| 2 * This file implements the CLIENT Session ID cache. | 2 * This file implements the CLIENT Session ID cache. |
| 3 * | 3 * |
| 4 * This Source Code Form is subject to the terms of the Mozilla Public | 4 * This Source Code Form is subject to the terms of the Mozilla Public |
| 5 * License, v. 2.0. If a copy of the MPL was not distributed with this | 5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 7 | 7 |
| 8 #include "cert.h" | 8 #include "cert.h" |
| 9 #include "pk11pub.h" | 9 #include "pk11pub.h" |
| 10 #include "secitem.h" | 10 #include "secitem.h" |
| 11 #include "ssl.h" | 11 #include "ssl.h" |
| 12 #include "nss.h" | 12 #include "nss.h" |
| 13 | 13 |
| 14 #include "sslimpl.h" | 14 #include "sslimpl.h" |
| 15 #include "sslproto.h" | 15 #include "sslproto.h" |
| 16 #include "nssilock.h" | 16 #include "nssilock.h" |
| 17 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) | 17 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) |
| 18 #include <time.h> | 18 #include <time.h> |
| 19 #endif | 19 #endif |
| 20 | 20 |
| 21 PRUint32 ssl_sid_timeout = 100; | 21 PRUint32 ssl_sid_timeout = 100; |
| 22 PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */ | 22 PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */ |
| 23 | 23 |
| 24 static sslSessionID *cache = NULL; | 24 static sslSessionID *cache = NULL; |
| 25 static PZLock * cacheLock = NULL; | 25 static PZLock *cacheLock = NULL; |
| 26 | 26 |
| 27 /* sids can be in one of 4 states: | 27 /* sids can be in one of 4 states: |
| 28 * | 28 * |
| 29 * never_cached, » created, but not yet put into cache. | 29 * never_cached, created, but not yet put into cache. |
| 30 * in_client_cache, » in the client cache's linked list. | 30 * in_client_cache, in the client cache's linked list. |
| 31 * in_server_cache, » entry came from the server's cache file. | 31 * in_server_cache, entry came from the server's cache file. |
| 32 * invalid_cache» has been removed from the cache. | 32 * invalid_cache has been removed from the cache. |
| 33 */ | 33 */ |
| 34 | 34 |
| 35 #define LOCK_CACHE » lock_cache() | 35 #define LOCK_CACHE lock_cache() |
| 36 #define UNLOCK_CACHE» PZ_Unlock(cacheLock) | 36 #define UNLOCK_CACHE PZ_Unlock(cacheLock) |
| 37 | 37 |
| 38 static PRCallOnceType lockOnce; | 38 static PRCallOnceType lockOnce; |
| 39 | 39 |
| 40 /* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys | 40 /* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys |
| 41 * the session cache locks on shutdown and resets them to their initial | 41 * the session cache locks on shutdown and resets them to their initial |
| 42 * state. */ | 42 * state. */ |
| 43 static SECStatus | 43 static SECStatus |
| 44 FreeSessionCacheLocks(void* appData, void* nssData) | 44 FreeSessionCacheLocks(void *appData, void *nssData) |
| 45 { | 45 { |
| 46 static const PRCallOnceType pristineCallOnce; | 46 static const PRCallOnceType pristineCallOnce; |
| 47 SECStatus rv; | 47 SECStatus rv; |
| 48 | 48 |
| 49 if (!cacheLock) { | 49 if (!cacheLock) { |
| 50 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); | 50 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); |
| 51 return SECFailure; | 51 return SECFailure; |
| 52 } | 52 } |
| 53 | 53 |
| 54 PZ_DestroyLock(cacheLock); | 54 PZ_DestroyLock(cacheLock); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 85 | 85 |
| 86 rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL); | 86 rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL); |
| 87 PORT_Assert(SECSuccess == rv); | 87 PORT_Assert(SECSuccess == rv); |
| 88 if (SECSuccess != rv) { | 88 if (SECSuccess != rv) { |
| 89 return PR_FAILURE; | 89 return PR_FAILURE; |
| 90 } | 90 } |
| 91 return PR_SUCCESS; | 91 return PR_SUCCESS; |
| 92 } | 92 } |
| 93 | 93 |
| 94 SECStatus | 94 SECStatus |
| 95 ssl_InitSessionCacheLocks(void) | 95 ssl_InitSessionCacheLocks() |
| 96 { | 96 { |
| 97 return (PR_SUCCESS == | 97 return (PR_SUCCESS == |
| 98 PR_CallOnce(&lockOnce, InitSessionCacheLocks)) ? | 98 PR_CallOnce(&lockOnce, InitSessionCacheLocks)) |
| 99 SECSuccess : SECFailure; | 99 ? SECSuccess |
| 100 : SECFailure; |
| 100 } | 101 } |
| 101 | 102 |
| 102 static void | 103 static void |
| 103 lock_cache(void) | 104 lock_cache(void) |
| 104 { | 105 { |
| 105 ssl_InitSessionCacheLocks(); | 106 ssl_InitSessionCacheLocks(); |
| 106 PZ_Lock(cacheLock); | 107 PZ_Lock(cacheLock); |
| 107 } | 108 } |
| 108 | 109 |
| 109 /* BEWARE: This function gets called for both client and server SIDs !! | 110 /* BEWARE: This function gets called for both client and server SIDs !! |
| 110 * If the unreferenced sid is not in the cache, Free sid and its contents. | 111 * If the unreferenced sid is not in the cache, Free sid and its contents. |
| 111 */ | 112 */ |
| 112 static void | 113 static void |
| 113 ssl_DestroySID(sslSessionID *sid) | 114 ssl_DestroySID(sslSessionID *sid) |
| 114 { | 115 { |
| 115 int i; | 116 int i; |
| 116 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); | 117 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); |
| 117 PORT_Assert(sid->references == 0); | 118 PORT_Assert(sid->references == 0); |
| 118 PORT_Assert(sid->cached != in_client_cache); | 119 PORT_Assert(sid->cached != in_client_cache); |
| 119 | 120 |
| 120 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | 121 if (sid->version < SSL_LIBRARY_VERSION_3_0) { |
| 121 » SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); | 122 SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); |
| 122 » SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); | 123 SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); |
| 123 } else { | 124 } else { |
| 124 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { | 125 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { |
| 125 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, | 126 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, |
| 126 PR_FALSE); | 127 PR_FALSE); |
| 127 } | 128 } |
| 128 if (sid->u.ssl3.srvName.data) { | 129 if (sid->u.ssl3.srvName.data) { |
| 129 SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); | 130 SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); |
| 130 } | 131 } |
| 132 if (sid->u.ssl3.signedCertTimestamps.data) { |
| 133 SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); |
| 134 } |
| 131 if (sid->u.ssl3.originalHandshakeHash.data) { | 135 if (sid->u.ssl3.originalHandshakeHash.data) { |
| 132 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); | 136 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); |
| 133 } | 137 } |
| 134 if (sid->u.ssl3.signedCertTimestamps.data) { | |
| 135 SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); | |
| 136 } | |
| 137 | 138 |
| 138 if (sid->u.ssl3.lock) { | 139 if (sid->u.ssl3.lock) { |
| 139 NSSRWLock_Destroy(sid->u.ssl3.lock); | 140 PR_DestroyRWLock(sid->u.ssl3.lock); |
| 140 } | 141 } |
| 141 } | 142 } |
| 142 | 143 |
| 143 if (sid->peerID != NULL) | 144 if (sid->peerID != NULL) |
| 144 » PORT_Free((void *)sid->peerID);»» /* CONST */ | 145 PORT_Free((void *)sid->peerID); /* CONST */ |
| 145 | 146 |
| 146 if (sid->urlSvrName != NULL) | 147 if (sid->urlSvrName != NULL) |
| 147 » PORT_Free((void *)sid->urlSvrName);» /* CONST */ | 148 PORT_Free((void *)sid->urlSvrName); /* CONST */ |
| 148 | 149 |
| 149 if ( sid->peerCert ) { | 150 if (sid->peerCert) { |
| 150 » CERT_DestroyCertificate(sid->peerCert); | 151 CERT_DestroyCertificate(sid->peerCert); |
| 151 } | 152 } |
| 152 for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { | 153 for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { |
| 153 CERT_DestroyCertificate(sid->peerCertChain[i]); | 154 CERT_DestroyCertificate(sid->peerCertChain[i]); |
| 154 } | 155 } |
| 155 if (sid->peerCertStatus.items) { | 156 if (sid->peerCertStatus.items) { |
| 156 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); | 157 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); |
| 157 } | 158 } |
| 158 | 159 |
| 159 if ( sid->localCert ) { | 160 if (sid->localCert) { |
| 160 » CERT_DestroyCertificate(sid->localCert); | 161 CERT_DestroyCertificate(sid->localCert); |
| 161 } | 162 } |
| 162 | 163 |
| 163 PORT_ZFree(sid, sizeof(sslSessionID)); | 164 PORT_ZFree(sid, sizeof(sslSessionID)); |
| 164 } | 165 } |
| 165 | 166 |
| 166 /* BEWARE: This function gets called for both client and server SIDs !! | 167 /* BEWARE: This function gets called for both client and server SIDs !! |
| 167 * Decrement reference count, and | 168 * Decrement reference count, and |
| 168 * free sid if ref count is zero, and sid is not in the cache. | 169 * free sid if ref count is zero, and sid is not in the cache. |
| 169 * Does NOT remove from the cache first. | 170 * Does NOT remove from the cache first. |
| 170 * If the sid is still in the cache, it is left there until next time | 171 * If the sid is still in the cache, it is left there until next time |
| 171 * the cache list is traversed. | 172 * the cache list is traversed. |
| 172 */ | 173 */ |
| 173 static void | 174 static void |
| 174 ssl_FreeLockedSID(sslSessionID *sid) | 175 ssl_FreeLockedSID(sslSessionID *sid) |
| 175 { | 176 { |
| 176 PORT_Assert(sid->references >= 1); | 177 PORT_Assert(sid->references >= 1); |
| 177 if (--sid->references == 0) { | 178 if (--sid->references == 0) { |
| 178 » ssl_DestroySID(sid); | 179 ssl_DestroySID(sid); |
| 179 } | 180 } |
| 180 } | 181 } |
| 181 | 182 |
| 182 /* BEWARE: This function gets called for both client and server SIDs !! | 183 /* BEWARE: This function gets called for both client and server SIDs !! |
| 183 * Decrement reference count, and | 184 * Decrement reference count, and |
| 184 * free sid if ref count is zero, and sid is not in the cache. | 185 * free sid if ref count is zero, and sid is not in the cache. |
| 185 * Does NOT remove from the cache first. | 186 * Does NOT remove from the cache first. |
| 186 * These locks are necessary because the sid _might_ be in the cache list. | 187 * These locks are necessary because the sid _might_ be in the cache list. |
| 187 */ | 188 */ |
| 188 void | 189 void |
| 189 ssl_FreeSID(sslSessionID *sid) | 190 ssl_FreeSID(sslSessionID *sid) |
| 190 { | 191 { |
| 191 LOCK_CACHE; | 192 LOCK_CACHE; |
| 192 ssl_FreeLockedSID(sid); | 193 ssl_FreeLockedSID(sid); |
| 193 UNLOCK_CACHE; | 194 UNLOCK_CACHE; |
| 194 } | 195 } |
| 195 | 196 |
| 196 /************************************************************************/ | 197 /************************************************************************/ |
| 197 | 198 |
| 198 /* | 199 /* |
| 199 ** Lookup sid entry in cache by Address, port, and peerID string. | 200 ** Lookup sid entry in cache by Address, port, and peerID string. |
| 200 ** If found, Increment reference count, and return pointer to caller. | 201 ** If found, Increment reference count, and return pointer to caller. |
| 201 ** If it has timed out or ref count is zero, remove from list and free it. | 202 ** If it has timed out or ref count is zero, remove from list and free it. |
| 202 */ | 203 */ |
| 203 | 204 |
| 204 sslSessionID * | 205 sslSessionID * |
| 205 ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, | 206 ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, |
| 206 const char * urlSvrName) | 207 const char *urlSvrName) |
| 207 { | 208 { |
| 208 sslSessionID **sidp; | 209 sslSessionID **sidp; |
| 209 sslSessionID * sid; | 210 sslSessionID *sid; |
| 210 PRUint32 now; | 211 PRUint32 now; |
| 211 | 212 |
| 212 if (!urlSvrName) | 213 if (!urlSvrName) |
| 213 » return NULL; | 214 return NULL; |
| 214 now = ssl_Time(); | 215 now = ssl_Time(); |
| 215 LOCK_CACHE; | 216 LOCK_CACHE; |
| 216 sidp = &cache; | 217 sidp = &cache; |
| 217 while ((sid = *sidp) != 0) { | 218 while ((sid = *sidp) != 0) { |
| 218 » PORT_Assert(sid->cached == in_client_cache); | 219 PORT_Assert(sid->cached == in_client_cache); |
| 219 » PORT_Assert(sid->references >= 1); | 220 PORT_Assert(sid->references >= 1); |
| 220 | 221 |
| 221 » SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid)); | 222 SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid)); |
| 222 | 223 |
| 223 » if (sid->expirationTime < now) { | 224 if (sid->expirationTime < now) { |
| 224 » /* | 225 /* |
| 225 » ** This session-id timed out. | 226 ** This session-id timed out. |
| 226 » ** Don't even care who it belongs to, blow it out of our cache. | 227 ** Don't even care who it belongs to, blow it out of our cache. |
| 227 » */ | 228 */ |
| 228 » SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d", | 229 SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d", |
| 229 » » » now - sid->creationTime, sid->references)); | 230 now - sid->creationTime, sid->references)); |
| 230 | 231 |
| 231 » *sidp = sid->next; »» » /* delink it from the list. */ | 232 *sidp = sid->next; /* delink it
from the list. */ |
| 232 » sid->cached = invalid_cache;» /* mark not on list. */ | 233 sid->cached = invalid_cache; /* mark not
on list. */ |
| 233 » ssl_FreeLockedSID(sid);» » /* drop ref count, free. */ | 234 ssl_FreeLockedSID(sid); /* drop ref
count, free. */ |
| 234 » } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP
addr matches */ | 235 } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP
addr matches */ |
| 235 » (sid->port == port) && /* server port matches */ | 236 (sid->port == port) && /* server po
rt matches */ |
| 236 » » /* proxy (peerID) matches */ | 237 /* proxy (peerID) matches */ |
| 237 » » (((peerID == NULL) && (sid->peerID == NULL)) || | 238 (((peerID == NULL) && (sid->peerID == NULL)) || |
| 238 » » ((peerID != NULL) && (sid->peerID != NULL) && | 239 ((peerID != NULL) && (sid->peerID != NULL) && |
| 239 » » PORT_Strcmp(sid->peerID, peerID) == 0)) && | 240 PORT_Strcmp(sid->peerID, peerID) == 0)) && |
| 240 » » /* is cacheable */ | 241 /* is cacheable */ |
| 241 » » (sid->version < SSL_LIBRARY_VERSION_3_0 || | 242 (sid->version < SSL_LIBRARY_VERSION_3_0 || |
| 242 » » sid->u.ssl3.keys.resumable) && | 243 sid->u.ssl3.keys.resumable) && |
| 243 » » /* server hostname matches. */ | 244 /* server hostname matches. */ |
| 244 » (sid->urlSvrName != NULL) && | 245 (sid->urlSvrName != NULL) && |
| 245 » » ((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) || | 246 (0 == PORT_Strcmp(urlSvrName, sid->urlSvrName))) { |
| 246 » » ((sid->peerCert != NULL) && (SECSuccess == | 247 /* Hit */ |
| 247 » » CERT_VerifyCertName(sid->peerCert, urlSvrName))) ) | 248 sid->lastAccessTime = now; |
| 248 » » ) { | 249 sid->references++; |
| 249 » /* Hit */ | 250 break; |
| 250 » sid->lastAccessTime = now; | 251 } else { |
| 251 » sid->references++; | 252 sidp = &sid->next; |
| 252 » break; | 253 } |
| 253 » } else { | |
| 254 » sidp = &sid->next; | |
| 255 » } | |
| 256 } | 254 } |
| 257 UNLOCK_CACHE; | 255 UNLOCK_CACHE; |
| 258 return sid; | 256 return sid; |
| 259 } | 257 } |
| 260 | 258 |
| 261 /* | 259 /* |
| 262 ** Add an sid to the cache or return a previously cached entry to the cache. | 260 ** Add an sid to the cache or return a previously cached entry to the cache. |
| 263 ** Although this is static, it is called via ss->sec.cache(). | 261 ** Although this is static, it is called via ss->sec.cache(). |
| 264 */ | 262 */ |
| 265 static void | 263 static void |
| 266 CacheSID(sslSessionID *sid) | 264 CacheSID(sslSessionID *sid) |
| 267 { | 265 { |
| 268 PRUint32 expirationPeriod; | 266 PRUint32 expirationPeriod; |
| 269 | 267 |
| 270 PORT_Assert(sid->cached == never_cached); | 268 PORT_Assert(sid->cached == never_cached); |
| 271 | 269 |
| 272 SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%
04x " | 270 SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%
04x " |
| 273 » » "time=%x cached=%d", | 271 "time=%x cached=%d", |
| 274 » » sid, sid->cached, sid->addr.pr_s6_addr32[0], | 272 sid, sid->cached, sid->addr.pr_s6_addr32[0], |
| 275 » » sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], | 273 sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], |
| 276 » » sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, | 274 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, |
| 277 » » sid->cached)); | 275 sid->cached)); |
| 278 | 276 |
| 279 if (!sid->urlSvrName) { | 277 if (!sid->urlSvrName) { |
| 280 /* don't cache this SID because it can never be matched */ | 278 /* don't cache this SID because it can never be matched */ |
| 281 return; | 279 return; |
| 282 } | 280 } |
| 283 | 281 |
| 284 /* XXX should be different trace for version 2 vs. version 3 */ | 282 /* XXX should be different trace for version 2 vs. version 3 */ |
| 285 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | 283 if (sid->version < SSL_LIBRARY_VERSION_3_0) { |
| 286 » expirationPeriod = ssl_sid_timeout; | 284 expirationPeriod = ssl_sid_timeout; |
| 287 » PRINT_BUF(8, (0, "sessionID:", | 285 PRINT_BUF(8, (0, "sessionID:", |
| 288 » » sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); | 286 sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); |
| 289 » PRINT_BUF(8, (0, "masterKey:", | 287 PRINT_BUF(8, (0, "masterKey:", |
| 290 » » sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); | 288 sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); |
| 291 » PRINT_BUF(8, (0, "cipherArg:", | 289 PRINT_BUF(8, (0, "cipherArg:", |
| 292 » » sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); | 290 sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); |
| 293 } else { | 291 } else { |
| 294 » if (sid->u.ssl3.sessionIDLength == 0 && | 292 if (sid->u.ssl3.sessionIDLength == 0 && |
| 295 » sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) | 293 sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) |
| 296 » return; | 294 return; |
| 297 | 295 |
| 298 » /* Client generates the SessionID if this was a stateless resume. */ | 296 /* Client generates the SessionID if this was a stateless resume. */ |
| 299 » if (sid->u.ssl3.sessionIDLength == 0) { | 297 if (sid->u.ssl3.sessionIDLength == 0) { |
| 300 » SECStatus rv; | 298 SECStatus rv; |
| 301 » rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, | 299 rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, |
| 302 » » SSL3_SESSIONID_BYTES); | 300 SSL3_SESSIONID_BYTES); |
| 303 » if (rv != SECSuccess) | 301 if (rv != SECSuccess) |
| 304 » » return; | 302 return; |
| 305 » sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; | 303 sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; |
| 306 » } | 304 } |
| 307 » expirationPeriod = ssl3_sid_timeout; | 305 expirationPeriod = ssl3_sid_timeout; |
| 308 » PRINT_BUF(8, (0, "sessionID:", | 306 PRINT_BUF(8, (0, "sessionID:", |
| 309 » » sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); | 307 sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); |
| 310 | 308 |
| 311 » sid->u.ssl3.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); | 309 sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL); |
| 312 » if (!sid->u.ssl3.lock) { | 310 if (!sid->u.ssl3.lock) { |
| 313 » return; | 311 return; |
| 314 » } | 312 } |
| 315 } | 313 } |
| 316 PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); | 314 PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); |
| 317 if (!sid->creationTime) | 315 if (!sid->creationTime) |
| 318 » sid->lastAccessTime = sid->creationTime = ssl_Time(); | 316 sid->lastAccessTime = sid->creationTime = ssl_Time(); |
| 319 if (!sid->expirationTime) | 317 if (!sid->expirationTime) |
| 320 » sid->expirationTime = sid->creationTime + expirationPeriod; | 318 sid->expirationTime = sid->creationTime + expirationPeriod; |
| 321 | 319 |
| 322 /* | 320 /* |
| 323 * Put sid into the cache. Bump reference count to indicate that | 321 * Put sid into the cache. Bump reference count to indicate that |
| 324 * cache is holding a reference. Uncache will reduce the cache | 322 * cache is holding a reference. Uncache will reduce the cache |
| 325 * reference. | 323 * reference. |
| 326 */ | 324 */ |
| 327 LOCK_CACHE; | 325 LOCK_CACHE; |
| 328 sid->references++; | 326 sid->references++; |
| 329 sid->cached = in_client_cache; | 327 sid->cached = in_client_cache; |
| 330 sid->next = cache; | 328 sid->next = cache; |
| 331 cache = sid; | 329 cache = sid; |
| 332 UNLOCK_CACHE; | 330 UNLOCK_CACHE; |
| 333 } | 331 } |
| 334 | 332 |
| 335 /* | 333 /* |
| 336 * If sid "zap" is in the cache, | 334 * If sid "zap" is in the cache, |
| 337 * removes sid from cache, and decrements reference count. | 335 * removes sid from cache, and decrements reference count. |
| 338 * Caller must hold cache lock. | 336 * Caller must hold cache lock. |
| 339 */ | 337 */ |
| 340 static void | 338 static void |
| 341 UncacheSID(sslSessionID *zap) | 339 UncacheSID(sslSessionID *zap) |
| 342 { | 340 { |
| 343 sslSessionID **sidp = &cache; | 341 sslSessionID **sidp = &cache; |
| 344 sslSessionID *sid; | 342 sslSessionID *sid; |
| 345 | 343 |
| 346 if (zap->cached != in_client_cache) { | 344 if (zap->cached != in_client_cache) { |
| 347 » return; | 345 return; |
| 348 } | 346 } |
| 349 | 347 |
| 350 SSL_TRC(8,("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x
%04x " | 348 SSL_TRC(8, ("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0
x%04x " |
| 351 » "time=%x cipher=%d", | 349 "time=%x cipher=%d", |
| 352 » zap, zap->cached, zap->addr.pr_s6_addr32[0], | 350 zap, zap->cached, zap->addr.pr_s6_addr32[0], |
| 353 » zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2], | 351 zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2], |
| 354 » zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime, | 352 zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime, |
| 355 » zap->u.ssl2.cipherType)); | 353 zap->u.ssl2.cipherType)); |
| 356 if (zap->version < SSL_LIBRARY_VERSION_3_0) { | 354 if (zap->version < SSL_LIBRARY_VERSION_3_0) { |
| 357 » PRINT_BUF(8, (0, "sessionID:", | 355 PRINT_BUF(8, (0, "sessionID:", |
| 358 » » zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID))); | 356 zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID))); |
| 359 » PRINT_BUF(8, (0, "masterKey:", | 357 PRINT_BUF(8, (0, "masterKey:", |
| 360 » » zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len)); | 358 zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len)); |
| 361 » PRINT_BUF(8, (0, "cipherArg:", | 359 PRINT_BUF(8, (0, "cipherArg:", |
| 362 » » zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len)); | 360 zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len)); |
| 363 } | 361 } |
| 364 | 362 |
| 365 /* See if it's in the cache, if so nuke it */ | 363 /* See if it's in the cache, if so nuke it */ |
| 366 while ((sid = *sidp) != 0) { | 364 while ((sid = *sidp) != 0) { |
| 367 » if (sid == zap) { | 365 if (sid == zap) { |
| 368 » /* | 366 /* |
| 369 » ** Bingo. Reduce reference count by one so that when | 367 ** Bingo. Reduce reference count by one so that when |
| 370 » ** everyone is done with the sid we can free it up. | 368 ** everyone is done with the sid we can free it up. |
| 371 » */ | 369 */ |
| 372 » *sidp = zap->next; | 370 *sidp = zap->next; |
| 373 » zap->cached = invalid_cache; | 371 zap->cached = invalid_cache; |
| 374 » ssl_FreeLockedSID(zap); | 372 ssl_FreeLockedSID(zap); |
| 375 » return; | 373 return; |
| 376 » } | 374 } |
| 377 » sidp = &sid->next; | 375 sidp = &sid->next; |
| 378 } | 376 } |
| 379 } | 377 } |
| 380 | 378 |
| 381 /* If sid "zap" is in the cache, | 379 /* If sid "zap" is in the cache, |
| 382 * removes sid from cache, and decrements reference count. | 380 * removes sid from cache, and decrements reference count. |
| 383 * Although this function is static, it is called externally via | 381 * Although this function is static, it is called externally via |
| 384 * ss->sec.uncache(). | 382 * ss->sec.uncache(). |
| 385 */ | 383 */ |
| 386 static void | 384 static void |
| 387 LockAndUncacheSID(sslSessionID *zap) | 385 LockAndUncacheSID(sslSessionID *zap) |
| 388 { | 386 { |
| 389 LOCK_CACHE; | 387 LOCK_CACHE; |
| 390 UncacheSID(zap); | 388 UncacheSID(zap); |
| 391 UNLOCK_CACHE; | 389 UNLOCK_CACHE; |
| 392 | |
| 393 } | 390 } |
| 394 | 391 |
| 395 /* choose client or server cache functions for this sslsocket. */ | 392 /* choose client or server cache functions for this sslsocket. */ |
| 396 void | 393 void |
| 397 ssl_ChooseSessionIDProcs(sslSecurityInfo *sec) | 394 ssl_ChooseSessionIDProcs(sslSecurityInfo *sec) |
| 398 { | 395 { |
| 399 if (sec->isServer) { | 396 if (sec->isServer) { |
| 400 » sec->cache = ssl_sid_cache; | 397 sec->cache = ssl_sid_cache; |
| 401 » sec->uncache = ssl_sid_uncache; | 398 sec->uncache = ssl_sid_uncache; |
| 402 } else { | 399 } else { |
| 403 » sec->cache = CacheSID; | 400 sec->cache = CacheSID; |
| 404 » sec->uncache = LockAndUncacheSID; | 401 sec->uncache = LockAndUncacheSID; |
| 405 } | 402 } |
| 406 } | 403 } |
| 407 | 404 |
| 408 /* wipe out the entire client session cache. */ | 405 /* wipe out the entire client session cache. */ |
| 409 void | 406 void |
| 410 SSL_ClearSessionCache(void) | 407 SSL_ClearSessionCache(void) |
| 411 { | 408 { |
| 412 LOCK_CACHE; | 409 LOCK_CACHE; |
| 413 while(cache != NULL) | 410 while (cache != NULL) |
| 414 » UncacheSID(cache); | 411 UncacheSID(cache); |
| 415 UNLOCK_CACHE; | 412 UNLOCK_CACHE; |
| 416 } | 413 } |
| 417 | 414 |
| 418 /* returns an unsigned int containing the number of seconds in PR_Now() */ | 415 /* returns an unsigned int containing the number of seconds in PR_Now() */ |
| 419 PRUint32 | 416 PRUint32 |
| 420 ssl_Time(void) | 417 ssl_Time(void) |
| 421 { | 418 { |
| 422 PRUint32 myTime; | 419 PRUint32 myTime; |
| 423 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) | 420 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) |
| 424 myTime = time(NULL);» /* accurate until the year 2038. */ | 421 myTime = time(NULL); /* accurate until the year 2038. */ |
| 425 #else | 422 #else |
| 426 /* portable, but possibly slower */ | 423 /* portable, but possibly slower */ |
| 427 PRTime now; | 424 PRTime now; |
| 428 PRInt64 ll; | 425 PRInt64 ll; |
| 429 | 426 |
| 430 now = PR_Now(); | 427 now = PR_Now(); |
| 431 LL_I2L(ll, 1000000L); | 428 LL_I2L(ll, 1000000L); |
| 432 LL_DIV(now, now, ll); | 429 LL_DIV(now, now, ll); |
| 433 LL_L2UI(myTime, now); | 430 LL_L2UI(myTime, now); |
| 434 #endif | 431 #endif |
| 435 return myTime; | 432 return myTime; |
| 436 } | 433 } |
| 437 | 434 |
| 438 void | 435 void |
| 439 ssl3_SetSIDSessionTicket(sslSessionID *sid, | 436 ssl3_SetSIDSessionTicket(sslSessionID *sid, |
| 440 /*in/out*/ NewSessionTicket *newSessionTicket) | 437 /*in/out*/ NewSessionTicket *newSessionTicket) |
| 441 { | 438 { |
| 442 PORT_Assert(sid); | 439 PORT_Assert(sid); |
| 443 PORT_Assert(newSessionTicket); | 440 PORT_Assert(newSessionTicket); |
| 444 PORT_Assert(newSessionTicket->ticket.data); | 441 PORT_Assert(newSessionTicket->ticket.data); |
| 445 PORT_Assert(newSessionTicket->ticket.len != 0); | 442 PORT_Assert(newSessionTicket->ticket.len != 0); |
| 446 | 443 |
| 447 /* if sid->u.ssl3.lock, we are updating an existing entry that is already | 444 /* if sid->u.ssl3.lock, we are updating an existing entry that is already |
| 448 * cached or was once cached, so we need to acquire and release the write | 445 * cached or was once cached, so we need to acquire and release the write |
| 449 * lock. Otherwise, this is a new session that isn't shared with anything | 446 * lock. Otherwise, this is a new session that isn't shared with anything |
| 450 * yet, so no locking is needed. | 447 * yet, so no locking is needed. |
| 451 */ | 448 */ |
| 452 if (sid->u.ssl3.lock) { | 449 if (sid->u.ssl3.lock) { |
| 453 » NSSRWLock_LockWrite(sid->u.ssl3.lock); | 450 PR_RWLock_Wlock(sid->u.ssl3.lock); |
| 454 » if (sid->u.ssl3.locked.sessionTicket.ticket.data) { | 451 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { |
| 455 » SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, | 452 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, |
| 456 » » » PR_FALSE); | 453 PR_FALSE); |
| 457 » } | 454 } |
| 458 } | 455 } |
| 459 | 456 |
| 460 PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); | 457 PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); |
| 461 | 458 |
| 462 /* Do a shallow copy, moving the ticket data. */ | 459 /* Do a shallow copy, moving the ticket data. */ |
| 463 sid->u.ssl3.locked.sessionTicket = *newSessionTicket; | 460 sid->u.ssl3.locked.sessionTicket = *newSessionTicket; |
| 464 newSessionTicket->ticket.data = NULL; | 461 newSessionTicket->ticket.data = NULL; |
| 465 newSessionTicket->ticket.len = 0; | 462 newSessionTicket->ticket.len = 0; |
| 466 | 463 |
| 467 if (sid->u.ssl3.lock) { | 464 if (sid->u.ssl3.lock) { |
| 468 » NSSRWLock_UnlockWrite(sid->u.ssl3.lock); | 465 PR_RWLock_Unlock(sid->u.ssl3.lock); |
| 469 } | 466 } |
| 470 } | 467 } |
| OLD | NEW |