security/nss/lib/ssl/sslnonce.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial