Bug 1876574 - Add SameSite bit to partition-key origin attribute for first-party partitioning - r=timhuang

This patch is a no-op for observable functionality. All it does is add a bit to the partitionKey for OA, and then adds plumbing to be able to set it, and where it is required, sets it to false.
This is serialized identically to the absence of the bit, so nothing changes at all.

Differential Revision: https://phabricator.services.mozilla.com/D203155
This commit is contained in:
Benjamin VanderSloot
2024-03-29 17:12:12 +00:00
parent dcc22863d4
commit 13ffd24df0
13 changed files with 215 additions and 70 deletions

View File

@@ -22,8 +22,8 @@ static const char kSanitizedChar = '+';
namespace mozilla { namespace mozilla {
static void MakeTopLevelInfo(const nsACString& aScheme, const nsACString& aHost, static void MakeTopLevelInfo(const nsACString& aScheme, const nsACString& aHost,
int32_t aPort, bool aUseSite, int32_t aPort, bool aForeignByAncestorContext,
nsAString& aTopLevelInfo) { bool aUseSite, nsAString& aTopLevelInfo) {
if (!aUseSite) { if (!aUseSite) {
aTopLevelInfo.Assign(NS_ConvertUTF8toUTF16(aHost)); aTopLevelInfo.Assign(NS_ConvertUTF8toUTF16(aHost));
return; return;
@@ -41,19 +41,26 @@ static void MakeTopLevelInfo(const nsACString& aScheme, const nsACString& aHost,
site.Append(","); site.Append(",");
site.AppendInt(aPort); site.AppendInt(aPort);
} }
if (aForeignByAncestorContext) {
site.Append(",f");
}
site.AppendLiteral(")"); site.AppendLiteral(")");
aTopLevelInfo.Assign(NS_ConvertUTF8toUTF16(site)); aTopLevelInfo.Assign(NS_ConvertUTF8toUTF16(site));
} }
static void MakeTopLevelInfo(const nsACString& aScheme, const nsACString& aHost, static void MakeTopLevelInfo(const nsACString& aScheme, const nsACString& aHost,
bool aUseSite, nsAString& aTopLevelInfo) { bool aForeignByAncestorContext, bool aUseSite,
MakeTopLevelInfo(aScheme, aHost, -1, aUseSite, aTopLevelInfo); nsAString& aTopLevelInfo) {
MakeTopLevelInfo(aScheme, aHost, -1, aForeignByAncestorContext, aUseSite,
aTopLevelInfo);
} }
static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument, static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
nsIURI* aURI, bool aIsFirstPartyEnabled, nsIURI* aURI,
bool aForced, bool aUseSite, bool aForeignByAncestorContext,
bool aIsFirstPartyEnabled, bool aForced,
bool aUseSite,
nsString OriginAttributes::*aTarget, nsString OriginAttributes::*aTarget,
OriginAttributes& aOriginAttributes) { OriginAttributes& aOriginAttributes) {
nsresult rv; nsresult rv;
@@ -86,7 +93,7 @@ static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
if (scheme.EqualsLiteral("about")) { if (scheme.EqualsLiteral("about")) {
MakeTopLevelInfo(scheme, nsLiteralCString(ABOUT_URI_FIRST_PARTY_DOMAIN), MakeTopLevelInfo(scheme, nsLiteralCString(ABOUT_URI_FIRST_PARTY_DOMAIN),
aUseSite, topLevelInfo); aForeignByAncestorContext, aUseSite, topLevelInfo);
return; return;
} }
@@ -128,7 +135,8 @@ static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
nsAutoCString baseDomain; nsAutoCString baseDomain;
rv = tldService->GetBaseDomain(uri, 0, baseDomain); rv = tldService->GetBaseDomain(uri, 0, baseDomain);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
MakeTopLevelInfo(scheme, baseDomain, aUseSite, topLevelInfo); MakeTopLevelInfo(scheme, baseDomain, aForeignByAncestorContext, aUseSite,
topLevelInfo);
return; return;
} }
@@ -160,12 +168,14 @@ static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
ipAddr = host; ipAddr = host;
} }
MakeTopLevelInfo(scheme, ipAddr, port, aUseSite, topLevelInfo); MakeTopLevelInfo(scheme, ipAddr, port, aForeignByAncestorContext, aUseSite,
topLevelInfo);
return; return;
} }
if (aUseSite) { if (aUseSite) {
MakeTopLevelInfo(scheme, host, port, aUseSite, topLevelInfo); MakeTopLevelInfo(scheme, host, port, aForeignByAncestorContext, aUseSite,
topLevelInfo);
return; return;
} }
@@ -173,7 +183,8 @@ static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
nsAutoCString publicSuffix; nsAutoCString publicSuffix;
rv = tldService->GetPublicSuffix(uri, publicSuffix); rv = tldService->GetPublicSuffix(uri, publicSuffix);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
MakeTopLevelInfo(scheme, publicSuffix, port, aUseSite, topLevelInfo); MakeTopLevelInfo(scheme, publicSuffix, port, aForeignByAncestorContext,
aUseSite, topLevelInfo);
return; return;
} }
} }
@@ -182,7 +193,7 @@ static void PopulateTopLevelInfoFromURI(const bool aIsTopLevelDocument,
void OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument, void OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument,
nsIURI* aURI, bool aForced) { nsIURI* aURI, bool aForced) {
PopulateTopLevelInfoFromURI( PopulateTopLevelInfoFromURI(
aIsTopLevelDocument, aURI, IsFirstPartyEnabled(), aForced, aIsTopLevelDocument, aURI, false, IsFirstPartyEnabled(), aForced,
StaticPrefs::privacy_firstparty_isolate_use_site(), StaticPrefs::privacy_firstparty_isolate_use_site(),
&OriginAttributes::mFirstPartyDomain, *this); &OriginAttributes::mFirstPartyDomain, *this);
} }
@@ -203,19 +214,21 @@ void OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument,
mFirstPartyDomain = aDomain; mFirstPartyDomain = aDomain;
} }
void OriginAttributes::SetPartitionKey(nsIURI* aURI) { void OriginAttributes::SetPartitionKey(nsIURI* aURI,
bool aForeignByAncestorContext) {
PopulateTopLevelInfoFromURI( PopulateTopLevelInfoFromURI(
false /* aIsTopLevelDocument */, aURI, IsFirstPartyEnabled(), false /* aIsTopLevelDocument */, aURI, aForeignByAncestorContext,
true /* aForced */, StaticPrefs::privacy_dynamic_firstparty_use_site(), IsFirstPartyEnabled(), true /* aForced */,
StaticPrefs::privacy_dynamic_firstparty_use_site(),
&OriginAttributes::mPartitionKey, *this); &OriginAttributes::mPartitionKey, *this);
} }
void OriginAttributes::SetPartitionKey(const nsACString& aDomain) { void OriginAttributes::SetPartitionKey(const nsACString& aOther) {
SetPartitionKey(NS_ConvertUTF8toUTF16(aDomain)); SetPartitionKey(NS_ConvertUTF8toUTF16(aOther));
} }
void OriginAttributes::SetPartitionKey(const nsAString& aDomain) { void OriginAttributes::SetPartitionKey(const nsAString& aOther) {
mPartitionKey = aDomain; mPartitionKey = aOther;
} }
void OriginAttributes::CreateSuffix(nsACString& aStr) const { void OriginAttributes::CreateSuffix(nsACString& aStr) const {
@@ -419,17 +432,20 @@ bool OriginAttributes::IsPrivateBrowsing(const nsACString& aOrigin) {
bool OriginAttributes::ParsePartitionKey(const nsAString& aPartitionKey, bool OriginAttributes::ParsePartitionKey(const nsAString& aPartitionKey,
nsAString& outScheme, nsAString& outScheme,
nsAString& outBaseDomain, nsAString& outBaseDomain,
int32_t& outPort) { int32_t& outPort,
bool& outForeignByAncestorContext) {
outScheme.Truncate(); outScheme.Truncate();
outBaseDomain.Truncate(); outBaseDomain.Truncate();
outPort = -1; outPort = -1;
outForeignByAncestorContext = false;
// Partition keys have the format "(<scheme>,<baseDomain>,[port])". The port // Partition keys have the format
// is optional. For example: "(https,example.com,8443)" or // "(<scheme>,<baseDomain>[,port][,foreignancestorbit])". The port and
// "(http,example.org)". // ancestor bits are optional. For example: "(https,example.com,8443)" or
// When privacy.dynamic_firstparty.use_site = false, the partitionKey contains // "(http,example.org)", or "(http,example.info,f)", or
// only the host, e.g. "example.com". // "(http,example.biz,8443,f)". When privacy.dynamic_firstparty.use_site =
// See MakeTopLevelInfo for the partitionKey serialization code. // false, the partitionKey contains only the host, e.g. "example.com". See
// MakeTopLevelInfo for the partitionKey serialization code.
if (aPartitionKey.IsEmpty()) { if (aPartitionKey.IsEmpty()) {
return true; return true;
@@ -466,14 +482,27 @@ bool OriginAttributes::ParsePartitionKey(const nsAString& aPartitionKey,
} else if (fieldIndex == 1) { } else if (fieldIndex == 1) {
outBaseDomain.Assign(field); outBaseDomain.Assign(field);
} else if (fieldIndex == 2) { } else if (fieldIndex == 2) {
// Parse the port which is represented in the partitionKey string as a // The first optional argument is either "f" or a port number
// decimal (base 10) number. if (field.EqualsLiteral("f")) {
long port = strtol(NS_ConvertUTF16toUTF8(field).get(), nullptr, 10); outForeignByAncestorContext = true;
// Invalid port. } else {
if (NS_WARN_IF(port == 0)) { // Parse the port which is represented in the partitionKey string as a
// decimal (base 10) number.
long port = strtol(NS_ConvertUTF16toUTF8(field).get(), nullptr, 10);
// Invalid port.
if (NS_WARN_IF(port == 0)) {
return false;
}
outPort = static_cast<int32_t>(port);
}
} else if (fieldIndex == 3) {
// The second optional argument, if it exists, is "f" and the first
// optional argument was a port
if (field.EqualsLiteral("f") || outPort == -1) {
NS_WARNING("Invalid partitionKey. Invalid token.");
return false; return false;
} }
outPort = static_cast<int32_t>(port); outForeignByAncestorContext = true;
} else { } else {
NS_WARNING("Invalid partitionKey. Too many tokens"); NS_WARNING("Invalid partitionKey. Too many tokens");
return false; return false;

View File

@@ -27,9 +27,9 @@ class OriginAttributes : public dom::OriginAttributesDictionary {
void SetFirstPartyDomain(const bool aIsTopLevelDocument, void SetFirstPartyDomain(const bool aIsTopLevelDocument,
const nsAString& aDomain, bool aForced = false); const nsAString& aDomain, bool aForced = false);
void SetPartitionKey(nsIURI* aURI); void SetPartitionKey(nsIURI* aURI, bool aForeignByAncestorContext);
void SetPartitionKey(const nsACString& aDomain); void SetPartitionKey(const nsACString& aOther);
void SetPartitionKey(const nsAString& aDomain); void SetPartitionKey(const nsAString& aOther);
enum { enum {
STRIP_FIRST_PARTY_DOMAIN = 0x01, STRIP_FIRST_PARTY_DOMAIN = 0x01,
@@ -129,13 +129,13 @@ class OriginAttributes : public dom::OriginAttributesDictionary {
// different than 0. // different than 0.
static bool IsPrivateBrowsing(const nsACString& aOrigin); static bool IsPrivateBrowsing(const nsACString& aOrigin);
// Parse a partitionKey of the format "(<scheme>,<baseDomain>,[port])" into // Parse a partitionKey of the format
// its components. // "(<scheme>,<baseDomain>,[port],[ancestorbit])" into its components. Returns
// Returns false if the partitionKey cannot be parsed because the format is // false if the partitionKey cannot be parsed because the format is invalid.
// invalid.
static bool ParsePartitionKey(const nsAString& aPartitionKey, static bool ParsePartitionKey(const nsAString& aPartitionKey,
nsAString& outScheme, nsAString& outBaseDomain, nsAString& outScheme, nsAString& outBaseDomain,
int32_t& outPort); int32_t& outPort,
bool& outForeignByAncestorContext);
}; };
class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary { class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
@@ -193,8 +193,9 @@ class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
nsString scheme; nsString scheme;
nsString baseDomain; nsString baseDomain;
int32_t port; int32_t port;
bool ancestor;
bool success = OriginAttributes::ParsePartitionKey( bool success = OriginAttributes::ParsePartitionKey(
aAttrs.mPartitionKey, scheme, baseDomain, port); aAttrs.mPartitionKey, scheme, baseDomain, port, ancestor);
if (!success) { if (!success) {
return false; return false;
} }
@@ -210,6 +211,10 @@ class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
if (pkPattern.mPort.WasPassed() && pkPattern.mPort.Value() != port) { if (pkPattern.mPort.WasPassed() && pkPattern.mPort.Value() != port) {
return false; return false;
} }
if (pkPattern.mForeignByAncestorContext.WasPassed() &&
pkPattern.mForeignByAncestorContext.Value() != ancestor) {
return false;
}
} }
} }
@@ -262,6 +267,12 @@ class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary {
self.mPort.Value() != other.mPort.Value()) { self.mPort.Value() != other.mPort.Value()) {
return false; return false;
} }
if (self.mForeignByAncestorContext.WasPassed() &&
other.mForeignByAncestorContext.WasPassed() &&
self.mForeignByAncestorContext.Value() !=
other.mForeignByAncestorContext.Value()) {
return false;
}
} }
return true; return true;

View File

@@ -1289,9 +1289,10 @@ void ChromeUtils::GetBaseDomainFromPartitionKey(dom::GlobalObject& aGlobal,
nsString scheme; nsString scheme;
nsString pkBaseDomain; nsString pkBaseDomain;
int32_t port; int32_t port;
bool ancestor;
if (!mozilla::OriginAttributes::ParsePartitionKey(aPartitionKey, scheme, if (!mozilla::OriginAttributes::ParsePartitionKey(
pkBaseDomain, port)) { aPartitionKey, scheme, pkBaseDomain, port, ancestor)) {
aRv.Throw(NS_ERROR_FAILURE); aRv.Throw(NS_ERROR_FAILURE);
return; return;
} }
@@ -1317,7 +1318,10 @@ void ChromeUtils::GetPartitionKeyFromURL(dom::GlobalObject& aGlobal,
} }
mozilla::OriginAttributes attrs; mozilla::OriginAttributes attrs;
attrs.SetPartitionKey(uri); // For now, uses assume the partition key is cross-site.
// We will need to not make this assumption to allow access
// to same-site partitioned cookies in the cookie extension API.
attrs.SetPartitionKey(uri, false);
aPartitionKey = attrs.mPartitionKey; aPartitionKey = attrs.mPartitionKey;
} }

View File

@@ -975,6 +975,7 @@ dictionary PartitionKeyPatternDictionary {
DOMString scheme; DOMString scheme;
DOMString baseDomain; DOMString baseDomain;
long port; long port;
boolean foreignByAncestorContext;
}; };
dictionary CompileScriptOptionsDictionary { dictionary CompileScriptOptionsDictionary {

View File

@@ -544,10 +544,11 @@ nsresult ServiceWorkerPrivate::Initialize() {
nsAutoString scheme; nsAutoString scheme;
nsAutoString pkBaseDomain; nsAutoString pkBaseDomain;
int32_t unused; int32_t unused;
bool unused2;
if (OriginAttributes::ParsePartitionKey( if (OriginAttributes::ParsePartitionKey(
principal->OriginAttributesRef().mPartitionKey, scheme, principal->OriginAttributesRef().mPartitionKey, scheme,
pkBaseDomain, unused)) { pkBaseDomain, unused, unused2)) {
nsCOMPtr<nsIURI> firstPartyURI; nsCOMPtr<nsIURI> firstPartyURI;
rv = NS_NewURI(getter_AddRefs(firstPartyURI), rv = NS_NewURI(getter_AddRefs(firstPartyURI),
scheme + u"://"_ns + pkBaseDomain); scheme + u"://"_ns + pkBaseDomain);
@@ -592,7 +593,8 @@ nsresult ServiceWorkerPrivate::Initialize() {
} }
} }
} else { } else {
net::CookieJarSettings::Cast(cookieJarSettings)->SetPartitionKey(uri); net::CookieJarSettings::Cast(cookieJarSettings)
->SetPartitionKey(uri, false);
// The service worker is for a first-party context, we can use the uri of // The service worker is for a first-party context, we can use the uri of
// the service worker as the first-party domain to get the fingerprinting // the service worker as the first-party domain to get the fingerprinting

View File

@@ -678,7 +678,8 @@ nsresult CompareNetwork::Initialize(nsIPrincipal* aPrincipal,
net::CookieJarSettings::Cast(cookieJarSettings) net::CookieJarSettings::Cast(cookieJarSettings)
->SetPartitionKey(aPrincipal->OriginAttributesRef().mPartitionKey); ->SetPartitionKey(aPrincipal->OriginAttributesRef().mPartitionKey);
} else { } else {
net::CookieJarSettings::Cast(cookieJarSettings)->SetPartitionKey(uri); net::CookieJarSettings::Cast(cookieJarSettings)
->SetPartitionKey(uri, false);
} }
// Note that because there is no "serviceworker" RequestContext type, we can // Note that because there is no "serviceworker" RequestContext type, we can

View File

@@ -15,6 +15,7 @@
#include "mozilla/PermissionManager.h" #include "mozilla/PermissionManager.h"
#include "mozilla/SchedulerGroup.h" #include "mozilla/SchedulerGroup.h"
#include "mozilla/StaticPrefs_network.h" #include "mozilla/StaticPrefs_network.h"
#include "mozilla/StoragePrincipalHelper.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
@@ -196,7 +197,7 @@ CookieJarSettings::InitWithURI(nsIURI* aURI, bool aIsPrivate) {
mCookieBehavior = nsICookieManager::GetCookieBehavior(aIsPrivate); mCookieBehavior = nsICookieManager::GetCookieBehavior(aIsPrivate);
SetPartitionKey(aURI); SetPartitionKey(aURI, false);
return NS_OK; return NS_OK;
} }
@@ -526,14 +527,26 @@ void CookieJarSettings::Merge(const CookieJarSettingsArgs& aData) {
} }
} }
void CookieJarSettings::SetPartitionKey(nsIURI* aURI) { void CookieJarSettings::SetPartitionKey(nsIURI* aURI,
bool aForeignByAncestorContext) {
MOZ_ASSERT(aURI); MOZ_ASSERT(aURI);
OriginAttributes attrs; OriginAttributes attrs;
attrs.SetPartitionKey(aURI); attrs.SetPartitionKey(aURI, aForeignByAncestorContext);
mPartitionKey = std::move(attrs.mPartitionKey); mPartitionKey = std::move(attrs.mPartitionKey);
} }
void CookieJarSettings::UpdatePartitionKeyForDocumentLoadedByChannel(
nsIChannel* aChannel) {
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
bool foreignByAncestorContext =
false; // Bug 1876575 will change this to
// loadInfo->GetIsInThirdPartyContext() &&
// !loadInfo->GetIsThirdPartyContextToTopWindow();
StoragePrincipalHelper::UpdatePartitionKeyWithForeignAncestorBit(
mPartitionKey, foreignByAncestorContext);
}
void CookieJarSettings::UpdateIsOnContentBlockingAllowList( void CookieJarSettings::UpdateIsOnContentBlockingAllowList(
nsIChannel* aChannel) { nsIChannel* aChannel) {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess()); MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());

