Autogenerated with:
cp dom/.clang-format netwerk/ && mach format netwerk/**.{cpp,h,mm}
Manual fixes:
* mozurl/cbindgen.toml (including headers earlier)
* NetlinkService.h (forward-declaring a necessary struct)
* nsIWebSocketChannel.idl (forward-declaring OriginAttributes).
* nsAsyncRedirectVerifyHelper.h (forward-declaring nsIEventTarget)
* CapsuleEncoder.h gets a missing Capsule forward-decl.
* WebSocketConnectionBase.h gets some missing includes.
* HappyEyeballsConnectionAttempt gets some missing includes.
* nsUDPSocket missed nsSocketTransportService2.h for OnSocketThread().
* HttpInfo missed a forward declaration.
* MockHttpAuth missed an nsCOMPtr include.
* nsHttpAuthManager missed a forward declaration for nsIHttpAuthCache.
* WebTransportSessionProxy was using mozilla::Mutex in a member without
including it.
* win32 fixes to keep include order because windows headers suck.
* nsInputStreamPump needs an Atomics.h include.
Differential Revision: https://phabricator.services.mozilla.com/D311696
240 lines
9.3 KiB
C++
240 lines
9.3 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 SSLTokensCache_h_
|
|
#define SSLTokensCache_h_
|
|
|
|
#include "CertVerifier.h" // For EVStatus
|
|
#include "mozilla/Maybe.h"
|
|
#include "mozilla/OriginAttributes.h"
|
|
#include "mozilla/Span.h"
|
|
#include "mozilla/StaticMutex.h"
|
|
#include "mozilla/StaticPrefs_network.h"
|
|
#include "mozilla/StaticPtr.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
#include "nsClassHashtable.h"
|
|
#include "nsIAsyncShutdown.h"
|
|
#include "nsIFile.h"
|
|
#include "nsIMemoryReporter.h"
|
|
#include "nsIObserver.h"
|
|
#include "nsISerialEventTarget.h"
|
|
#include "nsISupportsImpl.h"
|
|
#include "nsITransportSecurityInfo.h"
|
|
#include "nsTArray.h"
|
|
#include "nsTHashMap.h"
|
|
#include "nsXULAppAPI.h"
|
|
|
|
class CommonSocketControl;
|
|
struct SslTokensPersistedRecord;
|
|
|
|
namespace mozilla {
|
|
namespace ipc {
|
|
class ByteBuf;
|
|
}
|
|
} // namespace mozilla
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
struct SessionCacheInfo {
|
|
SessionCacheInfo Clone() const;
|
|
|
|
psm::EVStatus mEVStatus = psm::EVStatus::NotEV;
|
|
uint16_t mCertificateTransparencyStatus =
|
|
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE;
|
|
nsTArray<uint8_t> mServerCertBytes;
|
|
Maybe<nsTArray<nsTArray<uint8_t>>> mSucceededCertChainBytes;
|
|
Maybe<bool> mIsBuiltCertChainRootBuiltInRoot;
|
|
nsITransportSecurityInfo::OverridableErrorCategory mOverridableErrorCategory;
|
|
Maybe<nsTArray<nsTArray<uint8_t>>> mHandshakeCertificatesBytes;
|
|
};
|
|
|
|
class SSLTokensCache : public nsIMemoryReporter,
|
|
public nsIObserver,
|
|
public nsIAsyncShutdownBlocker {
|
|
public:
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSIMEMORYREPORTER
|
|
NS_DECL_NSIOBSERVER
|
|
NS_DECL_NSIASYNCSHUTDOWNBLOCKER
|
|
|
|
friend class ExpirationComparator;
|
|
|
|
static nsresult Init();
|
|
static nsresult Shutdown();
|
|
|
|
static nsresult Put(const nsACString& aKey, const uint8_t* aToken,
|
|
uint32_t aTokenLen, CommonSocketControl* aSocketControl);
|
|
static nsresult Put(const nsACString& aKey, const uint8_t* aToken,
|
|
uint32_t aTokenLen, CommonSocketControl* aSocketControl,
|
|
PRTime aExpirationTime);
|
|
static nsresult Get(const nsACString& aKey, nsTArray<uint8_t>& aToken,
|
|
SessionCacheInfo& aResult, uint64_t* aTokenId = nullptr);
|
|
static nsresult Remove(const nsACString& aKey, uint64_t aId);
|
|
static nsresult RemoveAll(const nsACString& aKey);
|
|
static void Clear();
|
|
static void RemoveByHostAndOAPattern(
|
|
const nsACString& aHost, const mozilla::OriginAttributesPattern& aPattern)
|
|
MOZ_EXCLUDES(sLock);
|
|
static void RemoveBySiteAndOAPattern(
|
|
const nsACString& aSite, const mozilla::OriginAttributesPattern& aPattern)
|
|
MOZ_EXCLUDES(sLock);
|
|
|
|
// Serialize the current cache state into STCF format for IPC transport.
|
|
static nsTArray<uint8_t> SerializeForIPC();
|
|
|
|
// Replace the cache with STCF data received via IPC.
|
|
static void DeserializeFromIPC(mozilla::Span<const uint8_t> aData);
|
|
// Dispatches DeserializeFromIPC to a background thread; no-ops on empty buf.
|
|
static void DeserializeFromIPCAsync(mozilla::ipc::ByteBuf&& aBuf);
|
|
|
|
#ifdef ENABLE_TESTS
|
|
// Test-only helpers.
|
|
static void TriggerWriteForTest(const nsACString& aPath);
|
|
static void LoadForTest(const nsACString& aPath);
|
|
static uint32_t CountForTest();
|
|
static void PutForTest(const nsACString& aKey);
|
|
static uint32_t CacheSizeForTest();
|
|
#endif
|
|
|
|
private:
|
|
class TokenCacheRecord; // defined below
|
|
|
|
SSLTokensCache();
|
|
virtual ~SSLTokensCache();
|
|
|
|
nsresult RemoveLocked(const nsACString& aKey, uint64_t aId)
|
|
MOZ_REQUIRES(sLock);
|
|
nsresult RemoveAllLocked(const nsACString& aKey) MOZ_REQUIRES(sLock);
|
|
// Extracts the first valid (non-expired) record for aKey, updating
|
|
// mCacheSize and mExpirationArray. Sets *aTokenId if non-null.
|
|
// Returns the owned record on hit, nullptr on miss.
|
|
UniquePtr<TokenCacheRecord> GetRecordLocked(const nsACString& aKey,
|
|
uint64_t* aTokenId)
|
|
MOZ_REQUIRES(sLock);
|
|
|
|
void EvictIfNecessary() MOZ_REQUIRES(sLock);
|
|
void LogStats() MOZ_REQUIRES(sLock);
|
|
void ClearCacheLocked() MOZ_REQUIRES(sLock);
|
|
// Returns true if a token for aKey with aOverridableError should be
|
|
// persisted to disk (not PBM and no cert-error override).
|
|
static bool ShouldPersistKey(const nsACString& aKey,
|
|
uint8_t aOverridableError);
|
|
|
|
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
|
MOZ_REQUIRES(sLock);
|
|
|
|
static mozilla::StaticRefPtr<SSLTokensCache> gInstance MOZ_GUARDED_BY(sLock);
|
|
static StaticMutex sLock;
|
|
static uint64_t sRecordId MOZ_GUARDED_BY(sLock);
|
|
|
|
uint32_t mCacheSize MOZ_GUARDED_BY(sLock){0};
|
|
|
|
// Persistence state (parent process only)
|
|
bool mWriteObserversRegistered MOZ_GUARDED_BY(sLock){false};
|
|
nsCOMPtr<nsIFile> mBackingFile MOZ_GUARDED_BY(sLock);
|
|
nsCOMPtr<nsISerialEventTarget> mWriteTaskQueue MOZ_GUARDED_BY(sLock);
|
|
bool mLoadComplete MOZ_GUARDED_BY(sLock){false};
|
|
TimeStamp mLoadStartTime MOZ_GUARDED_BY(sLock);
|
|
// Bumped by Clear() to invalidate in-flight background loads.
|
|
uint32_t mLoadGeneration MOZ_GUARDED_BY(sLock){0};
|
|
void DoWrite(bool aSynchronous) MOZ_EXCLUDES(sLock);
|
|
void RegisterShutdownBlocker() MOZ_EXCLUDES(sLock);
|
|
void RemoveShutdownBlocker() MOZ_EXCLUDES(sLock);
|
|
nsCOMPtr<nsIAsyncShutdownClient> mShutdownBarrier MOZ_GUARDED_BY(sLock);
|
|
// Sets up gInstance's mBackingFile/mWriteTaskQueue and captures load
|
|
// timing. Returns the path to load on success, empty if ProfD is
|
|
// unavailable. Parent-process only; caller must hold sLock and have
|
|
// verified mBackingFile is not yet set.
|
|
static nsCString SetupPersistenceLocked(uint32_t& aLoadGen)
|
|
MOZ_REQUIRES(sLock);
|
|
static void DispatchLoad(nsCString aPath, uint32_t aLoadGen);
|
|
static void OnLoadCompleteNotify(uint32_t aCount);
|
|
// aExpectedGen: mLoadGeneration captured at load start; insertion is skipped
|
|
// if Clear() has run since (generation mismatch).
|
|
// Returns true if the record was inserted, false if skipped (generation
|
|
// mismatch after a concurrent Clear()).
|
|
static bool PutFromPersisted(const SslTokensPersistedRecord* aRec,
|
|
uint32_t aExpectedGen);
|
|
|
|
struct LoadCtx {
|
|
uint32_t loadGen;
|
|
uint32_t count = 0;
|
|
};
|
|
static void LoadCallback(void* aCtx, const SslTokensPersistedRecord* aRec);
|
|
static nsDependentCSubstring BasePartFromKey(const nsACString& aKey);
|
|
static nsDependentCSubstring HostFromBasePart(
|
|
const nsDependentCSubstring& aBasePart);
|
|
static OriginAttributes OAFromPeerId(const nsACString& aPeerId);
|
|
static void RemoveByMatchAndOAPattern(
|
|
const nsACString& aValue, const nsACString& aSeparatedValue,
|
|
const mozilla::OriginAttributesPattern& aPattern) MOZ_EXCLUDES(sLock);
|
|
|
|
// Builds a snapshot of all currently cached records that should be
|
|
// persisted (filtered by ShouldPersistKey). Each snapshot record
|
|
// borrows the token bytes via raw pointer (valid only while sLock is
|
|
// held); cert chain fields are cloned so the snapshot owns them.
|
|
nsTArray<SslTokensPersistedRecord> CollectSnapshotLocked() const
|
|
MOZ_REQUIRES(sLock);
|
|
static nsTArray<uint8_t> SerializeSnapshotLocked() MOZ_REQUIRES(sLock);
|
|
// Removes entries matching aPredicate.
|
|
template <typename Pred>
|
|
void RemoveMatchingLocked(Pred&& aPredicate) MOZ_REQUIRES(sLock);
|
|
// FFI callback used by LoadForTest.
|
|
static void PutFromPersistedCallback(void*,
|
|
const SslTokensPersistedRecord* aRec);
|
|
|
|
class TokenCacheRecord {
|
|
public:
|
|
~TokenCacheRecord();
|
|
|
|
uint32_t Size() const;
|
|
|
|
nsCString mKey;
|
|
PRTime mExpirationTime = 0;
|
|
// Compressed (token || serialized SessionCacheInfo). Storing them together
|
|
// lets the compressor find redundancies across the NSS token and the cert
|
|
// chain fields (both carry the same cert DER).
|
|
nsTArray<uint8_t> mCompressedPayload;
|
|
// Cached separately to allow ShouldPersistKey() filtering without
|
|
// decompressing the payload.
|
|
uint8_t mOverridableError = 0;
|
|
uint64_t mId = 0;
|
|
};
|
|
|
|
class TokenCacheEntry {
|
|
public:
|
|
uint32_t Size() const;
|
|
// Add a record into |mRecords|. To make sure |mRecords| is sorted, we
|
|
// iterate |mRecords| everytime to find a right place to insert the new
|
|
// record.
|
|
void AddRecord(UniquePtr<TokenCacheRecord>&& aRecord,
|
|
nsTArray<TokenCacheRecord*>& aExpirationArray);
|
|
// This function returns the first record in |mRecords|.
|
|
const UniquePtr<TokenCacheRecord>& Get();
|
|
UniquePtr<TokenCacheRecord> RemoveWithId(uint64_t aId);
|
|
uint32_t RecordCount() const { return mRecords.Length(); }
|
|
const nsTArray<UniquePtr<TokenCacheRecord>>& Records() const {
|
|
return mRecords;
|
|
}
|
|
|
|
private:
|
|
// The records in this array are ordered by the expiration time.
|
|
nsTArray<UniquePtr<TokenCacheRecord>> mRecords;
|
|
};
|
|
|
|
void OnRecordDestroyed(TokenCacheRecord* aRec) MOZ_REQUIRES(sLock);
|
|
uint64_t InsertRecordLocked(UniquePtr<TokenCacheRecord> aRec)
|
|
MOZ_REQUIRES(sLock);
|
|
|
|
nsClassHashtable<nsCStringHashKey, TokenCacheEntry> mTokenCacheRecords
|
|
MOZ_GUARDED_BY(sLock);
|
|
nsTArray<TokenCacheRecord*> mExpirationArray MOZ_GUARDED_BY(sLock);
|
|
};
|
|
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#endif // SSLTokensCache_h_
|