Files
palemoon27/dom/security/nsCSPService.cpp
T
roytam1 b3dd358267 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1247362 - move mAnonymousGlobalScope tracing into nsMessageManagerScriptExecutor; r=mccr8 (9b33b54bc9)
- Bug 1195881 - Contextual Identity working under e10s. r=tanvi r=sicking r=baku (b3fd69bd92)
- Bug 1174624 - Add the Transferable parameter into SendAsyncMessage of nsFrameMessageManager. r=baku (33911dc6f7)
- Bug 1174624 - Add PortIdentifier copy code in order to communicate with same process. r=baku (d597f24e20)
- Bug 1234176 - Do not send memory pressure events to applications sent into the background. r=dhylands (687f154573)
- Bug 1201394 - Remove unused mLRUPoolSize member variable. r=gsvelto (a109934b8d)
- Bug 1144132 follow up to fix static check build bustage on a CLOSED TREE with r=me (050f49060e)
- Bug 1153394 - make HangMonitorChild::sInstance an atomic variable; r=billm (89e6905f3f)
- Bug 1202952 - Fix directory picking for e10s on Windows by making FilePickerParent use the correct nsIFilePicker API for directory picking. r=roc (a7e964d4fa)
- Bug 1227312 - Avoid calling FinalizeChildData twice in GenerateCompleteMinidump. r=ted (c29e6786ae)
- Bug 1222109 - Initialize mHasGamepadListener in InitializeMembers(); r=cleu (8057137e5d)
- Bug 1231498 - ContentParent::RecvCreateWindow() should fail in opt builds if passed bad chromeflags. r=billm (639fb93101)
- minor indentation (f5dbd8996c)
- fix misspatch (3b306e0084)
- Bug 1101264: Truncate long sourceName messages since they can be massive data: URLs. r=bent (c528048e58)
- Bug 1233497 - Update test_bug1086684.html to not access CPOWs unsafely inside SpecialPowers. r=mrbkap (d5d161eac2)
- align tests (24d98036dc)
- Bug 1232931 Return null instead of throwing if swm.getWorkerByID() cannot find the worker. r=ochameau IGNORE IDL for comment only change (17f293f323)
- Bug 1186812 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in dom/{ipc,plugins}/. r=jimm. (a944fa4480)
- Bug 1234656 - Add TouchEvent ctor, r=mbrubeck (842245df14)
- Bug 1246854 - Remove unnecessary warning. r=botond (7d0532e516)
- Bug 1245393 - Measure s{,Default}RootBranch in the Preferences memory reporter. r=froydnj. (be200f9ebe)
- Bug 1089232 - Updates nsContentPrefService to take an extra isPrivate argument. r=adw (9ea4fe075d)
- Bug 1229519: Fix toolkit/components/contentprefs to pass eslint checks. r=mconley (e48b64448b)
- Bug 663570 - MetaCSP Part 6: CSP preload changes (r=sicking) (65700820c1)
- Bug 1030936 - [CSP] remove fast-path for certified apps once the C++ backend is activated. r=ckerschb (e9527e9cfc)
- Bug 1228497 - initialize 3 members in class. r=christophkerschbaumer (44414e8429)
- Bug 1208946 - Strip URIs in CSP reports (r=dveditz) (dd6c18a8ff)
- Bug 1247464 - Run CSP report URIs through the URL classifier. r=ckerschb (ebb3570172)
- Bug 1242909, r=ckerschb (569de89b26)
- Bug 1119565: Ensure that a plugin listener's stream type is always set, even when it is STREAM_TYPE_UNKNOWN; r=jimm (43fb9ebdb9)
- Bug 1228116 - Relax Security checks for DTD loads. r=sicking (b77e2c4531)
- Bug 1195173 - Use channel->ascynOpen2 layout/style/Loader.cpp (r=bz) (97de97b864)
- let-var (fb35f8f50c)
- Bug 1226324 - Do not use NS_ENSURCE_SUCCESS(rv, NS_OK) within nsContentSecurityManager. r=tanvi (745ecaf562)
- Bug 1221365 - Tests for "Is origin potentially trustworthy?" logic. r=ckerschb,bkelly (1d520ebcc5)
- Bug 1132211 - Dispatch an event when <input type=password> is added to a document (including outside of a form). r=smaug (3e9acb8bf3)
- Bug 1217766 - All PDFs trigger the insecure password warning. r=MattN,bz (0ea7e35b96)
- Bug 1155471 - Mark some members of nsNodeInfoManager as MOZ_NON_OWNING_REF; r=baku (bd47bcea10)
- Tests for bug 1200856; r=sicking (454ff8048a)
- Bug 1243453 P1 Make nsCORSListenerProxy call UpdateChannel() for internal redirects. r=sicking (f2a45b1997)
- Bug 1243453 P2 Test XHR with a non-intercepting service worker. r=ehsan (d83b31ab3d)
- Bug 1169233 - Get grey (inactive) text color from menu labels. r=karlt (470155483b)
- Bug 1161056 - Gtk3 - use sMozWindowBackground colors for combobox background. r=karlt (4502f5583a)
- Bug 1169232 - [gtk3] Add background class to tooltip window to get correct background color. r=karlt (9421a23b1c)
- Bug 1219717 - Derive text color/background from GtkTextView. r=karlt (a39cd997ee)
- Bug 1241239 - Fix missing 'using mozilla::LogLevel' in nsIdleServiceGTK.cpp. r=karlt (16bacfc530)
- Bug 1209659 - Disable client-side decorations on broken Gtk3 versions (<3.20). r=karlt (d5cbd4c0fb)
- Bug 540078 - Remove assertion annotations that are no longer needed and add crashtest. (89f33bb00c)
- Bug 1168219 - Make nsIWidget::Configuration::mChild a smart pointer on widget/qt too. r=froydnj (0f2f97a31b)
- Bug 1234385: Add downloadable blocklist support for between comparison types, by recognizing driverVersionMax when parsing. r=benwa (87617d0fa1)
- Bug 1112712 - DOM key mapping for soft1 soft2 and call keys r=schien (3f4360e64b)
- Bug 1237691 - Implement Oculus Head Pose Prediction (3f6b0122e3)
- Bug 1041882 - Remove Froyo-specific OMX plugin support. r=snorp (eb2f6dd36a)
- Bug 1205930 - Tighten up warnings handling in media/omx-plugin/. r=gerald. (86845d720a)
- Bug 1153849 - Use MOZ_JPEG_CFLAGS when build libyuv with system jpeg. r=jesup (a38f53057d)
- Bug 1240635 - Interpret glyph x-offsets on SVG vertical text paths in the correct direction. r=longsonr (ce90452da1)
- Bug 1185266 - Look up painting properties on the SVGTextFrame when painting text frames that are direct children of <text>. r=jwatt (9c89ab71eb)
- Bug 1143096 - Init all WebMBufferedParser members - r=kinetik (7df2e4e0c3)
- Bug 1231855 - Avoid inserting out of (timecode) order entries in WebMBufferedParser. r=jya (f7806faec4)
2023-12-21 11:24:17 +08:00

