Bug 1761242 - Expose computing security flags for early hint preloader r=ckerschb,smaug

Differential Revision: https://phabricator.services.mozilla.com/D144798
This commit is contained in:
Manuel Bucher 2022-06-08 14:33:10 +00:00
Родитель 84e0467a0f
Коммит 35abf46688
8 изменённых файлов: 115 добавлений и 56 удалений

Просмотреть файл

@ -23,6 +23,7 @@
#include "js/loader/ModuleLoadRequest.h"
#include "xpcpublic.h"
#include "GeckoProfiler.h"
#include "nsContentSecurityManager.h"
#include "nsIContent.h"
#include "nsJSUtils.h"
#include "mozilla/dom/AutoEntryScript.h"
@ -88,24 +89,20 @@ bool ModuleLoader::CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) {
}
nsresult ModuleLoader::StartFetch(ModuleLoadRequest* aRequest) {
nsSecurityFlags securityFlags;
// According to the spec, module scripts have different behaviour to classic
// scripts and always use CORS. Only exception: Non linkable about: pages
// which load local module scripts.
if (GetScriptLoader()->IsAboutPageLoadingChromeURI(
aRequest, GetScriptLoader()->GetDocument())) {
securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
} else {
securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
if (aRequest->CORSMode() == CORS_NONE ||
aRequest->CORSMode() == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else {
MOZ_ASSERT(aRequest->CORSMode() == CORS_USE_CREDENTIALS);
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
}
bool isAboutPageLoadingChromeURI = ScriptLoader::IsAboutPageLoadingChromeURI(
aRequest, GetScriptLoader()->GetDocument());
nsContentSecurityManager::CORSSecurityMapping corsMapping =
isAboutPageLoadingChromeURI
? nsContentSecurityManager::CORSSecurityMapping::DISABLE_CORS_CHECKS
: nsContentSecurityManager::CORSSecurityMapping::REQUIRE_CORS_CHECKS;
nsSecurityFlags securityFlags =
nsContentSecurityManager::ComputeSecurityFlags(aRequest->CORSMode(),
corsMapping);
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;

Просмотреть файл

@ -32,6 +32,7 @@
#include "js/Utility.h"
#include "xpcpublic.h"
#include "GeckoProfiler.h"
#include "nsContentSecurityManager.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIContent.h"
#include "nsJSUtils.h"
@ -556,14 +557,9 @@ nsresult ScriptLoader::StartClassicLoad(ScriptLoadRequest* aRequest) {
}
nsSecurityFlags securityFlags =
aRequest->CORSMode() == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
: nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
if (aRequest->CORSMode() == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aRequest->CORSMode() == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
nsContentSecurityManager::ComputeSecurityFlags(
aRequest->CORSMode(), nsContentSecurityManager::CORSSecurityMapping::
CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS);
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;

Просмотреть файл

@ -992,6 +992,44 @@ void nsContentSecurityManager::MeasureUnexpectedPrivilegedLoads(
extra);
}
/* static */
nsSecurityFlags nsContentSecurityManager::ComputeSecurityFlags(
mozilla::CORSMode aCORSMode, CORSSecurityMapping aCORSSecurityMapping) {
if (aCORSSecurityMapping == CORSSecurityMapping::DISABLE_CORS_CHECKS) {
return nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
}
switch (aCORSMode) {
case CORS_NONE:
if (aCORSSecurityMapping == CORSSecurityMapping::REQUIRE_CORS_CHECKS) {
// CORS_NONE gets treated like CORS_ANONYMOUS in this mode
return nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT |
nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aCORSSecurityMapping ==
CORSSecurityMapping::CORS_NONE_MAPS_TO_INHERITED_CONTEXT) {
// CORS_NONE inherits
return nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT;
} else {
// CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS, the only remaining enum
// variant. CORSSecurityMapping::DISABLE_CORS_CHECKS returned early.
MOZ_ASSERT(aCORSSecurityMapping ==
CORSSecurityMapping::CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS);
return nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
}
case CORS_ANONYMOUS:
return nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT |
nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
case CORS_USE_CREDENTIALS:
return nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT |
nsILoadInfo::SEC_COOKIES_INCLUDE;
break;
default:
MOZ_ASSERT_UNREACHABLE("Invalid aCORSMode enum value");
return nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT |
nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
}
}
/* static */
nsresult nsContentSecurityManager::CheckAllowLoadInSystemPrivilegedContext(
nsIChannel* aChannel) {

Просмотреть файл

@ -7,9 +7,11 @@
#ifndef nsContentSecurityManager_h___
#define nsContentSecurityManager_h___
#include "mozilla/CORSMode.h"
#include "nsIContentSecurityManager.h"
#include "nsIChannel.h"
#include "nsIChannelEventSink.h"
#include "nsILoadInfo.h"
class nsILoadInfo;
class nsIStreamListener;
@ -42,6 +44,33 @@ class nsContentSecurityManager : public nsIContentSecurityManager,
nsIURI* aFinalURI,
const nsACString& aRemoteType);
enum CORSSecurityMapping {
// Disables all CORS checking overriding the value of aCORSMode. All checks
// are disabled even when CORSMode::CORS_ANONYMOUS or
// CORSMode::CORS_USE_CREDENTIALS is passed. This is mostly used for chrome
// code, where we don't need security checks. See
// SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL for the detailed explanation
// of the security mode.
DISABLE_CORS_CHECKS,
// Disables all CORS checking on CORSMode::CORS_NONE. The other two CORS
// modes CORSMode::CORS_ANONYMOUS and CORSMode::CORS_USE_CREDENTIALS are
// respected.
CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS,
// Allow load from any origin, but cross-origin requests require CORS. See
// SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT. Like above the other two
// CORS modes are unaffected and get parsed.
CORS_NONE_MAPS_TO_INHERITED_CONTEXT,
// Always require the server to acknowledge the request via CORS.
// CORSMode::CORS_NONE is parsed as if CORSMode::CORS_ANONYMOUS is passed.
REQUIRE_CORS_CHECKS,
};
// computes the security flags for the requested CORS mode
// @param aCORSSecurityMapping: See CORSSecurityMapping for variant
// descriptions
static nsSecurityFlags ComputeSecurityFlags(
mozilla::CORSMode aCORSMode, CORSSecurityMapping aCORSSecurityMapping);
private:
static nsresult CheckChannel(nsIChannel* aChannel);
static nsresult CheckFTPSubresourceLoad(nsIChannel* aChannel);

Просмотреть файл

@ -37,6 +37,7 @@
#include "nsCRT.h"
#include "nsComponentManagerUtils.h"
#include "nsContentPolicyUtils.h"
#include "nsContentSecurityManager.h"
#include "nsContentUtils.h"
#include "nsHttpChannel.h"
#include "nsIAsyncVerifyRedirectCallback.h"
@ -860,14 +861,10 @@ static nsresult NewImageChannel(
//
nsSecurityFlags securityFlags =
aCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
: nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
if (aCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
nsContentSecurityManager::ComputeSecurityFlags(
aCORSMode, nsContentSecurityManager::CORSSecurityMapping::
CORS_NONE_MAPS_TO_INHERITED_CONTEXT);
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
// Note we are calling NS_NewChannelWithTriggeringPrincipal() here with a

Просмотреть файл

@ -8,6 +8,7 @@
#include "gfxUserFontSet.h"
#include "mozilla/dom/Document.h"
#include "nsContentSecurityManager.h"
#include "nsIClassOfService.h"
#include "nsIHttpChannel.h"
#include "nsISupportsPriority.h"
@ -53,13 +54,15 @@ nsresult FontPreloader::BuildChannel(
// aCORSMode is ignored. We always load as crossorigin=anonymous, but a
// preload started with anything other then "anonymous" will never be found.
nsContentSecurityManager::CORSSecurityMapping corsMapping =
aURI->SchemeIs("file")
? nsContentSecurityManager::CORSSecurityMapping::
CORS_NONE_MAPS_TO_INHERITED_CONTEXT
: nsContentSecurityManager::CORSSecurityMapping::REQUIRE_CORS_CHECKS;
uint32_t securityFlags = 0;
if (aURI->SchemeIs("file")) {
securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT;
} else {
securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
}
nsSecurityFlags securityFlags =
nsContentSecurityManager::ComputeSecurityFlags(CORSMode::CORS_NONE,
corsMapping);
nsContentPolicyType contentPolicyType =
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD

Просмотреть файл

@ -25,6 +25,7 @@
#include "nsITimedChannel.h"
#include "nsICachingChannel.h"
#include "nsSyncLoadService.h"
#include "nsContentSecurityManager.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIContent.h"
@ -1230,9 +1231,14 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
mDocument);
}
// Synchronous loads should only be used internally. Therefore no CORS
// policy is needed.
nsSecurityFlags securityFlags =
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT |
nsILoadInfo::SEC_ALLOW_CHROME;
nsContentSecurityManager::ComputeSecurityFlags(
CORSMode::CORS_NONE, nsContentSecurityManager::CORSSecurityMapping::
CORS_NONE_MAPS_TO_INHERITED_CONTEXT);
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
nsContentPolicyType contentPolicyType =
aLoadData.mPreloadKind == StylePreloadKind::None
@ -1376,16 +1382,12 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
mSyncCallback = true;
#endif
CORSMode ourCORSMode = aLoadData.mSheet->GetCORSMode();
nsSecurityFlags securityFlags =
ourCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
: nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
if (ourCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (ourCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
nsContentSecurityManager::ComputeSecurityFlags(
aLoadData.mSheet->GetCORSMode(),
nsContentSecurityManager::CORSSecurityMapping::
CORS_NONE_MAPS_TO_INHERITED_CONTEXT);
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
nsContentPolicyType contentPolicyType =

Просмотреть файл

@ -7,12 +7,14 @@
#include "FetchPreloader.h"
#include "mozilla/CORSMode.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/Document.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Unused.h"
#include "nsContentPolicyUtils.h"
#include "nsContentSecurityManager.h"
#include "nsContentUtils.h"
#include "nsIChannel.h"
#include "nsIClassOfService.h"
@ -86,14 +88,9 @@ nsresult FetchPreloader::CreateChannel(
nsresult rv;
nsSecurityFlags securityFlags =
aCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
: nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
if (aCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
nsContentSecurityManager::ComputeSecurityFlags(
aCORSMode, nsContentSecurityManager::CORSSecurityMapping::
CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannelWithTriggeringPrincipal(