diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 5fa60b3bc5a..2a4502978b0 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -275,8 +275,34 @@ nsTokenEventRunnable::Run() return nssComponent->DispatchEvent(mType, mTokenName); } +// We must ensure that the nsNSSComponent has been loaded before +// creating any other components. +PRBool EnsureNSSInitialized(PRBool ensure) +{ + static PRBool haveLoaded = PR_FALSE; + + if (!ensure) { + haveLoaded = PR_FALSE; + return PR_FALSE; + } + + if (haveLoaded) + return PR_TRUE; + + nsCOMPtr nssComponent + = do_GetService(PSM_COMPONENT_CONTRACTID); + + // If we succeeded to get the PSM service rise the flag to avoid + // unnecessary calls to GetService. + if (nssComponent) + haveLoaded = PR_TRUE; + + return haveLoaded; +} + nsNSSComponent::nsNSSComponent() - :mNSSInitialized(PR_FALSE), mThreadList(nsnull) + :mNSSInitialized(PR_FALSE), mThreadList(nsnull), + mSSLThread(NULL), mCertVerificationThread(NULL) { mutex = PR_NewLock(); @@ -296,19 +322,11 @@ nsNSSComponent::nsNSSComponent() // registering all identity data until first needed. memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType)); - nsSSLIOLayerHelpers::Init(); - NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!"); ++mInstanceCount; hashTableCerts = nsnull; mShutdownObjectList = nsNSSShutDownList::construct(); mIsNetworkDown = PR_FALSE; - mSSLThread = new nsSSLThread(); - if (mSSLThread) - mSSLThread->startThread(); - mCertVerificationThread = new nsCertVerificationThread(); - if (mCertVerificationThread) - mCertVerificationThread->startThread(); } nsNSSComponent::~nsNSSComponent() @@ -357,6 +375,8 @@ nsNSSComponent::~nsNSSComponent() mutex = nsnull; } + EnsureNSSInitialized(PR_FALSE); + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n")); } @@ -1470,9 +1490,6 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox) return NS_ERROR_FAILURE; } - hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare, - certHashtable_valueCompare, 0, 0 ); - nsresult rv; nsCAutoString profileStr; nsCOMPtr profilePath; @@ -1521,6 +1538,9 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox) if (NS_FAILED(rv)) return rv; + hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare, + certHashtable_valueCompare, 0, 0 ); + #if defined(XP_MACOSX) // function may modify the parameters // ignore return code from conversion, we continue anyway @@ -1710,8 +1730,7 @@ nsNSSComponent::Init() PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n")); - if (!mutex || !mShutdownObjectList || - !mSSLThread || !mCertVerificationThread) + if (!mutex || !mShutdownObjectList) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n")); return NS_ERROR_OUT_OF_MEMORY; @@ -1747,9 +1766,30 @@ nsNSSComponent::Init() rv = InitializeNSS(PR_TRUE); // ok to show a warning box on failure if (NS_FAILED(rv)) { PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n")); + + DeregisterObservers(); + mPIPNSSBundle = nsnull; return rv; } + nsSSLIOLayerHelpers::Init(); + + mSSLThread = new nsSSLThread(); + if (mSSLThread) + mSSLThread->startThread(); + mCertVerificationThread = new nsCertVerificationThread(); + if (mCertVerificationThread) + mCertVerificationThread->startThread(); + + if (!mSSLThread || !mCertVerificationThread) + { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n")); + + DeregisterObservers(); + mPIPNSSBundle = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + InitializeCRLUpdateTimer(); RegisterPSMContentListener(); @@ -2186,6 +2226,31 @@ nsNSSComponent::RegisterObservers() return NS_OK; } +nsresult +nsNSSComponent::DeregisterObservers() +{ + if (!mObserversRegistered) + return NS_OK; + + nsCOMPtr observerService(do_GetService("@mozilla.org/observer-service;1")); + NS_ASSERTION(observerService, "could not get observer service"); + if (observerService) { + mObserversRegistered = PR_FALSE; + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: removing observers\n")); + + observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + + observerService->RemoveObserver(this, PROFILE_APPROVE_CHANGE_TOPIC); + observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC); + observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC); + observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC); + observerService->RemoveObserver(this, PROFILE_AFTER_CHANGE_TOPIC); + observerService->RemoveObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC); + observerService->RemoveObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC); + } + return NS_OK; +} + NS_IMETHODIMP nsNSSComponent::RememberCert(CERTCertificate *cert) { diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index d4cad2f5548..aaf36ed0096 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -93,6 +93,8 @@ #define NS_CRYPTO_HMAC_CLASSNAME "Mozilla Crypto HMAC Function Component" #define NS_CRYPTO_HMAC_CID {0xa496d0a2, 0xdff7, 0x4e23, {0xbd, 0x65, 0x1c, 0xa7, 0x42, 0xfa, 0x17, 0x8a}} +extern PRBool EnsureNSSInitialized(PRBool reset); + //-------------------------------------------- // Now we need a content listener to register //-------------------------------------------- @@ -287,6 +289,7 @@ private: nsresult ConfigureInternalPKCS11Token(); nsresult RegisterPSMContentListener(); nsresult RegisterObservers(); + nsresult DeregisterObservers(); nsresult DownloadCrlSilently(); nsresult PostCRLImportEvent(const nsCSubstring &urlString, nsIStreamListener *psmDownloader); nsresult getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key); diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index c0f0cc2db63..bd88891fab6 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -777,8 +777,10 @@ void nsSSLIOLayerHelpers::Cleanup() if (mSharedPollableEvent) PR_DestroyPollableEvent(mSharedPollableEvent); - if (mutex) + if (mutex) { PR_DestroyLock(mutex); + mutex = nsnull; + } } static nsresult @@ -1771,6 +1773,7 @@ nsSSLIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) return nsSSLThread::requestPoll(socketInfo, in_flags, out_flags); } +PRBool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = PR_FALSE; PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity; PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods; PRLock *nsSSLIOLayerHelpers::mutex = nsnull; @@ -1932,40 +1935,43 @@ static PRStatus PR_CALLBACK PSMConnectcontinue(PRFileDesc *fd, PRInt16 out_flags nsresult nsSSLIOLayerHelpers::Init() { - nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer"); - nsSSLIOLayerMethods = *PR_GetDefaultIOMethods(); + if (!nsSSLIOLayerInitialized) { + nsSSLIOLayerInitialized = PR_TRUE; + nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer"); + nsSSLIOLayerMethods = *PR_GetDefaultIOMethods(); - nsSSLIOLayerMethods.available = (PRAvailableFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.available64 = (PRAvailable64FN)_PSM_InvalidInt64; - nsSSLIOLayerMethods.fsync = (PRFsyncFN)_PSM_InvalidStatus; - nsSSLIOLayerMethods.seek = (PRSeekFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.seek64 = (PRSeek64FN)_PSM_InvalidInt64; - nsSSLIOLayerMethods.fileInfo = (PRFileInfoFN)_PSM_InvalidStatus; - nsSSLIOLayerMethods.fileInfo64 = (PRFileInfo64FN)_PSM_InvalidStatus; - nsSSLIOLayerMethods.writev = (PRWritevFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.accept = (PRAcceptFN)_PSM_InvalidDesc; - nsSSLIOLayerMethods.bind = (PRBindFN)_PSM_InvalidStatus; - nsSSLIOLayerMethods.listen = (PRListenFN)_PSM_InvalidStatus; - nsSSLIOLayerMethods.shutdown = (PRShutdownFN)_PSM_InvalidStatus; - nsSSLIOLayerMethods.recvfrom = (PRRecvfromFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.sendto = (PRSendtoFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.acceptread = (PRAcceptreadFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.transmitfile = (PRTransmitfileFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.sendfile = (PRSendfileFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.available = (PRAvailableFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.available64 = (PRAvailable64FN)_PSM_InvalidInt64; + nsSSLIOLayerMethods.fsync = (PRFsyncFN)_PSM_InvalidStatus; + nsSSLIOLayerMethods.seek = (PRSeekFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.seek64 = (PRSeek64FN)_PSM_InvalidInt64; + nsSSLIOLayerMethods.fileInfo = (PRFileInfoFN)_PSM_InvalidStatus; + nsSSLIOLayerMethods.fileInfo64 = (PRFileInfo64FN)_PSM_InvalidStatus; + nsSSLIOLayerMethods.writev = (PRWritevFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.accept = (PRAcceptFN)_PSM_InvalidDesc; + nsSSLIOLayerMethods.bind = (PRBindFN)_PSM_InvalidStatus; + nsSSLIOLayerMethods.listen = (PRListenFN)_PSM_InvalidStatus; + nsSSLIOLayerMethods.shutdown = (PRShutdownFN)_PSM_InvalidStatus; + nsSSLIOLayerMethods.recvfrom = (PRRecvfromFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.sendto = (PRSendtoFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.acceptread = (PRAcceptreadFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.transmitfile = (PRTransmitfileFN)_PSM_InvalidInt; + nsSSLIOLayerMethods.sendfile = (PRSendfileFN)_PSM_InvalidInt; - nsSSLIOLayerMethods.getsockname = PSMGetsockname; - nsSSLIOLayerMethods.getpeername = PSMGetpeername; - nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption; - nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption; - nsSSLIOLayerMethods.recv = PSMRecv; - nsSSLIOLayerMethods.send = PSMSend; - nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue; + nsSSLIOLayerMethods.getsockname = PSMGetsockname; + nsSSLIOLayerMethods.getpeername = PSMGetpeername; + nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption; + nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption; + nsSSLIOLayerMethods.recv = PSMRecv; + nsSSLIOLayerMethods.send = PSMSend; + nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue; - nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect; - nsSSLIOLayerMethods.close = nsSSLIOLayerClose; - nsSSLIOLayerMethods.write = nsSSLIOLayerWrite; - nsSSLIOLayerMethods.read = nsSSLIOLayerRead; - nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll; + nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect; + nsSSLIOLayerMethods.close = nsSSLIOLayerClose; + nsSSLIOLayerMethods.write = nsSSLIOLayerWrite; + nsSSLIOLayerMethods.read = nsSSLIOLayerRead; + nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll; + } mutex = PR_NewLock(); if (!mutex) diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index 21f9c28b9f0..6bb7cea866d 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -248,6 +248,7 @@ public: static nsresult Init(); static void Cleanup(); + static PRBool nsSSLIOLayerInitialized; static PRDescIdentity nsSSLIOLayerIdentity; static PRIOMethods nsSSLIOLayerMethods; diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index 5d0032f0ba9..50fd77e1972 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -79,26 +79,6 @@ #include "nsSSLStatus.h" #include "nsNSSIOLayer.h" -// We must ensure that the nsNSSComponent has been loaded before -// creating any other components. -static void EnsureNSSInitialized(PRBool triggeredByNSSComponent) -{ - static PRBool haveLoaded = PR_FALSE; - if (haveLoaded) - return; - - haveLoaded = PR_TRUE; - - if (triggeredByNSSComponent) { - // We must prevent a recursion, as nsNSSComponent creates - // additional instances - return; - } - - nsCOMPtr nssComponent - = do_GetService(PSM_COMPONENT_CONTRACTID); -} - // These two macros are ripped off from nsIGenericFactory.h and slightly // modified. #define NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(triggeredByNSSComponent, \ @@ -110,7 +90,9 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ nsresult rv; \ _InstanceClass * inst; \ \ - EnsureNSSInitialized(triggeredByNSSComponent); \ + if (!triggeredByNSSComponent && \ + !EnsureNSSInitialized(PR_TRUE)) \ + return NS_ERROR_FAILURE; \ \ *aResult = NULL; \ if (NULL != aOuter) { \ @@ -140,7 +122,9 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ nsresult rv; \ _InstanceClass * inst; \ \ - EnsureNSSInitialized(triggeredByNSSComponent); \ + if (!triggeredByNSSComponent && \ + !EnsureNSSInitialized(PR_TRUE)) \ + return NS_ERROR_FAILURE; \ \ *aResult = NULL; \ if (NULL != aOuter) { \