1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2 --- a/nss/lib/ssl/ssl3con.c 2014-01-17 17:49:26.062517203 -0800 3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-17 17:51:23.974478249 -0800 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 @@ -6474,6 +6475,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 @@ -8048,6 +8050,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 @@ -9662,6 +9665,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 @@ -9940,6 +9981,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; 81 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 82 --- a/nss/lib/ssl/sslimpl.h 2014-01-17 17:49:26.072517368 -0800 83 +++ b/nss/lib/ssl/sslimpl.h 2014-01-17 17:51:23.984478418 -0800 84 @@ -595,6 +595,8 @@ 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 /* The global cache lock must be held when accessing these members when the 92 * sid is in any cache. 93 @@ -609,6 +611,7 @@ struct sslSessionIDStr { 94 */ 95 96 CERTCertificate * peerCert; 97 + CERTCertificate * peerCertChain[MAX_PEER_CERT_CHAIN_SIZE]; 98 SECItemArray peerCertStatus; /* client only */ 99 const char * peerID; /* client only */ 100 const char * urlSvrName; /* client only */ 101 diff -pu a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c 102 --- a/nss/lib/ssl/sslnonce.c 2014-01-17 17:49:26.072517368 -0800 103 +++ b/nss/lib/ssl/sslnonce.c 2014-01-17 17:51:23.984478418 -0800 104 @@ -164,6 +164,7 @@ lock_cache(void) 105 static void 106 ssl_DestroySID(sslSessionID *sid) 107 { 108 + int i; 109 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); 110 PORT_Assert(sid->references == 0); 111 PORT_Assert(sid->cached != in_client_cache); 112 @@ -194,6 +195,9 @@ ssl_DestroySID(sslSessionID *sid) 113 if ( sid->peerCert ) { 114 CERT_DestroyCertificate(sid->peerCert); 115 } 116 + for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { 117 + CERT_DestroyCertificate(sid->peerCertChain[i]); 118 + } 119 if (sid->peerCertStatus.items) { 120 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); 121 } 122