Bug 682927 - Dis-trust DigiNotar root certificate, part 3; r=kaie,dveditz

This commit is contained in:
Brian Smith 2011-08-30 10:33:04 -04:00
Родитель 2552ad09db
Коммит 2789fe6ab4
4 изменённых файлов: 84 добавлений и 5 удалений

Просмотреть файл

@ -1038,6 +1038,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;
@ -1083,7 +1130,7 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
}
}
}
SECStatus rv = PSM_SSL_PKIX_AuthCertificate(fd, serverCert, checksig, isServer);
// We want to remember the CA certs in the temp db, so that the application can find the
@ -1099,14 +1146,28 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
nsc = nsNSSCertificate::Create(serverCert);
}
if (SECSuccess == rv) {
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 (rv == SECSuccess) {
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);
@ -1142,6 +1203,9 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
PR_FREEIF(nickname);
}
}
if (certList) {
CERT_DestroyCertList(certList);
}

Просмотреть файл

@ -55,6 +55,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();

Просмотреть файл

@ -226,7 +226,8 @@ nsNSSSocketInfo::nsNSSSocketInfo()
mAllowTLSIntoleranceTimeout(PR_TRUE),
mRememberClientAuthCertificate(PR_FALSE),
mHandshakeStartTime(0),
mPort(0)
mPort(0),
mIsCertIssuerBlacklisted(PR_FALSE)
{
mThreadData = new nsSSLSocketThreadData;
}
@ -3440,6 +3441,10 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
cvout, (void*)infoObject);
}
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.

Просмотреть файл

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