/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
// static void ThirdPartyUtil::Startup() {
nsCOMPtr<mozIThirdPartyUtil> tpu; if (NS_WARN_IF(!(tpu = do_GetService(THIRDPARTYUTIL_CONTRACTID)))) {
NS_WARNING("Failed to get third party util!");
}
}
// static
ThirdPartyUtil* ThirdPartyUtil::GetInstance() { if (gService) { return gService;
}
nsCOMPtr<mozIThirdPartyUtil> tpuService =
mozilla::components::ThirdPartyUtil::Service(); if (!tpuService) { return nullptr;
}
MOZ_ASSERT(
gService, "gService must have been initialized in nsEffectiveTLDService::Init"); return gService;
}
// Determine if aFirstDomain is a different base domain to aSecondURI; or, if // the concept of base domain does not apply, determine if the two hosts are not // string-identical.
nsresult ThirdPartyUtil::IsThirdPartyInternal(const nsCString& aFirstDomain,
nsIURI* aSecondURI, bool* aResult) { if (!aSecondURI) { return NS_ERROR_INVALID_ARG;
}
// BlobURLs are always first-party. if (aSecondURI->SchemeIs("blob")) {
*aResult = false; return NS_OK;
}
// Get the base domain for aSecondURI.
nsAutoCString secondDomain;
nsresult rv = GetBaseDomain(aSecondURI, secondDomain);
LOG(("ThirdPartyUtil::IsThirdPartyInternal %s =? %s", aFirstDomain.get(),
secondDomain.get())); if (NS_FAILED(rv)) { return rv;
}
nsCOMPtr<nsIPrincipal> prin = scriptObjPrin->GetPrincipal(); if (!prin) { return NS_ERROR_INVALID_ARG;
}
prin.forget(result); return NS_OK;
}
// Get the URI associated with a window.
NS_IMETHODIMP
ThirdPartyUtil::GetURIFromWindow(mozIDOMWindowProxy* aWin, nsIURI** result) {
nsCOMPtr<nsIPrincipal> prin;
nsresult rv = GetPrincipalFromWindow(aWin, getter_AddRefs(prin)); if (NS_FAILED(rv)) { return rv;
}
if (prin->GetIsNullPrincipal()) {
LOG(("ThirdPartyUtil::GetURIFromWindow can't use null principal\n")); return NS_ERROR_INVALID_ARG;
} auto* basePrin = BasePrincipal::Cast(prin); return basePrin->GetURI(result);
}
// Determine if aFirstURI is third party with respect to aSecondURI. See docs // for mozIThirdPartyUtil.
NS_IMETHODIMP
ThirdPartyUtil::IsThirdPartyURI(nsIURI* aFirstURI, nsIURI* aSecondURI, bool* aResult) {
NS_ENSURE_ARG(aFirstURI);
NS_ENSURE_ARG(aSecondURI);
NS_ASSERTION(aResult, "null outparam pointer");
// If the optional aURI is provided, determine whether aWindow is foreign with // respect to aURI. If the optional aURI is not provided, determine whether the // given "window hierarchy" is third party. See docs for mozIThirdPartyUtil.
NS_IMETHODIMP
ThirdPartyUtil::IsThirdPartyWindow(mozIDOMWindowProxy* aWindow, nsIURI* aURI, bool* aResult) {
NS_ENSURE_ARG(aWindow);
NS_ASSERTION(aResult, "null outparam pointer");
bool result;
// Ignore about:blank and about:srcdoc URIs here since they have no domain // and attempting to compare against them will fail. if (aURI && !NS_IsAboutBlank(aURI) && !NS_IsAboutSrcdoc(aURI)) {
nsCOMPtr<nsIPrincipal> prin;
nsresult rv = GetPrincipalFromWindow(aWindow, getter_AddRefs(prin));
NS_ENSURE_SUCCESS(rv, rv); // Determine whether aURI is foreign with respect to the current principal.
rv = prin->IsThirdPartyURI(aURI, &result); if (NS_FAILED(rv)) { return rv;
}
if (result) {
*aResult = true; return NS_OK;
}
}
nsPIDOMWindowOuter* current = nsPIDOMWindowOuter::From(aWindow); auto* const browsingContext = current->GetBrowsingContext();
MOZ_ASSERT(browsingContext);
if (browsingContext->IsTopContent()) {
*aResult = false; return NS_OK;
}
// If the document is sandboxed, it's always third party.
RefPtr<Document> doc = current->GetExtantDoc(); if (doc && (doc->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
*aResult = true; return NS_OK;
}
// Determine if the URI associated with aChannel or any URI of the window // hierarchy associated with the channel is foreign with respect to aSecondURI. // See docs for mozIThirdPartyUtil.
NS_IMETHODIMP
ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel, nsIURI* aURI, bool* aResult) {
LOG(("ThirdPartyUtil::IsThirdPartyChannel [channel=%p]", aChannel));
NS_ENSURE_ARG(aChannel);
NS_ASSERTION(aResult, "null outparam pointer");
nsresult rv; bool doForce = false;
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
do_QueryInterface(aChannel); if (httpChannelInternal) {
uint32_t flags = 0; // Avoid checking the return value here since some channel implementations // may return NS_ERROR_NOT_IMPLEMENTED.
mozilla::Unused << httpChannelInternal->GetThirdPartyFlags(&flags);
// If aURI was not supplied, and we're forcing, then we're by definition // not foreign. If aURI was supplied, we still want to check whether it's // foreign with respect to the channel URI. (The forcing only applies to // whatever window hierarchy exists above the channel.) if (doForce && !aURI) {
*aResult = false; return NS_OK;
}
}
// Obtain the URI from the channel, and its base domain.
nsCOMPtr<nsIURI> channelURI;
rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI)); if (NS_FAILED(rv)) { return rv;
}
if (!doForce) {
parentIsThird = loadInfo->GetIsInThirdPartyContext(); if (!parentIsThird && loadInfo->GetExternalContentPolicyType() !=
ExtContentPolicy::TYPE_DOCUMENT) { // Check if the channel itself is third-party to its own requestor. // Unfortunately, we have to go through the loading principal.
loadingPrincipal = BasePrincipal::Cast(loadInfo->GetLoadingPrincipal());
}
}
// Special consideration must be done for about:blank and about:srcdoc URIs // because those inherit the principal from the parent context. For them, // let's consider the principal URI. if (NS_IsAboutBlank(channelURI) || NS_IsAboutSrcdoc(channelURI)) {
nsCOMPtr<nsIPrincipal> principalToInherit =
loadInfo->FindPrincipalToInherit(aChannel); if (!principalToInherit) {
*aResult = true; return NS_OK;
}
rv = principalToInherit->GetBaseDomain(channelDomain); if (NS_FAILED(rv)) { return rv;
}
if (loadingPrincipal) {
rv = loadingPrincipal->IsThirdPartyPrincipal(principalToInherit,
&parentIsThird); if (NS_FAILED(rv)) { return rv;
}
}
} else {
rv = GetBaseDomain(channelURI, channelDomain); if (NS_FAILED(rv)) { return rv;
}
if (loadingPrincipal) {
rv = loadingPrincipal->IsThirdPartyURI(channelURI, &parentIsThird); if (NS_FAILED(rv)) { return rv;
}
}
}
// If we're not comparing to a URI, we have our answer. Otherwise, if // parentIsThird, we're not forcing and we know that we're a third-party // request. if (!aURI || parentIsThird) {
*aResult = parentIsThird; return NS_OK;
}
// Determine whether aURI is foreign with respect to channelURI. return IsThirdPartyInternal(channelDomain, aURI, aResult);
}
// Find the associated window and its parent window.
nsCOMPtr<nsILoadContext> ctx;
NS_QueryNotificationCallbacks(aChannel, ctx); if (!ctx) { return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<mozIDOMWindowProxy> window;
ctx->GetAssociatedWindow(getter_AddRefs(window)); if (!window) { return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsPIDOMWindowOuter> top =
nsGlobalWindowOuter::Cast(window)
->GetTopExcludingExtensionAccessibleContentFrames(aURIBeingLoaded);
top.forget(aWin); return NS_OK;
}
// Get the base domain for aHostURI; e.g. for "www.bbc.co.uk", this would be // "bbc.co.uk". Only properly-formed URI's are tolerated, though a trailing // dot may be present. If aHostURI is an IP address, an alias such as // 'localhost', an eTLD such as 'co.uk', or the empty string, aBaseDomain will // be the exact host. Blob URIs will incur a lookup for their blob URL entry, // and will perform the same construction from their principal's base domain. // The result of this function should only be used in exact // string comparisons, since substring comparisons will not be valid for the // special cases elided above.
NS_IMETHODIMP
ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI, nsACString& aBaseDomain) { if (!aHostURI) { return NS_ERROR_INVALID_ARG;
}
// First, get the base domain from aHostURI. In the common case, this is // direct. For blob URLs we get this from the blob url's entry in the blob url // store.
nsresult rv;
nsCOMPtr<nsIPrincipal> blobPrincipal; if (aHostURI->SchemeIs("blob")) { if (BlobURLProtocolHandler::GetBlobURLPrincipal(
aHostURI, getter_AddRefs(blobPrincipal))) { // If the blob URL is expired, this will be the uuid of a NullPrincipal
rv = blobPrincipal->GetBaseDomain(aBaseDomain);
} else { // If the blob is expired and no longer has a map entry, we fail
rv = nsresult::NS_ERROR_DOM_BAD_URI;
}
} else {
rv = mTLDService->GetBaseDomain(aHostURI, 0, aBaseDomain);
}
// If the URI is a null principal, we get the UUID portion instead of the base // domain because a null principal uri doesn't have a base domain. if (aHostURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME)) {
rv = aHostURI->GetFilePath(aBaseDomain);
}
// Get the base domain. this will fail if the host contains a leading dot, // more than one trailing dot, or is otherwise malformed. if (rv == NS_ERROR_HOST_IS_IP_ADDRESS ||
rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) { // aHostURI is either an IP address, an alias such as 'localhost', an eTLD // such as 'co.uk', or the empty string. Uses the normalized host in such // cases.
// The aHostURI can be a view-source URI, in which case we need to get the // base domain from the inner most URI. if (net::SchemeIsViewSource(aHostURI)) {
rv = NS_GetInnermostURIHost(aHostURI, aBaseDomain);
} else {
rv = aHostURI->GetAsciiHost(aBaseDomain);
}
}
if (NS_FAILED(rv)) { return rv;
}
// aHostURI (and thus aBaseDomain) may be the string '.'. If so, fail. if (aBaseDomain.Length() == 1 && aBaseDomain.Last() == '.') { return NS_ERROR_INVALID_ARG;
}
// Reject any URIs without a host that aren't file:// URIs. This makes it the // only way we can get a base domain consisting of the empty string, which // means we can safely perform foreign tests on such URIs where "not foreign" // means "the involved URIs are all file://". if (aBaseDomain.IsEmpty() && !aHostURI->SchemeIs("file")) { return NS_ERROR_INVALID_ARG;
}
bool isForeign = true; if (aChannel &&
(!aRequireThirdPartyCheck || aRequireThirdPartyCheck(loadInfo))) {
IsThirdPartyChannel(aChannel, aURI ? aURI : uri.get(), &isForeign);
} if (isForeign) {
result += ThirdPartyAnalysis::IsForeign;
}
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aChannel); if (classifiedChannel) { if (classifiedChannel->IsThirdPartyTrackingResource()) {
result += ThirdPartyAnalysis::IsThirdPartyTrackingResource;
} if (classifiedChannel->IsThirdPartySocialTrackingResource()) {
result += ThirdPartyAnalysis::IsThirdPartySocialTrackingResource;
}
// Check first-party storage access even for non-tracking resources, since // we will need the result when computing the access rights for the reject // foreign cookie behavior mode.
// If the caller has requested third-party checks, we will only perform the // storage access check once we know we're in the third-party context. bool performStorageChecks =
aRequireThirdPartyCheck ? result.contains(ThirdPartyAnalysis::IsForeign)
: true; if (performStorageChecks &&
ShouldAllowAccessFor(aChannel, aURI ? aURI : uri.get(),
aRejectedReason)) {
result += ThirdPartyAnalysis::IsStorageAccessPermissionGranted;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.