Bug 682927 - Dis-trust DigiNotar root certificate, part 3; patch by Brian Smith <bsmith@mozilla.com>, 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
This commit is contained in:
alqahira%ardisson.org
2011-08-31 03:15:13 +00:00
parent 8f48182ca1
commit be365a3b73
4 changed files with 82 additions and 3 deletions

View File

@@ -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, &notBefore, &notAfter) != 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<nsINSSComponent> 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);
}

View File

@@ -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();

View File

@@ -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.

View File

@@ -197,6 +197,12 @@ public:
PRStatus CloseSocketAndDestroy();
PRBool IsCertIssuerBlacklisted() const {
return mIsCertIssuerBlacklisted;
}
void SetCertIssuerBlacklisted() {
mIsCertIssuerBlacklisted = PR_TRUE;
}
protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRFileDesc* mFd;
@@ -223,6 +229,7 @@ protected:
PRIntervalTime mHandshakeStartTime;
PRInt32 mPort;
nsXPIDLCString mHostName;
PRErrorCode mIsCertIssuerBlacklisted;
/* SSL Status */
nsRefPtr<nsSSLStatus> mSSLStatus;