gecko-dev/security/manager/ssl/nsNSSComponent.h
David Keeler 3961574fa2 bug 1381154 - remove smartcard monitoring threads r=jcj,mgoodwin
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
2017-09-28 14:27:21 -07:00

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_