| Index: net/third_party/nss/ssl/sslnonce.c
 | 
| ===================================================================
 | 
| --- net/third_party/nss/ssl/sslnonce.c	(revision 242942)
 | 
| +++ net/third_party/nss/ssl/sslnonce.c	(working copy)
 | 
| @@ -123,18 +123,23 @@
 | 
|  	SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
 | 
|  	SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
 | 
|      } else {
 | 
| -	if (sid->u.ssl3.sessionTicket.ticket.data) {
 | 
| -	    SECITEM_FreeItem(&sid->u.ssl3.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.originalHandshakeHash.data) {
 | 
| -	  SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, 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.originalHandshakeHash.data) {
 | 
| +            SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, 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->peerID != NULL)
 | 
| @@ -156,7 +161,7 @@
 | 
|      if ( sid->localCert ) {
 | 
|  	CERT_DestroyCertificate(sid->localCert);
 | 
|      }
 | 
| -
 | 
| +    
 | 
|      PORT_ZFree(sid, sizeof(sslSessionID));
 | 
|  }
 | 
|  
 | 
| @@ -267,6 +272,9 @@
 | 
|  CacheSID(sslSessionID *sid)
 | 
|  {
 | 
|      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], 
 | 
| @@ -274,9 +282,6 @@
 | 
|  		sid->addr.pr_s6_addr32[3],  sid->port, sid->creationTime,
 | 
|  		sid->cached));
 | 
|  
 | 
| -    if (sid->cached == in_client_cache)
 | 
| -	return;
 | 
| -
 | 
|      if (!sid->urlSvrName) {
 | 
|          /* don't cache this SID because it can never be matched */
 | 
|          return;
 | 
| @@ -293,8 +298,9 @@
 | 
|  		  sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len));
 | 
|      } else {
 | 
|  	if (sid->u.ssl3.sessionIDLength == 0 &&
 | 
| -	    sid->u.ssl3.sessionTicket.ticket.data == NULL)
 | 
| +	    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;
 | 
| @@ -307,6 +313,11 @@
 | 
|  	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)
 | 
| @@ -430,41 +441,38 @@
 | 
|      return myTime;
 | 
|  }
 | 
|  
 | 
| -SECStatus
 | 
| -ssl3_SetSIDSessionTicket(sslSessionID *sid, NewSessionTicket *session_ticket)
 | 
| +void
 | 
| +ssl3_SetSIDSessionTicket(sslSessionID *sid,
 | 
| +                         /*in/out*/ NewSessionTicket *newSessionTicket)
 | 
|  {
 | 
| -    SECStatus rv;
 | 
| +    PORT_Assert(sid);
 | 
| +    PORT_Assert(newSessionTicket);
 | 
|  
 | 
| -    /* We need to lock the cache, as this sid might already be in the cache. */
 | 
| -    LOCK_CACHE;
 | 
| +    /* if sid->u.ssl3.lock, we are updating an existing entry that is already
 | 
| +     * cached or was once cached, so we need to acquire and release the write
 | 
| +     * lock. Otherwise, this is a new session that isn't shared with anything
 | 
| +     * yet, so no locking is needed.
 | 
| +     */
 | 
| +    if (sid->u.ssl3.lock) {
 | 
| +	PR_RWLock_Wlock(sid->u.ssl3.lock);
 | 
|  
 | 
| -    /* Don't modify sid if it has ever been cached. */
 | 
| -    if (sid->cached != never_cached) {
 | 
| -	UNLOCK_CACHE;
 | 
| -	return SECSuccess;
 | 
| +	/* A server might have sent us an empty ticket, which has the
 | 
| +	 * effect of clearing the previously known ticket.
 | 
| +	 */
 | 
| +	if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
 | 
| +	    SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
 | 
| +			     PR_FALSE);
 | 
| +	}
 | 
|      }
 | 
|  
 | 
| -    /* A server might have sent us an empty ticket, which has the
 | 
| -     * effect of clearing the previously known ticket.
 | 
| -     */
 | 
| -    if (sid->u.ssl3.sessionTicket.ticket.data)
 | 
| -	SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
 | 
| -    if (session_ticket->ticket.len > 0) {
 | 
| -	rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.sessionTicket.ticket,
 | 
| -	    &session_ticket->ticket);
 | 
| -	if (rv != SECSuccess) {
 | 
| -	    UNLOCK_CACHE;
 | 
| -	    return rv;
 | 
| -	}
 | 
| -    } else {
 | 
| -	sid->u.ssl3.sessionTicket.ticket.data = NULL;
 | 
| -	sid->u.ssl3.sessionTicket.ticket.len = 0;
 | 
| +    PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data);
 | 
| +
 | 
| +    /* Do a shallow copy, moving the ticket data. */
 | 
| +    sid->u.ssl3.locked.sessionTicket = *newSessionTicket;
 | 
| +    newSessionTicket->ticket.data = NULL;
 | 
| +    newSessionTicket->ticket.len = 0;
 | 
| +
 | 
| +    if (sid->u.ssl3.lock) {
 | 
| +	PR_RWLock_Unlock(sid->u.ssl3.lock);
 | 
|      }
 | 
| -    sid->u.ssl3.sessionTicket.received_timestamp =
 | 
| -	session_ticket->received_timestamp;
 | 
| -    sid->u.ssl3.sessionTicket.ticket_lifetime_hint =
 | 
| -	session_ticket->ticket_lifetime_hint;
 | 
| -
 | 
| -    UNLOCK_CACHE;
 | 
| -    return SECSuccess;
 | 
|  }
 | 
| 
 |