View File

@@ -161,12 +161,14 @@ class CookieJarSettings final : public nsICookieJarSettings {
void UpdateIsOnContentBlockingAllowList(nsIChannel* aChannel); void UpdateIsOnContentBlockingAllowList(nsIChannel* aChannel);
void SetPartitionKey(nsIURI* aURI); void SetPartitionKey(nsIURI* aURI, bool aForeignByAncestorContext);
void SetPartitionKey(const nsAString& aPartitionKey) { void SetPartitionKey(const nsAString& aPartitionKey) {
mPartitionKey = aPartitionKey; mPartitionKey = aPartitionKey;
} }
const nsAString& GetPartitionKey() { return mPartitionKey; }; const nsAString& GetPartitionKey() { return mPartitionKey; };
void UpdatePartitionKeyForDocumentLoadedByChannel(nsIChannel* aChannel);
void SetFingerprintingRandomizationKey(const nsTArray<uint8_t>& aKey) { void SetFingerprintingRandomizationKey(const nsTArray<uint8_t>& aKey) {
mFingerprintingRandomKey.reset(); mFingerprintingRandomKey.reset();

View File

@@ -2423,7 +2423,6 @@ HttpBaseChannel::GetDocumentURI(nsIURI** aDocumentURI) {
NS_IMETHODIMP NS_IMETHODIMP
HttpBaseChannel::SetDocumentURI(nsIURI* aDocumentURI) { HttpBaseChannel::SetDocumentURI(nsIURI* aDocumentURI) {
ENSURE_CALLED_BEFORE_CONNECT(); ENSURE_CALLED_BEFORE_CONNECT();
mDocumentURI = aDocumentURI; mDocumentURI = aDocumentURI;
return NS_OK; return NS_OK;
} }

View File

@@ -1009,6 +1009,14 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
->MarkOverriddenFingerprintingSettingsAsSet(); ->MarkOverriddenFingerprintingSettingsAsSet();
#endif #endif
nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
// For subdocuments, the channel's partition key is that of the parent
// document. This document may have a different partition key, particularly
// one without the same-site bit.
net::CookieJarSettings::Cast(cookieJarSettings)
->UpdatePartitionKeyForDocumentLoadedByChannel(aChannel);
// We only update the IsOnContentBlockingAllowList flag and the partition key // We only update the IsOnContentBlockingAllowList flag and the partition key
// for the top-level http channel. // for the top-level http channel.
// //
@@ -1024,9 +1032,6 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
return; return;
} }
nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
// Update the IsOnContentBlockingAllowList flag in the CookieJarSettings // Update the IsOnContentBlockingAllowList flag in the CookieJarSettings
// if this is a top level loading. For sub-document loading, this flag // if this is a top level loading. For sub-document loading, this flag
// would inherit from the parent. // would inherit from the parent.
@@ -1037,7 +1042,7 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
// propagated to non-top level loads via CookieJarSetting. // propagated to non-top level loads via CookieJarSetting.
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
Unused << aChannel->GetURI(getter_AddRefs(uri)); Unused << aChannel->GetURI(getter_AddRefs(uri));
net::CookieJarSettings::Cast(cookieJarSettings)->SetPartitionKey(uri); net::CookieJarSettings::Cast(cookieJarSettings)->SetPartitionKey(uri, false);
// Generate the fingerprinting randomization key for top-level loads. The key // Generate the fingerprinting randomization key for top-level loads. The key
// will automatically be propagated to sub loads. // will automatically be propagated to sub loads.

View File

@@ -86,8 +86,11 @@ bool ChooseOriginAttributes(nsIChannel* aChannel, OriginAttributes& aAttrs,
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return false; return false;
} }
bool foreignByAncestorContext =
aAttrs.SetPartitionKey(principalURI); false; // Bug 1876575 will change this to
// loadInfo->GetIsInThirdPartyContext() &&
// !loadInfo->GetIsThirdPartyContextToTopWindow();
aAttrs.SetPartitionKey(principalURI, foreignByAncestorContext);
return true; return true;
} }
@@ -560,7 +563,7 @@ void StoragePrincipalHelper::UpdateOriginAttributesForNetworkState(
return; return;
} }
aAttributes.SetPartitionKey(aFirstPartyURI); aAttributes.SetPartitionKey(aFirstPartyURI, false);
} }
enum SupportedScheme { HTTP, HTTPS }; enum SupportedScheme { HTTP, HTTPS };
@@ -664,8 +667,9 @@ bool StoragePrincipalHelper::PartitionKeyHasBaseDomain(
nsString scheme; nsString scheme;
nsString pkBaseDomain; nsString pkBaseDomain;
int32_t port; int32_t port;
bool success = OriginAttributes::ParsePartitionKey(aPartitionKey, scheme, bool foreign;
pkBaseDomain, port); bool success = OriginAttributes::ParsePartitionKey(
aPartitionKey, scheme, pkBaseDomain, port, foreign);
if (!success) { if (!success) {
return false; return false;
@@ -674,4 +678,26 @@ bool StoragePrincipalHelper::PartitionKeyHasBaseDomain(
return aBaseDomain.Equals(pkBaseDomain); return aBaseDomain.Equals(pkBaseDomain);
} }
// static
void StoragePrincipalHelper::UpdatePartitionKeyWithForeignAncestorBit(
nsAString& aKey, bool aForeignByAncestorContext) {
bool site = 0 == aKey.Find(u"(");
if (!site) {
return;
}
if (aForeignByAncestorContext) {
int32_t index = aKey.Find(u",f)");
if (index == -1) {
uint32_t cutStart = aKey.Length() - 1;
aKey.ReplaceLiteral(cutStart, 1, u",f)");
}
} else {
int32_t index = aKey.Find(u",f)");
if (index != -1) {
uint32_t cutLength = aKey.Length() - index;
aKey.ReplaceLiteral(index, cutLength, u")");
}
}
}
} // namespace mozilla } // namespace mozilla

View File

@@ -351,6 +351,14 @@ class StoragePrincipalHelper final {
static bool PartitionKeyHasBaseDomain(const nsAString& aPartitionKey, static bool PartitionKeyHasBaseDomain(const nsAString& aPartitionKey,
const nsAString& aBaseDomain); const nsAString& aBaseDomain);
// Partition keys can have the same-site bit added or removed from them.
// "(https,foo.com)", false -> "(https,foo.com)"
// "(https,foo.com,f)", false -> "(https,foo.com)"
// "(https,foo.com,f)", true -> "(https,foo.com,f)"
// "(https,foo.com)", true -> "(https,foo.com,f)"
static void UpdatePartitionKeyWithForeignAncestorBit(
nsAString& aKey, bool aForeignByAncestorContext);
}; };
} // namespace mozilla } // namespace mozilla

