Chromium Code Reviews| Index: net/third_party/nss/ssl/ssl3con.c |
| =================================================================== |
| --- net/third_party/nss/ssl/ssl3con.c (revision 89500) |
| +++ net/third_party/nss/ssl/ssl3con.c (working copy) |
| @@ -8018,78 +8018,127 @@ |
| goto loser; /* don't send alerts on memory errors */ |
| } |
| - /* First get the peer cert. */ |
| - remaining -= 3; |
| - if (remaining < 0) |
| - goto decode_loser; |
| + if (length == 12 && ssl3_ExtensionNegotiated(ss, ssl_cached_info_xtn)) { |
| + /* We are dealing with a certificate_chain digest */ |
| + ssl3CertNode *certNodeCurrent; |
| - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
| - if (size <= 0) |
| - goto loser; /* fatal alert already sent by ConsumeHandshake. */ |
| + /* Make sure the digests match. */ |
| + if (memcmp(b+4, ss->ssl3.certChainDigest, 8)) { |
|
wtc
2011/06/20 22:21:51
Nit: add spaces around the '+' sign.
rkn
2011/06/20 23:52:51
Done.
|
| + desc = handshake_failure; |
| + goto alert_loser; |
| + } |
| - if (remaining < size) |
| - goto decode_loser; |
| + ss->ssl3.digestReceived = PR_TRUE; |
|
wtc
2011/06/20 22:21:51
Nit: perhaps we should do this before the memcmp c
rkn
2011/06/20 23:52:51
Done.
|
| - certItem.data = b; |
| - certItem.len = size; |
| - b += size; |
| - length -= size; |
| - remaining -= size; |
| - |
| - ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, |
| - PR_FALSE, PR_TRUE); |
| - if (ss->sec.peerCert == NULL) { |
| - /* We should report an alert if the cert was bad, but not if the |
| - * problem was just some local problem, like memory error. |
| - */ |
| - goto ambiguous_err; |
| - } |
| - |
| - /* Now get all of the CA certs. */ |
| - while (remaining > 0) { |
| - remaining -= 3; |
| - if (remaining < 0) |
| + /* First get the peer cert. */ |
| + if (ss->ssl3.predictedCertChain[0] == NULL) { |
| + desc = handshake_failure; |
| + goto alert_loser; |
| + } |
| + ss->sec.peerCert = CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); |
| + |
| + /* Now get all of the CA certs. */ |
| + if (ss->ssl3.predictedCertChain[1] == NULL) { |
| + ss->ssl3.peerCertChain = NULL; |
| + } else { |
| + int i = 1; |
| + ss->ssl3.peerCertChain = certNodeCurrent |
| + = PORT_ArenaNew(arena, ssl3CertNode); |
| + if (certNodeCurrent == NULL) { |
| + goto loser; /* don't send alerts on memory errors */ |
| + } |
| + while (ss->ssl3.predictedCertChain[i] != NULL) { |
| + certNodeCurrent->cert = |
| + CERT_DupCertificate(ss->ssl3.predictedCertChain[i]); |
| + i++; |
| + if (ss->ssl3.predictedCertChain[i] == NULL) { |
| + certNodeCurrent->next = NULL; |
| + } else { |
| + certNodeCurrent->next = PORT_ArenaNew(arena, ssl3CertNode); |
| + if (certNodeCurrent->next == NULL) { |
| + goto loser; /* don't send alerts on memory errors */ |
| + } |
| + certNodeCurrent = certNodeCurrent->next; |
| + } |
| + } |
| + } |
|
wtc
2011/06/20 22:21:51
I believe we can rewrite lines 8041-8064 as follow
rkn
2011/06/20 23:52:51
Done. I made this change, but I added the line
|
| + } else { |
| + /* We are dealing with a regular certificate message */ |
| + ss->ssl3.digestReceived = PR_FALSE; |
| + |
| + /* First get the peer cert. */ |
| + remaining -= 3; |
| + if (remaining < 0) |
| goto decode_loser; |
| - |
| - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
| - if (size <= 0) |
| + |
| + size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
| + if (size <= 0) |
| goto loser; /* fatal alert already sent by ConsumeHandshake. */ |
| - |
| - if (remaining < size) |
| + |
| + if (remaining < size) |
| goto decode_loser; |
| - |
| - certItem.data = b; |
| - certItem.len = size; |
| - b += size; |
| - length -= size; |
| - remaining -= size; |
| - |
| - c = PORT_ArenaNew(arena, ssl3CertNode); |
| - if (c == NULL) { |
| - goto loser; /* don't send alerts on memory errors */ |
| - } |
| - |
| - c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, |
| - PR_FALSE, PR_TRUE); |
| - if (c->cert == NULL) { |
| + |
| + certItem.data = b; |
| + certItem.len = size; |
| + b += size; |
| + length -= size; |
| + remaining -= size; |
| + |
| + ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, |
| + NULL, PR_FALSE, PR_TRUE); |
| + if (ss->sec.peerCert == NULL) { |
| + /* We should report an alert if the cert was bad, but not if the |
| + * problem was just some local problem, like memory error. |
| + */ |
| goto ambiguous_err; |
| - } |
| - |
| - if (c->cert->trust) |
| - trusted = PR_TRUE; |
| - |
| - c->next = NULL; |
| - if (lastCert) { |
| - lastCert->next = c; |
| - } else { |
| - certs = c; |
| - } |
| - lastCert = c; |
| + } |
| + |
| + /* Now get all of the CA certs. */ |
| + while (remaining > 0) { |
| + remaining -= 3; |
| + if (remaining < 0) |
| + goto decode_loser; |
| + |
| + size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
| + if (size <= 0) |
| + goto loser; /* fatal alert already sent by ConsumeHandshake. */ |
| + |
| + if (remaining < size) |
| + goto decode_loser; |
| + |
| + certItem.data = b; |
| + certItem.len = size; |
| + b += size; |
| + length -= size; |
| + remaining -= size; |
| + |
| + c = PORT_ArenaNew(arena, ssl3CertNode); |
| + if (c == NULL) { |
| + goto loser; /* don't send alerts on memory errors */ |
| + } |
| + |
| + c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, |
| + PR_FALSE, PR_TRUE); |
| + if (c->cert == NULL) { |
| + goto ambiguous_err; |
| + } |
| + |
| + if (c->cert->trust) |
| + trusted = PR_TRUE; |
|
wtc
2011/06/20 22:21:51
We probably should duplicate these two lines (line
rkn
2011/06/20 23:52:51
I am holding off on making this change, because I
|
| + |
| + c->next = NULL; |
| + if (lastCert) { |
| + lastCert->next = c; |
| + } else { |
| + certs = c; |
| + } |
| + lastCert = c; |
| + } |
| + |
| + if (remaining != 0) |
| + goto decode_loser; |
| } |
| - if (remaining != 0) |
| - goto decode_loser; |
| - |
| SECKEY_UpdateCertPQG(ss->sec.peerCert); |
| /* |
| @@ -8250,7 +8299,10 @@ |
| (void)SSL3_SendAlert(ss, alert_fatal, desc); |
| loser: |
| - ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; |
| + if (ss->ssl3.peerCertChain == NULL) { |
| + ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; |
| + } |
| + PORT_Assert(certs == NULL); |
| ssl3_CleanupPeerCerts(ss); |
| if (ss->sec.peerCert != NULL) { |
| @@ -9736,6 +9788,21 @@ |
| return rv; |
| } |
| +static void |
| +ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { |
| + unsigned int i; |
| + |
| + if (!ss->ssl3.predictedCertChain) |
| + return; |
| + |
| + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { |
| + CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); |
| + } |
| + |
| + PORT_Free(ss->ssl3.predictedCertChain); |
| + ss->ssl3.predictedCertChain = NULL; |
| +} |
| + |
| /* Called from ssl_DestroySocketContents() in sslsock.c */ |
| void |
| ssl3_DestroySSL3Info(sslSocket *ss) |
| @@ -9759,6 +9826,9 @@ |
| ss->ssl3.clientCertChain = NULL; |
| } |
| + if (ss->ssl3.predictedCertChain != NULL) |
| + ssl3_CleanupPredictedPeerCertificates(ss); |
| + |
| /* clean up handshake */ |
| if (ss->opt.bypassPKCS11) { |
| SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); |