1diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2--- a/nss/lib/ssl/ssl3con.c 2013-07-31 12:29:35.584231452 -0700 3+++ b/nss/lib/ssl/ssl3con.c 2013-07-31 12:31:22.785789376 -0700 4@@ -43,6 +43,7 @@ 5 6 static SECStatus ssl3_AuthCertificate(sslSocket *ss); 7 static void ssl3_CleanupPeerCerts(sslSocket *ss); 8+static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); 9 static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, 10 PK11SlotInfo * serverKeySlot); 11 static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); 12@@ -6141,6 +6142,7 @@ ssl3_HandleServerHello(sslSocket *ss, SS 13 /* copy the peer cert from the SID */ 14 if (sid->peerCert != NULL) { 15 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); 16+ ssl3_CopyPeerCertsFromSID(ss, sid); 17 } 18 19 /* NULL value for PMS signifies re-use of the old MS */ 20@@ -7538,6 +7540,7 @@ compression_found: 21 ss->sec.ci.sid = sid; 22 if (sid->peerCert != NULL) { 23 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); 24+ ssl3_CopyPeerCertsFromSID(ss, sid); 25 } 26 27 /* 28@@ -9147,6 +9150,44 @@ ssl3_CleanupPeerCerts(sslSocket *ss) 29 ss->ssl3.peerCertChain = NULL; 30 } 31 32+static void 33+ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid) 34+{ 35+ PLArenaPool *arena; 36+ ssl3CertNode *lastCert = NULL; 37+ ssl3CertNode *certs = NULL; 38+ int i; 39+ 40+ if (!sid->peerCertChain[0]) 41+ return; 42+ PORT_Assert(!ss->ssl3.peerCertArena); 43+ PORT_Assert(!ss->ssl3.peerCertChain); 44+ ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 45+ for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { 46+ ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode); 47+ c->cert = CERT_DupCertificate(sid->peerCertChain[i]); 48+ c->next = NULL; 49+ if (lastCert) { 50+ lastCert->next = c; 51+ } else { 52+ certs = c; 53+ } 54+ lastCert = c; 55+ } 56+ ss->ssl3.peerCertChain = certs; 57+} 58+ 59+static void 60+ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid) 61+{ 62+ int i = 0; 63+ ssl3CertNode *c = certs; 64+ for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) { 65+ PORT_Assert(!sid->peerCertChain[i]); 66+ sid->peerCertChain[i] = CERT_DupCertificate(c->cert); 67+ } 68+} 69+ 70 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete 71 * ssl3 CertificateStatus message. 72 * Caller must hold Handshake and RecvBuf locks. 73@@ -9432,6 +9473,7 @@ ssl3_AuthCertificate(sslSocket *ss) 74 } 75 76 ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); 77+ ssl3_CopyPeerCertsToSID(ss->ssl3.peerCertChain, ss->sec.ci.sid); 78 79 if (!ss->sec.isServer) { 80 CERTCertificate *cert = ss->sec.peerCert; 81diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 82--- a/nss/lib/ssl/sslimpl.h 2013-07-31 12:07:10.974699609 -0700 83+++ b/nss/lib/ssl/sslimpl.h 2013-07-31 12:31:22.785789376 -0700 84@@ -572,10 +572,13 @@ typedef enum { never_cached, 85 invalid_cache /* no longer in any cache. */ 86 } Cached; 87 88+#define MAX_PEER_CERT_CHAIN_SIZE 8 89+ 90 struct sslSessionIDStr { 91 sslSessionID * next; /* chain used for client sockets, only */ 92 93 CERTCertificate * peerCert; 94+ CERTCertificate * peerCertChain[MAX_PEER_CERT_CHAIN_SIZE]; 95 SECItemArray peerCertStatus; /* client only */ 96 const char * peerID; /* client only */ 97 const char * urlSvrName; /* client only */ 98diff -pu a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c 99--- a/nss/lib/ssl/sslnonce.c 2013-07-31 12:07:10.974699609 -0700 100+++ b/nss/lib/ssl/sslnonce.c 2013-07-31 12:31:22.785789376 -0700 101@@ -164,6 +164,7 @@ lock_cache(void) 102 static void 103 ssl_DestroySID(sslSessionID *sid) 104 { 105+ int i; 106 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); 107 PORT_Assert((sid->references == 0)); 108 109@@ -183,6 +184,9 @@ ssl_DestroySID(sslSessionID *sid) 110 if ( sid->peerCert ) { 111 CERT_DestroyCertificate(sid->peerCert); 112 } 113+ for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { 114+ CERT_DestroyCertificate(sid->peerCertChain[i]); 115+ } 116 if (sid->peerCertStatus.items) { 117 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); 118 } 119