| diff -pu -r a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c |
| --- a/net/third_party/nss/ssl/ssl3con.c 2012-11-09 15:19:29.665155332 -0800 |
| +++ b/net/third_party/nss/ssl/ssl3con.c 2012-11-09 15:20:08.835732728 -0800 |
| @@ -42,6 +42,7 @@ |
| #endif |
| |
| static void ssl3_CleanupPeerCerts(sslSocket *ss); |
| +static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); |
| static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, |
| PK11SlotInfo * serverKeySlot); |
| static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); |
| @@ -5575,6 +5576,7 @@ ssl3_HandleServerHello(sslSocket *ss, SS |
| /* copy the peer cert from the SID */ |
| if (sid->peerCert != NULL) { |
| ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); |
| + ssl3_CopyPeerCertsFromSID(ss, sid); |
| } |
| |
| |
| @@ -6916,6 +6918,7 @@ compression_found: |
| ss->sec.ci.sid = sid; |
| if (sid->peerCert != NULL) { |
| ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); |
| + ssl3_CopyPeerCertsFromSID(ss, sid); |
| } |
| |
| /* |
| @@ -8323,6 +8326,44 @@ ssl3_CleanupPeerCerts(sslSocket *ss) |
| ss->ssl3.peerCertChain = NULL; |
| } |
| |
| +static void |
| +ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid) |
| +{ |
| + PRArenaPool *arena; |
| + ssl3CertNode *lastCert = NULL; |
| + ssl3CertNode *certs = NULL; |
| + int i; |
| + |
| + if (!sid->peerCertChain[0]) |
| + return; |
| + PORT_Assert(!ss->ssl3.peerCertArena); |
| + PORT_Assert(!ss->ssl3.peerCertChain); |
| + ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| + for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { |
| + ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode); |
| + c->cert = CERT_DupCertificate(sid->peerCertChain[i]); |
| + c->next = NULL; |
| + if (lastCert) { |
| + lastCert->next = c; |
| + } else { |
| + certs = c; |
| + } |
| + lastCert = c; |
| + } |
| + ss->ssl3.peerCertChain = certs; |
| +} |
| + |
| +static void |
| +ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid) |
| +{ |
| + int i = 0; |
| + ssl3CertNode *c = certs; |
| + for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) { |
| + PORT_Assert(!sid->peerCertChain[i]); |
| + sid->peerCertChain[i] = CERT_DupCertificate(c->cert); |
| + } |
| +} |
| + |
| /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
| * ssl3 Certificate message. |
| * Caller must hold Handshake and RecvBuf locks. |
| @@ -8510,6 +8551,7 @@ ssl3_HandleCertificate(sslSocket *ss, SS |
| } |
| |
| ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); |
| + ssl3_CopyPeerCertsToSID(ss->ssl3.peerCertChain, ss->sec.ci.sid); |
| |
| if (!ss->sec.isServer) { |
| CERTCertificate *cert = ss->sec.peerCert; |
| diff -pu -r a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h |
| --- a/net/third_party/nss/ssl/sslimpl.h 2012-09-27 18:46:45.000000000 -0700 |
| +++ b/net/third_party/nss/ssl/sslimpl.h 2012-11-09 15:20:08.835732728 -0800 |
| @@ -571,10 +571,13 @@ typedef enum { never_cached, |
| invalid_cache /* no longer in any cache. */ |
| } Cached; |
| |
| +#define MAX_PEER_CERT_CHAIN_SIZE 8 |
| + |
| struct sslSessionIDStr { |
| sslSessionID * next; /* chain used for client sockets, only */ |
| |
| CERTCertificate * peerCert; |
| + CERTCertificate * peerCertChain[MAX_PEER_CERT_CHAIN_SIZE]; |
| const char * peerID; /* client only */ |
| const char * urlSvrName; /* client only */ |
| CERTCertificate * localCert; |
| diff -pu -r a/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c |
| --- a/net/third_party/nss/ssl/sslnonce.c 2012-04-25 07:50:12.000000000 -0700 |
| +++ b/net/third_party/nss/ssl/sslnonce.c 2012-11-09 15:20:08.835732728 -0800 |
| @@ -165,6 +165,7 @@ lock_cache(void) |
| static void |
| ssl_DestroySID(sslSessionID *sid) |
| { |
| + int i; |
| SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); |
| PORT_Assert((sid->references == 0)); |
| |
| @@ -184,6 +185,9 @@ ssl_DestroySID(sslSessionID *sid) |
| if ( sid->peerCert ) { |
| CERT_DestroyCertificate(sid->peerCert); |
| } |
| + for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { |
| + CERT_DestroyCertificate(sid->peerCertChain[i]); |
| + } |
| if ( sid->localCert ) { |
| CERT_DestroyCertificate(sid->localCert); |
| } |