mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
3961574fa2
Modified from bug 1248818 comment 11: Before this patch, if a user had a smart card (PKCS#11 device) with removable slots, Firefox would launch a thread for each module and loop, calling SECMOD_WaitForAnyTokenEvent to be alerted to any insertions/removals. At shutdown, we would call SECMOD_CancelWait, which would cancel any waiting threads. However, since that involved calling 3rd party code, we really had no idea if these modules were behaving correctly (and, indeed, they often weren't, judging by the shutdown crashes we were getting). The real solution is to stop relying on PKCS#11, but since that's unlikely in the near future, the next best thing would be to load these modules in a child process. That way, misbehaving modules don't cause Firefox to hang/crash/etc. That's a lot of engineering work, though, so what this patch does is avoids the issue by never calling SECMOD_WaitForAnyTokenEvent (and thus we never have to call SECMOD_CancelWait, etc.). Instead, every time Firefox performs an operation that may be affected by a newly added or removed smart card, it first has NSS refresh its view of any removable slots. This is similar to how we ensure the loadable roots module has been loaded (see bug 1372656). MozReview-Commit-ID: JpmLdV7Vvor --HG-- extra : rebase_source : d3503d19fa9297106d661a017a38c30969fa39b4
244 lines
7.4 KiB
C++
244 lines
7.4 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* 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 _nsNSSComponent_h_
|
|
#define _nsNSSComponent_h_
|
|
|
|
#include "ScopedNSSTypes.h"
|
|
#include "SharedCertVerifier.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/Monitor.h"
|
|
#include "mozilla/Mutex.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIObserver.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsNSSCallbacks.h"
|
|
#include "prerror.h"
|
|
#include "sslt.h"
|
|
|
|
#ifdef XP_WIN
|
|
#include "windows.h" // this needs to be before the following includes
|
|
#include "wincrypt.h"
|
|
#endif // XP_WIN
|
|
|
|
class nsIDOMWindow;
|
|
class nsIPrompt;
|
|
class nsIX509CertList;
|
|
class SmartCardThreadList;
|
|
|
|
namespace mozilla { namespace psm {
|
|
|
|
MOZ_MUST_USE
|
|
::already_AddRefed<mozilla::psm::SharedCertVerifier>
|
|
GetDefaultCertVerifier();
|
|
|
|
} } // namespace mozilla::psm
|
|
|
|
|
|
#define NS_NSSCOMPONENT_CID \
|
|
{0x4cb64dfd, 0xca98, 0x4e24, {0xbe, 0xfd, 0x0d, 0x92, 0x85, 0xa3, 0x3b, 0xcb}}
|
|
|
|
#define PSM_COMPONENT_CONTRACTID "@mozilla.org/psm;1"
|
|
|
|
#define NS_INSSCOMPONENT_IID \
|
|
{ 0xa0a8f52b, 0xea18, 0x4abc, \
|
|
{ 0xa3, 0xca, 0xec, 0xcf, 0x70, 0x4f, 0xfe, 0x63 } }
|
|
|
|
extern bool EnsureNSSInitializedChromeOrContent();
|
|
|
|
class NS_NO_VTABLE nsINSSComponent : public nsISupports
|
|
{
|
|
public:
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INSSCOMPONENT_IID)
|
|
|
|
NS_IMETHOD GetPIPNSSBundleString(const char* name,
|
|
nsAString& outString) = 0;
|
|
NS_IMETHOD PIPBundleFormatStringFromName(const char* name,
|
|
const char16_t** params,
|
|
uint32_t numParams,
|
|
nsAString& outString) = 0;
|
|
|
|
NS_IMETHOD GetNSSBundleString(const char* name,
|
|
nsAString& outString) = 0;
|
|
|
|
NS_IMETHOD LogoutAuthenticatedPK11() = 0;
|
|
|
|
#ifdef DEBUG
|
|
NS_IMETHOD IsCertTestBuiltInRoot(CERTCertificate* cert, bool& result) = 0;
|
|
#endif
|
|
|
|
NS_IMETHOD IsCertContentSigningRoot(CERTCertificate* cert, bool& result) = 0;
|
|
|
|
#ifdef XP_WIN
|
|
NS_IMETHOD GetEnterpriseRoots(nsIX509CertList** enterpriseRoots) = 0;
|
|
#endif
|
|
|
|
NS_IMETHOD BlockUntilLoadableRootsLoaded() = 0;
|
|
NS_IMETHOD CheckForSmartCardChanges() = 0;
|
|
|
|
// Main thread only
|
|
NS_IMETHOD HasActiveSmartCards(bool& result) = 0;
|
|
NS_IMETHOD HasUserCertsInstalled(bool& result) = 0;
|
|
|
|
virtual ::already_AddRefed<mozilla::psm::SharedCertVerifier>
|
|
GetDefaultCertVerifier() = 0;
|
|
};
|
|
|
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsINSSComponent, NS_INSSCOMPONENT_IID)
|
|
|
|
class nsNSSShutDownList;
|
|
|
|
// Implementation of the PSM component interface.
|
|
class nsNSSComponent final : public nsINSSComponent
|
|
, public nsIObserver
|
|
{
|
|
public:
|
|
// LoadLoadableRootsTask updates mLoadableRootsLoaded and
|
|
// mLoadableRootsLoadedResult and then signals mLoadableRootsLoadedMonitor.
|
|
friend class LoadLoadableRootsTask;
|
|
|
|
NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
|
|
|
|
nsNSSComponent();
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
nsresult Init();
|
|
|
|
static nsresult GetNewPrompter(nsIPrompt** result);
|
|
|
|
NS_IMETHOD GetPIPNSSBundleString(const char* name,
|
|
nsAString& outString) override;
|
|
NS_IMETHOD PIPBundleFormatStringFromName(const char* name,
|
|
const char16_t** params,
|
|
uint32_t numParams,
|
|
nsAString& outString) override;
|
|
NS_IMETHOD GetNSSBundleString(const char* name, nsAString& outString) override;
|
|
NS_IMETHOD LogoutAuthenticatedPK11() override;
|
|
|
|
#ifdef DEBUG
|
|
NS_IMETHOD IsCertTestBuiltInRoot(CERTCertificate* cert, bool& result) override;
|
|
#endif
|
|
|
|
NS_IMETHOD IsCertContentSigningRoot(CERTCertificate* cert, bool& result) override;
|
|
|
|
#ifdef XP_WIN
|
|
NS_IMETHOD GetEnterpriseRoots(nsIX509CertList** enterpriseRoots) override;
|
|
#endif
|
|
|
|
NS_IMETHOD BlockUntilLoadableRootsLoaded() override;
|
|
NS_IMETHOD CheckForSmartCardChanges() override;
|
|
|
|
// Main thread only
|
|
NS_IMETHOD HasActiveSmartCards(bool& result) override;
|
|
NS_IMETHOD HasUserCertsInstalled(bool& result) override;
|
|
|
|
::already_AddRefed<mozilla::psm::SharedCertVerifier>
|
|
GetDefaultCertVerifier() override;
|
|
|
|
// The following two methods are thread-safe.
|
|
static bool AreAnyWeakCiphersEnabled();
|
|
static void UseWeakCiphersOnSocket(PRFileDesc* fd);
|
|
|
|
static void FillTLSVersionRange(SSLVersionRange& rangeOut,
|
|
uint32_t minFromPrefs,
|
|
uint32_t maxFromPrefs,
|
|
SSLVersionRange defaults);
|
|
|
|
protected:
|
|
virtual ~nsNSSComponent();
|
|
|
|
private:
|
|
nsresult InitializeNSS();
|
|
void ShutdownNSS();
|
|
|
|
void UnloadLoadableRoots();
|
|
void setValidationOptions(bool isInitialSetting);
|
|
nsresult setEnabledTLSVersions();
|
|
nsresult InitializePIPNSSBundle();
|
|
nsresult ConfigureInternalPKCS11Token();
|
|
nsresult RegisterObservers();
|
|
|
|
void MaybeEnableFamilySafetyCompatibility();
|
|
void MaybeImportEnterpriseRoots();
|
|
#ifdef XP_WIN
|
|
void ImportEnterpriseRootsForLocation(
|
|
DWORD locationFlag, const mozilla::MutexAutoLock& proofOfLock);
|
|
nsresult MaybeImportFamilySafetyRoot(PCCERT_CONTEXT certificate,
|
|
bool& wasFamilySafetyRoot);
|
|
nsresult LoadFamilySafetyRoot();
|
|
void UnloadFamilySafetyRoot();
|
|
|
|
void UnloadEnterpriseRoots(const mozilla::MutexAutoLock& proofOfLock);
|
|
#endif // XP_WIN
|
|
|
|
// mLoadableRootsLoadedMonitor protects mLoadableRootsLoaded.
|
|
mozilla::Monitor mLoadableRootsLoadedMonitor;
|
|
bool mLoadableRootsLoaded;
|
|
nsresult mLoadableRootsLoadedResult;
|
|
|
|
// mMutex protects all members that are accessed from more than one thread.
|
|
// While this lock is held, the same thread must not attempt to acquire a
|
|
// nsNSSShutDownPreventionLock (acquiring a nsNSSShutDownPreventionLock and
|
|
// then acquiring this lock is fine).
|
|
mozilla::Mutex mMutex;
|
|
|
|
// The following members are accessed from more than one thread:
|
|
nsCOMPtr<nsIStringBundle> mPIPNSSBundle;
|
|
nsCOMPtr<nsIStringBundle> mNSSErrorsBundle;
|
|
bool mNSSInitialized;
|
|
#ifdef DEBUG
|
|
nsString mTestBuiltInRootHash;
|
|
#endif
|
|
nsString mContentSigningRootHash;
|
|
RefPtr<mozilla::psm::SharedCertVerifier> mDefaultCertVerifier;
|
|
#ifdef XP_WIN
|
|
mozilla::UniqueCERTCertificate mFamilySafetyRoot;
|
|
mozilla::UniqueCERTCertList mEnterpriseRoots;
|
|
#endif // XP_WIN
|
|
|
|
// The following members are accessed only on the main thread:
|
|
static int mInstanceCount;
|
|
};
|
|
|
|
inline nsresult
|
|
BlockUntilLoadableRootsLoaded()
|
|
{
|
|
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
|
|
if (!component) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return component->BlockUntilLoadableRootsLoaded();
|
|
}
|
|
|
|
inline nsresult
|
|
CheckForSmartCardChanges()
|
|
{
|
|
#ifndef MOZ_NO_SMART_CARDS
|
|
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
|
|
if (!component) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return component->CheckForSmartCardChanges();
|
|
#else
|
|
return NS_OK;
|
|
#endif
|
|
}
|
|
|
|
class nsNSSErrors
|
|
{
|
|
public:
|
|
static const char* getDefaultErrorStringName(PRErrorCode err);
|
|
static const char* getOverrideErrorStringName(PRErrorCode aErrorCode);
|
|
static nsresult getErrorMessageFromCode(PRErrorCode err,
|
|
nsINSSComponent* component,
|
|
nsString& returnedMessage);
|
|
};
|
|
|
|
#endif // _nsNSSComponent_h_
|