2017-10-27 00:54:59 +03:00
|
|
|
/* -*- 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/. */
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "nsContentSecurityManager.h"
|
2017-09-12 08:06:38 +03:00
|
|
|
#include "nsEscape.h"
|
2017-11-13 23:25:02 +03:00
|
|
|
#include "nsDataHandler.h"
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "nsIChannel.h"
|
2016-05-17 13:04:11 +03:00
|
|
|
#include "nsIHttpChannelInternal.h"
|
2018-01-30 07:10:53 +03:00
|
|
|
#include "nsINode.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"
|
2017-01-03 22:59:30 +03:00
|
|
|
#include "nsIURIFixup.h"
|
2017-02-03 06:49:07 +03:00
|
|
|
#include "nsIImageLoadingContent.h"
|
2018-09-28 16:06:29 +03:00
|
|
|
#include "nsIRedirectHistoryEntry.h"
|
2017-02-03 06:49:07 +03:00
|
|
|
|
2019-01-03 23:55:38 +03:00
|
|
|
#include "mozilla/BasePrincipal.h"
|
2019-04-18 16:54:43 +03:00
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
2015-07-20 05:12:11 +03:00
|
|
|
#include "mozilla/dom/Element.h"
|
2018-03-01 11:44:30 +03:00
|
|
|
#include "mozilla/dom/nsMixedContentBlocker.h"
|
2019-04-10 01:39:01 +03:00
|
|
|
#include "mozilla/dom/BrowserChild.h"
|
2018-12-17 04:27:58 +03:00
|
|
|
#include "mozilla/Components.h"
|
2018-09-28 16:06:29 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2019-04-10 17:20:12 +03:00
|
|
|
#include "xpcpublic.h"
|
2018-09-28 16:06:29 +03:00
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager,
|
|
|
|
nsIChannelEventSink)
|
2015-09-18 19:27:15 +03:00
|
|
|
|
2018-09-28 16:06:29 +03:00
|
|
|
static mozilla::LazyLogModule sCSMLog("CSMLog");
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* static */
|
|
|
|
bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
2017-11-03 15:23:11 +03:00
|
|
|
nsIChannel* aChannel) {
|
2017-09-06 10:33:10 +03:00
|
|
|
// Let's block all toplevel document navigations to a data: URI.
|
|
|
|
// In all cases where the toplevel document is navigated to a
|
2019-07-08 19:37:45 +03:00
|
|
|
// data: URI the triggeringPrincipal is a contentPrincipal, or
|
2017-09-06 10:33:10 +03:00
|
|
|
// 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
|
2019-07-08 19:37:45 +03:00
|
|
|
// using a contentPrincipal, but we want to block those loads.
|
2017-09-06 10:33:10 +03:00
|
|
|
if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-02-20 15:27:25 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2017-11-03 15:23:11 +03:00
|
|
|
if (loadInfo->GetExternalContentPolicyType() !=
|
|
|
|
nsIContentPolicy::TYPE_DOCUMENT) {
|
2017-09-06 10:33:10 +03:00
|
|
|
return true;
|
|
|
|
}
|
2017-11-08 22:01:41 +03:00
|
|
|
if (loadInfo->GetForceAllowDataURI()) {
|
|
|
|
// if the loadinfo explicitly allows the data URI navigation, let's allow it
|
|
|
|
// now
|
|
|
|
return true;
|
|
|
|
}
|
2017-11-03 15:23:11 +03:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, true);
|
2017-09-06 10:33:10 +03:00
|
|
|
bool isDataURI =
|
2017-11-03 15:23:11 +03:00
|
|
|
(NS_SUCCEEDED(uri->SchemeIs("data", &isDataURI)) && isDataURI);
|
2017-09-06 10:33:10 +03:00
|
|
|
if (!isDataURI) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-11-13 23:25:02 +03:00
|
|
|
|
|
|
|
nsAutoCString spec;
|
|
|
|
rv = uri->GetSpec(spec);
|
|
|
|
NS_ENSURE_SUCCESS(rv, true);
|
|
|
|
nsAutoCString contentType;
|
|
|
|
bool base64;
|
2018-09-07 17:47:51 +03:00
|
|
|
rv = nsDataHandler::ParseURI(spec, contentType, nullptr, base64, nullptr);
|
2017-11-13 23:25:02 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, true);
|
|
|
|
|
2017-09-06 17:27:05 +03:00
|
|
|
// Whitelist data: images as long as they are not SVGs
|
2017-11-13 23:25:02 +03:00
|
|
|
if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/")) &&
|
|
|
|
!contentType.EqualsLiteral("image/svg+xml")) {
|
2017-09-06 17:27:05 +03:00
|
|
|
return true;
|
|
|
|
}
|
2017-11-13 23:25:02 +03:00
|
|
|
// Whitelist all plain text types as well as data: PDFs.
|
|
|
|
if (nsContentUtils::IsPlainTextType(contentType) ||
|
|
|
|
contentType.EqualsLiteral("application/pdf")) {
|
2017-09-14 08:34:41 +03:00
|
|
|
return true;
|
|
|
|
}
|
2017-11-03 15:23:11 +03:00
|
|
|
// Redirecting to a toplevel data: URI is not allowed, hence we make
|
|
|
|
// sure the RedirectChain is empty.
|
|
|
|
if (!loadInfo->GetLoadTriggeredFromExternal() &&
|
|
|
|
nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) &&
|
|
|
|
loadInfo->RedirectChain().IsEmpty()) {
|
2017-09-06 10:33:10 +03:00
|
|
|
return true;
|
|
|
|
}
|
2017-09-12 08:06:38 +03:00
|
|
|
nsAutoCString dataSpec;
|
2017-11-03 15:23:11 +03:00
|
|
|
uri->GetSpec(dataSpec);
|
2017-09-12 08:06:38 +03:00
|
|
|
if (dataSpec.Length() > 50) {
|
|
|
|
dataSpec.Truncate(50);
|
|
|
|
dataSpec.AppendLiteral("...");
|
2017-09-06 10:33:10 +03:00
|
|
|
}
|
2018-05-30 22:21:18 +03:00
|
|
|
nsCOMPtr<nsISupports> context = loadInfo->ContextForTopLevelLoad();
|
2019-04-10 01:39:01 +03:00
|
|
|
nsCOMPtr<nsIBrowserChild> browserChild = do_QueryInterface(context);
|
2019-01-02 16:05:23 +03:00
|
|
|
nsCOMPtr<Document> doc;
|
2019-04-10 01:39:01 +03:00
|
|
|
if (browserChild) {
|
|
|
|
doc = static_cast<mozilla::dom::BrowserChild*>(browserChild.get())
|
2019-04-13 04:53:10 +03:00
|
|
|
->GetTopLevelDocument();
|
2017-11-03 15:23:11 +03:00
|
|
|
}
|
2019-06-09 00:26:12 +03:00
|
|
|
AutoTArray<nsString, 1> params;
|
|
|
|
CopyUTF8toUTF16(NS_UnescapeURL(dataSpec), *params.AppendElement());
|
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
|
|
NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), doc,
|
|
|
|
nsContentUtils::eSECURITY_PROPERTIES,
|
|
|
|
"BlockTopLevelDataURINavigation", params);
|
2017-09-06 10:33:10 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* static */
|
|
|
|
bool nsContentSecurityManager::AllowInsecureRedirectToDataURI(
|
2018-02-18 21:52:52 +03:00
|
|
|
nsIChannel* aNewChannel) {
|
2019-02-20 15:27:25 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aNewChannel->LoadInfo();
|
2018-02-18 21:52:52 +03:00
|
|
|
if (loadInfo->GetExternalContentPolicyType() !=
|
|
|
|
nsIContentPolicy::TYPE_SCRIPT) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> newURI;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI));
|
|
|
|
if (NS_FAILED(rv) || !newURI) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool isDataURI =
|
|
|
|
(NS_SUCCEEDED(newURI->SchemeIs("data", &isDataURI)) && isDataURI);
|
|
|
|
if (!isDataURI) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Web Extensions are exempt from that restriction and are allowed to redirect
|
|
|
|
// a channel to a data: URI. When a web extension redirects a channel, we set
|
|
|
|
// a flag on the loadInfo which allows us to identify such redirects here.
|
|
|
|
if (loadInfo->GetAllowInsecureRedirectToDataURI()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString dataSpec;
|
|
|
|
newURI->GetSpec(dataSpec);
|
|
|
|
if (dataSpec.Length() > 50) {
|
|
|
|
dataSpec.Truncate(50);
|
|
|
|
dataSpec.AppendLiteral("...");
|
|
|
|
}
|
2019-01-02 16:05:23 +03:00
|
|
|
nsCOMPtr<Document> doc;
|
2018-02-18 21:52:52 +03:00
|
|
|
nsINode* node = loadInfo->LoadingNode();
|
|
|
|
if (node) {
|
|
|
|
doc = node->OwnerDoc();
|
|
|
|
}
|
2019-06-09 00:26:12 +03:00
|
|
|
AutoTArray<nsString, 1> params;
|
|
|
|
CopyUTF8toUTF16(NS_UnescapeURL(dataSpec), *params.AppendElement());
|
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
|
|
NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), doc,
|
|
|
|
nsContentUtils::eSECURITY_PROPERTIES,
|
|
|
|
"BlockSubresourceRedirectToData", params);
|
2018-02-18 21:52:52 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-04-18 16:54:43 +03:00
|
|
|
/* static */
|
|
|
|
void nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
|
|
|
nsIPrincipal* subjectPrincipal, JSContext* cx) {
|
|
|
|
if (!subjectPrincipal->IsSystemPrincipal()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Preferences::GetBool("security.allow_eval_with_system_principal")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static StaticAutoPtr<nsTArray<nsCString>> sUrisAllowEval;
|
|
|
|
JS::AutoFilename scriptFilename;
|
|
|
|
if (JS::DescribeScriptedCaller(cx, &scriptFilename)) {
|
|
|
|
if (!sUrisAllowEval) {
|
|
|
|
sUrisAllowEval = new nsTArray<nsCString>();
|
|
|
|
nsAutoCString urisAllowEval;
|
|
|
|
Preferences::GetCString("security.uris_using_eval_with_system_principal",
|
|
|
|
urisAllowEval);
|
|
|
|
for (const nsACString& filenameString : urisAllowEval.Split(',')) {
|
|
|
|
sUrisAllowEval->AppendElement(filenameString);
|
|
|
|
}
|
|
|
|
ClearOnShutdown(&sUrisAllowEval);
|
|
|
|
}
|
|
|
|
|
2019-07-13 02:05:25 +03:00
|
|
|
nsAutoCString fileName;
|
2019-04-18 16:54:43 +03:00
|
|
|
fileName = nsAutoCString(scriptFilename.get());
|
|
|
|
// Extract file name alone if scriptFilename contains line number
|
|
|
|
// separated by multiple space delimiters in few cases.
|
|
|
|
int32_t fileNameIndex = fileName.FindChar(' ');
|
|
|
|
if (fileNameIndex != -1) {
|
|
|
|
fileName = Substring(fileName, 0, fileNameIndex);
|
|
|
|
}
|
|
|
|
ToLowerCase(fileName);
|
|
|
|
|
|
|
|
for (auto& uriEntry : *sUrisAllowEval) {
|
|
|
|
if (StringEndsWith(fileName, uriEntry)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-13 02:05:25 +03:00
|
|
|
MOZ_ASSERT(false, "do not use eval with system privileges");
|
2019-04-18 16:54:43 +03:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* static */
|
|
|
|
nsresult nsContentSecurityManager::CheckFTPSubresourceLoad(
|
2018-04-06 01:27:02 +03:00
|
|
|
nsIChannel* aChannel) {
|
2018-05-02 14:32:08 +03:00
|
|
|
// We dissallow using FTP resources as a subresource almost everywhere.
|
2018-03-26 22:05:08 +03:00
|
|
|
// The only valid way to use FTP resources is loading it as
|
|
|
|
// a top level document.
|
2018-04-09 22:07:01 +03:00
|
|
|
if (!mozilla::net::nsIOService::BlockFTPSubresources()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2018-03-26 22:05:08 +03:00
|
|
|
|
2019-02-20 15:27:25 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2018-03-26 22:05:08 +03:00
|
|
|
nsContentPolicyType type = loadInfo->GetExternalContentPolicyType();
|
2018-06-22 00:31:13 +03:00
|
|
|
|
|
|
|
// Allow top-level FTP documents and save-as download of FTP files on
|
|
|
|
// HTTP pages.
|
|
|
|
if (type == nsIContentPolicy::TYPE_DOCUMENT ||
|
|
|
|
type == nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD) {
|
2018-04-06 01:27:02 +03:00
|
|
|
return NS_OK;
|
2018-03-26 22:05:08 +03:00
|
|
|
}
|
|
|
|
|
2018-06-19 14:58:41 +03:00
|
|
|
// Allow the system principal to load everything. This is meant to
|
|
|
|
// temporarily fix downloads and pdf.js.
|
|
|
|
nsIPrincipal* triggeringPrincipal = loadInfo->TriggeringPrincipal();
|
|
|
|
if (nsContentUtils::IsSystemPrincipal(triggeringPrincipal)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-26 22:05:08 +03:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
2018-04-06 01:27:02 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!uri) {
|
|
|
|
return NS_OK;
|
2018-03-26 22:05:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isFtpURI = (NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtpURI)) && isFtpURI);
|
|
|
|
if (!isFtpURI) {
|
2018-04-06 01:27:02 +03:00
|
|
|
return NS_OK;
|
2018-03-26 22:05:08 +03:00
|
|
|
}
|
|
|
|
|
2018-05-02 14:32:08 +03:00
|
|
|
// Allow loading FTP subresources in FTP documents, like XML.
|
|
|
|
nsCOMPtr<nsIURI> triggeringURI;
|
|
|
|
triggeringPrincipal->GetURI(getter_AddRefs(triggeringURI));
|
|
|
|
if (triggeringURI && nsContentUtils::SchemeIs(triggeringURI, "ftp")) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
nsCOMPtr<Document> doc;
|
2018-03-26 22:05:08 +03:00
|
|
|
if (nsINode* node = loadInfo->LoadingNode()) {
|
|
|
|
doc = node->OwnerDoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString spec;
|
|
|
|
uri->GetSpec(spec);
|
2019-06-09 00:26:12 +03:00
|
|
|
AutoTArray<nsString, 1> params;
|
|
|
|
CopyUTF8toUTF16(NS_UnescapeURL(spec), *params.AppendElement());
|
2018-03-26 22:05:08 +03:00
|
|
|
|
|
|
|
nsContentUtils::ReportToConsole(
|
|
|
|
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("FTP_URI_BLOCKED"), doc,
|
2019-06-09 00:26:12 +03:00
|
|
|
nsContentUtils::eSECURITY_PROPERTIES, "BlockSubresourceFTP", params);
|
2018-03-26 22:05:08 +03:00
|
|
|
|
2018-04-06 01:27:02 +03:00
|
|
|
return NS_ERROR_CONTENT_BLOCKED;
|
2018-03-26 22:05:08 +03:00
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
static nsresult ValidateSecurityFlags(nsILoadInfo* aLoadInfo) {
|
|
|
|
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
|
|
|
|
|
2018-03-29 13:16:23 +03:00
|
|
|
// We should never perform a security check on a loadInfo that uses the flag
|
|
|
|
// SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, because that is only used for
|
|
|
|
// temporary loadInfos used for explicit nsIContentPolicy checks, but never be
|
|
|
|
// set as a security flag on an actual channel.
|
2015-07-20 05:12:11 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-11-28 06:30:56 +03:00
|
|
|
auto appType = nsIDocShell::APP_TYPE_UNKNOWN;
|
2016-04-27 20:41:13 +03:00
|
|
|
nsINode* node = aLoadInfo->LoadingNode();
|
|
|
|
if (!node) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-01-02 16:05:23 +03:00
|
|
|
Document* doc = node->OwnerDoc();
|
2016-04-27 20:41:13 +03:00
|
|
|
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));
|
2018-11-28 06:30:56 +03:00
|
|
|
if (docShell) {
|
|
|
|
appType = docShell->GetAppType();
|
2016-04-27 20:41:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return appType == nsIDocShell::APP_TYPE_EDITOR;
|
|
|
|
}
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
static nsresult DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
|
2019-07-08 13:47:05 +03:00
|
|
|
// In practice, these DTDs are just used for localization, so applying the
|
|
|
|
// same principal check as Fluent.
|
|
|
|
if (aLoadInfo->InternalContentPolicyType() ==
|
|
|
|
nsIContentPolicy::TYPE_INTERNAL_DTD) {
|
|
|
|
return nsContentUtils::PrincipalAllowsL10n(aLoadInfo->TriggeringPrincipal())
|
|
|
|
? NS_OK
|
|
|
|
: NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is used in order to allow a privileged DOMParser to parse documents
|
|
|
|
// that need to access localization DTDs. We just allow through
|
|
|
|
// TYPE_INTERNAL_FORCE_ALLOWED_DTD no matter what the triggering principal is.
|
|
|
|
if (aLoadInfo->InternalContentPolicyType() ==
|
|
|
|
nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD) {
|
2015-11-26 00:38:05 +03:00
|
|
|
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(), aURI, 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;
|
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
static nsresult DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo,
|
|
|
|
nsIChannel* aChannel) {
|
2015-11-04 11:05:16 +03:00
|
|
|
if (aLoadInfo->GetAllowChrome() &&
|
|
|
|
(URIHasFlags(aURI, nsIProtocolHandler::URI_IS_UI_RESOURCE) ||
|
2017-09-26 03:21:01 +03:00
|
|
|
nsContentUtils::SchemeIs(aURI, "moz-safe-about"))) {
|
2015-11-04 11:05:16 +03:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
|
|
|
static nsresult 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;
|
|
|
|
}
|
|
|
|
|
2018-10-31 21:02:46 +03:00
|
|
|
// We use the triggering principal here, rather than the loading principal
|
|
|
|
// to ensure that anonymous CORS content in the browser resources and in
|
|
|
|
// WebExtensions is allowed to load.
|
|
|
|
nsIPrincipal* principal = aLoadInfo->TriggeringPrincipal();
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsCORSListenerProxy> corsListener = new nsCORSListenerProxy(
|
2015-07-20 05:12:11 +03:00
|
|
|
aInAndOutListener, principal,
|
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;
|
|
|
|
}
|
|
|
|
|
2016-05-17 13:04:11 +03:00
|
|
|
static nsresult DoContentSecurityChecks(nsIChannel* aChannel,
|
|
|
|
nsILoadInfo* aLoadInfo) {
|
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;
|
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);
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
switch (contentPolicyType) {
|
2015-07-31 18:58:14 +03:00
|
|
|
case nsIContentPolicy::TYPE_OTHER: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-19 05:59:18 +03:00
|
|
|
case nsIContentPolicy::TYPE_SCRIPT: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("application/javascript");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:02 +03:00
|
|
|
case nsIContentPolicy::TYPE_IMAGE: {
|
2016-04-27 20:41:13 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
2016-02-03 07:35:02 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case nsIContentPolicy::TYPE_STYLESHEET: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("text/css");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-06-28 10:37:55 +03:00
|
|
|
case nsIContentPolicy::TYPE_OBJECT: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-10 20:25:20 +03:00
|
|
|
case nsIContentPolicy::TYPE_DOCUMENT: {
|
2017-01-03 22:59:30 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
2015-08-10 20:25:20 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
|
|
|
|
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();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-13 18:53:28 +03:00
|
|
|
case nsIContentPolicy::TYPE_PING: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-08-05 06:06:19 +03:00
|
|
|
case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
|
|
|
|
// alias nsIContentPolicy::TYPE_DATAREQUEST:
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsINode> node = aLoadInfo->LoadingNode();
|
2018-01-30 07:10:53 +03:00
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
|
2017-09-05 19:01:07 +03:00
|
|
|
"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();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsINode> node = aLoadInfo->LoadingNode();
|
2018-01-30 07:10:53 +03:00
|
|
|
MOZ_ASSERT(
|
|
|
|
!node || node->NodeType() == nsINode::ELEMENT_NODE,
|
2017-09-05 19:01:07 +03:00
|
|
|
"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();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsINode> node = aLoadInfo->LoadingNode();
|
2018-01-30 07:10:53 +03:00
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
|
2017-09-05 19:01:07 +03:00
|
|
|
"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();
|
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");
|
|
|
|
} else {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
}
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsINode> node = aLoadInfo->LoadingNode();
|
2018-01-30 07:10:53 +03:00
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsINode::ELEMENT_NODE,
|
2017-09-05 19:01:07 +03:00
|
|
|
"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();
|
2015-07-28 06:39:17 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-27 21:57:56 +03:00
|
|
|
case nsIContentPolicy::TYPE_CSP_REPORT: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-29 02:34:47 +03:00
|
|
|
case nsIContentPolicy::TYPE_XSLT: {
|
|
|
|
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsINode> node = aLoadInfo->LoadingNode();
|
2018-01-30 07:10:53 +03:00
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
|
2017-09-05 19:01:07 +03:00
|
|
|
"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();
|
2017-09-05 19:01:07 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
2018-03-29 13:16:23 +03:00
|
|
|
nsCOMPtr<nsINode> node = aLoadInfo->LoadingNode();
|
2018-01-30 07:10:53 +03:00
|
|
|
MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
|
2017-09-05 19:01:07 +03:00
|
|
|
"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();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-07-25 20:29:22 +03:00
|
|
|
case nsIContentPolicy::TYPE_IMAGESET: {
|
2016-04-27 20:41:13 +03:00
|
|
|
mimeTypeGuess = EmptyCString();
|
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");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-16 14:27:01 +03:00
|
|
|
case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-03-24 01:27:08 +03:00
|
|
|
case nsIContentPolicy::TYPE_SPECULATIVE: {
|
|
|
|
mimeTypeGuess = EmptyCString();
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
|
|
|
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
2018-03-29 13:16:23 +03:00
|
|
|
rv = NS_CheckContentLoadPolicy(uri, aLoadInfo, mimeTypeGuess, &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)) {
|
2019-04-26 13:59:41 +03:00
|
|
|
NS_SetRequestBlockingReasonIfNull(
|
|
|
|
aLoadInfo, nsILoadInfo::BLOCKING_REASON_CONTENT_POLICY_GENERAL);
|
|
|
|
|
2017-01-03 22:59:30 +03:00
|
|
|
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
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-09-28 16:06:29 +03:00
|
|
|
static void LogPrincipal(nsIPrincipal* aPrincipal,
|
|
|
|
const nsAString& aPrincipalName) {
|
|
|
|
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" %s: SystemPrincipal\n",
|
|
|
|
NS_ConvertUTF16toUTF8(aPrincipalName).get()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (aPrincipal) {
|
|
|
|
if (aPrincipal->GetIsNullPrincipal()) {
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" %s: NullPrincipal\n",
|
|
|
|
NS_ConvertUTF16toUTF8(aPrincipalName).get()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (aPrincipal->GetIsExpandedPrincipal()) {
|
2019-01-14 17:24:44 +03:00
|
|
|
nsCOMPtr<nsIExpandedPrincipal> expanded(do_QueryInterface(aPrincipal));
|
|
|
|
const nsTArray<nsCOMPtr<nsIPrincipal>>& allowList = expanded->AllowList();
|
2018-10-22 15:49:10 +03:00
|
|
|
nsAutoCString origin;
|
2019-01-14 17:24:44 +03:00
|
|
|
origin.AssignLiteral("[Expanded Principal [");
|
|
|
|
for (size_t i = 0; i < allowList.Length(); ++i) {
|
|
|
|
if (i != 0) {
|
|
|
|
origin.AppendLiteral(", ");
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString subOrigin;
|
|
|
|
DebugOnly<nsresult> rv = allowList.ElementAt(i)->GetOrigin(subOrigin);
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
|
|
origin.Append(subOrigin);
|
|
|
|
}
|
|
|
|
origin.AppendLiteral("]]");
|
|
|
|
|
2018-10-22 15:49:10 +03:00
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" %s: %s\n", NS_ConvertUTF16toUTF8(aPrincipalName).get(),
|
|
|
|
origin.get()));
|
2018-09-28 16:06:29 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> principalURI;
|
|
|
|
nsAutoCString principalSpec;
|
|
|
|
aPrincipal->GetURI(getter_AddRefs(principalURI));
|
|
|
|
if (principalURI) {
|
|
|
|
principalURI->GetSpec(principalSpec);
|
|
|
|
}
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" %s: %s\n", NS_ConvertUTF16toUTF8(aPrincipalName).get(),
|
|
|
|
principalSpec.get()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" %s: nullptr\n", NS_ConvertUTF16toUTF8(aPrincipalName).get()));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void LogSecurityFlags(nsSecurityFlags securityFlags) {
|
|
|
|
struct DebugSecFlagType {
|
|
|
|
unsigned long secFlag;
|
|
|
|
char secTypeStr[128];
|
|
|
|
};
|
|
|
|
static const DebugSecFlagType secTypes[] = {
|
|
|
|
{nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
|
|
|
|
"SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK"},
|
|
|
|
{nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
|
|
|
|
"SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS"},
|
|
|
|
{nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
|
|
|
"SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED"},
|
|
|
|
{nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
|
|
|
|
"SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS"},
|
|
|
|
{nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
|
|
|
"SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL"},
|
|
|
|
{nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
|
|
|
|
"SEC_REQUIRE_CORS_DATA_INHERITS"},
|
|
|
|
{nsILoadInfo::SEC_COOKIES_DEFAULT, "SEC_COOKIES_DEFAULT"},
|
|
|
|
{nsILoadInfo::SEC_COOKIES_INCLUDE, "SEC_COOKIES_INCLUDE"},
|
|
|
|
{nsILoadInfo::SEC_COOKIES_SAME_ORIGIN, "SEC_COOKIES_SAME_ORIGIN"},
|
|
|
|
{nsILoadInfo::SEC_COOKIES_OMIT, "SEC_COOKIES_OMIT"},
|
|
|
|
{nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL, "SEC_FORCE_INHERIT_PRINCIPAL"},
|
|
|
|
{nsILoadInfo::SEC_SANDBOXED, "SEC_SANDBOXED"},
|
|
|
|
{nsILoadInfo::SEC_ABOUT_BLANK_INHERITS, "SEC_ABOUT_BLANK_INHERITS"},
|
|
|
|
{nsILoadInfo::SEC_ALLOW_CHROME, "SEC_ALLOW_CHROME"},
|
|
|
|
{nsILoadInfo::SEC_DISALLOW_SCRIPT, "SEC_DISALLOW_SCRIPT"},
|
|
|
|
{nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS, "SEC_DONT_FOLLOW_REDIRECTS"},
|
|
|
|
{nsILoadInfo::SEC_LOAD_ERROR_PAGE, "SEC_LOAD_ERROR_PAGE"},
|
|
|
|
{nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL_OVERRULE_OWNER,
|
|
|
|
"SEC_FORCE_INHERIT_PRINCIPAL_OVERRULE_OWNER"}};
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-09-28 16:06:29 +03:00
|
|
|
for (const DebugSecFlagType flag : secTypes) {
|
|
|
|
if (securityFlags & flag.secFlag) {
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug, (" %s,\n", flag.secTypeStr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void DebugDoContentSecurityCheck(nsIChannel* aChannel,
|
|
|
|
nsILoadInfo* aLoadInfo) {
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
|
|
|
|
|
|
|
// we only log http channels, unless loglevel is 5.
|
|
|
|
if (httpChannel || MOZ_LOG_TEST(sCSMLog, LogLevel::Verbose)) {
|
|
|
|
nsCOMPtr<nsIURI> channelURI;
|
|
|
|
nsAutoCString channelSpec;
|
|
|
|
nsAutoCString channelMethod;
|
|
|
|
NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
|
|
|
|
if (channelURI) {
|
|
|
|
channelURI->GetSpec(channelSpec);
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug, ("doContentSecurityCheck {\n"));
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" channelURI: %s\n", channelSpec.get()));
|
|
|
|
|
|
|
|
// Log HTTP-specific things
|
|
|
|
if (httpChannel) {
|
|
|
|
nsresult rv;
|
|
|
|
rv = httpChannel->GetRequestMethod(channelMethod);
|
|
|
|
if (!NS_FAILED(rv)) {
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" HTTP Method: %s\n", channelMethod.get()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Log Principals
|
|
|
|
nsCOMPtr<nsIPrincipal> requestPrincipal = aLoadInfo->TriggeringPrincipal();
|
|
|
|
LogPrincipal(aLoadInfo->LoadingPrincipal(),
|
|
|
|
NS_LITERAL_STRING("loadingPrincipal"));
|
|
|
|
LogPrincipal(requestPrincipal, NS_LITERAL_STRING("triggeringPrincipal"));
|
|
|
|
LogPrincipal(aLoadInfo->PrincipalToInherit(),
|
|
|
|
NS_LITERAL_STRING("principalToInherit"));
|
|
|
|
|
|
|
|
// Log Redirect Chain
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug, (" RedirectChain:\n"));
|
|
|
|
for (nsIRedirectHistoryEntry* redirectHistoryEntry :
|
|
|
|
aLoadInfo->RedirectChain()) {
|
|
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
|
|
redirectHistoryEntry->GetPrincipal(getter_AddRefs(principal));
|
|
|
|
LogPrincipal(principal, NS_LITERAL_STRING("->"));
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" internalContentPolicyType: %d\n",
|
|
|
|
aLoadInfo->InternalContentPolicyType()));
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" externalContentPolicyType: %d\n",
|
|
|
|
aLoadInfo->GetExternalContentPolicyType()));
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" upgradeInsecureRequests: %s\n",
|
|
|
|
aLoadInfo->GetUpgradeInsecureRequests() ? "true" : "false"));
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" initalSecurityChecksDone: %s\n",
|
|
|
|
aLoadInfo->GetInitialSecurityCheckDone() ? "true" : "false"));
|
|
|
|
|
|
|
|
// Log CSPrequestPrincipal
|
2019-05-22 02:14:27 +03:00
|
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadInfo->GetCsp();
|
2018-09-28 16:06:29 +03:00
|
|
|
if (csp) {
|
|
|
|
nsAutoString parsedPolicyStr;
|
|
|
|
uint32_t count = 0;
|
|
|
|
csp->GetPolicyCount(&count);
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug, (" CSP (%d): ", count));
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
|
|
csp->GetPolicyString(i, parsedPolicyStr);
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
|
|
|
(" %s\n", NS_ConvertUTF16toUTF8(parsedPolicyStr).get()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Security Flags
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug, (" securityFlags: "));
|
|
|
|
LogSecurityFlags(aLoadInfo->GetSecurityFlags());
|
|
|
|
MOZ_LOG(sCSMLog, LogLevel::Debug, ("}\n\n"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-29 13:06:15 +03:00
|
|
|
#ifdef EARLY_BETA_OR_EARLIER
|
2019-04-10 17:20:12 +03:00
|
|
|
// Assert that we never use the SystemPrincipal to load remote documents
|
|
|
|
// i.e., HTTP, HTTPS, FTP URLs
|
|
|
|
static void AssertSystemPrincipalMustNotLoadRemoteDocuments(
|
|
|
|
nsIChannel* aChannel) {
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
|
|
|
|
|
|
|
// bail out, if we're not loading with a SystemPrincipal
|
|
|
|
if (!nsContentUtils::IsSystemPrincipal(loadInfo->LoadingPrincipal())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsContentPolicyType contentPolicyType =
|
|
|
|
loadInfo->GetExternalContentPolicyType();
|
|
|
|
if ((contentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) &&
|
|
|
|
(contentPolicyType != nsIContentPolicy::TYPE_SUBDOCUMENT)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> finalURI;
|
|
|
|
NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalURI));
|
|
|
|
// bail out, if URL isn't pointing to remote resource
|
|
|
|
if (!nsContentUtils::SchemeIs(finalURI, "http") &&
|
|
|
|
!nsContentUtils::SchemeIs(finalURI, "https") &&
|
|
|
|
!nsContentUtils::SchemeIs(finalURI, "ftp")) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-15 11:03:58 +03:00
|
|
|
|
|
|
|
// FIXME The discovery feature in about:addons uses the SystemPrincpal.
|
2019-07-03 16:59:28 +03:00
|
|
|
// We should remove the exception for AMO with bug 1544011.
|
|
|
|
// We should remove the exception for Firefox Accounts with bug 1561310.
|
2019-04-15 11:03:58 +03:00
|
|
|
static nsAutoCString sDiscoveryPrePath;
|
2019-07-03 16:59:28 +03:00
|
|
|
# ifdef ANDROID
|
|
|
|
static nsAutoCString sFxaSPrePath;
|
|
|
|
# endif
|
|
|
|
static bool recvdPrefValues = false;
|
|
|
|
if (!recvdPrefValues) {
|
2019-04-15 11:03:58 +03:00
|
|
|
nsAutoCString discoveryURLString;
|
2019-04-15 12:10:00 +03:00
|
|
|
Preferences::GetCString("extensions.webservice.discoverURL",
|
|
|
|
discoveryURLString);
|
|
|
|
// discoverURL is by default suffixed with parameters in path like
|
|
|
|
// /%LOCALE%/ so, we use the prePath for comparison
|
2019-04-15 11:03:58 +03:00
|
|
|
nsCOMPtr<nsIURI> discoveryURL;
|
|
|
|
NS_NewURI(getter_AddRefs(discoveryURL), discoveryURLString);
|
|
|
|
if (discoveryURL) {
|
|
|
|
discoveryURL->GetPrePath(sDiscoveryPrePath);
|
|
|
|
}
|
2019-07-03 16:59:28 +03:00
|
|
|
# ifdef ANDROID
|
|
|
|
nsAutoCString fxaURLString;
|
|
|
|
Preferences::GetCString("identity.fxaccounts.remote.webchannel.uri",
|
|
|
|
fxaURLString);
|
|
|
|
nsCOMPtr<nsIURI> fxaURL;
|
|
|
|
NS_NewURI(getter_AddRefs(fxaURL), fxaURLString);
|
|
|
|
if (fxaURL) {
|
|
|
|
fxaURL->GetPrePath(sFxaSPrePath);
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
recvdPrefValues = true;
|
2019-04-15 11:03:58 +03:00
|
|
|
}
|
|
|
|
nsAutoCString requestedPrePath;
|
|
|
|
finalURI->GetPrePath(requestedPrePath);
|
2019-07-03 16:59:28 +03:00
|
|
|
|
2019-04-15 11:03:58 +03:00
|
|
|
if (requestedPrePath.Equals(sDiscoveryPrePath)) {
|
|
|
|
return;
|
|
|
|
}
|
2019-07-03 16:59:28 +03:00
|
|
|
# ifdef ANDROID
|
|
|
|
if (requestedPrePath.Equals(sFxaSPrePath)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
# endif
|
2019-04-10 17:20:12 +03:00
|
|
|
if (xpc::AreNonLocalConnectionsDisabled()) {
|
|
|
|
bool disallowSystemPrincipalRemoteDocuments = Preferences::GetBool(
|
|
|
|
"security.disallow_non_local_systemprincipal_in_tests");
|
|
|
|
if (disallowSystemPrincipalRemoteDocuments) {
|
|
|
|
// our own mochitest needs NS_ASSERTION instead of MOZ_ASSERT
|
|
|
|
NS_ASSERTION(false, "SystemPrincipal must not load remote documents.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// but other mochitest are exempt from this
|
|
|
|
return;
|
|
|
|
}
|
2019-05-29 13:06:15 +03:00
|
|
|
MOZ_RELEASE_ASSERT(false, "SystemPrincipal must not load remote documents.");
|
2019-04-10 17:20:12 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-20 05:12:11 +03:00
|
|
|
/*
|
|
|
|
* 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
|
2019-02-12 19:08:25 +03:00
|
|
|
* The streamListener that is passed to channel->AsyncOpen() that is now
|
2015-07-20 05:12:11 +03:00
|
|
|
* 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);
|
2019-02-20 15:27:25 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2018-09-28 16:06:29 +03:00
|
|
|
if (MOZ_UNLIKELY(MOZ_LOG_TEST(sCSMLog, LogLevel::Debug))) {
|
|
|
|
DebugDoContentSecurityCheck(aChannel, loadInfo);
|
|
|
|
}
|
|
|
|
|
2019-05-29 13:06:15 +03:00
|
|
|
#ifdef EARLY_BETA_OR_EARLIER
|
2019-04-10 17:20:12 +03:00
|
|
|
AssertSystemPrincipalMustNotLoadRemoteDocuments(aChannel);
|
|
|
|
#endif
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
2018-04-06 01:27:02 +03:00
|
|
|
// Apply this after CSP to match Chrome.
|
|
|
|
rv = CheckFTPSubresourceLoad(aChannel);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
// 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) {
|
2019-02-20 15:27:25 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aOldChannel->LoadInfo();
|
|
|
|
nsresult rv = CheckChannel(aNewChannel);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = CheckFTPSubresourceLoad(aNewChannel);
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aOldChannel->Cancel(rv);
|
|
|
|
return rv;
|
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
|
|
|
|
2018-01-23 11:57:47 +03:00
|
|
|
// Do not allow insecure redirects to data: URIs
|
2018-02-18 21:52:52 +03:00
|
|
|
if (!AllowInsecureRedirectToDataURI(aNewChannel)) {
|
|
|
|
// cancel the old channel and return an error
|
|
|
|
aOldChannel->Cancel(NS_ERROR_CONTENT_BLOCKED);
|
|
|
|
return NS_ERROR_CONTENT_BLOCKED;
|
2018-01-23 11:57:47 +03:00
|
|
|
}
|
|
|
|
|
2015-12-07 02:33:14 +03:00
|
|
|
const uint32_t flags =
|
|
|
|
nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
|
|
|
|
nsIScriptSecurityManager::DISALLOW_SCRIPT;
|
2019-02-20 15:27:25 +03:00
|
|
|
rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
|
2015-12-07 02:33:14 +03:00
|
|
|
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) {
|
2019-02-20 15:27:25 +03:00
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->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);
|
|
|
|
|
|
|
|
// 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)) {
|
2018-04-23 19:43:36 +03:00
|
|
|
NS_ENSURE_FALSE(loadInfo->GetDontFollowRedirects(), NS_ERROR_DOM_BAD_URI);
|
2015-12-07 02:33:15 +03:00
|
|
|
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);
|
|
|
|
|
2019-01-03 23:55:38 +03:00
|
|
|
if (aPrincipal->IsSystemPrincipal()) {
|
2016-04-26 13:30:43 +03:00
|
|
|
*aIsTrustWorthy = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-11-06 22:10:17 +03:00
|
|
|
*aIsTrustWorthy = false;
|
2016-04-26 13:30:43 +03:00
|
|
|
if (aPrincipal->GetIsNullPrincipal()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-08 19:37:45 +03:00
|
|
|
MOZ_ASSERT(aPrincipal->GetIsContentPrincipal(),
|
2016-04-26 13:30:43 +03:00
|
|
|
"Nobody is expected to call us with an nsIExpandedPrincipal");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
2019-02-25 15:15:15 +03:00
|
|
|
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
2019-05-13 17:40:40 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
*aIsTrustWorthy = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
|
2019-05-09 17:29:38 +03:00
|
|
|
|
2015-11-06 22:10:17 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|