Bug 1407056: Part 1 - Provide more consistent principal/origin URL to content policies. r=bz,ckerschb

We're currently fairly vague and inconsistent about the values we provide to
content policy implementations for requestOrigin and requestPrincipal. In some
cases they're the triggering principal, sometimes the loading principal,
sometimes the channel principal.

Our existing content policy implementations which require or expect a loading
principal currently retrieve it from the context node. Since no current
callers require the principal to be the loading principal, and some already
expect it to be the triggering principal (which there's currently no other way
to retrieve), I chose to pass the triggering principal whenever possible, but
use the loading principal to determine the origin URL.

As a follow-up, I'd like to change the nsIContentPolicy interface to
explicitly receive loading and triggering principals, or possibly just
LoadInfo instances, rather than poorly-defined request
origin/principal/context args. But since that may cause trouble for
comm-central, I'd rather not do it as part of this bug.

MozReview-Commit-ID: LqD9GxdzMte

--HG--
extra : rebase_source : 41ce439912ae7b895e0a3b0e660fa6ba571eb50f
This commit is contained in:
Kris Maglione 2017-10-12 15:43:55 -07:00
parent 046e4a269a
commit 5fdcb5a5d2
18 changed files with 98 additions and 58 deletions

View File

@ -10011,6 +10011,9 @@ nsDocShell::InternalLoad(nsIURI* aURI,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(contentType,
aURI,
// This is a top-level load, so the loading
// principal is null.
nullptr,
aTriggeringPrincipal,
requestingContext,
EmptyCString(), // mime guess

View File

@ -1603,7 +1603,8 @@ WebSocketImpl::Init(JSContext* aCx,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET,
uri,
aPrincipal,
aPrincipal, // loading principal
aPrincipal, // triggering principal
originDoc,
EmptyCString(),
nullptr,

View File

@ -150,7 +150,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
return NS_ERROR_FAILURE; \
\
return policy-> action (contentType, contentLocation, requestOrigin, \
context, mimeType, extra, originPrincipal, \
context, mimeType, extra, triggeringPrincipal, \
decision); \
PR_END_MACRO
@ -158,7 +158,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
#define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \
PR_BEGIN_MACRO \
return _policy-> action (contentType, contentLocation, requestOrigin, \
context, mimeType, extra, originPrincipal, \
context, mimeType, extra, triggeringPrincipal, \
decision); \
PR_END_MACRO
@ -171,8 +171,12 @@ NS_CP_ContentTypeName(uint32_t contentType)
#define CHECK_PRINCIPAL_AND_DATA(action) \
nsCOMPtr<nsIURI> requestOrigin; \
PR_BEGIN_MACRO \
if (originPrincipal) { \
bool isSystem = originPrincipal->GetIsSystemPrincipal(); \
if (loadingPrincipal) { \
/* We exempt most loads into any document with the system principal \
* from content policy checks, mostly as an optimization. Which means \
* that we need to apply this check to the loading principal, not the \
* principal that triggered the load. */ \
bool isSystem = loadingPrincipal->GetIsSystemPrincipal(); \
if (isSystem && contentType != nsIContentPolicy::TYPE_DOCUMENT) { \
*decision = nsIContentPolicy::ACCEPT; \
nsCOMPtr<nsINode> n = do_QueryInterface(context); \
@ -193,30 +197,32 @@ NS_CP_ContentTypeName(uint32_t contentType)
dataPolicy-> action (externalType, contentLocation, \
requestOrigin, context, \
mimeType, extra, \
originPrincipal, decision); \
triggeringPrincipal, decision); \
} \
} \
} \
return NS_OK; \
} \
nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin)); \
nsresult rv = loadingPrincipal->GetURI(getter_AddRefs(requestOrigin)); \
NS_ENSURE_SUCCESS(rv, rv); \
} \
PR_END_MACRO
/**
* Alias for calling ShouldLoad on the content policy service. Parameters are
* the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
* parameter, which should be non-null if possible, and the last parameter,
* the same as nsIContentPolicy::shouldLoad, except for the loadingPrincipal
* and triggeringPrincipal parameters (which should be non-null if possible,
* and have the same semantics as in nsLoadInfo), and the last parameter,
* which can be used to pass in a pointer to a useful service if the caller
* already has it. The origin URI to pass to shouldLoad will be the URI of
* originPrincipal, unless originPrincipal is null (in which case a null origin
* URI will be passed).
* loadingPrincipal, unless loadingPrincipal is null (in which case a null
* origin URI will be passed).
*/
inline nsresult
NS_CheckContentLoadPolicy(uint32_t contentType,
nsIURI *contentLocation,
nsIPrincipal *originPrincipal,
nsIPrincipal *loadingPrincipal,
nsIPrincipal *triggeringPrincipal,
nsISupports *context,
const nsACString &mimeType,
nsISupports *extra,
@ -232,17 +238,19 @@ NS_CheckContentLoadPolicy(uint32_t contentType,
/**
* Alias for calling ShouldProcess on the content policy service. Parameters
* are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
* parameter, which should be non-null if possible, and the last parameter,
* which can be used to pass in a pointer to a useful service if the caller
* already has it. The origin URI to pass to shouldLoad will be the URI of
* originPrincipal, unless originPrincipal is null (in which case a null origin
* URI will be passed).
* are the same as nsIContentPolicy::shouldLoad, except for the and
* triggeringPrincipal parameters (which should be non-null if possible, and
* have the same semantics as in nsLoadInfo), and the last parameter, which
* can be used to pass in a pointer to a useful service if the caller already
* has it. The origin URI to pass to shouldLoad will be the URI of
* loadingPrincipal, unless loadingPrincipal is null (in which case a null
* origin URI will be passed).
*/
inline nsresult
NS_CheckContentProcessPolicy(uint32_t contentType,
nsIURI *contentLocation,
nsIPrincipal *originPrincipal,
nsIPrincipal *loadingPrincipal,
nsIPrincipal *triggeringPrincipal,
nsISupports *context,
const nsACString &mimeType,
nsISupports *extra,

View File

@ -3627,6 +3627,7 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
rv = NS_CheckContentLoadPolicy(aContentType,
aURI,
aLoadingPrincipal,
aLoadingPrincipal, // triggering principal
aContext,
EmptyCString(), //mime guess
nullptr, //extra

View File

@ -399,8 +399,11 @@ interface nsIContentPolicy : nsISupports
* not be null
*
* @param aRequestOrigin OPTIONAL. the location of the resource that
* initiated this load request; can be null if
* inapplicable
* that is loading the request. This will generally
* be the URI of the loading principal for the
* resulting request (as determined by its
* LoadInfo), but may vary depending on the
* caller. Can be null if inapplicable.
*
* @param aContext OPTIONAL. the nsIDOMNode or nsIDOMWindow that
* initiated the request, or something that can QI
@ -420,8 +423,12 @@ interface nsIContentPolicy : nsISupports
* @param aRequestPrincipal an OPTIONAL argument, defines the principal that
* caused the load. This is optional only for
* non-gecko code: all gecko code should set this
* argument. For navigation events, this is
* the principal of the page that caused this load.
* argument. This should generally be the same as
* the triggering principal for the resulting
* request (as determined by its LoadInfo), but may
* vary depending on the caller. Sometimes it will
* be the loading principal or final channel
* principal instead.
*
* @return ACCEPT or REJECT_*
*

View File

@ -1482,7 +1482,8 @@ nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy)
*aContentPolicy = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
mURI,
doc->NodePrincipal(),
doc->NodePrincipal(), // loading principal
doc->NodePrincipal(), // triggering principal
thisContent,
mContentType,
nullptr, //extra
@ -1535,7 +1536,8 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy)
nsresult rv =
NS_CheckContentProcessPolicy(objectType,
mURI ? mURI : mBaseURI,
doc->NodePrincipal(),
doc->NodePrincipal(), // loading principal
doc->NodePrincipal(), // triggering principal
static_cast<nsIImageLoadingContent*>(this),
mContentType,
nullptr, //extra

View File

@ -102,10 +102,13 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
secMan->GetChannelResultPrincipal(channel, getter_AddRefs(channelPrincipal));
}
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
int16_t decision = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE,
channelURI,
channelPrincipal,
loadInfo ? loadInfo->TriggeringPrincipal() : nullptr,
domWindow->GetFrameElementInternal(),
mimeType,
nullptr,

View File

@ -188,7 +188,8 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
mURL,
principal,
principal, // loading principal
principal, // triggering principal
element,
contentType,
nullptr,

View File

@ -303,7 +303,8 @@ ScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
aURI,
aDocument->NodePrincipal(),
aDocument->NodePrincipal(), // loading principal
aDocument->NodePrincipal(), // triggering principal
aContext,
NS_LossyConvertUTF16toASCII(aType),
nullptr, //extra

View File

@ -456,18 +456,11 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
}
// 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();
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
uri,
principal,
aLoadInfo->LoadingPrincipal(),
aLoadInfo->TriggeringPrincipal(),
requestingContext,
mimeTypeGuess,
nullptr, //extra,

View File

@ -267,6 +267,7 @@ public:
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(aLoadInfo->InternalContentPolicyType(), uri,
aLoadInfo->LoadingPrincipal(),
aLoadInfo->TriggeringPrincipal(),
aLoadInfo->LoadingNode(), EmptyCString(),
nullptr, &decision);
NS_ENSURE_SUCCESS(rv, false);

View File

@ -873,7 +873,8 @@ ServiceWorkerManager::Register(mozIDOMWindow* aWindow,
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
aScriptURI,
documentPrincipal,
documentPrincipal, // loading principal
documentPrincipal, // triggering principal
doc,
EmptyCString(),
nullptr,

View File

@ -702,7 +702,8 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XSLT,
url,
mDocument->NodePrincipal(),
mDocument->NodePrincipal(), // loading principal
mDocument->NodePrincipal(), // triggering principal
aElement,
type,
nullptr,

View File

@ -590,6 +590,7 @@ ShouldLoadCachedImage(imgRequest* aImgRequest,
int16_t decision = nsIContentPolicy::REJECT_REQUEST;
rv = NS_CheckContentLoadPolicy(aPolicyType,
contentLocation,
aTriggeringPrincipal, // loading principal
aTriggeringPrincipal,
aLoadingContext,
EmptyCString(), //mime guess

View File

@ -1391,7 +1391,8 @@ FontFaceSet::IsFontLoadAllowed(nsIURI* aFontLocation,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_FONT,
aFontLocation,
aPrincipal,
aPrincipal, // loading principal
aPrincipal, // triggering principal
mDocument,
EmptyCString(), // mime type
nullptr, // aExtra

View File

@ -887,14 +887,15 @@ Loader::ObsoleteSheet(nsIURI* aURI)
}
nsresult
Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload)
{
// When performing a system load (e.g. aUseSystemPrincipal = true)
// then aSourcePrincipal == null; don't consult content policies.
if (!aSourcePrincipal) {
// then aLoadingPrincipal == null; don't consult content policies.
if (!aLoadingPrincipal) {
return NS_OK;
}
@ -905,7 +906,8 @@ Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
aTargetURI,
aSourcePrincipal,
aLoadingPrincipal,
aTriggeringPrincipal,
aContext,
NS_LITERAL_CSTRING("text/css"),
nullptr, //extra param
@ -1948,18 +1950,18 @@ Loader::LoadStyleLink(nsIContent* aElement,
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
nsIPrincipal* principal = aTriggeringPrincipal;
if (!principal) {
principal = aElement ? aElement->NodePrincipal()
nsIPrincipal* loadingPrincipal = aElement ? aElement->NodePrincipal()
: mDocument->NodePrincipal();
}
nsIPrincipal* principal = aTriggeringPrincipal ? aTriggeringPrincipal
: loadingPrincipal;
nsISupports* context = aElement;
if (!context) {
context = mDocument;
}
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aURL, context, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Don't fire the error event if our document is loaded as data. We're
// supposed to not even try to do loads in that case... Unfortunately, we
@ -2095,13 +2097,18 @@ Loader::LoadChildSheet(StyleSheet* aParentSheet,
owningNode = topSheet->GetOwnerNode();
}
nsISupports* context = owningNode;
if (!context) {
nsISupports* context = nullptr;
nsIPrincipal* loadingPrincipal = nullptr;
if (owningNode) {
context = owningNode;
loadingPrincipal = owningNode->NodePrincipal();
} else if (mDocument) {
context = mDocument;
loadingPrincipal = mDocument->NodePrincipal();
}
nsIPrincipal* principal = aParentSheet->Principal();
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aURL, context, false);
NS_ENSURE_SUCCESS(rv, rv);
SheetLoadData* parentData = nullptr;
@ -2288,7 +2295,11 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = CheckContentPolicy(aOriginPrincipal, aURL, mDocument, aIsPreload);
nsCOMPtr<nsIPrincipal> loadingPrincipal = (aOriginPrincipal && mDocument
? mDocument->NodePrincipal()
: nullptr);
nsresult rv = CheckContentPolicy(loadingPrincipal, aOriginPrincipal,
aURL, mDocument, aIsPreload);
NS_ENSURE_SUCCESS(rv, rv);
StyleSheetState state;

View File

@ -477,7 +477,8 @@ private:
friend class SheetLoadData;
friend class StreamLoader;
nsresult CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload);

View File

@ -187,7 +187,10 @@ var ContentPolicy = {
data.frameAncestors = frameAncestors;
}
if (requestOrigin) {
data.originUrl = requestOrigin.spec;
data.documentUrl = requestOrigin.spec;
}
if (requestPrincipal && requestPrincipal.URI) {
data.originUrl = requestPrincipal.URI.spec;
}
mm.sendAsyncMessage("WebRequest:ShouldLoad", data);