Created
January 26, 2010 16:22
-
-
Save agl/286966 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c | |
index 8d4b05d..414707e 100644 | |
--- a/mozilla/security/nss/lib/ssl/ssl3con.c | |
+++ b/mozilla/security/nss/lib/ssl/ssl3con.c | |
@@ -5607,7 +5607,36 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, | |
return rv; | |
} | |
+static SSL3AlertDescription | |
+ssl3_CertErrorToAlert(PRBool isTLS, int errCode) | |
+{ | |
+ switch (errCode) { | |
+ case SEC_ERROR_LIBRARY_FAILURE: return unsupported_certificate; | |
+ case SEC_ERROR_EXPIRED_CERTIFICATE: return certificate_expired; | |
+ case SEC_ERROR_REVOKED_CERTIFICATE: return certificate_revoked; | |
+ case SEC_ERROR_INADEQUATE_KEY_USAGE: | |
+ case SEC_ERROR_INADEQUATE_CERT_TYPE: | |
+ return certificate_unknown; | |
+ case SEC_ERROR_UNTRUSTED_CERT: | |
+ return isTLS ? access_denied : certificate_unknown; | |
+ case SEC_ERROR_UNKNOWN_ISSUER: | |
+ case SEC_ERROR_UNTRUSTED_ISSUER: | |
+ return isTLS ? unknown_ca : certificate_unknown; | |
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: | |
+ return isTLS ? unknown_ca : certificate_expired; | |
+ case PR_OUT_OF_MEMORY_ERROR: | |
+ case SEC_ERROR_BAD_DATABASE: | |
+ case SEC_ERROR_NO_MEMORY: | |
+ return internal_error; | |
+ | |
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: | |
+ case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: | |
+ case SEC_ERROR_CA_CERT_INVALID: | |
+ case SEC_ERROR_BAD_SIGNATURE: | |
+ default: return bad_certificate; | |
+ } | |
+} | |
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete | |
* ssl3 Server Hello Done message. | |
@@ -5619,6 +5648,13 @@ ssl3_HandleServerHelloDone(sslSocket *ss) | |
SECStatus rv; | |
SSL3WaitState ws = ss->ssl3.hs.ws; | |
PRBool send_verify = PR_FALSE; | |
+ PRBool isServer = (PRBool)(!!ss->sec.isServer); | |
+ PRBool retWouldBlock = PR_FALSE; | |
+ SSL3AlertDescription desc = bad_certificate; | |
+ PRBool isTLS; | |
+ int errCode; | |
+ | |
+ isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); | |
SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake", | |
SSL_GETPID(), ss->fd)); | |
@@ -5634,6 +5670,29 @@ ssl3_HandleServerHelloDone(sslSocket *ss) | |
return SECFailure; | |
} | |
+ /* | |
+ * Ask caller-supplied callback function to validate cert chain. | |
+ */ | |
+ rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd, | |
+ PR_TRUE, isServer); | |
+ if (rv) { | |
+ if (!ss->handleBadCert) { | |
+ goto bad_cert; | |
+ } | |
+ rv = (SECStatus)(*ss->handleBadCert)(ss->badCertArg, ss->fd); | |
+ if ( rv ) { | |
+ if ( rv != SECWouldBlock ) | |
+ goto bad_cert; | |
+ | |
+ /* someone will handle this connection asynchronously*/ | |
+ SSL_DBG(("%d: SSL3[%d]: go to async cert handler", | |
+ SSL_GETPID(), ss->fd)); | |
+ ssl_SetAlwaysBlock(ss); | |
+ retWouldBlock = PR_TRUE; | |
+ } | |
+ /* cert is good */ | |
+ } | |
+ | |
ssl_GetXmitBufLock(ss); /*******************************/ | |
if (ss->ssl3.sendEmptyCert) { | |
@@ -5679,8 +5738,26 @@ ssl3_HandleServerHelloDone(sslSocket *ss) | |
ss->ssl3.hs.ws = wait_new_session_ticket; | |
else | |
ss->ssl3.hs.ws = wait_change_cipher; | |
+ | |
+ if (retWouldBlock) | |
+ return SECWouldBlock; | |
return SECSuccess; | |
+bad_cert: | |
+ errCode = PORT_GetError(); | |
+ desc = ssl3_CertErrorToAlert(isTLS, errCode); | |
+ SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d", | |
+ SSL_GETPID(), ss->fd, errCode)); | |
+ ssl3_CleanupPeerCerts(ss); | |
+ (void)ssl_MapLowLevelError(errCode); | |
+ | |
+ /* internal_error is not a valid SSL3 alert */ | |
+ if (desc != internal_error || isTLS) | |
+ (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
+ | |
+ /* We don't have the XmitBufLock when jumping to bad_cert */ | |
+ return rv; | |
+ | |
loser: | |
ssl_ReleaseXmitBufLock(ss); | |
return rv; | |
@@ -7637,7 +7714,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
CERTCertificate *cert; | |
PRInt32 remaining = 0; | |
PRInt32 size; | |
- SECStatus rv; | |
+ SECStatus rv = SECSuccess; | |
PRBool isServer = (PRBool)(!!ss->sec.isServer); | |
PRBool trusted = PR_FALSE; | |
PRBool isTLS; | |
@@ -7768,33 +7845,6 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
SECKEY_UpdateCertPQG(ss->sec.peerCert); | |
- /* | |
- * Ask caller-supplied callback function to validate cert chain. | |
- */ | |
- rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd, | |
- PR_TRUE, isServer); | |
- if (rv) { | |
- errCode = PORT_GetError(); | |
- if (!ss->handleBadCert) { | |
- goto bad_cert; | |
- } | |
- rv = (SECStatus)(*ss->handleBadCert)(ss->badCertArg, ss->fd); | |
- if ( rv ) { | |
- if ( rv == SECWouldBlock ) { | |
- /* someone will handle this connection asynchronously*/ | |
- SSL_DBG(("%d: SSL3[%d]: go to async cert handler", | |
- SSL_GETPID(), ss->fd)); | |
- ss->ssl3.peerCertChain = certs; | |
- certs = NULL; | |
- ssl_SetAlwaysBlock(ss); | |
- goto cert_block; | |
- } | |
- /* cert is bad */ | |
- goto bad_cert; | |
- } | |
- /* cert is good */ | |
- } | |
- | |
/* start SSL Step Up, if appropriate */ | |
cert = ss->sec.peerCert; | |
if (!isServer && | |
@@ -7872,47 +7922,11 @@ cert_block: | |
} | |
} | |
- /* rv must normally be equal to SECSuccess here. If we called | |
- * handleBadCert, it can also be SECWouldBlock. | |
- */ | |
return rv; | |
ambiguous_err: | |
errCode = PORT_GetError(); | |
- switch (errCode) { | |
- case PR_OUT_OF_MEMORY_ERROR: | |
- case SEC_ERROR_BAD_DATABASE: | |
- case SEC_ERROR_NO_MEMORY: | |
- if (isTLS) { | |
- desc = internal_error; | |
- goto alert_loser; | |
- } | |
- goto loser; | |
- } | |
- /* fall through to bad_cert. */ | |
- | |
-bad_cert: /* caller has set errCode. */ | |
- switch (errCode) { | |
- case SEC_ERROR_LIBRARY_FAILURE: desc = unsupported_certificate; break; | |
- case SEC_ERROR_EXPIRED_CERTIFICATE: desc = certificate_expired; break; | |
- case SEC_ERROR_REVOKED_CERTIFICATE: desc = certificate_revoked; break; | |
- case SEC_ERROR_INADEQUATE_KEY_USAGE: | |
- case SEC_ERROR_INADEQUATE_CERT_TYPE: | |
- desc = certificate_unknown; break; | |
- case SEC_ERROR_UNTRUSTED_CERT: | |
- desc = isTLS ? access_denied : certificate_unknown; break; | |
- case SEC_ERROR_UNKNOWN_ISSUER: | |
- case SEC_ERROR_UNTRUSTED_ISSUER: | |
- desc = isTLS ? unknown_ca : certificate_unknown; break; | |
- case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: | |
- desc = isTLS ? unknown_ca : certificate_expired; break; | |
- | |
- case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: | |
- case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: | |
- case SEC_ERROR_CA_CERT_INVALID: | |
- case SEC_ERROR_BAD_SIGNATURE: | |
- default: desc = bad_certificate; break; | |
- } | |
+ desc = ssl3_CertErrorToAlert(isTLS, errCode); | |
SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d", | |
SSL_GETPID(), ss->fd, errCode)); | |
@@ -7922,7 +7936,9 @@ decode_loser: | |
desc = isTLS ? decode_error : bad_certificate; | |
alert_loser: | |
- (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
+ /* internal_error is not a valid SSL3 alert */ | |
+ if (desc != internal_error || isTLS) | |
+ (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
loser: | |
ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment