Serialize SSLTokensCache to ssl_tokens_cache.bin so TLS session tickets survive browser restarts, enabling 0-RTT on first connections. A new Rust crate handles zlib-compressed (Adler-32 integrity) bincode serialization and atomic tmp→rename writes. Cert chain data is excluded from the persisted format. The cache writes to disk when the application is backgrounded (covering Android OOM kills), daily when idle, and at graceful shutdown via nsIAsyncShutdownBlocker, keeping all file I/O off the main thread. The background read uses nsAutoLowPriorityIO to yield disk bandwidth to startup-critical reads. Consumed and evicted tokens are removed from the Rust shadow immediately, bounding its memory use independently of write frequency. The cache is always partitioned by top-level site via OriginAttributes, matching cookie-partitioning semantics. CLEAR_TLS_TOKEN_CACHE is part of CLEAR_COOKIES_AND_SITE_DATA and CLEAR_FORGET_ABOUT_SITE. Differential Revision: https://phabricator.services.mozilla.com/D288348
192 lines
6.7 KiB
C++
192 lines
6.7 KiB
C++
/*
|
|
* 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 "nsINSSComponent.h"
|
|
#ifdef ENABLE_TESTS
|
|
# include "nsISSLTokensCacheTest.h"
|
|
#endif
|
|
|
|
#include "EnterpriseRoots.h"
|
|
#include "ScopedNSSTypes.h"
|
|
#include "SharedCertVerifier.h"
|
|
#include "mozilla/Monitor.h"
|
|
#include "mozilla/Mutex.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIObserver.h"
|
|
#include "nsISerialEventTarget.h"
|
|
#include "nsNSSCallbacks.h"
|
|
#include "nsServiceManagerUtils.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 nsITimer;
|
|
|
|
namespace mozilla {
|
|
namespace psm {
|
|
|
|
[[nodiscard]] ::already_AddRefed<mozilla::psm::SharedCertVerifier>
|
|
GetDefaultCertVerifier();
|
|
UniqueCERTCertList FindClientCertificatesWithPrivateKeys();
|
|
CertVerifier::CertificateTransparencyMode GetCertificateTransparencyMode();
|
|
|
|
} // namespace psm
|
|
} // namespace mozilla
|
|
|
|
#define NS_NSSCOMPONENT_CID \
|
|
{0x4cb64dfd, 0xca98, 0x4e24, {0xbe, 0xfd, 0x0d, 0x92, 0x85, 0xa3, 0x3b, 0xcb}}
|
|
|
|
bool EnsureNSSInitializedChromeOrContent();
|
|
bool HandleTLSPrefChange(const nsCString& aPref);
|
|
void SetValidationOptionsCommon();
|
|
void PrepareForShutdownInSocketProcess();
|
|
|
|
// RAII helper class to indicate that gecko is searching for client auth
|
|
// certificates. Will automatically stop indicating that a search is happening
|
|
// when it goes out of scope.
|
|
// osclientcerts (or ipcclientcerts, in the socket process) will call
|
|
// IsGeckoSearchingForClientAuthCertificates() to determine if gecko is
|
|
// searching for client auth certificates. If so, the module knows to refresh
|
|
// its list of certificates and keys (which can be costly).
|
|
// In theory, two separate threads could both create a
|
|
// AutoSearchingForClientAuthCertificates at overlapping times. If one goes out
|
|
// of scope sooner than the other, IsGeckoSearchingForClientAuthCertificates()
|
|
// could potentially incorrectly return false for the slower thread. However,
|
|
// as long as the faster thread has ensured that osclientcerts/ipcclientcerts
|
|
// has updated its list of known certificates, a second search would be
|
|
// redundant anyway, so it doesn't matter.
|
|
class AutoSearchingForClientAuthCertificates {
|
|
public:
|
|
AutoSearchingForClientAuthCertificates();
|
|
~AutoSearchingForClientAuthCertificates();
|
|
};
|
|
|
|
// Implementation of the PSM component interface.
|
|
class nsNSSComponent final : public nsINSSComponent,
|
|
public nsIObserver
|
|
#ifdef ENABLE_TESTS
|
|
,
|
|
public nsISSLTokensCacheTest
|
|
#endif
|
|
{
|
|
public:
|
|
// LoadLoadableCertsTask updates mLoadableCertsLoaded and
|
|
// mLoadableCertsLoadedResult and then signals mLoadableCertsLoadedMonitor.
|
|
friend class LoadLoadableCertsTask;
|
|
// BackgroundImportEnterpriseCertsTask calls ImportEnterpriseRoots and
|
|
// UpdateCertVerifierWithEnterpriseRoots.
|
|
friend class BackgroundImportEnterpriseCertsTask;
|
|
|
|
nsNSSComponent();
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSINSSCOMPONENT
|
|
NS_DECL_NSIOBSERVER
|
|
#ifdef ENABLE_TESTS
|
|
NS_DECL_NSISSLTOKENSCACHETEST
|
|
#endif
|
|
|
|
nsresult Init();
|
|
|
|
static nsresult GetNewPrompter(nsIPrompt** result);
|
|
|
|
static void FillTLSVersionRange(SSLVersionRange& rangeOut,
|
|
uint32_t minFromPrefs, uint32_t maxFromPrefs,
|
|
SSLVersionRange defaults);
|
|
|
|
static nsresult SetEnabledTLSVersions();
|
|
|
|
// This function does the actual work of clearing the session cache. It is to
|
|
// be used by the socket process (where there is no nsINSSComponent) and
|
|
// internally by nsNSSComponent.
|
|
// NB: NSS must have already been initialized before this is called.
|
|
static void DoClearSSLExternalAndInternalSessionCache();
|
|
|
|
protected:
|
|
~nsNSSComponent();
|
|
|
|
private:
|
|
nsresult InitializeNSS();
|
|
void PrepareForShutdown();
|
|
|
|
void setValidationOptions(const mozilla::MutexAutoLock& proofOfLock);
|
|
void GetRevocationBehaviorFromPrefs(
|
|
/*out*/ mozilla::psm::CertVerifier::OcspDownloadConfig* odc,
|
|
/*out*/ mozilla::psm::CertVerifier::OcspStrictConfig* osc,
|
|
/*out*/ uint32_t* certShortLifetimeInDays,
|
|
/*out*/ TimeDuration& softTimeout,
|
|
/*out*/ TimeDuration& hardTimeout);
|
|
void UpdateCertVerifierWithEnterpriseRoots();
|
|
nsresult RegisterObservers();
|
|
|
|
void MaybeImportEnterpriseRoots();
|
|
void ImportEnterpriseRoots();
|
|
void UnloadEnterpriseRoots();
|
|
nsresult CommonGetEnterpriseCerts(
|
|
nsTArray<nsTArray<uint8_t>>& enterpriseCerts, bool getRoots);
|
|
|
|
// mLoadableCertsLoadedMonitor protects mLoadableCertsLoaded.
|
|
mozilla::Monitor mLoadableCertsLoadedMonitor;
|
|
bool mLoadableCertsLoaded MOZ_GUARDED_BY(mLoadableCertsLoadedMonitor);
|
|
nsresult mLoadableCertsLoadedResult
|
|
MOZ_GUARDED_BY(mLoadableCertsLoadedMonitor);
|
|
|
|
// mMutex protects all members that are accessed from more than one thread.
|
|
mozilla::Mutex mMutex;
|
|
|
|
// The following members are accessed from more than one thread:
|
|
|
|
#ifdef DEBUG
|
|
nsCString mTestBuiltInRootHash MOZ_GUARDED_BY(mMutex);
|
|
#endif
|
|
RefPtr<mozilla::psm::SharedCertVerifier> mDefaultCertVerifier
|
|
MOZ_GUARDED_BY(mMutex);
|
|
nsString mMitmCanaryIssuer MOZ_GUARDED_BY(mMutex);
|
|
bool mMitmDetecionEnabled MOZ_GUARDED_BY(mMutex);
|
|
nsTArray<EnterpriseCert> mEnterpriseCerts MOZ_GUARDED_BY(mMutex);
|
|
|
|
// The following members are accessed only on the main thread:
|
|
static int mInstanceCount;
|
|
// A serial event target used primarily for operations that modify the NSS
|
|
// module DB. Using this queue for all such tasks avoids threading issues in
|
|
// NSS.
|
|
nsCOMPtr<nsISerialEventTarget> mNSSTaskQueue;
|
|
};
|
|
|
|
inline nsresult BlockUntilLoadableCertsLoaded() {
|
|
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
|
|
if (!component) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return component->BlockUntilLoadableCertsLoaded();
|
|
}
|
|
|
|
// In theory a token on a PKCS#11 module can be inserted or removed at any
|
|
// time. Operations that may depend on resources on external tokens should call
|
|
// this to ensure they have a recent view of the token.
|
|
nsresult CheckForSmartCardChanges();
|
|
|
|
// Gets the path to the current profile as a string in a way that NSS can make
|
|
// use of it. In particular, uses UTF-8 file paths on Windows (regardless of
|
|
// the current system code page), because that's what SQLite (which provides
|
|
// NSS' storage) requires.
|
|
nsresult GetNSSProfilePath(nsAutoCString& aProfilePath);
|
|
|
|
// Helper to determine if the platform is in safe mode or not. Conservatively
|
|
// defaults to `true` if no nsIXULRuntime is available.
|
|
bool GetInSafeMode();
|
|
|
|
#endif // _nsNSSComponent_h_
|