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 |