forked from mirrors/gecko-dev
Bug 1876575, part 1 - Make AntiTracking::IsThirdParty* aware of ABA case - r=anti-tracking-reviewers,cookie-reviewers,timhuang
Differential Revision: https://phabricator.services.mozilla.com/D203180
This commit is contained in:
parent
d3ef19887a
commit
ba265bda60
5 changed files with 105 additions and 63 deletions
|
|
@ -4,9 +4,11 @@
|
|||
* 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/. */
|
||||
|
||||
#include "mozIThirdPartyUtil.h"
|
||||
#include "mozilla/AntiTrackingUtils.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/ContentBlockingAllowList.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/net/CookieJarSettings.h"
|
||||
|
|
@ -539,10 +541,9 @@ void CookieJarSettings::SetPartitionKey(nsIURI* aURI,
|
|||
void CookieJarSettings::UpdatePartitionKeyForDocumentLoadedByChannel(
|
||||
nsIChannel* aChannel) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
bool thirdParty = AntiTrackingUtils::IsThirdPartyChannel(aChannel);
|
||||
bool foreignByAncestorContext =
|
||||
false; // Bug 1876575 will change this to
|
||||
// loadInfo->GetIsInThirdPartyContext() &&
|
||||
// !loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
thirdParty && !loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
StoragePrincipalHelper::UpdatePartitionKeyWithForeignAncestorBit(
|
||||
mPartitionKey, foreignByAncestorContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -825,7 +825,8 @@ void AntiTrackingUtils::ComputeIsThirdPartyToTopWindow(nsIChannel* aChannel) {
|
|||
// whether the page is third-party, so we use channel result principal
|
||||
// instead. By doing this, an the resource inherits the principal from
|
||||
// its parent is considered not a third-party.
|
||||
if (NS_IsAboutBlank(uri) || NS_IsAboutSrcdoc(uri)) {
|
||||
if (NS_IsAboutBlank(uri) || NS_IsAboutSrcdoc(uri) ||
|
||||
uri->SchemeIs("blob")) {
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (NS_WARN_IF(!ssm)) {
|
||||
return;
|
||||
|
|
@ -851,10 +852,36 @@ void AntiTrackingUtils::ComputeIsThirdPartyToTopWindow(nsIChannel* aChannel) {
|
|||
bool AntiTrackingUtils::IsThirdPartyChannel(nsIChannel* aChannel) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
// We only care whether the channel is 3rd-party with respect to
|
||||
// the top-level.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
return loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
// We have to handle blob URLs here because they always fail
|
||||
// IsThirdPartyChannel because of how blob URLs are constructed. We just
|
||||
// recompare to their ancestor chain from the loadInfo, bailing if any is
|
||||
// third party.
|
||||
nsAutoCString scheme;
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(channelURI));
|
||||
if (NS_SUCCEEDED(rv) && channelURI->SchemeIs("blob")) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
for (const nsCOMPtr<nsIPrincipal>& principal :
|
||||
loadInfo->AncestorPrincipals()) {
|
||||
bool thirdParty = true;
|
||||
rv = loadInfo->PrincipalToInherit()->IsThirdPartyPrincipal(principal,
|
||||
&thirdParty);
|
||||
if (NS_SUCCEEDED(rv) && thirdParty) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIThirdPartyUtil> tpuService =
|
||||
mozilla::components::ThirdPartyUtil::Service();
|
||||
if (!tpuService) {
|
||||
return true;
|
||||
}
|
||||
bool thirdParty = true;
|
||||
rv = tpuService->IsThirdPartyChannel(aChannel, nullptr, &thirdParty);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
return thirdParty;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
@ -907,19 +934,29 @@ bool AntiTrackingUtils::IsThirdPartyWindow(nsPIDOMWindowInner* aWindow,
|
|||
/* static */
|
||||
bool AntiTrackingUtils::IsThirdPartyDocument(Document* aDocument) {
|
||||
MOZ_ASSERT(aDocument);
|
||||
if (!aDocument->GetChannel()) {
|
||||
nsCOMPtr<mozIThirdPartyUtil> tpuService =
|
||||
mozilla::components::ThirdPartyUtil::Service();
|
||||
if (!tpuService) {
|
||||
return true;
|
||||
}
|
||||
bool thirdParty = true;
|
||||
if (!aDocument->GetChannel() ||
|
||||
aDocument->GetDocumentURI()->SchemeIs("blob")) {
|
||||
// If we can't get the channel from the document, i.e. initial about:blank
|
||||
// page, we use the browsingContext of the document to check if it's in the
|
||||
// third-party context. If the browsing context is still not available, we
|
||||
// will treat the window as third-party.
|
||||
// We also rely on IsThirdPartyContext for blob documents because the
|
||||
// IsThirdPartyChannel check relies on getting the BaseDomain,
|
||||
// which correctly fails for blobs URIs.
|
||||
RefPtr<BrowsingContext> bc = aDocument->GetBrowsingContext();
|
||||
return bc ? IsThirdPartyContext(bc) : true;
|
||||
}
|
||||
|
||||
// We only care whether the channel is 3rd-party with respect to
|
||||
// the top-level.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aDocument->GetChannel()->LoadInfo();
|
||||
return loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
nsresult rv = tpuService->IsThirdPartyChannel(aDocument->GetChannel(),
|
||||
nullptr, &thirdParty);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
return thirdParty;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
@ -927,41 +964,47 @@ bool AntiTrackingUtils::IsThirdPartyContext(BrowsingContext* aBrowsingContext) {
|
|||
MOZ_ASSERT(aBrowsingContext);
|
||||
MOZ_ASSERT(aBrowsingContext->IsInProcess());
|
||||
|
||||
if (aBrowsingContext->IsTopContent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the top browsing context is not in the same process, it's cross-origin.
|
||||
if (!aBrowsingContext->Top()->IsInProcess()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// iframes with SANDBOX_ORIGIN are always third-party contexts
|
||||
// because they are a unique origin
|
||||
nsIDocShell* docShell = aBrowsingContext->GetDocShell();
|
||||
if (!docShell) {
|
||||
return true;
|
||||
}
|
||||
Document* doc = docShell->GetExtantDocument();
|
||||
if (!doc) {
|
||||
if (!doc || doc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
|
||||
return true;
|
||||
}
|
||||
nsIPrincipal* principal = doc->NodePrincipal();
|
||||
|
||||
nsIDocShell* topDocShell = aBrowsingContext->Top()->GetDocShell();
|
||||
if (!topDocShell) {
|
||||
return true;
|
||||
BrowsingContext* traversingParent = aBrowsingContext->GetParent();
|
||||
while (traversingParent) {
|
||||
// If the parent browsing context is not in the same process, it's
|
||||
// cross-origin.
|
||||
if (!traversingParent->IsInProcess()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIDocShell* parentDocShell = traversingParent->GetDocShell();
|
||||
if (!parentDocShell) {
|
||||
return true;
|
||||
}
|
||||
Document* parentDoc = parentDocShell->GetDocument();
|
||||
if (!parentDoc || parentDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
|
||||
return true;
|
||||
}
|
||||
nsIPrincipal* parentPrincipal = parentDoc->NodePrincipal();
|
||||
|
||||
auto* parentBasePrin = BasePrincipal::Cast(parentPrincipal);
|
||||
bool isThirdParty = true;
|
||||
|
||||
parentBasePrin->IsThirdPartyPrincipal(principal, &isThirdParty);
|
||||
if (isThirdParty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
traversingParent = traversingParent->GetParent();
|
||||
}
|
||||
Document* topDoc = topDocShell->GetDocument();
|
||||
if (!topDoc) {
|
||||
return true;
|
||||
}
|
||||
nsIPrincipal* topPrincipal = topDoc->NodePrincipal();
|
||||
|
||||
auto* topBasePrin = BasePrincipal::Cast(topPrincipal);
|
||||
bool isThirdParty = true;
|
||||
|
||||
topBasePrin->IsThirdPartyPrincipal(principal, &isThirdParty);
|
||||
|
||||
return isThirdParty;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
@ -1009,13 +1052,17 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
|
|||
->MarkOverriddenFingerprintingSettingsAsSet();
|
||||
#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);
|
||||
ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
|
||||
if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
|
||||
contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
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
|
||||
// for the top-level http channel.
|
||||
|
|
@ -1027,14 +1074,15 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
|
|||
// The partition key is computed based on the site, so it's no point to set it
|
||||
// for channels other than http channels.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel || loadInfo->GetExternalContentPolicyType() !=
|
||||
ExtContentPolicy::TYPE_DOCUMENT) {
|
||||
if (!httpChannel || contentType != ExtContentPolicy::TYPE_DOCUMENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the IsOnContentBlockingAllowList flag in the CookieJarSettings
|
||||
// if this is a top level loading. For sub-document loading, this flag
|
||||
// would inherit from the parent.
|
||||
nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
|
||||
Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
|
||||
net::CookieJarSettings::Cast(cookieJarSettings)
|
||||
->UpdateIsOnContentBlockingAllowList(aChannel);
|
||||
|
||||
|
|
|
|||
|
|
@ -475,7 +475,6 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
|
|||
[aParentContext, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
|
||||
aCookieBehavior,
|
||||
aReason](int aAllowMode) -> RefPtr<StorageAccessPermissionGrantPromise> {
|
||||
MOZ_ASSERT(!aParentContext->IsInProcess());
|
||||
// We don't have the window, send an IPC to the content process that
|
||||
// owns the parent window. But there is a special case, for window.open,
|
||||
// we'll return to the content process we need to inform when this
|
||||
|
|
@ -1060,12 +1059,7 @@ StorageAccessAPIHelper::CheckSameSiteCallingContextDecidesStorageAccessAPI(
|
|||
}
|
||||
}
|
||||
|
||||
nsIChannel* chan = aDocument->GetChannel();
|
||||
if (!chan) {
|
||||
return Some(false);
|
||||
}
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
|
||||
if (loadInfo->GetIsThirdPartyContextToTopWindow()) {
|
||||
if (AntiTrackingUtils::IsThirdPartyDocument(aDocument)) {
|
||||
return Some(false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,9 +87,8 @@ bool ChooseOriginAttributes(nsIChannel* aChannel, OriginAttributes& aAttrs,
|
|||
return false;
|
||||
}
|
||||
bool foreignByAncestorContext =
|
||||
false; // Bug 1876575 will change this to
|
||||
// loadInfo->GetIsInThirdPartyContext() &&
|
||||
// !loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
AntiTrackingUtils::IsThirdPartyChannel(aChannel) &&
|
||||
!loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
aAttrs.SetPartitionKey(principalURI, foreignByAncestorContext);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -316,7 +315,7 @@ nsresult StoragePrincipalHelper::GetPrincipal(nsIChannel* aChannel,
|
|||
// We only support foreign partitioned principal when dFPI is enabled.
|
||||
if (cjs->GetCookieBehavior() ==
|
||||
nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
|
||||
loadInfo->GetIsThirdPartyContextToTopWindow()) {
|
||||
AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
|
||||
outPrincipal = partitionedPrincipal;
|
||||
}
|
||||
break;
|
||||
|
|
@ -482,7 +481,7 @@ bool StoragePrincipalHelper::GetOriginAttributes(
|
|||
// Otherwise, we will use the regular principal.
|
||||
if (cjs->GetCookieBehavior() ==
|
||||
nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
|
||||
loadInfo->GetIsThirdPartyContextToTopWindow()) {
|
||||
AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
|
||||
ChooseOriginAttributes(aChannel, aAttributes, true);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "MainThreadUtils.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
|
||||
#include "mozilla/AntiTrackingUtils.h"
|
||||
#include "mozilla/ArrayIterator.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
|
|
@ -1268,9 +1269,8 @@ Maybe<nsTArray<uint8_t>> nsRFPService::GenerateKey(nsIChannel* aChannel) {
|
|||
// Set the partitionKey using the top level URI to ensure that the key is
|
||||
// specific to the top level site.
|
||||
bool foreignByAncestorContext =
|
||||
false; // Bug 1876575 will change this to
|
||||
// loadInfo->GetIsInThirdPartyContext() &&
|
||||
// !loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
AntiTrackingUtils::IsThirdPartyChannel(aChannel) &&
|
||||
loadInfo->GetIsThirdPartyContextToTopWindow();
|
||||
attrs.SetPartitionKey(topLevelURI, foreignByAncestorContext);
|
||||
|
||||
nsAutoCString oaSuffix;
|
||||
|
|
@ -2050,7 +2050,7 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
|
|||
}
|
||||
|
||||
// The channel is for the first-party load.
|
||||
if (!loadInfo->GetIsThirdPartyContextToTopWindow()) {
|
||||
if (!AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
|
||||
return GetOverriddenFingerprintingSettingsForURI(uri, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue