From b36633903e5903d5ca1a071cfb371b22c0eb27e8 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 6 Dec 2012 22:05:27 -0500 Subject: [PATCH] Bug 769288 - Part 1: Make PSM more amenable to storing concurrent private and non-private data. r=bsmith --- .../pki/resources/content/exceptionDialog.js | 7 +- .../ssl/public/nsIRecentBadCertsService.idl | 10 +- security/manager/ssl/public/nsIX509CertDB.idl | 13 +- security/manager/ssl/src/Makefile.in | 1 + .../ssl/src/SSLServerCertVerification.cpp | 57 ++++--- security/manager/ssl/src/SharedSSLState.cpp | 111 ++++++++++++++ security/manager/ssl/src/SharedSSLState.h | 54 +++++++ .../manager/ssl/src/nsClientAuthRemember.cpp | 12 ++ .../manager/ssl/src/nsClientAuthRemember.h | 1 + security/manager/ssl/src/nsNSSCallbacks.cpp | 8 +- .../manager/ssl/src/nsNSSCertificateDB.cpp | 21 +++ security/manager/ssl/src/nsNSSCertificateDB.h | 5 + security/manager/ssl/src/nsNSSComponent.cpp | 53 +------ security/manager/ssl/src/nsNSSComponent.h | 4 - security/manager/ssl/src/nsNSSIOLayer.cpp | 144 ++++++++++++++---- security/manager/ssl/src/nsNSSIOLayer.h | 58 ++++--- security/manager/ssl/src/nsNSSModule.cpp | 5 - security/manager/ssl/src/nsRecentBadCerts.cpp | 45 ++++-- security/manager/ssl/src/nsRecentBadCerts.h | 13 +- 19 files changed, 471 insertions(+), 151 deletions(-) create mode 100644 security/manager/ssl/src/SharedSSLState.cpp create mode 100644 security/manager/ssl/src/SharedSSLState.h diff --git a/security/manager/pki/resources/content/exceptionDialog.js b/security/manager/pki/resources/content/exceptionDialog.js index e6cae8415859..6d4eb89eacf9 100644 --- a/security/manager/pki/resources/content/exceptionDialog.js +++ b/security/manager/pki/resources/content/exceptionDialog.js @@ -88,8 +88,11 @@ function initExceptionDialog() { // returns true if found and global status could be set function findRecentBadCert(uri) { try { - var recentCertsSvc = Components.classes["@mozilla.org/security/recentbadcerts;1"] - .getService(Components.interfaces.nsIRecentBadCertsService); + var certDB = Components.classes["@mozilla.org/security/x509certdb;1"] + .getService(Components.interfaces.nsIX509CertDB); + if (!certDB) + return false; + var recentCertsSvc = certDB.getRecentBadCertsService(inPrivateBrowsingMode()); if (!recentCertsSvc) return false; diff --git a/security/manager/ssl/public/nsIRecentBadCertsService.idl b/security/manager/ssl/public/nsIRecentBadCertsService.idl index 398b792e4cc1..c221aa1dbd93 100644 --- a/security/manager/ssl/public/nsIRecentBadCertsService.idl +++ b/security/manager/ssl/public/nsIRecentBadCertsService.idl @@ -20,9 +20,8 @@ interface nsISSLStatus; * The implementation will decide how many entries it will hold, * the number is expected to be small. */ -[scriptable, uuid(a5ae8b05-a76e-408f-b0ba-02a831265749)] -interface nsIRecentBadCertsService : nsISupports { - +[scriptable, uuid(0fed7784-d152-44d6-95a7-67a59024de0f)] +interface nsIRecentBadCerts : nsISupports { /** * Retrieve the recently seen bad ssl status for the given hostname:port. * If no SSL cert was recently seen for the given hostname:port, return null. @@ -43,4 +42,9 @@ interface nsIRecentBadCertsService : nsISupports { */ void addBadCert(in AString aHostNameWithPort, in nsISSLStatus aStatus); + + /** + * Clear all stored cert data. + */ + void resetStoredCerts(); }; diff --git a/security/manager/ssl/public/nsIX509CertDB.idl b/security/manager/ssl/public/nsIX509CertDB.idl index cedbb2644473..aec9964a1fab 100644 --- a/security/manager/ssl/public/nsIX509CertDB.idl +++ b/security/manager/ssl/public/nsIX509CertDB.idl @@ -12,6 +12,7 @@ interface nsIX509Cert3; interface nsIFile; interface nsIInterfaceRequestor; interface nsIZipReader; +interface nsIRecentBadCerts; %{C++ #define NS_X509CERTDB_CONTRACTID "@mozilla.org/security/x509certdb;1" @@ -29,7 +30,7 @@ interface nsIOpenSignedJARFileCallback : nsISupports * This represents a service to access and manipulate * X.509 certificates stored in a database. */ -[scriptable, uuid(735d0363-e219-4387-b5c6-72e800c3ea0b)] +[scriptable, uuid(a18df2a5-84a9-46cd-9140-3fdb3879d9ff)] interface nsIX509CertDB : nsISupports { /** @@ -264,6 +265,16 @@ interface nsIX509CertDB : nsISupports { */ nsIX509Cert constructX509FromBase64(in string base64); + /* + * Obtain a reference to the appropriate service for recent + * bad certificates. May only be called on the main thread. + * + * @param isPrivate True if the service for certs for private connections + * is desired, false otherwise. + * @return The requested service. + */ + nsIRecentBadCerts getRecentBadCerts(in boolean isPrivate); + /** * Verifies the signature on the given JAR file to verify that it has a * valid signature. To be considered valid, there must be exactly one diff --git a/security/manager/ssl/src/Makefile.in b/security/manager/ssl/src/Makefile.in index 1ea14e33748b..86028d2e646c 100644 --- a/security/manager/ssl/src/Makefile.in +++ b/security/manager/ssl/src/Makefile.in @@ -74,6 +74,7 @@ CPPSRCS = \ PSMRunnable.cpp \ nsNSSVersion.cpp \ nsCertificatePrincipal.cpp \ + SharedSSLState.cpp \ $(NULL) ifdef MOZ_XUL diff --git a/security/manager/ssl/src/SSLServerCertVerification.cpp b/security/manager/ssl/src/SSLServerCertVerification.cpp index ae09139f1010..6bac3a3abfc6 100644 --- a/security/manager/ssl/src/SSLServerCertVerification.cpp +++ b/security/manager/ssl/src/SSLServerCertVerification.cpp @@ -112,6 +112,7 @@ #include "nsIConsoleService.h" #include "PSMRunnable.h" #include "ScopedNSSTypes.h" +#include "SharedSSLState.h" #include "ssl.h" #include "secerr.h" @@ -238,13 +239,15 @@ class CertErrorRunnable : public SyncRunnableBase uint32_t collectedErrors, PRErrorCode errorCodeTrust, PRErrorCode errorCodeMismatch, - PRErrorCode errorCodeExpired) + PRErrorCode errorCodeExpired, + uint32_t providerFlags) : mFdForLogging(fdForLogging), mCert(cert), mInfoObject(infoObject), mDefaultErrorCodeToReport(defaultErrorCodeToReport), mCollectedErrors(collectedErrors), mErrorCodeTrust(errorCodeTrust), mErrorCodeMismatch(errorCodeMismatch), - mErrorCodeExpired(errorCodeExpired) + mErrorCodeExpired(errorCodeExpired), + mProviderFlags(providerFlags) { } @@ -261,6 +264,7 @@ private: const PRErrorCode mErrorCodeTrust; const PRErrorCode mErrorCodeMismatch; const PRErrorCode mErrorCodeExpired; + const uint32_t mProviderFlags; }; SSLServerCertVerificationResult * @@ -296,12 +300,8 @@ CertErrorRunnable::CheckCertOverrides() if (NS_SUCCEEDED(nsrv)) { nsCOMPtr sslSocketControl = do_QueryInterface( NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject)); - uint32_t flags = 0; - if (sslSocketControl) { - sslSocketControl->GetProviderFlags(&flags); - } nsrv = stss->IsStsHost(mInfoObject->GetHostName(), - flags, + mProviderFlags, &strictTransportSecurityEnabled); } if (NS_FAILED(nsrv)) { @@ -371,8 +371,12 @@ CertErrorRunnable::CheckCertOverrides() } } - nsCOMPtr recentBadCertsService = - do_GetService(NS_RECENTBADCERTS_CONTRACTID); + nsCOMPtr certdb = do_GetService(NS_X509CERTDB_CONTRACTID); + nsCOMPtr recentBadCertsService; + if (certdb) { + bool isPrivate = mProviderFlags & nsISocketProvider::NO_PERMANENT_STORAGE; + certdb->GetRecentBadCerts(isPrivate, getter_AddRefs(recentBadCertsService)); + } if (recentBadCertsService) { NS_ConvertUTF8toUTF16 hostWithPortStringUTF16(hostWithPortString); @@ -418,7 +422,8 @@ CertErrorRunnable * CreateCertErrorRunnable(PRErrorCode defaultErrorCodeToReport, TransportSecurityInfo * infoObject, CERTCertificate * cert, - const void * fdForLogging) + const void * fdForLogging, + uint32_t providerFlags) { MOZ_ASSERT(infoObject); MOZ_ASSERT(cert); @@ -567,7 +572,8 @@ CreateCertErrorRunnable(PRErrorCode defaultErrorCodeToReport, static_cast(nssCert.get()), infoObject, defaultErrorCodeToReport, collected_errors, errorCodeTrust, - errorCodeMismatch, errorCodeExpired); + errorCodeMismatch, errorCodeExpired, + providerFlags); } // When doing async cert processing, we dispatch one of these runnables to the @@ -607,25 +613,29 @@ public: // Must be called only on the socket transport thread static SECStatus Dispatch(const void * fdForLogging, TransportSecurityInfo * infoObject, - CERTCertificate * serverCert); + CERTCertificate * serverCert, + uint32_t providerFlags); private: NS_DECL_NSIRUNNABLE // Must be called only on the socket transport thread SSLServerCertVerificationJob(const void * fdForLogging, TransportSecurityInfo * infoObject, - CERTCertificate * cert); + CERTCertificate * cert, + uint32_t providerFlags); const void * const mFdForLogging; const RefPtr mInfoObject; const ScopedCERTCertificate mCert; + const uint32_t mProviderFlags; }; SSLServerCertVerificationJob::SSLServerCertVerificationJob( const void * fdForLogging, TransportSecurityInfo * infoObject, - CERTCertificate * cert) + CERTCertificate * cert, uint32_t providerFlags) : mFdForLogging(fdForLogging) , mInfoObject(infoObject) , mCert(CERT_DupCertificate(cert)) + , mProviderFlags(providerFlags) { } @@ -977,7 +987,8 @@ AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert) /*static*/ SECStatus SSLServerCertVerificationJob::Dispatch(const void * fdForLogging, TransportSecurityInfo * infoObject, - CERTCertificate * serverCert) + CERTCertificate * serverCert, + uint32_t providerFlags) { // Runs on the socket transport thread if (!infoObject || !serverCert) { @@ -987,7 +998,8 @@ SSLServerCertVerificationJob::Dispatch(const void * fdForLogging, } RefPtr job( - new SSLServerCertVerificationJob(fdForLogging, infoObject, serverCert)); + new SSLServerCertVerificationJob(fdForLogging, infoObject, serverCert, + providerFlags)); nsresult nrv; if (!gCertVerificationThreadPool) { @@ -1042,7 +1054,7 @@ SSLServerCertVerificationJob::Run() error = PR_GetError(); if (error != 0) { RefPtr runnable(CreateCertErrorRunnable( - error, mInfoObject, mCert, mFdForLogging)); + error, mInfoObject, mCert, mFdForLogging, mProviderFlags)); if (!runnable) { // CreateCertErrorRunnable set a new error code error = PR_GetError(); @@ -1135,15 +1147,20 @@ AuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } - + + uint32_t providerFlags = 0; + socketInfo->GetProviderFlags(&providerFlags); + if (onSTSThread) { + // We *must* do certificate verification on a background thread because // we need the socket transport thread to be free for our OCSP requests, // and we *want* to do certificate verification on a background thread // because of the performance benefits of doing so. socketInfo->SetCertVerificationWaiting(); SECStatus rv = SSLServerCertVerificationJob::Dispatch( - static_cast(fd), socketInfo, serverCert); + static_cast(fd), socketInfo, serverCert, + providerFlags); return rv; } @@ -1160,7 +1177,7 @@ AuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) if (error != 0) { RefPtr runnable(CreateCertErrorRunnable( error, socketInfo, serverCert, - static_cast(fd))); + static_cast(fd), providerFlags)); if (!runnable) { // CreateCertErrorRunnable sets a new error code when it fails error = PR_GetError(); diff --git a/security/manager/ssl/src/SharedSSLState.cpp b/security/manager/ssl/src/SharedSSLState.cpp new file mode 100644 index 000000000000..6a4e7b1a493a --- /dev/null +++ b/security/manager/ssl/src/SharedSSLState.cpp @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SharedSSLState.h" +#include "nsClientAuthRemember.h" +#include "nsComponentManagerUtils.h" +#include "nsICertOverrideService.h" +#include "nsIObserverService.h" +#include "mozilla/Services.h" +#include "nsThreadUtils.h" +#include "nsCRT.h" + +namespace mozilla { +namespace psm { + +namespace { +class PrivateBrowsingObserver : public nsIObserver { +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + PrivateBrowsingObserver(SharedSSLState* aOwner) : mOwner(aOwner) {} + virtual ~PrivateBrowsingObserver() {} +private: + SharedSSLState* mOwner; +}; + +SharedSSLState* gPublicState; +SharedSSLState* gPrivateState; +} // anonymous namespace + +NS_IMPL_ISUPPORTS1(PrivateBrowsingObserver, nsIObserver) + +NS_IMETHODIMP +PrivateBrowsingObserver::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) { + mOwner->ResetStoredData(); + } + return NS_OK; +} + +SharedSSLState::SharedSSLState() +: mClientAuthRemember(new nsClientAuthRememberService) +{ + mIOLayerHelpers.Init(); + mClientAuthRemember->Init(); +} + +void +SharedSSLState::NotePrivateBrowsingStatus() +{ + mObserver = new PrivateBrowsingObserver(this); + nsCOMPtr obsSvc = mozilla::services::GetObserverService(); + obsSvc->AddObserver(mObserver, "last-pb-context-exited", false); +} + +void +SharedSSLState::ResetStoredData() +{ + mClientAuthRemember->ClearRememberedDecisions(); + mIOLayerHelpers.clearStoredData(); +} + +/*static*/ void +SharedSSLState::GlobalInit() +{ + MOZ_ASSERT(NS_IsMainThread(), "Not on main thread"); + gPublicState = new SharedSSLState(); + gPrivateState = new SharedSSLState(); + gPrivateState->NotePrivateBrowsingStatus(); +} + +/*static*/ void +SharedSSLState::GlobalCleanup() +{ + MOZ_ASSERT(NS_IsMainThread(), "Not on main thread"); + + gPrivateState->Cleanup(); + delete gPrivateState; + gPrivateState = nullptr; + + gPublicState->Cleanup(); + delete gPublicState; + gPublicState = nullptr; +} + +void +SharedSSLState::Cleanup() +{ + mIOLayerHelpers.Cleanup(); +} + +SharedSSLState* +PublicSSLState() +{ + return gPublicState; +} + +SharedSSLState* +PrivateSSLState() +{ + return gPrivateState; +} + +} // namespace psm +} // namespace mozilla diff --git a/security/manager/ssl/src/SharedSSLState.h b/security/manager/ssl/src/SharedSSLState.h new file mode 100644 index 000000000000..7a89fbca243b --- /dev/null +++ b/security/manager/ssl/src/SharedSSLState.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef SharedSSLState_h +#define SharedSSLState_h + +#include "mozilla/RefPtr.h" +#include "nsNSSIOLayer.h" + +class nsClientAuthRememberService; +class nsIRecentBadCertsService; +class nsICertOverrideService; +class nsIObserver; + +namespace mozilla { +namespace psm { + +class SharedSSLState { +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedSSLState) + SharedSSLState(); + + static void GlobalInit(); + static void GlobalCleanup(); + + nsClientAuthRememberService* GetClientAuthRememberService() { + return mClientAuthRemember; + } + + nsSSLIOLayerHelpers& IOLayerHelpers() { + return mIOLayerHelpers; + } + + void ResetStoredData(); + void NotePrivateBrowsingStatus(); + +private: + void Cleanup(); + + nsCOMPtr mObserver; + RefPtr mClientAuthRemember; + nsSSLIOLayerHelpers mIOLayerHelpers; +}; + +SharedSSLState* PublicSSLState(); +SharedSSLState* PrivateSSLState(); + +} // namespace psm +} // namespace mozilla + +#endif diff --git a/security/manager/ssl/src/nsClientAuthRemember.cpp b/security/manager/ssl/src/nsClientAuthRemember.cpp index b3ac013b4e26..ad595810da3a 100644 --- a/security/manager/ssl/src/nsClientAuthRemember.cpp +++ b/security/manager/ssl/src/nsClientAuthRemember.cpp @@ -21,8 +21,10 @@ #include "pk11pub.h" #include "certdb.h" #include "sechash.h" +#include "SharedSSLState.h" using namespace mozilla; +using namespace mozilla::psm; NS_IMPL_THREADSAFE_ISUPPORTS2(nsClientAuthRememberService, nsIObserver, @@ -80,6 +82,16 @@ void nsClientAuthRememberService::ClearRememberedDecisions() RemoveAllFromMemory(); } +void nsClientAuthRememberService::ClearAllRememberedDecisions() +{ + RefPtr svc = + PublicSSLState()->GetClientAuthRememberService(); + svc->ClearRememberedDecisions(); + + svc = PrivateSSLState()->GetClientAuthRememberService(); + svc->ClearRememberedDecisions(); +} + void nsClientAuthRememberService::RemoveAllFromMemory() { diff --git a/security/manager/ssl/src/nsClientAuthRemember.h b/security/manager/ssl/src/nsClientAuthRemember.h index 35a8a21b47a5..161303f07576 100644 --- a/security/manager/ssl/src/nsClientAuthRemember.h +++ b/security/manager/ssl/src/nsClientAuthRemember.h @@ -128,6 +128,7 @@ public: nsACString & aCertDBKey, bool *_retval); void ClearRememberedDecisions(); + static void ClearAllRememberedDecisions(); protected: mozilla::ReentrantMonitor monitor; diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp index d7809989c7a6..02188b78493d 100644 --- a/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -23,6 +23,7 @@ #include "nsIConsoleService.h" #include "nsIHttpChannelInternal.h" #include "nsCRT.h" +#include "SharedSSLState.h" #include "ssl.h" #include "sslproto.h" @@ -841,7 +842,8 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { // If the handshake completed, then we know the site is TLS tolerant (if this // was a TLS connection). - nsSSLIOLayerHelpers::rememberTolerantSite(infoObject); + nsSSLIOLayerHelpers& ioLayerHelpers = infoObject->SharedState().IOLayerHelpers(); + ioLayerHelpers.rememberTolerantSite(infoObject); if (SECSuccess != SSL_SecurityStatus(fd, &sslStatus, &cipherName, &keyLength, &encryptBits, &signer, nullptr)) { @@ -859,7 +861,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { if (SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn, &siteSupportsSafeRenego) != SECSuccess || !siteSupportsSafeRenego) { - bool wantWarning = (nsSSLIOLayerHelpers::getWarnLevelMissingRFC5746() > 0); + bool wantWarning = (ioLayerHelpers.getWarnLevelMissingRFC5746() > 0); nsCOMPtr console; if (infoObject && wantWarning) { @@ -875,7 +877,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { console->LogStringMessage(msg.get()); } } - if (nsSSLIOLayerHelpers::treatUnsafeNegotiationAsBroken()) { + if (ioLayerHelpers.treatUnsafeNegotiationAsBroken()) { secStatus = nsIWebProgressListener::STATE_IS_BROKEN; } } diff --git a/security/manager/ssl/src/nsNSSCertificateDB.cpp b/security/manager/ssl/src/nsNSSCertificateDB.cpp index 912ced9a8d68..b3314216a320 100644 --- a/security/manager/ssl/src/nsNSSCertificateDB.cpp +++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp @@ -31,6 +31,8 @@ #include "nsIPrompt.h" #include "nsThreadUtils.h" #include "ScopedNSSTypes.h" +#include "nsIObserverService.h" +#include "nsRecentBadCerts.h" #include "nspr.h" #include "certdb.h" @@ -1644,3 +1646,22 @@ nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval) NS_ADDREF(*_retval); return NS_OK; } + +NS_IMETHODIMP +nsNSSCertificateDB::GetRecentBadCerts(bool isPrivate, nsIRecentBadCerts** result) +{ + MOZ_ASSERT(NS_IsMainThread(), "RecentBadCerts should only be obtained on the main thread"); + if (isPrivate) { + if (!mPrivateRecentBadCerts) { + mPrivateRecentBadCerts = new nsRecentBadCerts; + mPrivateRecentBadCerts->InitPrivateBrowsingObserver(); + } + NS_ADDREF(*result = mPrivateRecentBadCerts); + } else { + if (!mPublicRecentBadCerts) { + mPublicRecentBadCerts = new nsRecentBadCerts; + } + NS_ADDREF(*result = mPublicRecentBadCerts); + } + return NS_OK; +} diff --git a/security/manager/ssl/src/nsNSSCertificateDB.h b/security/manager/ssl/src/nsNSSCertificateDB.h index efdbff80d339..c821322fbcb4 100644 --- a/security/manager/ssl/src/nsNSSCertificateDB.h +++ b/security/manager/ssl/src/nsNSSCertificateDB.h @@ -7,10 +7,12 @@ #include "nsIX509CertDB.h" #include "nsIX509CertDB2.h" +#include "mozilla/RefPtr.h" #include "certt.h" class nsCString; class nsIArray; +class nsRecentBadCerts; class nsNSSCertificateDB : public nsIX509CertDB, public nsIX509CertDB2 { @@ -48,6 +50,9 @@ private: uint32_t length); nsresult handleCACertDownload(nsIArray *x509Certs, nsIInterfaceRequestor *ctx); + + mozilla::RefPtr mPublicRecentBadCerts; + mozilla::RefPtr mPrivateRecentBadCerts; }; #define NS_X509CERTDB_CID { /* fb0bbc5c-452e-4783-b32c-80124693d871 */ \ diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 486a3e1f907b..aabe6fab9789 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -60,6 +60,7 @@ #include "nsSmartCardEvent.h" #include "nsIKeyModule.h" #include "ScopedNSSTypes.h" +#include "SharedSSLState.h" #include "nss.h" #include "pk11func.h" @@ -400,7 +401,7 @@ nsNSSComponent::~nsNSSComponent() // All cleanup code requiring services needs to happen in xpcom_shutdown ShutdownNSS(); - nsSSLIOLayerHelpers::Cleanup(); + SharedSSLState::GlobalCleanup(); RememberCertErrorsTable::Cleanup(); --mInstanceCount; delete mShutdownObjectList; @@ -1860,9 +1861,6 @@ nsNSSComponent::ShutdownNSS() ShutdownSmartCardThreads(); SSL_ClearSessionCache(); - if (mClientAuthRememberService) { - mClientAuthRememberService->ClearRememberedDecisions(); - } UnloadLoadableRoots(); CleanupIdentityInfo(); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n")); @@ -1933,27 +1931,8 @@ nsNSSComponent::Init() } RememberCertErrorsTable::Init(); - nsSSLIOLayerHelpers::Init(); - char *unrestricted_hosts=nullptr; - mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts); - if (unrestricted_hosts) { - nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts)); - nsMemory::Free(unrestricted_hosts); - unrestricted_hosts=nullptr; - } - - bool enabled = false; - mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled); - nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled); - - int32_t warnLevel = 1; - mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel); - nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel); + SharedSSLState::GlobalInit(); - mClientAuthRememberService = new nsClientAuthRememberService; - if (mClientAuthRememberService) - mClientAuthRememberService->Init(); - createBackgroundThreads(); if (!mCertVerificationThread) { @@ -2271,20 +2250,6 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic, mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled); SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN); - } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) { - char *unrestricted_hosts=nullptr; - mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts); - if (unrestricted_hosts) { - nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts)); - nsMemory::Free(unrestricted_hosts); - } - } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) { - mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled); - nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled); - } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) { - int32_t warnLevel = 1; - mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel); - nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel); #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8 } else if (prefName.Equals("security.ssl.enable_false_start")) { mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled); @@ -2387,9 +2352,7 @@ nsresult nsNSSComponent::LogoutAuthenticatedPK11() 0); } - if (mClientAuthRememberService) { - mClientAuthRememberService->ClearRememberedDecisions(); - } + nsClientAuthRememberService::ClearAllRememberedDecisions(); return mShutdownObjectList->doPK11Logout(); } @@ -2568,14 +2531,6 @@ nsNSSComponent::DoProfileChangeNetRestore() mIsNetworkDown = false; } -NS_IMETHODIMP -nsNSSComponent::GetClientAuthRememberService(nsClientAuthRememberService **cars) -{ - NS_ENSURE_ARG_POINTER(cars); - NS_IF_ADDREF(*cars = mClientAuthRememberService); - return NS_OK; -} - NS_IMETHODIMP nsNSSComponent::IsNSSInitialized(bool *initialized) { diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index 2391d95565d2..b47b989c21f5 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -154,8 +154,6 @@ class NS_NO_VTABLE nsINSSComponent : public nsISupports { NS_IMETHOD DispatchEvent(const nsAString &eventType, const nsAString &token) = 0; - NS_IMETHOD GetClientAuthRememberService(nsClientAuthRememberService **cars) = 0; - NS_IMETHOD EnsureIdentityInfoLoaded() = 0; NS_IMETHOD IsNSSInitialized(bool *initialized) = 0; @@ -259,7 +257,6 @@ public: NS_IMETHOD ShutdownSmartCardThread(SECMODModule *module); NS_IMETHOD PostEvent(const nsAString &eventType, const nsAString &token); NS_IMETHOD DispatchEvent(const nsAString &eventType, const nsAString &token); - NS_IMETHOD GetClientAuthRememberService(nsClientAuthRememberService **cars); NS_IMETHOD EnsureIdentityInfoLoaded(); NS_IMETHOD IsNSSInitialized(bool *initialized); @@ -327,7 +324,6 @@ private: nsCertVerificationThread *mCertVerificationThread; nsNSSHttpInterface mHttpForNSS; - mozilla::RefPtr mClientAuthRememberService; mozilla::RefPtr mDefaultCERTValInParam; mozilla::RefPtr mDefaultCERTValInParamLocalOnly; diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 7f52d25af224..8e84c9647b2b 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -28,6 +28,8 @@ #include "nsIConsoleService.h" #include "PSMRunnable.h" #include "ScopedNSSTypes.h" +#include "SharedSSLState.h" +#include "mozilla/Preferences.h" #include "ssl.h" #include "secerr.h" @@ -63,9 +65,10 @@ typedef enum {ASK, AUTO} SSM_UserCertChoice; extern PRLogModuleInfo* gPIPNSSLog; #endif -nsNSSSocketInfo::nsNSSSocketInfo(uint32_t providerFlags) +nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags) : mFd(nullptr), mCertVerificationState(before_cert_verification), + mSharedState(aState), mForSTARTTLS(false), mSSL3Enabled(false), mTLSEnabled(false), @@ -457,6 +460,11 @@ void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(bool aAllow) mAllowTLSIntoleranceTimeout = aAllow; } +SharedSSLState& nsNSSSocketInfo::SharedState() +{ + return mSharedState; +} + bool nsNSSSocketInfo::HandshakeTimeout() { if (!mAllowTLSIntoleranceTimeout) @@ -914,7 +922,8 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading, if (!wantRetry // no decision yet && isTLSIntoleranceError(err, socketInfo->GetHasCleartextPhase())) { - wantRetry = nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(socketInfo); + nsSSLIOLayerHelpers& helpers = socketInfo->SharedState().IOLayerHelpers(); + wantRetry = helpers.rememberPossibleTLSProblemSite(socketInfo); } } @@ -942,8 +951,8 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading, if (!wantRetry // no decision yet && !socketInfo->GetHasCleartextPhase()) // mirror PR_CONNECT_RESET_ERROR treament { - wantRetry = - nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(socketInfo); + nsSSLIOLayerHelpers& helpers = socketInfo->SharedState().IOLayerHelpers(); + wantRetry = helpers.rememberPossibleTLSProblemSite(socketInfo); } } } @@ -1031,12 +1040,16 @@ nsSSLIOLayerPoll(PRFileDesc * fd, int16_t in_flags, int16_t *out_flags) bool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = false; PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity; PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods; -Mutex *nsSSLIOLayerHelpers::mutex = nullptr; -nsTHashtable *nsSSLIOLayerHelpers::mTLSIntolerantSites = nullptr; -nsTHashtable *nsSSLIOLayerHelpers::mTLSTolerantSites = nullptr; -nsTHashtable *nsSSLIOLayerHelpers::mRenegoUnrestrictedSites = nullptr; -bool nsSSLIOLayerHelpers::mTreatUnsafeNegotiationAsBroken = false; -int32_t nsSSLIOLayerHelpers::mWarnLevelMissingRFC5746 = 1; + +nsSSLIOLayerHelpers::nsSSLIOLayerHelpers() +: mutex(nullptr) +, mTLSIntolerantSites(nullptr) +, mTLSTolerantSites(nullptr) +, mRenegoUnrestrictedSites(nullptr) +, mTreatUnsafeNegotiationAsBroken(false) +, mWarnLevelMissingRFC5746(1) +{ +} static int _PSM_InvalidInt(void) { @@ -1190,6 +1203,53 @@ static int64_t PSMAvailable64(void) return -1; } +namespace { +class PrefObserver : public nsIObserver { +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + PrefObserver(nsSSLIOLayerHelpers* aOwner) : mOwner(aOwner) {} + virtual ~PrefObserver() {} +private: + nsSSLIOLayerHelpers* mOwner; +}; +} // namespace anonymous + +NS_IMPL_THREADSAFE_ISUPPORTS1(PrefObserver, nsIObserver) + +NS_IMETHODIMP +PrefObserver::Observe(nsISupports *aSubject, const char *aTopic, + const PRUnichar *someData) +{ + if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) { + NS_ConvertUTF16toUTF8 prefName(someData); + + if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) { + nsCString unrestricted_hosts; + Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts); + if (!unrestricted_hosts.IsEmpty()) { + mOwner->setRenegoUnrestrictedSites(unrestricted_hosts); + } + } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) { + bool enabled; + Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled); + mOwner->setTreatUnsafeNegotiationAsBroken(enabled); + } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) { + int32_t warnLevel = 1; + Preferences::GetInt("security.ssl.warn_missing_rfc5746", &warnLevel); + mOwner->setWarnLevelMissingRFC5746(warnLevel); + } + } + return NS_OK; +} + +nsSSLIOLayerHelpers::~nsSSLIOLayerHelpers() +{ + Preferences::RemoveObserver(mPrefObserver, "security.ssl.renego_unrestricted_hosts"); + Preferences::RemoveObserver(mPrefObserver, "security.ssl.treat_unsafe_negotiation_as_broken"); + Preferences::RemoveObserver(mPrefObserver, "security.ssl.warn_missing_rfc5746"); +} + nsresult nsSSLIOLayerHelpers::Init() { if (!nsSSLIOLayerInitialized) { @@ -1244,23 +1304,50 @@ nsresult nsSSLIOLayerHelpers::Init() mRenegoUnrestrictedSites = new nsTHashtable(); mRenegoUnrestrictedSites->Init(1); - mTreatUnsafeNegotiationAsBroken = false; - + nsCString unrestricted_hosts; + Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts); + if (!unrestricted_hosts.IsEmpty()) { + setRenegoUnrestrictedSites(unrestricted_hosts); + } + + bool enabled = false; + Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled); + setTreatUnsafeNegotiationAsBroken(enabled); + + int32_t warnLevel = 1; + Preferences::GetInt("security.ssl.warn_missing_rfc5746", &warnLevel); + setWarnLevelMissingRFC5746(warnLevel); + + mPrefObserver = new PrefObserver(this); + Preferences::AddStrongObserver(mPrefObserver, + "security.ssl.renego_unrestricted_hosts"); + Preferences::AddStrongObserver(mPrefObserver, + "security.ssl.treat_unsafe_negotiation_as_broken"); + Preferences::AddStrongObserver(mPrefObserver, + "security.ssl.warn_missing_rfc5746"); + return NS_OK; } +void nsSSLIOLayerHelpers::clearStoredData() +{ + mRenegoUnrestrictedSites->Clear(); + mTLSTolerantSites->Clear(); + mTLSIntolerantSites->Clear(); +} + void nsSSLIOLayerHelpers::addIntolerantSite(const nsCString &str) { MutexAutoLock lock(*mutex); // Remember intolerant site only if it is not known as tolerant if (!mTLSTolerantSites->Contains(str)) - nsSSLIOLayerHelpers::mTLSIntolerantSites->PutEntry(str); + mTLSIntolerantSites->PutEntry(str); } void nsSSLIOLayerHelpers::removeIntolerantSite(const nsCString &str) { MutexAutoLock lock(*mutex); - nsSSLIOLayerHelpers::mTLSIntolerantSites->RemoveEntry(str); + mTLSIntolerantSites->RemoveEntry(str); } bool nsSSLIOLayerHelpers::isKnownAsIntolerantSite(const nsCString &str) @@ -1923,6 +2010,7 @@ void ClientAuthDataRunnable::RunOnTargetThread() SSM_UserCertChoice certChoice; int32_t NumberOfCerts = 0; void * wincx = mSocketInfo; + nsresult rv; /* create caNameStrings */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); @@ -2024,19 +2112,14 @@ void ClientAuthDataRunnable::RunOnTargetThread() nsXPIDLCString hostname; mSocketInfo->GetHostName(getter_Copies(hostname)); - nsresult rv; - NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID); - nsCOMPtr nssComponent(do_GetService(nssComponentCID, &rv)); - RefPtr cars; - if (nssComponent) { - nssComponent->GetClientAuthRememberService(byRef(cars)); - } + RefPtr cars = + mSocketInfo->SharedState().GetClientAuthRememberService(); bool hasRemembered = false; nsCString rememberedDBKey; if (cars) { bool found; - nsresult rv = cars->HasRememberedDecision(hostname, mServerCert, + rv = cars->HasRememberedDecision(hostname, mServerCert, rememberedDBKey, &found); if (NS_SUCCEEDED(rv) && found) { hasRemembered = true; @@ -2219,9 +2302,9 @@ if (!hasRemembered) } /* Throw up the client auth dialog and get back the index of the selected cert */ - rv = getNSSDialogs((void**)&dialogs, - NS_GET_IID(nsIClientAuthDialogs), - NS_CLIENTAUTHDIALOGS_CONTRACTID); + nsresult rv = getNSSDialogs((void**)&dialogs, + NS_GET_IID(nsIClientAuthDialogs), + NS_CLIENTAUTHDIALOGS_CONTRACTID); if (NS_FAILED(rv)) { NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certNicknameList); @@ -2380,7 +2463,7 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, bool forSTARTTLS, nsAutoCString key; key = nsDependentCString(host) + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port); - if (nsSSLIOLayerHelpers::isKnownAsIntolerantSite(key)) { + if (infoObject->SharedState().IOLayerHelpers().isKnownAsIntolerantSite(key)) { if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_TLS, false)) return NS_ERROR_FAILURE; @@ -2407,8 +2490,9 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, bool forSTARTTLS, if (SECSuccess != SSL_OptionSet(fd, SSL_HANDSHAKE_AS_CLIENT, true)) { return NS_ERROR_FAILURE; } - - if (nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(nsDependentCString(host))) { + + nsSSLIOLayerHelpers& ioHelpers = infoObject->SharedState().IOLayerHelpers(); + if (ioHelpers.isRenegoUnrestrictedSite(nsDependentCString(host))) { if (SECSuccess != SSL_OptionSet(fd, SSL_REQUIRE_SAFE_NEGOTIATION, false)) { return NS_ERROR_FAILURE; } @@ -2450,7 +2534,9 @@ nsSSLIOLayerAddToSocket(int32_t family, nsresult rv; PRStatus stat; - nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(providerFlags); + SharedSSLState* sharedState = + providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE ? PrivateSSLState() : PublicSSLState(); + nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags); if (!infoObject) return NS_ERROR_FAILURE; NS_ADDREF(infoObject); diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index 4ee3bd9b8aac..2f25e71d04c8 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -15,12 +15,20 @@ #include "nsTHashtable.h" #include "mozilla/TimeStamp.h" +namespace mozilla { +namespace psm { +class SharedSSLState; +} +} + +class nsIObserver; + class nsNSSSocketInfo : public mozilla::psm::TransportSecurityInfo, public nsISSLSocketControl, public nsIClientAuthUserDecision { public: - nsNSSSocketInfo(uint32_t providerFlags); + nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSISSLSOCKETCONTROL @@ -56,6 +64,8 @@ public: bool GetJoined() { return mJoined; } void SetSentClientCert() { mSentClientCert = true; } + mozilla::psm::SharedSSLState& SharedState(); + // XXX: These are only used on for diagnostic purposes enum CertVerificationState { before_cert_verification, @@ -83,6 +93,7 @@ private: CertVerificationState mCertVerificationState; + mozilla::psm::SharedSSLState& mSharedState; bool mForSTARTTLS; bool mSSL3Enabled; bool mTLSEnabled; @@ -109,37 +120,44 @@ private: class nsSSLIOLayerHelpers { public: - static nsresult Init(); - static void Cleanup(); + nsSSLIOLayerHelpers(); + ~nsSSLIOLayerHelpers(); + + nsresult Init(); + void Cleanup(); static bool nsSSLIOLayerInitialized; static PRDescIdentity nsSSLIOLayerIdentity; static PRIOMethods nsSSLIOLayerMethods; - static mozilla::Mutex *mutex; - static nsTHashtable *mTLSIntolerantSites; - static nsTHashtable *mTLSTolerantSites; + mozilla::Mutex *mutex; + nsTHashtable *mTLSIntolerantSites; + nsTHashtable *mTLSTolerantSites; - static nsTHashtable *mRenegoUnrestrictedSites; - static bool mTreatUnsafeNegotiationAsBroken; - static int32_t mWarnLevelMissingRFC5746; + nsTHashtable *mRenegoUnrestrictedSites; + bool mTreatUnsafeNegotiationAsBroken; + int32_t mWarnLevelMissingRFC5746; - static void setTreatUnsafeNegotiationAsBroken(bool broken); - static bool treatUnsafeNegotiationAsBroken(); + void setTreatUnsafeNegotiationAsBroken(bool broken); + bool treatUnsafeNegotiationAsBroken(); - static void setWarnLevelMissingRFC5746(int32_t level); - static int32_t getWarnLevelMissingRFC5746(); + void setWarnLevelMissingRFC5746(int32_t level); + int32_t getWarnLevelMissingRFC5746(); static void getSiteKey(nsNSSSocketInfo *socketInfo, nsCSubstring &key); - static bool rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo); - static void rememberTolerantSite(nsNSSSocketInfo *socketInfo); + bool rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo); + void rememberTolerantSite(nsNSSSocketInfo *socketInfo); - static void addIntolerantSite(const nsCString &str); - static void removeIntolerantSite(const nsCString &str); - static bool isKnownAsIntolerantSite(const nsCString &str); + void addIntolerantSite(const nsCString &str); + void removeIntolerantSite(const nsCString &str); + bool isKnownAsIntolerantSite(const nsCString &str); - static void setRenegoUnrestrictedSites(const nsCString &str); - static bool isRenegoUnrestrictedSite(const nsCString &str); + void setRenegoUnrestrictedSites(const nsCString &str); + bool isRenegoUnrestrictedSite(const nsCString &str); + + void clearStoredData(); +private: + nsCOMPtr mPrefObserver; }; nsresult nsSSLIOLayerNewSocket(int32_t family, diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index 90debb592819..568c2be52ae5 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -38,7 +38,6 @@ #include "nsDataSignatureVerifier.h" #include "nsCertOverrideService.h" #include "nsRandomGenerator.h" -#include "nsRecentBadCerts.h" #include "nsSSLStatus.h" #include "TransportSecurityInfo.h" #include "NSSErrorsService.h" @@ -204,7 +203,6 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObjectFactory) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsDataSignatureVerifier) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsCertOverrideService, Init) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsRandomGenerator) -NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, TransportSecurityInfo) @@ -243,7 +241,6 @@ NS_DEFINE_NAMED_CID(NS_KEYMODULEOBJECTFACTORY_CID); NS_DEFINE_NAMED_CID(NS_DATASIGNATUREVERIFIER_CID); NS_DEFINE_NAMED_CID(NS_CERTOVERRIDE_CID); NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID); -NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID); NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID); NS_DEFINE_NAMED_CID(TRANSPORTSECURITYINFO_CID); NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID); @@ -281,7 +278,6 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = { { &kNS_DATASIGNATUREVERIFIER_CID, false, nullptr, nsDataSignatureVerifierConstructor }, { &kNS_CERTOVERRIDE_CID, false, nullptr, nsCertOverrideServiceConstructor }, { &kNS_RANDOMGENERATOR_CID, false, nullptr, nsRandomGeneratorConstructor }, - { &kNS_RECENTBADCERTS_CID, false, nullptr, nsRecentBadCertsServiceConstructor }, { &kNS_SSLSTATUS_CID, false, nullptr, nsSSLStatusConstructor }, { &kTRANSPORTSECURITYINFO_CID, false, nullptr, TransportSecurityInfoConstructor }, { &kNS_NSSERRORSSERVICE_CID, false, nullptr, NSSErrorsServiceConstructor }, @@ -324,7 +320,6 @@ static const mozilla::Module::ContractIDEntry kNSSContracts[] = { { NS_DATASIGNATUREVERIFIER_CONTRACTID, &kNS_DATASIGNATUREVERIFIER_CID }, { NS_CERTOVERRIDE_CONTRACTID, &kNS_CERTOVERRIDE_CID }, { NS_RANDOMGENERATOR_CONTRACTID, &kNS_RANDOMGENERATOR_CID }, - { NS_RECENTBADCERTS_CONTRACTID, &kNS_RECENTBADCERTS_CID }, { nullptr } }; diff --git a/security/manager/ssl/src/nsRecentBadCerts.cpp b/security/manager/ssl/src/nsRecentBadCerts.cpp index de378b9e9bb5..cae4fd1fb61c 100644 --- a/security/manager/ssl/src/nsRecentBadCerts.cpp +++ b/security/manager/ssl/src/nsRecentBadCerts.cpp @@ -6,7 +6,9 @@ #include "nsRecentBadCerts.h" #include "nsIX509Cert.h" +#include "nsIObserverService.h" #include "mozilla/RefPtr.h" +#include "mozilla/Services.h" #include "nsSSLStatus.h" #include "nsCOMPtr.h" #include "nsNSSCertificate.h" @@ -20,28 +22,41 @@ using namespace mozilla; -NS_IMPL_THREADSAFE_ISUPPORTS1(nsRecentBadCertsService, - nsIRecentBadCertsService) +NS_IMPL_THREADSAFE_ISUPPORTS2(nsRecentBadCerts, + nsIRecentBadCerts, + nsIObserver) -nsRecentBadCertsService::nsRecentBadCertsService() -:monitor("nsRecentBadCertsService.monitor") +nsRecentBadCerts::nsRecentBadCerts() +:monitor("nsRecentBadCerts.monitor") ,mNextStorePosition(0) { } -nsRecentBadCertsService::~nsRecentBadCertsService() +nsRecentBadCerts::~nsRecentBadCerts() { } -nsresult -nsRecentBadCertsService::Init() +void +nsRecentBadCerts::InitPrivateBrowsingObserver() { + nsCOMPtr obsSvc = mozilla::services::GetObserverService(); + obsSvc->AddObserver(this, "last-pb-context-exited", false); +} + +NS_IMETHODIMP +nsRecentBadCerts::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) { + ResetStoredCerts(); + } return NS_OK; } NS_IMETHODIMP -nsRecentBadCertsService::GetRecentBadCert(const nsAString & aHostNameWithPort, - nsISSLStatus **aStatus) +nsRecentBadCerts::GetRecentBadCert(const nsAString & aHostNameWithPort, + nsISSLStatus **aStatus) { NS_ENSURE_ARG_POINTER(aStatus); if (!aHostNameWithPort.Length()) @@ -101,7 +116,7 @@ nsRecentBadCertsService::GetRecentBadCert(const nsAString & aHostNameWithPort, } NS_IMETHODIMP -nsRecentBadCertsService::AddBadCert(const nsAString &hostWithPort, +nsRecentBadCerts::AddBadCert(const nsAString &hostWithPort, nsISSLStatus *aStatus) { NS_ENSURE_ARG(aStatus); @@ -146,3 +161,13 @@ nsRecentBadCertsService::AddBadCert(const nsAString &hostWithPort, return NS_OK; } + +NS_IMETHODIMP +nsRecentBadCerts::ResetStoredCerts() +{ + for (size_t i = 0; i < const_recently_seen_list_size; ++i) { + RecentBadCert &entry = mCerts[i]; + entry.Clear(); + } + return NS_OK; +} diff --git a/security/manager/ssl/src/nsRecentBadCerts.h b/security/manager/ssl/src/nsRecentBadCerts.h index e82f780c252a..d815482d3794 100644 --- a/security/manager/ssl/src/nsRecentBadCerts.h +++ b/security/manager/ssl/src/nsRecentBadCerts.h @@ -11,6 +11,7 @@ #include "mozilla/ReentrantMonitor.h" #include "nsIRecentBadCertsService.h" +#include "nsIObserver.h" #include "nsTHashtable.h" #include "nsString.h" #include "cert.h" @@ -54,16 +55,18 @@ private: RecentBadCert &operator=(const RecentBadCert &other) MOZ_DELETE; }; -class nsRecentBadCertsService MOZ_FINAL : public nsIRecentBadCertsService +class nsRecentBadCerts MOZ_FINAL : public nsIRecentBadCerts + , public nsIObserver { public: NS_DECL_ISUPPORTS - NS_DECL_NSIRECENTBADCERTSSERVICE + NS_DECL_NSIRECENTBADCERTS + NS_DECL_NSIOBSERVER - nsRecentBadCertsService(); - ~nsRecentBadCertsService(); + nsRecentBadCerts(); + ~nsRecentBadCerts(); - nsresult Init(); + void InitPrivateBrowsingObserver(); protected: mozilla::ReentrantMonitor monitor;