Bug 1195162 - Use channel->ascynOpen2 dom/xbl/nsXBLService.cpp (r=sicking)

This commit is contained in:
Christoph Kerschbaumer 2015-09-14 18:59:35 -07:00
parent 7b0eb74aba
commit 1e5ee64415
7 changed files with 100 additions and 190 deletions

View File

@ -4779,55 +4779,6 @@ static bool SchemeIs(nsIURI* aURI, const char* aScheme)
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
}
/* static */
nsresult
nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
nsIPrincipal* aLoadingPrincipal,
uint32_t aCheckLoadFlags,
bool aAllowData,
uint32_t aContentPolicyType,
nsISupports* aContext,
const nsAFlatCString& aMimeGuess,
nsISupports* aExtra)
{
NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal here");
if (aLoadingPrincipal == sSystemPrincipal) {
return NS_OK;
}
// XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
// CheckLoadURIWithPrincipal
nsresult rv = sSecurityManager->
CheckLoadURIWithPrincipal(aLoadingPrincipal, aURIToLoad, aCheckLoadFlags);
NS_ENSURE_SUCCESS(rv, rv);
// Content Policy
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(aContentPolicyType,
aURIToLoad,
aLoadingPrincipal,
aContext,
aMimeGuess,
aExtra,
&shouldLoad,
GetContentPolicy(),
sSecurityManager);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_CP_REJECTED(shouldLoad)) {
return NS_ERROR_CONTENT_BLOCKED;
}
// Same Origin
if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
SchemeIs(aURIToLoad, "chrome"))) {
return NS_OK;
}
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true, false);
}
bool
nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
{

View File

@ -1366,38 +1366,6 @@ public:
*/
static void NotifyInstalledMenuKeyboardListener(bool aInstalling);
/**
* Do security checks before loading a resource. Does the following checks:
* nsIScriptSecurityManager::CheckLoadURIWithPrincipal
* NS_CheckContentLoadPolicy
* nsIScriptSecurityManager::CheckSameOriginURI
*
* You will still need to do at least SameOrigin checks before on redirects.
*
* @param aURIToLoad URI that is getting loaded.
* @param aLoadingPrincipal Principal of the resource that is initiating
* the load
* @param aCheckLoadFlags Flags to be passed to
* nsIScriptSecurityManager::CheckLoadURIWithPrincipal
* NOTE: If this contains ALLOW_CHROME the
* CheckSameOriginURI check will be skipped if
* aURIToLoad is a chrome uri.
* @param aAllowData Set to true to skip CheckSameOriginURI check when
aURIToLoad is a data uri.
* @param aContentPolicyType Type \
* @param aContext Context |- to be passed to
* @param aMimeGuess Mimetype | NS_CheckContentLoadPolicy
* @param aExtra Extra /
*/
static nsresult CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
nsIPrincipal* aLoadingPrincipal,
uint32_t aCheckLoadFlags,
bool aAllowData,
uint32_t aContentPolicyType,
nsISupports* aContext,
const nsAFlatCString& aMimeGuess = EmptyCString(),
nsISupports* aExtra = nullptr);
/**
* Returns true if aPrincipal is the system principal.
*/

View File