View File

@@ -1267,7 +1267,11 @@ Maybe<nsTArray<uint8_t>> nsRFPService::GenerateKey(nsIChannel* aChannel) {
// Set the partitionKey using the top level URI to ensure that the key is // Set the partitionKey using the top level URI to ensure that the key is
// specific to the top level site. // specific to the top level site.
attrs.SetPartitionKey(topLevelURI); bool foreignByAncestorContext =
false; // Bug 1876575 will change this to
// loadInfo->GetIsInThirdPartyContext() &&
// !loadInfo->GetIsThirdPartyContextToTopWindow();
attrs.SetPartitionKey(topLevelURI, foreignByAncestorContext);
nsAutoCString oaSuffix; nsAutoCString oaSuffix;
attrs.CreateSuffix(oaSuffix); attrs.CreateSuffix(oaSuffix);
@@ -1337,8 +1341,14 @@ nsRFPService::CleanRandomKeyByPrincipal(nsIPrincipal* aPrincipal) {
OriginAttributes attrs = aPrincipal->OriginAttributesRef(); OriginAttributes attrs = aPrincipal->OriginAttributesRef();
nsCOMPtr<nsIURI> uri = aPrincipal->GetURI(); nsCOMPtr<nsIURI> uri = aPrincipal->GetURI();
attrs.SetPartitionKey(uri);
attrs.SetPartitionKey(uri, false);
ClearBrowsingSessionKey(attrs);
// We must also include the cross-site embeds of this principal that end up
// re-embedded back into the same principal's top level, otherwise state will
// persist for this target
attrs.SetPartitionKey(uri, true);
ClearBrowsingSessionKey(attrs); ClearBrowsingSessionKey(attrs);
return NS_OK; return NS_OK;
} }
@@ -1354,14 +1364,21 @@ nsRFPService::CleanRandomKeyByDomain(const nsACString& aDomain) {
// Use the originAttributes to get the partitionKey. // Use the originAttributes to get the partitionKey.
OriginAttributes attrs; OriginAttributes attrs;
attrs.SetPartitionKey(httpURI); attrs.SetPartitionKey(httpURI, false);
// Create a originAttributesPattern and set the http partitionKey to the // Create a originAttributesPattern and set the http partitionKey to the
// pattern. // pattern.
OriginAttributesPattern pattern; OriginAttributesPattern pattern;
pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey); pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
// We must also include the cross-site embeds of this principal that end up
// re-embedded back into the same principal's top level, otherwise state will
// persist for this target
attrs.SetPartitionKey(httpURI, true);
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern); ClearBrowsingSessionKey(pattern);
// Get https URI from the domain. // Get https URI from the domain.
@@ -1370,10 +1387,17 @@ nsRFPService::CleanRandomKeyByDomain(const nsACString& aDomain) {
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Use the originAttributes to get the partitionKey and set to the pattern. // Use the originAttributes to get the partitionKey and set to the pattern.
attrs.SetPartitionKey(httpsURI); attrs.SetPartitionKey(httpsURI, false);
pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey); pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
// We must also include the cross-site embeds of this principal that end up
// re-embedded back into the same principal's top level, otherwise state will
// persist for this target
attrs.SetPartitionKey(httpsURI, true);
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern); ClearBrowsingSessionKey(pattern);
return NS_OK; return NS_OK;
} }
@@ -1395,7 +1419,7 @@ nsRFPService::CleanRandomKeyByHost(const nsACString& aHost,
// Use the originAttributes to get the partitionKey. // Use the originAttributes to get the partitionKey.
OriginAttributes attrs; OriginAttributes attrs;
attrs.SetPartitionKey(httpURI); attrs.SetPartitionKey(httpURI, false);
// Set the partitionKey to the pattern. // Set the partitionKey to the pattern.
pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Reset();
@@ -1403,16 +1427,31 @@ nsRFPService::CleanRandomKeyByHost(const nsACString& aHost,
ClearBrowsingSessionKey(pattern); ClearBrowsingSessionKey(pattern);
// We must also include the cross-site embeds of this principal that end up
// re-embedded back into the same principal's top level, otherwise state will
// persist for this target
attrs.SetPartitionKey(httpURI, true);
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
// Get https URI from the host. // Get https URI from the host.
nsCOMPtr<nsIURI> httpsURI; nsCOMPtr<nsIURI> httpsURI;
rv = NS_NewURI(getter_AddRefs(httpsURI), "https://"_ns + aHost); rv = NS_NewURI(getter_AddRefs(httpsURI), "https://"_ns + aHost);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Use the originAttributes to get the partitionKey and set to the pattern. // Use the originAttributes to get the partitionKey and set to the pattern.
attrs.SetPartitionKey(httpsURI); attrs.SetPartitionKey(httpsURI, false);
pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey); pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
// We must also include the cross-site embeds of this principal that end up
// re-embedded back into the same principal's top level, otherwise state will
// persist for this target
attrs.SetPartitionKey(httpsURI, true);
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern); ClearBrowsingSessionKey(pattern);
return NS_OK; return NS_OK;
} }
@@ -2054,8 +2093,9 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
nsAutoString scheme; nsAutoString scheme;
nsAutoString domain; nsAutoString domain;
int32_t unused; int32_t unused;
bool unused2;
if (!OriginAttributes::ParsePartitionKey(partitionKey, scheme, domain, if (!OriginAttributes::ParsePartitionKey(partitionKey, scheme, domain,
unused)) { unused, unused2)) {
MOZ_ASSERT(false); MOZ_ASSERT(false);
return Nothing(); return Nothing();
} }
@@ -2096,12 +2136,16 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
cookieJarSettings->GetPartitionKey(partitionKey); cookieJarSettings->GetPartitionKey(partitionKey);
OriginAttributes attrs; OriginAttributes attrs;
attrs.SetPartitionKey(topURI); attrs.SetPartitionKey(topURI, false);
OriginAttributes attrsForeignByAncestor;
attrsForeignByAncestor.SetPartitionKey(topURI, true);
// The partitionKey of the channel could haven't been set here if the loading // The partitionKey of the channel could haven't been set here if the loading
// channel is top-level. // channel is top-level.
MOZ_ASSERT_IF(!partitionKey.IsEmpty(), MOZ_ASSERT_IF(!partitionKey.IsEmpty(),
attrs.mPartitionKey.Equals(partitionKey)); attrs.mPartitionKey.Equals(partitionKey) ||
attrsForeignByAncestor.mPartitionKey.Equals(partitionKey));
#endif #endif
return GetOverriddenFingerprintingSettingsForURI(topURI, uri); return GetOverriddenFingerprintingSettingsForURI(topURI, uri);