| Index: net/third_party/nss/ssl/ssl3con.c
|
| ===================================================================
|
| --- net/third_party/nss/ssl/ssl3con.c (revision 89911)
|
| +++ net/third_party/nss/ssl/ssl3con.c (working copy)
|
| @@ -7958,7 +7958,6 @@
|
| PRInt32 size;
|
| SECStatus rv;
|
| PRBool isServer = (PRBool)(!!ss->sec.isServer);
|
| - PRBool trusted = PR_FALSE;
|
| PRBool isTLS;
|
| SSL3AlertDescription desc = bad_certificate;
|
| int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
|
| @@ -8018,78 +8017,115 @@
|
| 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 */
|
| + int i;
|
|
|
| - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
|
| - if (size <= 0)
|
| - goto loser; /* fatal alert already sent by ConsumeHandshake. */
|
| + ss->ssl3.digestReceived = PR_TRUE;
|
|
|
| - if (remaining < size)
|
| - goto decode_loser;
|
| + /* Make sure the digests match. */
|
| + if (memcmp(b + 4, ss->ssl3.certChainDigest, 8)) {
|
| + desc = handshake_failure;
|
| + goto alert_loser;
|
| + }
|
|
|
| - 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. */
|
| + ss->ssl3.peerCertChain = NULL;
|
| + for (i = 1; ss->ssl3.predictedCertChain[i] != NULL; i++) {
|
| + c = PORT_ArenaNew(arena, ssl3CertNode);
|
| + if (c == NULL) {
|
| + goto loser; /* don't send alerts on memory errors */
|
| + }
|
| + c->cert = CERT_DupCertificate(ss->ssl3.predictedCertChain[i]);
|
| + c->next = NULL;
|
| + if (lastCert) {
|
| + lastCert->next = c;
|
| + } else {
|
| + ss->ssl3.peerCertChain = c;
|
| + }
|
| + lastCert = c;
|
| + }
|
| + } 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;
|
| + }
|
| +
|
| + 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 +8286,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 +9775,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 +9813,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);
|
|
|