@ -32,47 +32,30 @@ ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
return NS_OK;
}
nsresult
DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
static bool SchemeIs(nsIURI* aURI, const char* aScheme)
{
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
NS_ENSURE_TRUE(baseURI, false);
// 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)) {
return NS_OK;
}
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
bool sameOriginDataInherits =
securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
return loadingPrincipal->CheckMayLoad(aURI,
true, // report to console
sameOriginDataInherits);
bool isScheme = false;
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
}
nsresult
DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
nsresult rv = NS_OK;
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
// Please note that checkLoadURIWithPrincipal 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
if ((securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) &&
(securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
return NS_OK;
}
nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
// XXX: @arg nsIScriptSecurityManager::STANDARD
// lets use STANDARD for now and evaluate on a callsite basis, see also:
// http://mxr.mozilla.org/mozilla-central/source/caps/nsIScriptSecurityManager.idl#62
uint32_t flags = nsIScriptSecurityManager::STANDARD;
if (aLoadInfo->GetAllowChrome()) {
flags |= nsIScriptSecurityManager::ALLOW_CHROME;
}
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(loadingPrincipal,
aURI,
nsIScriptSecurityManager::STANDARD);
flags);
NS_ENSURE_SUCCESS(rv, rv);
// If the loadingPrincipal and the triggeringPrincipal are different, then make
@ -82,20 +65,33 @@ DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(triggeringPrincipal,
aURI,
nsIScriptSecurityManager::STANDARD);
flags);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
if (aLoadInfo->GetAllowChrome() && SchemeIs(aURI, "chrome")) {
// Enforce same-origin policy, except to chrome.
return DoCheckLoadURIChecks(aURI, aLoadInfo);
}
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
bool sameOriginDataInherits =
aLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
return loadingPrincipal->CheckMayLoad(aURI,
true, // report to console
sameOriginDataInherits);
}
nsresult
DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
{
if (aLoadInfo->GetSecurityMode() != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
return NS_OK;
}
MOZ_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(aInAndOutListener,
@ -144,12 +140,17 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
break;
}
case nsIContentPolicy::TYPE_REFRESH:
case nsIContentPolicy::TYPE_XBL: {
case nsIContentPolicy::TYPE_REFRESH: {
MOZ_ASSERT(false, "contentPolicyType not supported yet");
break;
}
case nsIContentPolicy::TYPE_XBL: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
break;
}
case nsIContentPolicy::TYPE_PING: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
@ -307,9 +308,14 @@ nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel,
rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI));
NS_ENSURE_SUCCESS(rv, rv);
// Perform Same Origin Policy check
rv = DoSOPChecks(finalChannelURI, loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
// 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)) {
rv = DoSOPChecks(finalChannelURI, loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
}
// if dealing with a redirected channel then we only enforce SOP
// and can return at this point.
@ -317,12 +323,20 @@ nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel,
return NS_OK;
}
rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
if ((securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) ||
(securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
// 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
rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
}
// Check if CORS needs to be set up
rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
NS_ENSURE_SUCCESS(rv, rv);
if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
NS_ENSURE_SUCCESS(rv, rv);
}
// Perform all ContentPolicy checks (MixedContent, CSP, ...)
rv = DoContentSecurityChecks(finalChannelURI, loadInfo);

View File