313 lines
11 KiB
C++

/* -*- 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/. */
#include "mozilla/Logging.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIPrincipal.h"
#include "nsIObserver.h"
#include "nsIContent.h"
#include "nsCSPService.h"
#include "nsIContentSecurityPolicy.h"
#include "nsError.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "mozilla/Preferences.h"
#include "nsIScriptError.h"
#include "nsContentUtils.h"
#include "nsContentPolicyUtils.h"
#include "nsPrincipal.h"
using namespace mozilla;
/* Keeps track of whether or not CSP is enabled */
bool CSPService::sCSPEnabled = true;
static LazyLogModule gCspPRLog("CSP");
CSPService::CSPService()
{
Preferences::AddBoolVarCache(&sCSPEnabled, "security.csp.enable");
}
CSPService::~CSPService()
{
mAppStatusCache.Clear();
}
NS_IMPL_ISUPPORTS(CSPService, nsIContentPolicy, nsIChannelEventSink)
// Helper function to identify protocols not subject to CSP.
bool
subjectToCSP(nsIURI* aURI) {
// The three protocols: data:, blob: and filesystem: share the same
// protocol flag (URI_IS_LOCAL_RESOURCE) with other protocols, like
// chrome:, resource:, moz-icon:, but those three protocols get
// special attention in CSP and are subject to CSP, hence we have
// to make sure those protocols are subject to CSP, see:
// http://www.w3.org/TR/CSP2/#source-list-guid-matching
bool match = false;
nsresult rv = aURI->SchemeIs("data", &match);
if (NS_SUCCEEDED(rv) && match) {
return true;
}
rv = aURI->SchemeIs("blob", &match);
if (NS_SUCCEEDED(rv) && match) {
return true;
}
rv = aURI->SchemeIs("filesystem", &match);
if (NS_SUCCEEDED(rv) && match) {
return true;
}
// finally we have to whitelist "about:" which does not fall in
// any of the two categories underneath but is not subject to CSP.
rv = aURI->SchemeIs("about", &match);
if (NS_SUCCEEDED(rv) && match) {
return false;
}
// Other protocols are not subject to CSP and can be whitelisted:
// * URI_IS_LOCAL_RESOURCE
// e.g. chrome:, data:, blob:, resource:, moz-icon:
// * URI_INHERITS_SECURITY_CONTEXT
// e.g. javascript:
//
// Please note that it should be possible for websites to
// whitelist their own protocol handlers with respect to CSP,
// hence we use protocol flags to accomplish that.
rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &match);
if (NS_SUCCEEDED(rv) && match) {
return false;
}
rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, &match);
if (NS_SUCCEEDED(rv) && match) {
return false;
}
// all other protocols are subject To CSP.
return true;
}
/* nsIContentPolicy implementation */
NS_IMETHODIMP
CSPService::ShouldLoad(uint32_t aContentType,
nsIURI *aContentLocation,
nsIURI *aRequestOrigin,
nsISupports *aRequestContext,
const nsACString &aMimeTypeGuess,
nsISupports *aExtra,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
if (!aContentLocation) {
return NS_ERROR_FAILURE;
}
if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
nsAutoCString location;
aContentLocation->GetSpec(location);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("CSPService::ShouldLoad called for %s", location.get()));
}
// default decision, CSP can revise it if there's a policy to enforce
*aDecision = nsIContentPolicy::ACCEPT;
// No need to continue processing if CSP is disabled or if the protocol
// is *not* subject to CSP.
// Please note, the correct way to opt-out of CSP using a custom
// protocolHandler is to set one of the nsIProtocolHandler flags
// that are whitelistet in subjectToCSP()
if (!sCSPEnabled || !subjectToCSP(aContentLocation)) {
return NS_OK;
}
// These content types are not subject to CSP content policy checks:
// TYPE_CSP_REPORT -- csp can't block csp reports
// TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
// TYPE_DOCUMENT -- used for frame-ancestors
if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
aContentType == nsIContentPolicy::TYPE_REFRESH ||
aContentType == nsIContentPolicy::TYPE_DOCUMENT) {
return NS_OK;
}
// query the principal of the document; if no document is passed, then
// fall back to using the requestPrincipal (e.g. service workers do not
// pass a document).
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
nsCOMPtr<nsIPrincipal> principal = node ? node->NodePrincipal()
: aRequestPrincipal;
if (!principal) {
// if we can't query a principal, then there is nothing to do.
return NS_OK;
}
nsresult rv = NS_OK;
// 1) Apply speculate CSP for preloads
bool isPreload = nsContentUtils::IsPreloadType(aContentType);
if (isPreload) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
rv = principal->GetPreloadCsp(getter_AddRefs(preloadCsp));
NS_ENSURE_SUCCESS(rv, rv);
if (preloadCsp) {
// obtain the enforcement decision
// (don't pass aExtra, we use that slot for redirects)
rv = preloadCsp->ShouldLoad(aContentType,
aContentLocation,
aRequestOrigin,
aRequestContext,
aMimeTypeGuess,
nullptr, // aExtra
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
// if the preload policy already denied the load, then there
// is no point in checking the real policy
if (NS_CP_REJECTED(*aDecision)) {
return NS_OK;
}
}
}
// 2) Apply actual CSP to all loads
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
// obtain the enforcement decision
// (don't pass aExtra, we use that slot for redirects)
rv = csp->ShouldLoad(aContentType,
aContentLocation,
aRequestOrigin,
aRequestContext,
aMimeTypeGuess,
nullptr,
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
CSPService::ShouldProcess(uint32_t aContentType,
nsIURI *aContentLocation,
nsIURI *aRequestOrigin,
nsISupports *aRequestContext,
const nsACString &aMimeTypeGuess,
nsISupports *aExtra,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
if (!aContentLocation)
return NS_ERROR_FAILURE;
*aDecision = nsIContentPolicy::ACCEPT;
return NS_OK;
}
/* nsIChannelEventSink implementation */
NS_IMETHODIMP
CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
uint32_t flags,
nsIAsyncVerifyRedirectCallback *callback)
{
nsAsyncRedirectAutoCallback autoCallback(callback);
nsCOMPtr<nsIURI> newUri;
nsresult rv = newChannel->GetURI(getter_AddRefs(newUri));
NS_ENSURE_SUCCESS(rv, rv);
// No need to continue processing if CSP is disabled or if the protocol
// is *not* subject to CSP.
// Please note, the correct way to opt-out of CSP using a custom
// protocolHandler is to set one of the nsIProtocolHandler flags
// that are whitelistet in subjectToCSP()
if (!sCSPEnabled || !subjectToCSP(newUri)) {
return NS_OK;
}
nsCOMPtr<nsILoadInfo> loadInfo;
rv = oldChannel->GetLoadInfo(getter_AddRefs(loadInfo));
// if no loadInfo on the channel, nothing for us to do
if (!loadInfo) {
return NS_OK;
}
/* Since redirecting channels don't call into nsIContentPolicy, we call our
* Content Policy implementation directly when redirects occur using the
* information set in the LoadInfo when channels are created.
*
* We check if the CSP permits this host for this type of load, if not,
* we cancel the load now.
*/
nsCOMPtr<nsIURI> originalUri;
rv = oldChannel->GetOriginalURI(getter_AddRefs(originalUri));
NS_ENSURE_SUCCESS(rv, rv);
nsContentPolicyType policyType = loadInfo->InternalContentPolicyType();
bool isPreload = nsContentUtils::IsPreloadType(policyType);
/* On redirect, if the content policy is a preload type, rejecting the preload
* results in the load silently failing, so we convert preloads to the actual
* type. See Bug 1219453.
*/
policyType =
nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(policyType);
int16_t aDecision = nsIContentPolicy::ACCEPT;
// 1) Apply speculative CSP for preloads
if (isPreload) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
loadInfo->LoadingPrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
if (preloadCsp) {
// Pass originalURI as aExtra to indicate the redirect
preloadCsp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aExtra
&aDecision);
// if the preload policy already denied the load, then there
// is no point in checking the real policy
if (NS_CP_REJECTED(aDecision)) {
autoCallback.DontCallback();
return NS_BINDING_FAILED;
}
}
}
// 2) Apply actual CSP to all loads
nsCOMPtr<nsIContentSecurityPolicy> csp;
loadInfo->LoadingPrincipal()->GetCsp(getter_AddRefs(csp));
if (csp) {
// Pass originalURI as aExtra to indicate the redirect
csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aExtra
&aDecision);
}
// if ShouldLoad doesn't accept the load, cancel the request
if (!NS_CP_ACCEPTED(aDecision)) {
autoCallback.DontCallback();
return NS_BINDING_FAILED;
}
return NS_OK;
}