From be365a3b73d8bea6ca480cabd320039f40cbe5d2 Mon Sep 17 00:00:00 2001 From: "alqahira%ardisson.org" Date: Wed, 31 Aug 2011 03:15:13 +0000 Subject: [PATCH] Bug 682927 - Dis-trust DigiNotar root certificate, part 3; patch by Brian Smith , r=kaie, r=dveditz, a/Cm2.0.8=me git-svn-id: svn://10.0.0.236/branches/CAMINO_2_0_8_MINIBRANCH@262770 18797224-902f-48f8-a5cc-f745e15eee43 --- .../manager/ssl/src/nsNSSCallbacks.cpp | 68 ++++++++++++++++++- .../security/manager/ssl/src/nsNSSCallbacks.h | 3 + .../security/manager/ssl/src/nsNSSIOLayer.cpp | 7 +- .../security/manager/ssl/src/nsNSSIOLayer.h | 7 ++ 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp b/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp index 500d5dba6b6..f2bd1a798ac 100644 --- a/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -973,6 +973,53 @@ static struct nsSerialBinaryBlacklistEntry myUTNBlacklistEntries[] = { { 0, 0 } // end marker }; +// Bug 682927: Do not trust any DigiNotar-issued certificates. +// We do this check after normal certificate validation because we do not +// want to override a "revoked" OCSP response. +PRErrorCode +PSM_SSL_BlacklistDigiNotar(CERTCertificate * serverCert, + CERTCertList * serverCertChain) +{ + PRBool isDigiNotarIssuedCert = PR_FALSE; + + for (CERTCertListNode *node = CERT_LIST_HEAD(serverCertChain); + !CERT_LIST_END(node, serverCertChain); + node = CERT_LIST_NEXT(node)) { + if (!node->cert->issuerName) + continue; + + if (strstr(node->cert->issuerName, "CN=DigiNotar")) { + isDigiNotarIssuedCert = PR_TRUE; + // Do not let the user override the error if the cert was + // chained from the "DigiNotar Root CA" cert and the cert was issued + // within the time window in which we think the mis-issuance(s) occurred. + if (strstr(node->cert->issuerName, "CN=DigiNotar Root CA")) { + PRTime cutoff = 0, notBefore = 0, notAfter = 0; + PRStatus status = PR_ParseTimeString("01-JUL-2011 00:00", PR_TRUE, &cutoff); + NS_ASSERTION(status == PR_SUCCESS, "PR_ParseTimeString failed"); + if (status != PR_SUCCESS || + CERT_GetCertTimes(serverCert, ¬Before, ¬After) != SECSuccess || + notBefore >= cutoff) { + return SEC_ERROR_REVOKED_CERTIFICATE; + } + } + } + + // By request of the Dutch government + if (!strcmp(node->cert->issuerName, + "CN=Staat der Nederlanden Root CA,O=Staat der Nederlanden,C=NL") && + CERT_LIST_END(CERT_LIST_NEXT(node), serverCertChain)) { + return 0; + } + } + + if (isDigiNotarIssuedCert) + return SEC_ERROR_UNTRUSTED_ISSUER; // user can override this + else + return 0; // No DigiNotor cert => carry on as normal +} + + SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, PRBool checksig, PRBool isServer) { nsNSSShutDownPreventionLock locker; @@ -1035,14 +1082,28 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, nsc = new nsNSSCertificate(serverCert); } + CERTCertList *certList = nsnull; + if (rv == SECSuccess) { + certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA); + if (!certList) { + rv = SECFailure; + } else { + PRErrorCode blacklistErrorCode = PSM_SSL_BlacklistDigiNotar(serverCert, + certList); + if (blacklistErrorCode != 0) { + infoObject->SetCertIssuerBlacklisted(); + PORT_SetError(blacklistErrorCode); + rv = SECFailure; + } + } + } + if (SECSuccess == rv) { if (nsc) { PRBool dummyIsEV; nsc->GetIsExtendedValidation(&dummyIsEV); // the nsc object will cache the status } - CERTCertList *certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA); - nsCOMPtr nssComponent; for (CERTCertListNode *node = CERT_LIST_HEAD(certList); @@ -1078,6 +1139,9 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, } } + } + + if (certList) { CERT_DestroyCertList(certList); } diff --git a/mozilla/security/manager/ssl/src/nsNSSCallbacks.h b/mozilla/security/manager/ssl/src/nsNSSCallbacks.h index 5ac7d6a4b89..bd5b25c0627 100644 --- a/mozilla/security/manager/ssl/src/nsNSSCallbacks.h +++ b/mozilla/security/manager/ssl/src/nsNSSCallbacks.h @@ -53,6 +53,9 @@ void PR_CALLBACK HandshakeCallback(PRFileDesc *fd, void *client_data); SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, PRBool checksig, PRBool isServer); +PRErrorCode PSM_SSL_BlacklistDigiNotar(CERTCertificate * serverCert, + CERTCertList * serverCertChain); + SECStatus RegisterMyOCSPAIAInfoCallback(); SECStatus UnregisterMyOCSPAIAInfoCallback(); diff --git a/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp b/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp index e01d96ba28d..b9e537e2814 100644 --- a/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -217,7 +217,8 @@ nsNSSSocketInfo::nsNSSSocketInfo() mHandshakeInProgress(PR_FALSE), mAllowTLSIntoleranceTimeout(PR_TRUE), mHandshakeStartTime(0), - mPort(0) + mPort(0), + mIsCertIssuerBlacklisted(PR_FALSE) { mThreadData = new nsSSLSocketThreadData; } @@ -2911,6 +2912,10 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) PR_Now(), (void*)infoObject, verify_log, NULL); + if (infoObject->IsCertIssuerBlacklisted()) { + collected_errors |= nsICertOverrideService::ERROR_UNTRUSTED; + } + // We ignore the result code of the cert verification. // Either it is a failure, which is expected, and we'll process the // verify log below. diff --git a/mozilla/security/manager/ssl/src/nsNSSIOLayer.h b/mozilla/security/manager/ssl/src/nsNSSIOLayer.h index 84ab83a4505..dfde6116ac3 100644 --- a/mozilla/security/manager/ssl/src/nsNSSIOLayer.h +++ b/mozilla/security/manager/ssl/src/nsNSSIOLayer.h @@ -197,6 +197,12 @@ public: PRStatus CloseSocketAndDestroy(); + PRBool IsCertIssuerBlacklisted() const { + return mIsCertIssuerBlacklisted; + } + void SetCertIssuerBlacklisted() { + mIsCertIssuerBlacklisted = PR_TRUE; + } protected: nsCOMPtr mCallbacks; PRFileDesc* mFd; @@ -223,6 +229,7 @@ protected: PRIntervalTime mHandshakeStartTime; PRInt32 mPort; nsXPIDLCString mHostName; + PRErrorCode mIsCertIssuerBlacklisted; /* SSL Status */ nsRefPtr mSSLStatus;