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

This commit is contained in:
Honza Bambas 2009-05-20 10:23:41 +02:00
Родитель 2b0d93ff16
Коммит 6e24518b15
3 изменённых файлов: 146 добавлений и 0 удалений

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

@ -25,6 +25,7 @@
* Terry Hayes <thayes@netscape.com>
* Kai Engert <kengert@redhat.com>
* Petr Kostka <petr.kostka@st.com>
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -903,6 +904,9 @@ void PR_CALLBACK HandshakeCallback(PRFileDesc* fd, void* client_data) {
infoObject->SetSSLStatus(status);
}
nsSSLIOLayerHelpers::mHostsWithCertErrors->LookupCertErrorBits(
infoObject, status);
CERTCertificate *serverCert = SSL_PeerCertificate(fd);
if (serverCert) {
nsRefPtr<nsNSSCertificate> nssc = new nsNSSCertificate(serverCert);
@ -1028,6 +1032,19 @@ 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.
nsSSLIOLayerHelpers::mHostsWithCertErrors->RememberCertHasError(
infoObject, nsnull, rv);
}
else {
// Certificate verification failed, update the status' bits.
nsSSLIOLayerHelpers::mHostsWithCertErrors->LookupCertErrorBits(
infoObject, status);
}
if (status && !status->mServerCert) {
status->mServerCert = nsc;
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,

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

@ -782,6 +782,11 @@ void nsSSLIOLayerHelpers::Cleanup()
PR_DestroyLock(mutex);
mutex = nsnull;
}
if (mHostsWithCertErrors) {
delete mHostsWithCertErrors;
mHostsWithCertErrors = nsnull;
}
}
static nsresult
@ -1474,6 +1479,95 @@ nsSSLIOLayerConnect(PRFileDesc* fd, const PRNetAddr* addr,
return status;
}
// nsPSMRememberCertErrorsTable
nsPSMRememberCertErrorsTable::nsPSMRememberCertErrorsTable()
{
mErrorHosts.Init(16);
}
nsresult
nsPSMRememberCertErrorsTable::GetHostPortKey(nsNSSSocketInfo* infoObject,
nsCAutoString &result)
{
nsresult rv;
result.Truncate();
nsXPIDLCString hostName;
rv = infoObject->GetHostName(getter_Copies(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);
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;
}
// Call this function to report a site that is possibly TLS intolerant.
// This function will return true, if the given socket is currently using TLS.
PRBool
@ -1779,6 +1873,7 @@ PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity;
PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods;
PRLock *nsSSLIOLayerHelpers::mutex = nsnull;
nsCStringHashSet *nsSSLIOLayerHelpers::mTLSIntolerantSites = nsnull;
nsPSMRememberCertErrorsTable *nsSSLIOLayerHelpers::mHostsWithCertErrors = nsnull;
PRFileDesc *nsSSLIOLayerHelpers::mSharedPollableEvent = nsnull;
nsNSSSocketInfo *nsSSLIOLayerHelpers::mSocketOwningPollableEvent = nsnull;
PRBool nsSSLIOLayerHelpers::mPollableEventCurrentlySet = PR_FALSE;
@ -1988,6 +2083,10 @@ nsresult nsSSLIOLayerHelpers::Init()
mTLSIntolerantSites->Init(1);
mHostsWithCertErrors = new nsPSMRememberCertErrorsTable();
if (!mHostsWithCertErrors || !mHostsWithCertErrors->mErrorHosts.IsInitialized())
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -3021,6 +3120,9 @@ 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;
nsSSLIOLayerHelpers::mHostsWithCertErrors->RememberCertHasError(
infoObject, status, SECFailure);
}
remaining_display_errors = collected_errors;

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

@ -57,6 +57,7 @@
#include "nsNSSShutDown.h"
#include "nsAutoPtr.h"
#include "nsNSSCertificate.h"
#include "nsDataHashtable.h"
class nsIChannel;
class nsSSLThread;
@ -242,6 +243,31 @@ friend class nsSSLThread;
class nsCStringHashSet;
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:
friend class nsSSLIOLayerHelpers;
nsPSMRememberCertErrorsTable();
void RememberCertHasError(nsNSSSocketInfo* infoObject,
nsSSLStatus* status,
SECStatus certVerificationResult);
void LookupCertErrorBits(nsNSSSocketInfo* infoObject,
nsSSLStatus* status);
};
class nsSSLIOLayerHelpers
{
public:
@ -254,6 +280,7 @@ public:
static PRLock *mutex;
static nsCStringHashSet *mTLSIntolerantSites;
static nsPSMRememberCertErrorsTable* mHostsWithCertErrors;
static PRBool rememberPossibleTLSProblemSite(PRFileDesc* fd, nsNSSSocketInfo *socketInfo);