2015-07-20 05:12:11 +03:00
|
|
|
#include "nsContentSecurityManager.h"
|
2017-09-12 08:06:38 +03:00
|
|
|
#include "nsEscape.h"
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "nsIChannel.h"
|
2016-05-17 13:04:11 +03:00
|
|
|
#include "nsIHttpChannelInternal.h"
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "nsIStreamListener.h"
|
|
|
|
#include "nsILoadInfo.h"
|
2017-09-06 10:33:10 +03:00
|
|
|
#include "nsIOService.h"
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsCORSListenerProxy.h"
|
|
|
|
#include "nsIStreamListener.h"
|
Bug 1246540 - HSTS Priming Proof of Concept. r=ckerschb, r=mayhemer, r=jld, r=smaug, r=dkeeler, r=jmaher, p=ally
HSTS priming changes the order of mixed-content blocking and HSTS
upgrades, and adds a priming request to check if a mixed-content load is
accesible over HTTPS and the server supports upgrading via the
Strict-Transport-Security header.
Every call site that uses AsyncOpen2 passes through the mixed-content
blocker, and has a LoadInfo. If the mixed-content blocker marks the load as
needing HSTS priming, nsHttpChannel will build and send an HSTS priming
request on the same URI with the scheme upgraded to HTTPS. If the server
allows the upgrade, then channel performs an internal redirect to the HTTPS URI,
otherwise use the result of mixed-content blocker to allow or block the
load.
nsISiteSecurityService adds an optional boolean out parameter to
determine if the HSTS state is already cached for negative assertions.
If the host has been probed within the previous 24 hours, no HSTS
priming check will be sent.
MozReview-Commit-ID: ES1JruCtDdX
--HG--
extra : rebase_source : 2ac6c93c49f2862fc0b9e595eb0598cd1ea4bedf
2016-09-27 18:27:00 +03:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsMixedContentBlocker.h"
|
2017-01-03 22:59:30 +03:00
|
|
|
#include "nsCDefaultURIFixup.h"
|
|
|
|
#include "nsIURIFixup.h"
|
2017-02-03 06:49:07 +03:00
|
|
|
#include "nsIImageLoadingContent.h"
|
2017-09-06 10:33:10 +03:00
|
|
|
#include "NullPrincipal.h"
|
2017-02-03 06:49:07 +03:00
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
NS_IMPL_ISUPPORTS(nsContentSecurityManager,
|
|
|
|
nsIContentSecurityManager,
|
|
|
|
nsIChannelEventSink)
|
2015-09-18 19:27:15 +03:00
|
|
|
|
2017-09-06 10:33:10 +03:00
|
|
|
/* static */ bool
|
|
|
|
nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
|
|
|
nsIURI* aURI,
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
|
|
|
nsIPrincipal* aTriggeringPrincipal,
|
|
|
|
bool aLoadFromExternal)
|
|
|
|
{
|
|
|
|
// Let's block all toplevel document navigations to a data: URI.
|
|
|
|
// In all cases where the toplevel document is navigated to a
|
|
|
|
// data: URI the triggeringPrincipal is a codeBasePrincipal, or
|
|
|
|
// a NullPrincipal. In other cases, e.g. typing a data: URL into
|
|
|
|
// the URL-Bar, the triggeringPrincipal is a SystemPrincipal;
|
|
|
|
// we don't want to block those loads. Only exception, loads coming
|
|
|
|
// from an external applicaton (e.g. Thunderbird) don't load
|
|
|
|
// using a codeBasePrincipal, but we want to block those loads.
|
|
|
|
if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool isDataURI =
|
|
|
|
(NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI);
|
|
|
|
if (!isDataURI) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-09-06 17:27:05 +03:00
|
|
|
// Whitelist data: images as long as they are not SVGs
|
|
|
|
nsAutoCString filePath;
|
|
|
|
aURI->GetFilePath(filePath);
|
|
|
|
if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) &&
|
|
|
|
!StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-09-14 08:34:41 +03:00
|
|
|
// Whitelist data: PDFs
|
|
|
|
if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/pdf"))) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-09-06 10:33:10 +03:00
|
|
|
if (!aLoadFromExternal &&
|
|
|
|
nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-09-12 08:06:38 +03:00
|
|
|
nsAutoCString dataSpec;
|
|
|
|
aURI->GetSpec(dataSpec);
|
|
|
|
if (dataSpec.Length() > 50) {
|
|
|
|
dataSpec.Truncate(50);
|
|
|
|
dataSpec.AppendLiteral("...");
|
2017-09-06 10:33:10 +03:00
|
|
|
}
|
2017-09-12 08:06:38 +03:00
|
|
|
NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
|
2017-09-06 10:33:10 +03:00
|
|
|
const char16_t* params[] = { specUTF16.get() };
|
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
|
|
NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
|
|
|
|
// no doc available, log to browser console
|
|
|
|
nullptr,
|
|
|
|
nsContentUtils::eSECURITY_PROPERTIES,
|
|
|
|
"BlockTopLevelDataURINavigation",
|
|
|
|
params, ArrayLength(params));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-04 11:05:16 +03:00
|
|
|
static nsresult
|
2015-07-20 05:12:11 +03:00
|
|
|
ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
|
|
|
|
{
|
|
|
|
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
|
|
|
|
|
|
|
|
if (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS &&
|
|
|
|
securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED &&
|
|
|
|
securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS &&
|
|
|
|
securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
|
|
|
|
securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
|
|
|
MOZ_ASSERT(false, "need one securityflag from nsILoadInfo to perform security checks");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// all good, found the right security flags
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
static bool SchemeIs(nsIURI* aURI, const char* aScheme)
|
2015-07-20 05:12:11 +03:00
|
|
|
{
|
2015-09-15 04:59:35 +03:00
|
|
|
nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
|
|
|
|
NS_ENSURE_TRUE(baseURI, false);
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
bool isScheme = false;
|
|
|
|
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
|
2015-07-20 05:12:11 +03:00
|
|
|
}
|
|
|
|
|
2016-04-27 20:41:13 +03:00
|
|
|
|
|
|
|
static bool IsImageLoadInEditorAppType(nsILoadInfo* aLoadInfo)
|
|
|
|
{
|
|
|
|
// Editor apps get special treatment here, editors can load images
|
|
|
|
// from anywhere. This allows editor to insert images from file://
|
|
|
|
// into documents that are being edited.
|
|
|
|
nsContentPolicyType type = aLoadInfo->InternalContentPolicyType();
|
|
|
|
if (type != nsIContentPolicy::TYPE_INTERNAL_IMAGE &&
|
|
|
|
type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD &&
|
2016-10-13 10:43:54 +03:00
|
|
|
type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON &&
|
2016-04-27 20:41:13 +03:00
|
|
|
type != nsIContentPolicy::TYPE_IMAGESET) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t appType = nsIDocShell::APP_TYPE_UNKNOWN;
|
|
|
|
nsINode* node = aLoadInfo->LoadingNode();
|
|
|
|
if (!node) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
nsIDocument* doc = node->OwnerDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
|
|
|
|
if (!docShellTreeItem) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> root;
|
|
|
|
docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
|
|
|
|
if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
|
|
|
|
appType = nsIDocShell::APP_TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
return appType == nsIDocShell::APP_TYPE_EDITOR;
|
|
|
|
}
|
|
|
|
|
2015-11-04 11:05:16 +03:00
|
|
|
static nsresult
|
2015-07-20 05:12:11 +03:00
|
|
|
DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
|
|
|
|
{
|
2015-11-26 00:38:05 +03:00
|
|
|
// Bug 1228117: determine the correct security policy for DTD loads
|
|
|
|
if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DTD) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-05-29 21:40:16 +03:00
|
|
|
if (IsImageLoadInEditorAppType(aLoadInfo)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
uint32_t flags = nsIScriptSecurityManager::STANDARD;
|
|
|
|
if (aLoadInfo->GetAllowChrome()) {
|
|
|
|
flags |= nsIScriptSecurityManager::ALLOW_CHROME;
|
|
|
|
}
|
2016-05-24 00:57:31 +03:00
|
|
|
if (aLoadInfo->GetDisallowScript()) {
|
|
|
|
flags |= nsIScriptSecurityManager::DISALLOW_SCRIPT;
|
|
|
|
}
|
2015-09-15 04:59:35 +03:00
|
|
|
|
2016-05-29 21:40:16 +03:00
|
|
|
// Only call CheckLoadURIWithPrincipal() using the TriggeringPrincipal and not
|
|
|
|
// the LoadingPrincipal when SEC_ALLOW_CROSS_ORIGIN_* security flags are set,
|
|
|
|
// to allow, e.g. user stylesheets to load chrome:// URIs.
|
|
|
|
return nsContentUtils::GetSecurityManager()->
|
|
|
|
CheckLoadURIWithPrincipal(aLoadInfo->TriggeringPrincipal(),
|
2015-07-20 05:12:11 +03:00
|
|
|
aURI,
|
2015-09-15 04:59:35 +03:00
|
|
|
flags);
|
2015-07-20 05:12:11 +03:00
|
|
|
}
|
|
|
|
|
2015-11-04 11:05:16 +03:00
|
|
|
static bool
|
|
|
|
URIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
|
|
|
|
{
|
|
|
|
bool hasFlags;
|
|
|
|
nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, false);
|
|
|
|
|
|
|
|
return hasFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsresult
|
2015-12-07 02:33:15 +03:00
|
|
|
DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel* aChannel)
|
2015-07-20 05:12:11 +03:00
|
|
|
{
|
2015-11-04 11:05:16 +03:00
|
|
|
if (aLoadInfo->GetAllowChrome() &&
|
|
|
|
(URIHasFlags(aURI, nsIProtocolHandler::URI_IS_UI_RESOURCE) ||
|
|
|
|
SchemeIs(aURI, "moz-safe-about"))) {
|
|
|
|
// UI resources are allowed.
|
2015-09-15 04:59:35 +03:00
|
|
|
return DoCheckLoadURIChecks(aURI, aLoadInfo);
|
2015-07-20 05:12:11 +03:00
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
NS_ENSURE_FALSE(NS_HasBeenCrossOrigin(aChannel, true),
|
|
|
|
NS_ERROR_DOM_BAD_URI);
|
2015-12-05 18:34:47 +03:00
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
return NS_OK;
|
2015-09-15 04:59:35 +03:00
|
|
|
}
|
|
|
|
|
2015-11-04 11:05:16 +03:00
|
|
|
static nsresult
|
2015-09-15 04:59:35 +03:00
|
|
|
DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
|
|
|
|
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
|
|
|
|
{
|
2015-10-27 00:22:59 +03:00
|
|
|
MOZ_RELEASE_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
|
2016-03-19 02:14:03 +03:00
|
|
|
|
|
|
|
// No need to set up CORS if TriggeringPrincipal is the SystemPrincipal.
|
|
|
|
// For example, allow user stylesheets to load XBL from external files
|
|
|
|
// without requiring CORS.
|
|
|
|
if (nsContentUtils::IsSystemPrincipal(aLoadInfo->TriggeringPrincipal())) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsCORSListenerProxy> corsListener =
|
2015-07-20 05:12:11 +03:00
|
|
|
new nsCORSListenerProxy(aInAndOutListener,
|
|
|
|
loadingPrincipal,
|
2015-12-07 02:33:15 +03:00
|
|
|
aLoadInfo->GetCookiePolicy() ==
|
|
|
|
nsILoadInfo::SEC_COOKIES_INCLUDE);
|
2015-07-20 05:12:11 +03:00
|
|
|
// XXX: @arg: DataURIHandling::Allow
|
|
|
|
// lets use DataURIHandling::Allow for now and then decide on callsite basis. see also:
|
|
|
|
// http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCORSListenerProxy.h#33
|
|
|
|
nsresult rv = corsListener->Init(aChannel, DataURIHandling::Allow);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
aInAndOutListener = corsListener;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-11-04 11:05:16 +03:00
|
|
|
static nsresult
|
2016-05-17 13:04:11 +03:00
|
|
|
DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
|
2015-07-20 05:12:11 +03:00
|
|
|
{
|
2015-10-19 21:14:54 +03:00
|
|
|
nsContentPolicyType contentPolicyType =
|
|
|
|
aLoadInfo->GetExternalContentPolicyType();
|
2015-10-16 00:07:06 +03:00
|
|
|
nsContentPolicyType internalContentPolicyType =
|
|
|
|
aLoadInfo->InternalContentPolicyType();
|
2015-10-19 21:14:54 +03:00
|
|
|
nsCString mimeTypeGuess;
|
2017-09-05 19:01:07 +03:00
|
|
|
nsCOMPtr<nsISupports> requestingContext = nullptr;
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2017-01-03 22:59:30 +03:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
|
|
|
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
|
|
|
// TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
|
|
|
|
// be wyciwyg:// channels. Let's fix up the URI so we can
|
|
|
|
// perform proper security checks.
|
|
|
|
nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
|
|
|
|
if (NS_SUCCEEDED(rv) && urifixup) {
|
|
|
|
nsCOMPtr<nsIURI> fixedURI;
|
|
|
|
rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
uri = fixedURI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-06-29 13:59:45 +03:00
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
switch(contentPolicyType) {
|
2015-07-31 18:58:14 +03:00
|
|
|
case nsIContentPolicy::TYPE_OTHER: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-19 05:59:18 +03:00
|
|
|
case nsIContentPolicy::TYPE_SCRIPT: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("application/javascript");
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:02 +03:00
|
|
|
case nsIContentPolicy::TYPE_IMAGE: {
|
2016-04-27 20:41:13 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2016-02-03 07:35:02 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case nsIContentPolicy::TYPE_STYLESHEET: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("text/css");
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-06-28 10:37:55 +03:00
|
|
|
case nsIContentPolicy::TYPE_OBJECT: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-10 20:25:20 +03:00
|
|
|
case nsIContentPolicy::TYPE_DOCUMENT: {
|
2017-01-03 22:59:30 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
2017-09-05 19:01:07 +03:00
|
|
|
requestingContext = aLoadInfo->ContextForTopLevelLoad();
|
2015-08-10 20:25:20 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
case nsIContentPolicy::TYPE_REFRESH: {
|
2015-08-05 06:05:37 +03:00
|
|
|
MOZ_ASSERT(false, "contentPolicyType not supported yet");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
case nsIContentPolicy::TYPE_XBL: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-13 18:53:28 +03:00
|
|
|
case nsIContentPolicy::TYPE_PING: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-05 06:06:19 +03:00
|
|
|
case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
|
|
|
|
// alias nsIContentPolicy::TYPE_DATAREQUEST:
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
|
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
|
|
|
|
"type_xml requires requestingContext of type Document");
|
|
|
|
}
|
|
|
|
#endif
|
2015-10-19 21:14:54 +03:00
|
|
|
// We're checking for the external TYPE_XMLHTTPREQUEST here in case
|
|
|
|
// an addon creates a request with that type.
|
2015-08-10 20:19:08 +03:00
|
|
|
if (internalContentPolicyType ==
|
2015-10-19 21:14:54 +03:00
|
|
|
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST ||
|
|
|
|
internalContentPolicyType ==
|
|
|
|
nsIContentPolicy::TYPE_XMLHTTPREQUEST) {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
2015-08-10 20:19:08 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
MOZ_ASSERT(internalContentPolicyType ==
|
|
|
|
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
|
|
|
|
"can not set mime type guess for unexpected internal type");
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING(TEXT_EVENT_STREAM);
|
|
|
|
}
|
2015-08-05 06:06:19 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-05 06:05:37 +03:00
|
|
|
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
|
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
|
|
|
|
"type_subrequest requires requestingContext of type Element");
|
|
|
|
}
|
|
|
|
#endif
|
2015-08-05 06:05:37 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-11-20 21:55:54 +03:00
|
|
|
case nsIContentPolicy::TYPE_DTD: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
|
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
|
|
|
|
"type_dtd requires requestingContext of type Document");
|
|
|
|
}
|
|
|
|
#endif
|
2015-11-20 21:55:54 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-25 20:29:22 +03:00
|
|
|
case nsIContentPolicy::TYPE_FONT: {
|
2016-03-02 00:06:13 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2015-07-20 05:12:11 +03:00
|
|
|
break;
|
2015-07-25 20:29:22 +03:00
|
|
|
}
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2015-07-25 20:29:22 +03:00
|
|
|
case nsIContentPolicy::TYPE_MEDIA: {
|
|
|
|
if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_TRACK) {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("text/vtt");
|
2015-07-20 05:12:11 +03:00
|
|
|
}
|
2015-07-25 20:29:22 +03:00
|
|
|
else {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
}
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
|
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
|
|
|
|
"type_media requires requestingContext of type Element");
|
|
|
|
}
|
|
|
|
#endif
|
2015-07-20 05:12:11 +03:00
|
|
|
break;
|
2015-07-25 20:29:22 +03:00
|
|
|
}
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2015-07-27 21:57:56 +03:00
|
|
|
case nsIContentPolicy::TYPE_WEBSOCKET: {
|
2016-05-17 13:04:11 +03:00
|
|
|
// Websockets have to use the proxied URI:
|
|
|
|
// ws:// instead of http:// for CSP checks
|
|
|
|
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal
|
|
|
|
= do_QueryInterface(aChannel);
|
|
|
|
MOZ_ASSERT(httpChannelInternal);
|
|
|
|
if (httpChannelInternal) {
|
2016-12-20 06:49:32 +03:00
|
|
|
rv = httpChannelInternal->GetProxyURI(getter_AddRefs(uri));
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
2016-05-17 13:04:11 +03:00
|
|
|
}
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2015-07-28 06:39:17 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-27 21:57:56 +03:00
|
|
|
case nsIContentPolicy::TYPE_CSP_REPORT: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-29 02:34:47 +03:00
|
|
|
case nsIContentPolicy::TYPE_XSLT: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
|
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
|
|
|
|
"type_xslt requires requestingContext of type Document");
|
|
|
|
}
|
|
|
|
#endif
|
2015-09-29 02:34:47 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-28 06:39:17 +03:00
|
|
|
case nsIContentPolicy::TYPE_BEACON: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
|
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
|
|
|
|
"type_beacon requires requestingContext of type Document");
|
|
|
|
}
|
|
|
|
#endif
|
2015-07-28 06:39:17 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-20 04:24:36 +03:00
|
|
|
case nsIContentPolicy::TYPE_FETCH: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-25 20:29:22 +03:00
|
|
|
case nsIContentPolicy::TYPE_IMAGESET: {
|
2016-04-27 20:41:13 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
2015-07-20 05:12:11 +03:00
|
|
|
break;
|
2015-07-25 20:29:22 +03:00
|
|
|
}
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2016-04-08 00:13:09 +03:00
|
|
|
case nsIContentPolicy::TYPE_WEB_MANIFEST: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("application/manifest+json");
|
|
|
|
requestingContext = aLoadInfo->LoadingNode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
default:
|
|
|
|
// nsIContentPolicy::TYPE_INVALID
|
|
|
|
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
|
|
|
|
}
|
|
|
|
|
2017-01-03 22:59:30 +03:00
|
|
|
// For document loads we use the triggeringPrincipal as the originPrincipal.
|
|
|
|
// Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
|
|
(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
|
|
|
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
|
|
|
|
? aLoadInfo->TriggeringPrincipal()
|
|
|
|
: aLoadInfo->LoadingPrincipal();
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
2016-05-17 13:04:11 +03:00
|
|
|
rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
|
|
|
|
uri,
|
2017-01-03 22:59:30 +03:00
|
|
|
principal,
|
2016-05-17 13:04:11 +03:00
|
|
|
requestingContext,
|
|
|
|
mimeTypeGuess,
|
|
|
|
nullptr, //extra,
|
|
|
|
&shouldLoad,
|
2017-07-11 01:00:03 +03:00
|
|
|
nsContentUtils::GetContentPolicy());
|
2017-01-03 22:59:30 +03:00
|
|
|
|
|
|
|
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
|
|
|
if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
|
|
|
|
(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
|
|
|
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
|
|
|
|
// for docshell loads we might have to return SHOW_ALT.
|
|
|
|
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
|
|
|
|
}
|
2015-07-20 05:12:11 +03:00
|
|
|
return NS_ERROR_CONTENT_BLOCKED;
|
|
|
|
}
|
Bug 1246540 - HSTS Priming Proof of Concept. r=ckerschb, r=mayhemer, r=jld, r=smaug, r=dkeeler, r=jmaher, p=ally
HSTS priming changes the order of mixed-content blocking and HSTS
upgrades, and adds a priming request to check if a mixed-content load is
accesible over HTTPS and the server supports upgrading via the
Strict-Transport-Security header.
Every call site that uses AsyncOpen2 passes through the mixed-content
blocker, and has a LoadInfo. If the mixed-content blocker marks the load as
needing HSTS priming, nsHttpChannel will build and send an HSTS priming
request on the same URI with the scheme upgraded to HTTPS. If the server
allows the upgrade, then channel performs an internal redirect to the HTTPS URI,
otherwise use the result of mixed-content blocker to allow or block the
load.
nsISiteSecurityService adds an optional boolean out parameter to
determine if the HSTS state is already cached for negative assertions.
If the host has been probed within the previous 24 hours, no HSTS
priming check will be sent.
MozReview-Commit-ID: ES1JruCtDdX
--HG--
extra : rebase_source : 2ac6c93c49f2862fc0b9e595eb0598cd1ea4bedf
2016-09-27 18:27:00 +03:00
|
|
|
|
|
|
|
if (nsMixedContentBlocker::sSendHSTSPriming) {
|
|
|
|
rv = nsMixedContentBlocker::MarkLoadInfoForPriming(uri,
|
|
|
|
requestingContext,
|
|
|
|
aLoadInfo);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Based on the security flags provided in the loadInfo of the channel,
|
|
|
|
* doContentSecurityCheck() performs the following content security checks
|
|
|
|
* before opening the channel:
|
|
|
|
*
|
|
|
|
* (1) Same Origin Policy Check (if applicable)
|
|
|
|
* (2) Allow Cross Origin but perform sanity checks whether a principal
|
|
|
|
* is allowed to access the following URL.
|
|
|
|
* (3) Perform CORS check (if applicable)
|
|
|
|
* (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...)
|
|
|
|
*
|
|
|
|
* @param aChannel
|
|
|
|
* The channel to perform the security checks on.
|
|
|
|
* @param aInAndOutListener
|
|
|
|
* The streamListener that is passed to channel->AsyncOpen2() that is now potentially
|
|
|
|
* wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs
|
|
|
|
* to be set as new streamListener on the channel.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel,
|
|
|
|
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aChannel);
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
|
|
|
|
|
|
|
if (!loadInfo) {
|
|
|
|
MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
// if dealing with a redirected channel then we have already installed
|
|
|
|
// streamlistener and redirect proxies and so we are done.
|
|
|
|
if (loadInfo->GetInitialSecurityCheckDone()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
// make sure that only one of the five security flags is set in the loadinfo
|
|
|
|
// e.g. do not require same origin and allow cross origin at the same time
|
|
|
|
nsresult rv = ValidateSecurityFlags(loadInfo);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// since aChannel was openend using asyncOpen2() we have to make sure
|
|
|
|
// that redirects of that channel also get openend using asyncOpen2()
|
|
|
|
// please note that some implementations of ::AsyncOpen2 might already
|
|
|
|
// have set that flag to true (e.g. nsViewSourceChannel) in which case
|
|
|
|
// we just set the flag again.
|
2016-08-12 08:19:29 +03:00
|
|
|
loadInfo->SetEnforceSecurity(true);
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
if (loadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
|
|
|
rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2015-12-07 02:33:15 +03:00
|
|
|
|
|
|
|
rv = CheckChannel(aChannel);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-12-07 02:33:14 +03:00
|
|
|
|
|
|
|
// Perform all ContentPolicy checks (MixedContent, CSP, ...)
|
2016-05-17 13:04:11 +03:00
|
|
|
rv = DoContentSecurityChecks(aChannel, loadInfo);
|
2015-12-07 02:33:14 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// now lets set the initalSecurityFlag for subsequent calls
|
2016-08-12 08:19:29 +03:00
|
|
|
loadInfo->SetInitialSecurityCheckDone(true);
|
2015-12-07 02:33:14 +03:00
|
|
|
|
|
|
|
// all security checks passed - lets allow the load
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|
|
|
nsIChannel* aNewChannel,
|
|
|
|
uint32_t aRedirFlags,
|
|
|
|
nsIAsyncVerifyRedirectCallback *aCb)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aOldChannel->GetLoadInfo();
|
|
|
|
// Are we enforcing security using LoadInfo?
|
|
|
|
if (loadInfo && loadInfo->GetEnforceSecurity()) {
|
|
|
|
nsresult rv = CheckChannel(aNewChannel);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aOldChannel->Cancel(rv);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-06 10:33:10 +03:00
|
|
|
// Redirecting to a toplevel data: URI is not allowed, hence we pass
|
|
|
|
// a NullPrincipal as the TriggeringPrincipal to
|
|
|
|
// AllowTopLevelNavigationToDataURI() which definitely blocks any
|
|
|
|
// data: URI load.
|
|
|
|
nsCOMPtr<nsILoadInfo> newLoadInfo = aNewChannel->GetLoadInfo();
|
|
|
|
if (newLoadInfo) {
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIPrincipal> nullTriggeringPrincipal = NullPrincipal::Create();
|
|
|
|
if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
|
|
|
uri,
|
|
|
|
newLoadInfo->GetExternalContentPolicyType(),
|
|
|
|
nullTriggeringPrincipal,
|
|
|
|
false)) {
|
|
|
|
// logging to console happens within AllowTopLevelNavigationToDataURI
|
|
|
|
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
// Also verify that the redirecting server is allowed to redirect to the
|
|
|
|
// given URI
|
|
|
|
nsCOMPtr<nsIPrincipal> oldPrincipal;
|
|
|
|
nsContentUtils::GetSecurityManager()->
|
|
|
|
GetChannelResultPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> newURI;
|
2017-07-13 06:51:00 +03:00
|
|
|
Unused << NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI));
|
|
|
|
NS_ENSURE_STATE(oldPrincipal && newURI);
|
2015-12-07 02:33:14 +03:00
|
|
|
|
|
|
|
const uint32_t flags =
|
|
|
|
nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
|
|
|
|
nsIScriptSecurityManager::DISALLOW_SCRIPT;
|
|
|
|
nsresult rv = nsContentUtils::GetSecurityManager()->
|
|
|
|
CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
|
Bug 1246540 - HSTS Priming Proof of Concept. r=ckerschb, r=mayhemer, r=jld, r=smaug, r=dkeeler, r=jmaher, p=ally
HSTS priming changes the order of mixed-content blocking and HSTS
upgrades, and adds a priming request to check if a mixed-content load is
accesible over HTTPS and the server supports upgrading via the
Strict-Transport-Security header.
Every call site that uses AsyncOpen2 passes through the mixed-content
blocker, and has a LoadInfo. If the mixed-content blocker marks the load as
needing HSTS priming, nsHttpChannel will build and send an HSTS priming
request on the same URI with the scheme upgraded to HTTPS. If the server
allows the upgrade, then channel performs an internal redirect to the HTTPS URI,
otherwise use the result of mixed-content blocker to allow or block the
load.
nsISiteSecurityService adds an optional boolean out parameter to
determine if the HSTS state is already cached for negative assertions.
If the host has been probed within the previous 24 hours, no HSTS
priming check will be sent.
MozReview-Commit-ID: ES1JruCtDdX
--HG--
extra : rebase_source : 2ac6c93c49f2862fc0b9e595eb0598cd1ea4bedf
2016-09-27 18:27:00 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-12-07 02:33:14 +03:00
|
|
|
|
|
|
|
aCb->OnRedirectVerifyCallback(NS_OK);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
static void
|
|
|
|
AddLoadFlags(nsIRequest *aRequest, nsLoadFlags aNewFlags)
|
|
|
|
{
|
|
|
|
nsLoadFlags flags;
|
|
|
|
aRequest->GetLoadFlags(&flags);
|
|
|
|
flags |= aNewFlags;
|
|
|
|
aRequest->SetLoadFlags(flags);
|
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
/*
|
|
|
|
* Check that this channel passes all security checks. Returns an error code
|
|
|
|
* if this requesst should not be permitted.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
|
|
|
MOZ_ASSERT(loadInfo);
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2017-01-03 22:59:30 +03:00
|
|
|
nsContentPolicyType contentPolicyType =
|
|
|
|
loadInfo->GetExternalContentPolicyType();
|
|
|
|
|
|
|
|
if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
|
|
|
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
|
|
|
// TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
|
|
|
|
// be wyciwyg:// channels. Let's fix up the URI so we can
|
|
|
|
// perform proper security checks.
|
|
|
|
nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
|
|
|
|
if (NS_SUCCEEDED(rv) && urifixup) {
|
|
|
|
nsCOMPtr<nsIURI> fixedURI;
|
|
|
|
rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
uri = fixedURI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
// Handle cookie policies
|
|
|
|
uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
|
|
|
|
if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
|
2016-04-14 02:30:28 +03:00
|
|
|
|
|
|
|
// We shouldn't have the SEC_COOKIES_SAME_ORIGIN flag for top level loads
|
|
|
|
MOZ_ASSERT(loadInfo->GetExternalContentPolicyType() !=
|
|
|
|
nsIContentPolicy::TYPE_DOCUMENT);
|
2015-12-07 02:33:15 +03:00
|
|
|
nsIPrincipal* loadingPrincipal = loadInfo->LoadingPrincipal();
|
|
|
|
|
|
|
|
// It doesn't matter what we pass for the third, data-inherits, argument.
|
|
|
|
// Any protocol which inherits won't pay attention to cookies anyway.
|
|
|
|
rv = loadingPrincipal->CheckMayLoad(uri, false, false);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) {
|
|
|
|
AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
|
|
|
|
}
|
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
|
2015-12-07 02:33:15 +03:00
|
|
|
|
|
|
|
// CORS mode is handled by nsCORSListenerProxy
|
2015-12-07 02:33:14 +03:00
|
|
|
if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
2015-12-07 02:33:15 +03:00
|
|
|
if (NS_HasBeenCrossOrigin(aChannel)) {
|
|
|
|
loadInfo->MaybeIncreaseTainting(LoadTainting::CORS);
|
|
|
|
}
|
2015-12-07 02:33:14 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-03-19 02:14:03 +03:00
|
|
|
// Allow subresource loads if TriggeringPrincipal is the SystemPrincipal.
|
|
|
|
// For example, allow user stylesheets to load XBL from external files.
|
|
|
|
if (nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) &&
|
|
|
|
loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT &&
|
|
|
|
loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
2016-03-02 03:11:37 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
// if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
|
|
|
|
if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) ||
|
|
|
|
(securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {
|
2015-12-07 02:33:15 +03:00
|
|
|
rv = DoSOPChecks(uri, loadInfo, aChannel);
|
2015-09-15 04:59:35 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2015-07-20 05:12:11 +03:00
|
|
|
|
2015-09-15 04:59:35 +03:00
|
|
|
if ((securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) ||
|
|
|
|
(securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
|
2015-12-07 02:33:15 +03:00
|
|
|
if (NS_HasBeenCrossOrigin(aChannel)) {
|
|
|
|
loadInfo->MaybeIncreaseTainting(LoadTainting::Opaque);
|
|
|
|
}
|
2015-09-15 04:59:35 +03:00
|
|
|
// Please note that DoCheckLoadURIChecks should only be enforced for
|
|
|
|
// cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set
|
|
|
|
// within the loadInfo, then then CheckLoadURIWithPrincipal is performed
|
|
|
|
// within nsCorsListenerProxy
|
2015-12-07 02:33:14 +03:00
|
|
|
rv = DoCheckLoadURIChecks(uri, loadInfo);
|
2015-12-05 18:34:47 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2017-02-03 06:49:07 +03:00
|
|
|
// TODO: Bug 1371237
|
|
|
|
// consider calling SetBlockedRequest in nsContentSecurityManager::CheckChannel
|
2015-12-05 18:34:47 +03:00
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-09-18 19:27:15 +03:00
|
|
|
|
|
|
|
// ==== nsIContentSecurityManager implementation =====
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsContentSecurityManager::PerformSecurityCheck(nsIChannel* aChannel,
|
|
|
|
nsIStreamListener* aStreamListener,
|
|
|
|
nsIStreamListener** outStreamListener)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIStreamListener> inAndOutListener = aStreamListener;
|
|
|
|
nsresult rv = doContentSecurityCheck(aChannel, inAndOutListener);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
inAndOutListener.forget(outStreamListener);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-11-06 22:10:17 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-04-26 13:30:43 +03:00
|
|
|
nsContentSecurityManager::IsOriginPotentiallyTrustworthy(nsIPrincipal* aPrincipal,
|
|
|
|
bool* aIsTrustWorthy)
|
2015-11-06 22:10:17 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2016-04-26 13:30:43 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aPrincipal);
|
2015-11-06 22:10:17 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aIsTrustWorthy);
|
|
|
|
|
2016-04-26 13:30:43 +03:00
|
|
|
if (aPrincipal->GetIsSystemPrincipal()) {
|
|
|
|
*aIsTrustWorthy = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The following implements:
|
|
|
|
// https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
|
|
|
|
|
2015-11-06 22:10:17 +03:00
|
|
|
*aIsTrustWorthy = false;
|
2016-04-26 13:30:43 +03:00
|
|
|
|
|
|
|
if (aPrincipal->GetIsNullPrincipal()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(aPrincipal->GetIsCodebasePrincipal(),
|
|
|
|
"Nobody is expected to call us with an nsIExpandedPrincipal");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
aPrincipal->GetURI(getter_AddRefs(uri));
|
|
|
|
|
2015-11-06 22:10:17 +03:00
|
|
|
nsAutoCString scheme;
|
2016-04-26 13:30:43 +03:00
|
|
|
nsresult rv = uri->GetScheme(scheme);
|
2015-11-20 01:22:57 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-11-06 22:10:17 +03:00
|
|
|
|
2016-04-26 13:30:43 +03:00
|
|
|
// Blobs are expected to inherit their principal so we don't expect to have
|
|
|
|
// a codebase principal with scheme 'blob' here. We can't assert that though
|
|
|
|
// since someone could mess with a non-blob URI to give it that scheme.
|
2016-09-01 08:01:16 +03:00
|
|
|
NS_WARNING_ASSERTION(!scheme.EqualsLiteral("blob"),
|
|
|
|
"IsOriginPotentiallyTrustworthy ignoring blob scheme");
|
2016-04-26 13:30:43 +03:00
|
|
|
|
2016-01-18 17:54:18 +03:00
|
|
|
// According to the specification, the user agent may choose to extend the
|
|
|
|
// trust to other, vendor-specific URL schemes. We use this for "resource:",
|
|
|
|
// which is technically a substituting protocol handler that is not limited to
|
|
|
|
// local resource mapping, but in practice is never mapped remotely as this
|
|
|
|
// would violate assumptions a lot of code makes.
|
2015-11-06 22:10:17 +03:00
|
|
|
if (scheme.EqualsLiteral("https") ||
|
|
|
|
scheme.EqualsLiteral("file") ||
|
2016-01-18 17:54:18 +03:00
|
|
|
scheme.EqualsLiteral("resource") ||
|
2015-11-10 21:50:46 +03:00
|
|
|
scheme.EqualsLiteral("app") ||
|
2016-06-02 18:14:27 +03:00
|
|
|
scheme.EqualsLiteral("moz-extension") ||
|
2015-11-10 21:50:46 +03:00
|
|
|
scheme.EqualsLiteral("wss")) {
|
2015-11-06 22:10:17 +03:00
|
|
|
*aIsTrustWorthy = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString host;
|
2016-04-26 13:30:43 +03:00
|
|
|
rv = uri->GetHost(host);
|
2015-11-20 01:22:57 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-11-06 22:10:17 +03:00
|
|
|
|
2017-09-06 11:13:45 +03:00
|
|
|
if (host.EqualsLiteral("127.0.0.1") ||
|
|
|
|
host.EqualsLiteral("localhost") ||
|
|
|
|
host.EqualsLiteral("::1")) {
|
2015-11-06 22:10:17 +03:00
|
|
|
*aIsTrustWorthy = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-10-10 18:32:24 +03:00
|
|
|
|
|
|
|
// If a host is not considered secure according to the default algorithm, then
|
|
|
|
// check to see if it has been whitelisted by the user. We only apply this
|
|
|
|
// whitelist for network resources, i.e., those with scheme "http" or "ws".
|
|
|
|
// The pref should contain a comma-separated list of hostnames.
|
|
|
|
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("ws")) {
|
2017-07-31 07:28:48 +03:00
|
|
|
nsAutoCString whitelist;
|
|
|
|
nsresult rv =
|
|
|
|
Preferences::GetCString("dom.securecontext.whitelist", whitelist);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2016-10-10 18:32:24 +03:00
|
|
|
nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
|
|
|
|
while (tokenizer.hasMoreTokens()) {
|
2017-06-20 12:19:52 +03:00
|
|
|
const nsACString& allowedHost = tokenizer.nextToken();
|
2016-10-10 18:32:24 +03:00
|
|
|
if (host.Equals(allowedHost)) {
|
|
|
|
*aIsTrustWorthy = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-06 22:10:17 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|