@ -856,21 +856,6 @@ static bool SchemeIs(nsIURI* aURI, const char* aScheme)
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
}
static bool
IsSystemOrChromeURLPrincipal(nsIPrincipal* aPrincipal)
{
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
return true;
}
nsCOMPtr<nsIURI> uri;
aPrincipal->GetURI(getter_AddRefs(uri));
NS_ENSURE_TRUE(uri, false);
bool isChrome = false;
return NS_SUCCEEDED(uri->SchemeIs("chrome", &isChrome)) && isChrome;
}
nsresult
nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsIDocument* aBoundDocument,
@ -883,45 +868,16 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
NS_PRECONDITION(!aOriginPrincipal || aBoundDocument,
"If we're doing a security check, we better have a document!");
nsresult rv;
if (aOriginPrincipal) {
// Security check - Enforce same-origin policy, except to chrome.
// We have to be careful to not pass aContent as the context here.
// Otherwise, if there is a JS-implemented content policy, we will attempt
// to wrap the content node, which will try to load XBL bindings for it, if
// any. Since we're not done loading this binding yet, that will reenter
// this method and we'll end up creating a binding and then immediately
// clobbering it in our table. That makes things very confused, leading to
// misbehavior and crashes.
rv = nsContentUtils::
CheckSecurityBeforeLoad(aBindingURI, aOriginPrincipal,
nsIScriptSecurityManager::ALLOW_CHROME,
gAllowDataURIs,
nsIContentPolicy::TYPE_XBL,
aBoundDocument);
NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED);
if (!IsSystemOrChromeURLPrincipal(aOriginPrincipal)) {
// Also make sure that we're same-origin with the bound document
// except if the stylesheet has the system principal.
if (!(gAllowDataURIs && SchemeIs(aBindingURI, "data")) &&
!SchemeIs(aBindingURI, "chrome")) {
rv = aBoundDocument->NodePrincipal()->CheckMayLoad(aBindingURI,
true, false);
NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED);
}
// Finally check if this document is allowed to use XBL at all.
NS_ENSURE_TRUE(aBoundDocument->AllowXULXBL(),
NS_ERROR_XBL_BLOCKED);
}
*aResult = nullptr;
if (aOriginPrincipal && !nsContentUtils::IsSystemPrincipal(aOriginPrincipal)) {
NS_ENSURE_TRUE(!aBoundDocument || aBoundDocument->AllowXULXBL(),
NS_ERROR_XBL_BLOCKED);
}
*aResult = nullptr;
nsRefPtr<nsXBLDocumentInfo> info;
nsCOMPtr<nsIURI> documentURI;
rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI));
nsresult rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef MOZ_XUL
@ -1005,9 +961,10 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
aForceSyncLoad = true;
nsCOMPtr<nsIDocument> document;
FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
aBindingURI, aOriginPrincipal, aForceSyncLoad,
getter_AddRefs(document));
rv = FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
aBindingURI, aOriginPrincipal, aForceSyncLoad,
getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
if (document) {
nsBindingManager *xblDocBindingManager = document->BindingManager();
@ -1081,30 +1038,31 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
if (aOriginPrincipal) {
// if there is an originPrincipal we should also have aBoundDocument
NS_ASSERTION(aBoundDocument, "can not create a channel without aBoundDocument");
MOZ_ASSERT(aBoundDocument, "can not create a channel without aBoundDocument");
if (!gAllowDataURIs && SchemeIs(aDocumentURI, "data")) {
return NS_ERROR_XBL_BLOCKED;
}
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
aDocumentURI,
aBoundDocument,
aOriginPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS |
nsILoadInfo::SEC_ALLOW_CHROME,
nsIContentPolicy::TYPE_XBL,
loadGroup);
}
else {
rv = NS_NewChannel(getter_AddRefs(channel),
aDocumentURI,
nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
nsIContentPolicy::TYPE_XBL,
loadGroup);
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInterfaceRequestor> sameOriginChecker = nsContentUtils::SameOriginChecker();
channel->SetNotificationCallbacks(sameOriginChecker);
if (!aForceSyncLoad) {
// We can be asynchronous
nsXBLStreamListener* xblListener =
@ -1126,7 +1084,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
xblListener->AddRequest(req);
// Now kick off the async read.
rv = channel->AsyncOpen(xblListener, nullptr);
rv = channel->AsyncOpen2(xblListener);
if (NS_FAILED(rv)) {
// Well, we won't be getting a load. Make sure to clean up our stuff!
if (bindingManager) {
@ -1148,7 +1106,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
// Now do a blocking synchronous parse of the file.
nsCOMPtr<nsIInputStream> in;
rv = channel->Open(getter_AddRefs(in));
rv = channel->Open2(getter_AddRefs(in));
NS_ENSURE_SUCCESS(rv, rv);
rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel);

View File

@ -3,6 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
toolkit.jar:
% content xbl-marquee %content/xbl-marquee/
% content xbl-marquee %content/xbl-marquee/ contentaccessible=yes
content/xbl-marquee/xbl-marquee.xml
content/xbl-marquee/xbl-marquee.css

View File

@ -211,6 +211,14 @@ LoadInfo::GetAboutBlankInherits(bool* aResult)
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetAllowChrome(bool* aResult)
{
*aResult =
(mSecurityFlags & nsILoadInfo::SEC_ALLOW_CHROME);
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetContentPolicyType(nsContentPolicyType* aResult)
{

View File

@ -22,7 +22,7 @@ typedef unsigned long nsSecurityFlags;
/**
* An nsILoadOwner represents per-load information about who started the load.
*/
[scriptable, builtinclass, uuid(99abb145-29d2-4a0a-8bca-213fa6211cc9)]
[scriptable, builtinclass, uuid(ef0080f3-33f5-475f-a3d6-9fd3be0612e3)]
interface nsILoadInfo : nsISupports
{
/**
@ -122,6 +122,11 @@ interface nsILoadInfo : nsISupports
*/
const unsigned long SEC_ABOUT_BLANK_INHERITS = (1<<8);
/**
* Allow chrome: to bypass security checks.
*/
const unsigned long SEC_ALLOW_CHROME = (1<<9);
/**
* The loadingPrincipal is the principal that is responsible for the load.
* It is *NOT* the principal tied to the resource/URI that this
@ -237,6 +242,12 @@ interface nsILoadInfo : nsISupports
*/
[infallible] readonly attribute boolean aboutBlankInherits;
/**
* If allowChrome is true, then use nsIScriptSecurityManager::ALLOW_CHROME
* when calling CheckLoadURIWithPrincipal().
*/
[infallible] readonly attribute boolean allowChrome;
/**
* The external contentPolicyType of the channel, used for security checks
* like Mixed Content Blocking and Content Security Policy.