| 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" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); | 116 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); |
| 117 PORT_Assert((sid->references == 0)); | 117 PORT_Assert((sid->references == 0)); |
| 118 | 118 |
| 119 if (sid->cached == in_client_cache) | 119 if (sid->cached == in_client_cache) |
| 120 return; /* it will get taken care of next time cache is traversed. */ | 120 return; /* it will get taken care of next time cache is traversed. */ |
| 121 | 121 |
| 122 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | 122 if (sid->version < SSL_LIBRARY_VERSION_3_0) { |
| 123 SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); | 123 SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); |
| 124 SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); | 124 SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); |
| 125 } else { | 125 } else { |
| 126 » if (sid->u.ssl3.sessionTicket.ticket.data) { | 126 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { |
| 127 » SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE); | 127 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, |
| 128 » } | 128 PR_FALSE); |
| 129 » if (sid->u.ssl3.srvName.data) { | 129 } |
| 130 » SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); | 130 if (sid->u.ssl3.srvName.data) { |
| 131 » } | 131 SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); |
| 132 » if (sid->u.ssl3.signedCertTimestamps.data) { | 132 } |
| 133 » SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); | 133 if (sid->u.ssl3.originalHandshakeHash.data) { |
| 134 » } | 134 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); |
| 135 » if (sid->u.ssl3.originalHandshakeHash.data) { | 135 } |
| 136 » SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); | 136 if (sid->u.ssl3.signedCertTimestamps.data) { |
| 137 » } | 137 SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); |
| 138 } |
| 139 |
| 140 if (sid->u.ssl3.lock) { |
| 141 PR_DestroyRWLock(sid->u.ssl3.lock); |
| 142 } |
| 138 } | 143 } |
| 139 | 144 |
| 140 if (sid->peerID != NULL) | 145 if (sid->peerID != NULL) |
| 141 PORT_Free((void *)sid->peerID); /* CONST */ | 146 PORT_Free((void *)sid->peerID); /* CONST */ |
| 142 | 147 |
| 143 if (sid->urlSvrName != NULL) | 148 if (sid->urlSvrName != NULL) |
| 144 PORT_Free((void *)sid->urlSvrName); /* CONST */ | 149 PORT_Free((void *)sid->urlSvrName); /* CONST */ |
| 145 | 150 |
| 146 if ( sid->peerCert ) { | 151 if ( sid->peerCert ) { |
| 147 CERT_DestroyCertificate(sid->peerCert); | 152 CERT_DestroyCertificate(sid->peerCert); |
| 148 } | 153 } |
| 149 for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { | 154 for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { |
| 150 CERT_DestroyCertificate(sid->peerCertChain[i]); | 155 CERT_DestroyCertificate(sid->peerCertChain[i]); |
| 151 } | 156 } |
| 152 if (sid->peerCertStatus.items) { | 157 if (sid->peerCertStatus.items) { |
| 153 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); | 158 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); |
| 154 } | 159 } |
| 155 | 160 |
| 156 if ( sid->localCert ) { | 161 if ( sid->localCert ) { |
| 157 CERT_DestroyCertificate(sid->localCert); | 162 CERT_DestroyCertificate(sid->localCert); |
| 158 } | 163 } |
| 159 | 164 |
| 160 PORT_ZFree(sid, sizeof(sslSessionID)); | 165 PORT_ZFree(sid, sizeof(sslSessionID)); |
| 161 } | 166 } |
| 162 | 167 |
| 163 /* BEWARE: This function gets called for both client and server SIDs !! | 168 /* BEWARE: This function gets called for both client and server SIDs !! |
| 164 * Decrement reference count, and | 169 * Decrement reference count, and |
| 165 * free sid if ref count is zero, and sid is not in the cache. | 170 * free sid if ref count is zero, and sid is not in the cache. |
| 166 * Does NOT remove from the cache first. | 171 * Does NOT remove from the cache first. |
| 167 * If the sid is still in the cache, it is left there until next time | 172 * If the sid is still in the cache, it is left there until next time |
| 168 * the cache list is traversed. | 173 * the cache list is traversed. |
| 169 */ | 174 */ |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 } | 265 } |
| 261 | 266 |
| 262 /* | 267 /* |
| 263 ** Add an sid to the cache or return a previously cached entry to the cache. | 268 ** Add an sid to the cache or return a previously cached entry to the cache. |
| 264 ** Although this is static, it is called via ss->sec.cache(). | 269 ** Although this is static, it is called via ss->sec.cache(). |
| 265 */ | 270 */ |
| 266 static void | 271 static void |
| 267 CacheSID(sslSessionID *sid) | 272 CacheSID(sslSessionID *sid) |
| 268 { | 273 { |
| 269 PRUint32 expirationPeriod; | 274 PRUint32 expirationPeriod; |
| 275 |
| 276 PORT_Assert(sid->cached == never_cached); |
| 277 |
| 270 SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%
04x " | 278 SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%
04x " |
| 271 "time=%x cached=%d", | 279 "time=%x cached=%d", |
| 272 sid, sid->cached, sid->addr.pr_s6_addr32[0], | 280 sid, sid->cached, sid->addr.pr_s6_addr32[0], |
| 273 sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], | 281 sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], |
| 274 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, | 282 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, |
| 275 sid->cached)); | 283 sid->cached)); |
| 276 | 284 |
| 277 if (sid->cached == in_client_cache) | |
| 278 return; | |
| 279 | |
| 280 if (!sid->urlSvrName) { | 285 if (!sid->urlSvrName) { |
| 281 /* don't cache this SID because it can never be matched */ | 286 /* don't cache this SID because it can never be matched */ |
| 282 return; | 287 return; |
| 283 } | 288 } |
| 284 | 289 |
| 285 /* XXX should be different trace for version 2 vs. version 3 */ | 290 /* XXX should be different trace for version 2 vs. version 3 */ |
| 286 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | 291 if (sid->version < SSL_LIBRARY_VERSION_3_0) { |
| 287 expirationPeriod = ssl_sid_timeout; | 292 expirationPeriod = ssl_sid_timeout; |
| 288 PRINT_BUF(8, (0, "sessionID:", | 293 PRINT_BUF(8, (0, "sessionID:", |
| 289 sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); | 294 sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); |
| 290 PRINT_BUF(8, (0, "masterKey:", | 295 PRINT_BUF(8, (0, "masterKey:", |
| 291 sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); | 296 sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); |
| 292 PRINT_BUF(8, (0, "cipherArg:", | 297 PRINT_BUF(8, (0, "cipherArg:", |
| 293 sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); | 298 sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); |
| 294 } else { | 299 } else { |
| 295 if (sid->u.ssl3.sessionIDLength == 0 && | 300 if (sid->u.ssl3.sessionIDLength == 0 && |
| 296 » sid->u.ssl3.sessionTicket.ticket.data == NULL) | 301 » sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) |
| 297 return; | 302 return; |
| 303 |
| 298 /* Client generates the SessionID if this was a stateless resume. */ | 304 /* Client generates the SessionID if this was a stateless resume. */ |
| 299 if (sid->u.ssl3.sessionIDLength == 0) { | 305 if (sid->u.ssl3.sessionIDLength == 0) { |
| 300 SECStatus rv; | 306 SECStatus rv; |
| 301 rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, | 307 rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, |
| 302 SSL3_SESSIONID_BYTES); | 308 SSL3_SESSIONID_BYTES); |
| 303 if (rv != SECSuccess) | 309 if (rv != SECSuccess) |
| 304 return; | 310 return; |
| 305 sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; | 311 sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; |
| 306 } | 312 } |
| 307 expirationPeriod = ssl3_sid_timeout; | 313 expirationPeriod = ssl3_sid_timeout; |
| 308 PRINT_BUF(8, (0, "sessionID:", | 314 PRINT_BUF(8, (0, "sessionID:", |
| 309 sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); | 315 sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); |
| 316 |
| 317 sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL); |
| 318 if (!sid->u.ssl3.lock) { |
| 319 return; |
| 320 } |
| 310 } | 321 } |
| 311 PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); | 322 PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); |
| 312 if (!sid->creationTime) | 323 if (!sid->creationTime) |
| 313 sid->lastAccessTime = sid->creationTime = ssl_Time(); | 324 sid->lastAccessTime = sid->creationTime = ssl_Time(); |
| 314 if (!sid->expirationTime) | 325 if (!sid->expirationTime) |
| 315 sid->expirationTime = sid->creationTime + expirationPeriod; | 326 sid->expirationTime = sid->creationTime + expirationPeriod; |
| 316 | 327 |
| 317 /* | 328 /* |
| 318 * Put sid into the cache. Bump reference count to indicate that | 329 * Put sid into the cache. Bump reference count to indicate that |
| 319 * cache is holding a reference. Uncache will reduce the cache | 330 * cache is holding a reference. Uncache will reduce the cache |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 PRInt64 ll; | 434 PRInt64 ll; |
| 424 | 435 |
| 425 now = PR_Now(); | 436 now = PR_Now(); |
| 426 LL_I2L(ll, 1000000L); | 437 LL_I2L(ll, 1000000L); |
| 427 LL_DIV(now, now, ll); | 438 LL_DIV(now, now, ll); |
| 428 LL_L2UI(myTime, now); | 439 LL_L2UI(myTime, now); |
| 429 #endif | 440 #endif |
| 430 return myTime; | 441 return myTime; |
| 431 } | 442 } |
| 432 | 443 |
| 433 SECStatus | 444 void |
| 434 ssl3_SetSIDSessionTicket(sslSessionID *sid, NewSessionTicket *session_ticket) | 445 ssl3_SetSIDSessionTicket(sslSessionID *sid, |
| 446 /*in/out*/ NewSessionTicket *newSessionTicket) |
| 435 { | 447 { |
| 436 SECStatus rv; | 448 PORT_Assert(sid); |
| 449 PORT_Assert(newSessionTicket); |
| 437 | 450 |
| 438 /* We need to lock the cache, as this sid might already be in the cache. */ | 451 /* if sid->u.ssl3.lock, we are updating an existing entry that is already |
| 439 LOCK_CACHE; | 452 * cached or was once cached, so we need to acquire and release the write |
| 453 * lock. Otherwise, this is a new session that isn't shared with anything |
| 454 * yet, so no locking is needed. |
| 455 */ |
| 456 if (sid->u.ssl3.lock) { |
| 457 » PR_RWLock_Wlock(sid->u.ssl3.lock); |
| 440 | 458 |
| 441 /* Don't modify sid if it has ever been cached. */ | 459 » /* A server might have sent us an empty ticket, which has the |
| 442 if (sid->cached != never_cached) { | 460 » * effect of clearing the previously known ticket. |
| 443 » UNLOCK_CACHE; | 461 » */ |
| 444 » return SECSuccess; | 462 » if (sid->u.ssl3.locked.sessionTicket.ticket.data) { |
| 463 » SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, |
| 464 » » » PR_FALSE); |
| 465 » } |
| 445 } | 466 } |
| 446 | 467 |
| 447 /* A server might have sent us an empty ticket, which has the | 468 PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); |
| 448 * effect of clearing the previously known ticket. | 469 |
| 449 */ | 470 /* Do a shallow copy, moving the ticket data. */ |
| 450 if (sid->u.ssl3.sessionTicket.ticket.data) | 471 sid->u.ssl3.locked.sessionTicket = *newSessionTicket; |
| 451 » SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE); | 472 newSessionTicket->ticket.data = NULL; |
| 452 if (session_ticket->ticket.len > 0) { | 473 newSessionTicket->ticket.len = 0; |
| 453 » rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.sessionTicket.ticket, | 474 |
| 454 » &session_ticket->ticket); | 475 if (sid->u.ssl3.lock) { |
| 455 » if (rv != SECSuccess) { | 476 » PR_RWLock_Unlock(sid->u.ssl3.lock); |
| 456 » UNLOCK_CACHE; | |
| 457 » return rv; | |
| 458 » } | |
| 459 } else { | |
| 460 » sid->u.ssl3.sessionTicket.ticket.data = NULL; | |
| 461 » sid->u.ssl3.sessionTicket.ticket.len = 0; | |
| 462 } | 477 } |
| 463 sid->u.ssl3.sessionTicket.received_timestamp = | |
| 464 session_ticket->received_timestamp; | |
| 465 sid->u.ssl3.sessionTicket.ticket_lifetime_hint = | |
| 466 session_ticket->ticket_lifetime_hint; | |
| 467 | |
| 468 UNLOCK_CACHE; | |
| 469 return SECSuccess; | |
| 470 } | 478 } |
| OLD | NEW |