Bug 445871 - SSL certificates added as exceptions should never be treated as EV, r=kaie

This commit is contained in:
Honza Bambas 2009-05-13 11:50:46 +02:00
parent 319919e714
commit e75c38706a
3 changed files with 135 additions and 3 deletions

View File

@ -691,6 +691,99 @@ void nsHTTPListener::send_done_signal()
}
}
// nsPSMRememberCertErrorsTable
nsPSMRememberCertErrorsTable sHostsWithCertErrors;
nsPSMRememberCertErrorsTable::nsPSMRememberCertErrorsTable()
{
mErrorHosts.Init(16);
}
nsresult
nsPSMRememberCertErrorsTable::GetHostPortKey(nsNSSSocketInfo* infoObject,
nsCAutoString &result)
{
nsresult rv;
result.Truncate();
char* hostName = nsnull;
rv = infoObject->GetHostName(&hostName);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 port;
rv = infoObject->GetPort(&port);
NS_ENSURE_SUCCESS(rv, rv);
result.Assign(hostName);
result.Append(':');
result.AppendInt(port);
nsCRT::free(hostName);
return NS_OK;
}
void
nsPSMRememberCertErrorsTable::RememberCertHasError(nsNSSSocketInfo* infoObject,
nsSSLStatus* status,
SECStatus certVerificationResult)
{
nsresult rv;
nsCAutoString hostPortKey;
rv = GetHostPortKey(infoObject, hostPortKey);
if (NS_FAILED(rv))
return;
if (certVerificationResult != SECSuccess) {
NS_ASSERTION(status,
"Must have nsSSLStatus object when remembering flags");
if (!status)
return;
CertStateBits bits;
bits.mIsDomainMismatch = status->mIsDomainMismatch;
bits.mIsNotValidAtThisTime = status->mIsNotValidAtThisTime;
bits.mIsUntrusted = status->mIsUntrusted;
mErrorHosts.Put(hostPortKey, bits);
}
else {
mErrorHosts.Remove(hostPortKey);
}
}
void
nsPSMRememberCertErrorsTable::LookupCertErrorBits(nsNSSSocketInfo* infoObject,
nsSSLStatus* status)
{
// Get remembered error bits from our cache, because of SSL session caching
// the NSS library potentially hasn't notified us for this socket.
if (status->mHaveCertErrorBits)
// Rather do not modify bits if already set earlier
return;
nsresult rv;
nsCAutoString hostPortKey;
rv = GetHostPortKey(infoObject, hostPortKey);
if (NS_FAILED(rv))
return;
CertStateBits bits;
if (!mErrorHosts.Get(hostPortKey, &bits))
// No record was found, this host had no cert errors
return;
// This host had cert errors, update the bits correctly
status->mHaveCertErrorBits = PR_TRUE;
status->mIsDomainMismatch = bits.mIsDomainMismatch;
status->mIsNotValidAtThisTime = bits.mIsNotValidAtThisTime;
status->mIsUntrusted = bits.mIsUntrusted;
}
static char*
ShowProtectedAuthPrompt(PK11SlotInfo* slot, nsIInterfaceRequestor *ir)
{
@ -903,6 +996,8 @@ void PR_CALLBACK HandshakeCallback(PRFileDesc* fd, void* client_data) {
infoObject->SetSSLStatus(status);
}
sHostsWithCertErrors.LookupCertErrorBits(infoObject, status);
CERTCertificate *serverCert = SSL_PeerCertificate(fd);
if (serverCert) {
nsRefPtr<nsNSSCertificate> nssc = new nsNSSCertificate(serverCert);
@ -1028,6 +1123,17 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
status = new nsSSLStatus();
infoObject->SetSSLStatus(status);
}
if (rv == SECSuccess) {
// Certificate verification succeeded delete any potential record
// of certificate error bits.
sHostsWithCertErrors.RememberCertHasError(infoObject, nsnull, rv);
}
else {
// Certificate verification failed, update the status' bits.
sHostsWithCertErrors.LookupCertErrorBits(infoObject, status);
}
if (status && !status->mServerCert) {
status->mServerCert = nsc;
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,

View File

@ -44,6 +44,7 @@
#include "pk11func.h"
#include "nspr.h"
#include "ocspt.h"
#include "nsDataHashtable.h"
#include "nsIStreamLoader.h"
char* PR_CALLBACK
@ -252,7 +253,30 @@ public:
void unregisterHttpClient();
};
class nsSSLStatus;
class nsNSSSocketInfo;
class nsPSMRememberCertErrorsTable
{
private:
struct CertStateBits
{
PRBool mIsDomainMismatch;
PRBool mIsNotValidAtThisTime;
PRBool mIsUntrusted;
};
nsDataHashtableMT<nsCStringHashKey, CertStateBits> mErrorHosts;
nsresult GetHostPortKey(nsNSSSocketInfo* infoObject, nsCAutoString& result);
public:
nsPSMRememberCertErrorsTable();
void RememberCertHasError(nsNSSSocketInfo* infoObject,
nsSSLStatus* status,
SECStatus certVerificationResult);
void LookupCertErrorBits(nsNSSSocketInfo* infoObject,
nsSSLStatus* status);
};
extern nsPSMRememberCertErrorsTable sHostsWithCertErrors;
#endif // _NSNSSCALLBACKS_H_

View File

@ -3021,6 +3021,8 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
status->mIsDomainMismatch = collected_errors & nsICertOverrideService::ERROR_MISMATCH;
status->mIsNotValidAtThisTime = collected_errors & nsICertOverrideService::ERROR_TIME;
status->mIsUntrusted = collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
sHostsWithCertErrors.RememberCertHasError(infoObject, status, SECFailure);
}
remaining_display_errors = collected_errors;