summaryrefslogtreecommitdiffstats
path: root/net/third_party/nss/patches/cachecerts.patch
blob: c91ad60b04a68fe36e64cb6edbde8974c16bffc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
index 45bf853..e3f9a9a 100644
--- a/mozilla/security/nss/lib/ssl/ssl3con.c
+++ b/mozilla/security/nss/lib/ssl/ssl3con.c
@@ -72,6 +72,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);
@@ -5136,6 +5137,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 	/* copy the peer cert from the SID */
 	if (sid->peerCert != NULL) {
 	    ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+	    ssl3_CopyPeerCertsFromSID(ss, sid);
 	}
 
 
@@ -6378,6 +6380,7 @@ compression_found:
 	ss->sec.ci.sid = sid;
 	if (sid->peerCert != NULL) {
 	    ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+	    ssl3_CopyPeerCertsFromSID(ss, sid);
 	}
 
 	/*
@@ -7746,6 +7749,38 @@ ssl3_CleanupPeerCerts(sslSocket *ss)
     ss->ssl3.peerCertChain = NULL;
 }
 
+static void
+ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
+{
+    PRArenaPool *arena;
+    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 = certs;
+	certs = 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.
@@ -7932,6 +7967,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
     }
 
     ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
+    ssl3_CopyPeerCertsToSID(certs, ss->sec.ci.sid);
 
     if (!ss->sec.isServer) {
 	/* set the server authentication and key exchange types and sizes
@@ -8103,6 +8139,8 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss)
     if (ss->handshake != NULL) {
 	ss->handshake = ssl_GatherRecord1stHandshake;
 	ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
+	ssl3_CopyPeerCertsToSID((ssl3CertNode *)ss->ssl3.peerCertChain,
+				ss->sec.ci.sid);
 
 	ssl_GetRecvBufLock(ss);
 	if (ss->ssl3.hs.msgState.buf != NULL) {
diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
index a800d56..fe7ac7a 100644
--- a/mozilla/security/nss/lib/ssl/sslimpl.h
+++ b/mozilla/security/nss/lib/ssl/sslimpl.h
@@ -569,10 +569,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 --git a/mozilla/security/nss/lib/ssl/sslnonce.c b/mozilla/security/nss/lib/ssl/sslnonce.c
index 63dc5a2..64adc1f 100644
--- a/mozilla/security/nss/lib/ssl/sslnonce.c
+++ b/mozilla/security/nss/lib/ssl/sslnonce.c
@@ -197,6 +197,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));
 
@@ -216,6 +217,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);
     }