mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 341604 - modify CheckMayLoad to allow sandboxed workers to load blob and data URIs r=jst
This commit is contained in:
parent
0fbebce11b
commit
01a802da01
@ -21,7 +21,7 @@ interface nsIContentSecurityPolicy;
|
||||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||
|
||||
[scriptable, uuid(6df7d16d-5b26-42a1-b1f7-069d46c37aa8)]
|
||||
[scriptable, uuid(825ffce8-962d-11e1-aef3-8f2b6188709b)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
{
|
||||
/**
|
||||
@ -173,7 +173,13 @@ interface nsIPrincipal : nsISerializable
|
||||
* located at the given URI under the same-origin policy. This means that
|
||||
* codebase principals are only allowed to load resources from the same
|
||||
* domain, the system principal is allowed to load anything, and null
|
||||
* principals are not allowed to load anything.
|
||||
* principals are not allowed to load anything. This is changed slightly
|
||||
* by the optional flag allowIfInheritsPrincipal (which defaults to false)
|
||||
* which allows the load of a data: URI (which inherits the principal of
|
||||
* its loader) or a URI with the same principal as its loader (eg. a
|
||||
* Blob URI).
|
||||
* In these cases, with allowIfInheritsPrincipal set to true, the URI can
|
||||
* be loaded by a null principal.
|
||||
*
|
||||
* If the load is allowed this function does nothing. If the load is not
|
||||
* allowed the function throws NS_ERROR_DOM_BAD_URI.
|
||||
@ -187,9 +193,13 @@ interface nsIPrincipal : nsISerializable
|
||||
* @param uri The URI about to be loaded.
|
||||
* @param report If true, will report a warning to the console service
|
||||
* if the load is not allowed.
|
||||
* @param allowIfInheritsPrincipal If true, the load is allowed if the
|
||||
* loadee inherits the principal of the
|
||||
* loader.
|
||||
* @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
|
||||
*/
|
||||
void checkMayLoad(in nsIURI uri, in boolean report);
|
||||
void checkMayLoad(in nsIURI uri, in boolean report,
|
||||
in boolean allowIfInheritsPrincipal);
|
||||
|
||||
/**
|
||||
* The subject name for the certificate. This actually identifies the
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPrincipal.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
|
||||
class nsIObjectInputStream;
|
||||
class nsIObjectOutputStream;
|
||||
@ -123,7 +126,7 @@ public:
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||
NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
|
||||
NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
|
||||
NS_IMETHOD GetAppId(PRUint32* aAppStatus);
|
||||
@ -158,6 +161,23 @@ public:
|
||||
virtual void GetScriptLocation(nsACString& aStr) MOZ_OVERRIDE;
|
||||
void SetURI(nsIURI* aURI);
|
||||
|
||||
static bool IsPrincipalInherited(nsIURI* aURI) {
|
||||
// return true if the loadee URI has
|
||||
// the URI_INHERITS_SECURITY_CONTEXT flag set.
|
||||
bool doesInheritSecurityContext;
|
||||
nsresult rv =
|
||||
NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&doesInheritSecurityContext);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the puny-encoded origin of aURI.
|
||||
*/
|
||||
@ -202,7 +222,7 @@ public:
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||
NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
|
||||
NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
|
||||
NS_IMETHOD GetAppId(PRUint32* aAppStatus);
|
||||
|
@ -292,8 +292,26 @@ nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
|
||||
{
|
||||
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
if (aAllowIfInheritsPrincipal) {
|
||||
if (nsPrincipal::IsPrincipalInherited(aURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Also allow the load if the principal of the URI being checked is exactly
|
||||
// us ie this.
|
||||
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
|
||||
if (uriPrinc) {
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
uriPrinc->GetPrincipal(getter_AddRefs(principal));
|
||||
|
||||
if (principal && principal == this) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI);
|
||||
|
@ -846,8 +846,16 @@ URIIsLocalFile(nsIURI *aURI)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
if (aAllowIfInheritsPrincipal) {
|
||||
// If the caller specified to allow loads of URIs that inherit
|
||||
// our principal, allow the load if this URI inherits its principal
|
||||
if (nsPrincipal::IsPrincipalInherited(aURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
||||
URIIsLocalFile(aURI)) {
|
||||
@ -1432,11 +1440,11 @@ nsExpandedPrincipal::SubsumesIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
|
||||
nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
nsresult rv;
|
||||
for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
|
||||
rv = mPrincipals[i]->CheckMayLoad(uri, aReport);
|
||||
rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
@ -1394,7 +1394,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hasFlags) {
|
||||
return aPrincipal->CheckMayLoad(targetBaseURI, true);
|
||||
return aPrincipal->CheckMayLoad(targetBaseURI, true, false);
|
||||
}
|
||||
|
||||
//-- get the source scheme
|
||||
|
@ -115,7 +115,7 @@ nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
|
||||
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1704,7 +1704,7 @@ public:
|
||||
static already_AddRefed<nsIDocument>
|
||||
GetDocumentFromScriptContext(nsIScriptContext *aScriptContext);
|
||||
|
||||
static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel);
|
||||
static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal);
|
||||
|
||||
/**
|
||||
* The method checks whether the caller can access native anonymous content.
|
||||
|
@ -1064,7 +1064,7 @@ nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
|
||||
}
|
||||
|
||||
// Documents must list a manifest from the same origin
|
||||
rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true);
|
||||
rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
|
||||
}
|
||||
|
@ -4606,7 +4606,7 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true);
|
||||
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true, false);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -5756,9 +5756,9 @@ nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel
|
||||
|
||||
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
|
||||
|
||||
nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
|
||||
nsresult rv = oldPrincipal->CheckMayLoad(newURI, false, false);
|
||||
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -5929,13 +5929,13 @@ nsContentUtils::GetDocumentFromScriptContext(nsIScriptContext *aScriptContext)
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel)
|
||||
nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false));
|
||||
return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false, aAllowIfInheritsPrincipal));
|
||||
}
|
||||
|
||||
nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
|
||||
@ -6722,7 +6722,7 @@ nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
// based on its own codebase later.
|
||||
//
|
||||
if (URIIsLocalFile(aURI) && aLoadingPrincipal &&
|
||||
NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false)) &&
|
||||
NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false, false)) &&
|
||||
// One more check here. CheckMayLoad will always return true for the
|
||||
// system principal, but we do NOT want to inherit in that case.
|
||||
!IsSystemPrincipal(aLoadingPrincipal)) {
|
||||
|
@ -743,10 +743,10 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI)
|
||||
}
|
||||
|
||||
if (!mHasBeenCrossSite &&
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false)) &&
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false, false)) &&
|
||||
(originalURI == uri ||
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(originalURI,
|
||||
false)))) {
|
||||
false, false)))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1065,18 +1065,12 @@ nsExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Allow data URIs (let them skip the CheckMayLoad call), since we want
|
||||
// Allow data URIs and other URI's that inherit their principal by passing
|
||||
// true as the 3rd argument of CheckMayLoad, since we want
|
||||
// to allow external resources from data URIs regardless of the difference
|
||||
// in URI scheme.
|
||||
bool doesInheritSecurityContext;
|
||||
rv =
|
||||
NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&doesInheritSecurityContext);
|
||||
if (NS_FAILED(rv) || !doesInheritSecurityContext) {
|
||||
rv = requestingPrincipal->CheckMayLoad(aURI, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = requestingPrincipal->CheckMayLoad(aURI, true, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
|
||||
|
@ -1713,18 +1713,9 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ...or if this is a same-origin request.
|
||||
if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// exempt data URIs from the same origin check.
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
bool dataScheme = false;
|
||||
if (NS_SUCCEEDED(NS_GetFinalChannelURI(aChannel,
|
||||
getter_AddRefs(channelURI))) &&
|
||||
NS_SUCCEEDED(channelURI->SchemeIs("data", &dataScheme)) &&
|
||||
dataScheme) {
|
||||
// If this is a same-origin request or the channel's URI inherits
|
||||
// its principal, it's allowed.
|
||||
if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel, true)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -932,7 +932,7 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
||||
if (!(gAllowDataURIs && SchemeIs(aBindingURI, "data")) &&
|
||||
!SchemeIs(aBindingURI, "chrome")) {
|
||||
rv = aBoundDocument->NodePrincipal()->CheckMayLoad(aBindingURI,
|
||||
true);
|
||||
true, false);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED);
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@ nsXMLDocument::Load(const nsAString& aUrl, bool *aReturn)
|
||||
// chrome document.
|
||||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
if (!nsContentUtils::IsSystemPrincipal(principal)) {
|
||||
rv = principal->CheckMayLoad(uri, false);
|
||||
rv = principal->CheckMayLoad(uri, false, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
|
@ -2658,7 +2658,7 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic,
|
||||
bool documentIsChrome = IsChromeURI(mDocumentURI);
|
||||
if (!documentIsChrome) {
|
||||
// Make sure we're allowed to load this overlay.
|
||||
rv = NodePrincipal()->CheckMayLoad(aURI, true);
|
||||
rv = NodePrincipal()->CheckMayLoad(aURI, true, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
*aFailureFromContent = true;
|
||||
return rv;
|
||||
|
@ -1328,7 +1328,7 @@ nsXULTemplateBuilder::LoadDataSourceUrls(nsIDocument* aDocument,
|
||||
|
||||
// don't add the uri to the list if the document is not allowed to
|
||||
// load it
|
||||
if (!isTrusted && NS_FAILED(docPrincipal->CheckMayLoad(uri, true)))
|
||||
if (!isTrusted && NS_FAILED(docPrincipal->CheckMayLoad(uri, true, false)))
|
||||
continue;
|
||||
|
||||
uriList->AppendElement(uri, false);
|
||||
|
@ -10072,7 +10072,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
nsCOMPtr<nsIPrincipal> principal = docScriptObj->GetPrincipal();
|
||||
|
||||
if (!principal ||
|
||||
NS_FAILED(principal->CheckMayLoad(newURI, true))) {
|
||||
NS_FAILED(principal->CheckMayLoad(newURI, true, false))) {
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
@ -300,11 +300,12 @@ public:
|
||||
rv = uri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We exempt data URLs from the same origin check.
|
||||
if (!scheme.EqualsLiteral("data")) {
|
||||
rv = principal->CheckMayLoad(uri, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// We pass true as the 3rd argument to checkMayLoad here.
|
||||
// This allows workers in sandboxed documents to load data URLs
|
||||
// (and other URLs that inherit their principal from their
|
||||
// creator.)
|
||||
rv = principal->CheckMayLoad(uri, false, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
rv = secMan->CheckLoadURIWithPrincipal(principal, uri, 0);
|
||||
@ -487,9 +488,9 @@ public:
|
||||
rv = finalURI->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We exempt data urls again.
|
||||
if (!scheme.EqualsLiteral("data") &&
|
||||
NS_FAILED(loadPrincipal->CheckMayLoad(finalURI, false))) {
|
||||
// We exempt data urls and other URI's that inherit their
|
||||
// principal again.
|
||||
if (NS_FAILED(loadPrincipal->CheckMayLoad(finalURI, false, true))) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
|
@ -1545,7 +1545,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
|
||||
if ((NS_SUCCEEDED(rv) && inherit) ||
|
||||
(nsContentUtils::URIIsLocalFile(aLoadData->mURI) &&
|
||||
NS_SUCCEEDED(aLoadData->mLoaderPrincipal->
|
||||
CheckMayLoad(aLoadData->mURI, false)))) {
|
||||
CheckMayLoad(aLoadData->mURI, false, false)))) {
|
||||
channel->SetOwner(aLoadData->mLoaderPrincipal);
|
||||
}
|
||||
}
|
||||
|
@ -890,9 +890,9 @@ RDFXMLDataSourceImpl::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
|
||||
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
|
||||
|
||||
rv = oldPrincipal->CheckMayLoad(newURI, false);
|
||||
rv = oldPrincipal->CheckMayLoad(newURI, false, false);
|
||||
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
|
Loading…
Reference in New Issue
Block a user