1 diff --git a/ssl/ssl3con.c b/ssl/ssl3con.c
2 index 163572c..60af5b0 100644
7 static SECStatus ssl3_AuthCertificate(sslSocket *ss);
8 static void ssl3_CleanupPeerCerts(sslSocket *ss);
9 +static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
10 static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
11 PK11SlotInfo * serverKeySlot);
12 static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
13 @@ -6549,6 +6550,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
14 /* copy the peer cert from the SID */
15 if (sid->peerCert != NULL) {
16 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
17 + ssl3_CopyPeerCertsFromSID(ss, sid);
20 /* NULL value for PMS signifies re-use of the old MS */
21 @@ -8140,6 +8142,7 @@ compression_found:
23 if (sid->peerCert != NULL) {
24 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
25 + ssl3_CopyPeerCertsFromSID(ss, sid);
29 @@ -9763,6 +9766,44 @@ ssl3_CleanupPeerCerts(sslSocket *ss)
30 ss->ssl3.peerCertChain = NULL;
34 +ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
37 + ssl3CertNode *lastCert = NULL;
38 + ssl3CertNode *certs = NULL;
41 + if (!sid->peerCertChain[0])
43 + PORT_Assert(!ss->ssl3.peerCertArena);
44 + PORT_Assert(!ss->ssl3.peerCertChain);
45 + ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
46 + for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
47 + ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
48 + c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
57 + ss->ssl3.peerCertChain = certs;
61 +ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid)
64 + ssl3CertNode *c = certs;
65 + for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
66 + PORT_Assert(!sid->peerCertChain[i]);
67 + sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
71 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
72 * ssl3 CertificateStatus message.
73 * Caller must hold Handshake and RecvBuf locks.
74 @@ -10041,6 +10082,7 @@ ssl3_AuthCertificate(sslSocket *ss)
77 ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
78 + ssl3_CopyPeerCertsToSID(ss->ssl3.peerCertChain, ss->sec.ci.sid);
80 if (!ss->sec.isServer) {
81 CERTCertificate *cert = ss->sec.peerCert;
82 diff --git a/ssl/sslimpl.h b/ssl/sslimpl.h
83 index 1b38a52..086f6d2 100644
86 @@ -597,6 +597,8 @@ typedef enum { never_cached,
87 invalid_cache /* no longer in any cache. */
90 +#define MAX_PEER_CERT_CHAIN_SIZE 8
92 struct sslSessionIDStr {
93 /* The global cache lock must be held when accessing these members when the
94 * sid is in any cache.
95 @@ -611,6 +613,7 @@ struct sslSessionIDStr {
98 CERTCertificate * peerCert;
99 + CERTCertificate * peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
100 SECItemArray peerCertStatus; /* client only */
101 const char * peerID; /* client only */
102 const char * urlSvrName; /* client only */
103 diff --git a/ssl/sslnonce.c b/ssl/sslnonce.c
104 index 2e861f1..be11008 100644
107 @@ -164,6 +164,7 @@ lock_cache(void)
109 ssl_DestroySID(sslSessionID *sid)
112 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached));
113 PORT_Assert(sid->references == 0);
114 PORT_Assert(sid->cached != in_client_cache);
115 @@ -194,6 +195,9 @@ ssl_DestroySID(sslSessionID *sid)
116 if ( sid->peerCert ) {
117 CERT_DestroyCertificate(sid->peerCert);
119 + for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
120 + CERT_DestroyCertificate(sid->peerCertChain[i]);
122 if (sid->peerCertStatus.items) {
123 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE);