Bug 863246 - Deny resource:// access to web content draft
authorChung-Sheng Fu <cfu@mozilla.com>
Thu, 18 May 2017 09:55:01 +0800
changeset 579940 31edb2abf0d2fe11abf9ae9fe79475e8bae21d37
parent 579939 043add1312d992baf55d933dc75fed75d070377c
child 579941 3352618d64189e148a09a3d9b0455a35b0e349a3
push id59417
push userbmo:cfu@mozilla.com
push dateThu, 18 May 2017 02:41:45 +0000
bugs863246
milestone55.0a1
Bug 863246 - Deny resource:// access to web content The caps part MozReview-Commit-ID: 2B6CLzFxeTw
caps/nsScriptSecurityManager.cpp
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -47,16 +47,17 @@
 #include "nsIObserverService.h"
 #include "nsIContent.h"
 #include "nsDOMJSUtils.h"
 #include "nsAboutProtocolUtils.h"
 #include "nsIClassInfo.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
+#include "nsIResProtocolHandler.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
 #include <stdint.h>
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
@@ -70,16 +71,19 @@
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nullptr;
 nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
 JSContext       *nsScriptSecurityManager::sContext   = nullptr;
 bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
 
+// Determines whether resource:// URIs should be blocked
+static const char * const kPrefBlockResourceUri = "security.block_resource_uri";
+
 ///////////////////////////
 // Convenience Functions //
 ///////////////////////////
 
 class nsAutoInPrincipalDomainOriginSetter {
 public:
     nsAutoInPrincipalDomainOriginSetter() {
         ++sInPrincipalDomainOrigin;
@@ -868,19 +872,20 @@ nsScriptSecurityManager::CheckLoadURIFla
     bool hasFlags = false;
     rv = NS_URIChainHasFlags(aTargetBaseURI,
                              nsIProtocolHandler::URI_IS_UI_RESOURCE,
                              &hasFlags);
     NS_ENSURE_SUCCESS(rv, rv);
     if (hasFlags) {
         if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) {
 
-            // For now, don't change behavior for resource:// or moz-icon:// and
-            // just allow them.
-            if (!targetScheme.EqualsLiteral("chrome")) {
+            // For now, don't change behavior for moz-icon:// and just allow it.
+            if (!targetScheme.EqualsLiteral("chrome") &&
+                    // resource:// is simply allowed if the preference kPrefBlockResourceUri is false
+                    (!Preferences::GetBool(kPrefBlockResourceUri) || !targetScheme.EqualsLiteral("resource"))) {
                 return NS_OK;
             }
 
             // Allow a URI_IS_UI_RESOURCE source to link to a URI_IS_UI_RESOURCE
             // target if ALLOW_CHROME is set.
             //
             // ALLOW_CHROME is a flag that we pass on all loads _except_ docshell
             // loads (since docshell loads run the loaded content with its origin
@@ -891,25 +896,37 @@ nsScriptSecurityManager::CheckLoadURIFla
             rv = NS_URIChainHasFlags(aSourceBaseURI,
                                      nsIProtocolHandler::URI_IS_UI_RESOURCE,
                                      &sourceIsUIResource);
             NS_ENSURE_SUCCESS(rv, rv);
             if (sourceIsUIResource) {
                 return NS_OK;
             }
 
-            // Allow the load only if the chrome package is whitelisted.
-            nsCOMPtr<nsIXULChromeRegistry> reg(do_GetService(
-                                                 NS_CHROMEREGISTRY_CONTRACTID));
-            if (reg) {
+            if (targetScheme.EqualsLiteral("resource")) {
+                nsCOMPtr<nsIProtocolHandler> ph;
+                rv = sIOService->GetProtocolHandler("resource", getter_AddRefs(ph));
+                NS_ENSURE_SUCCESS(rv, rv);
+                nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
                 bool accessAllowed = false;
-                reg->AllowContentToAccess(aTargetBaseURI, &accessAllowed);
+                rph->AllowContentToAccess(aTargetBaseURI, &accessAllowed);
                 if (accessAllowed) {
                     return NS_OK;
                 }
+            } else {
+                // Allow the load only if the chrome package is whitelisted.
+                nsCOMPtr<nsIXULChromeRegistry> reg(do_GetService(
+                                                    NS_CHROMEREGISTRY_CONTRACTID));
+                if (reg) {
+                    bool accessAllowed = false;
+                    reg->AllowContentToAccess(aTargetBaseURI, &accessAllowed);
+                    if (accessAllowed) {
+                        return NS_OK;
+                    }
+                }
             }
         }
 
         static bool sCanLoadChromeInContent = false;
         static bool sCachedCanLoadChromeInContentPref = false;
         if (!sCachedCanLoadChromeInContentPref) {
             sCachedCanLoadChromeInContentPref = true;
             mozilla::Preferences::AddBoolVarCache(&sCanLoadChromeInContent,