• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff -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;
81diff -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 */
101diff -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