Bug 1053725 - When one domain is whitelisted for file:// URI access, whitelist all subdomains. r=bz, a=sledru
authorBobby Holley <bobbyholley@gmail.com>
Mon, 08 Sep 2014 22:22:22 -0700
changeset 216735 a91c79c7e64e
parent 216734 e608db37bafb
child 216736 f58da8f6f47e
push id3893
push userryanvm@gmail.com
push date2014-09-15 15:46 +0000
treeherdermozilla-beta@1c636d0e8ec1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, sledru
bugs1053725
milestone33.0
Bug 1053725 - When one domain is whitelisted for file:// URI access, whitelist all subdomains. r=bz, a=sledru
caps/nsScriptSecurityManager.cpp
caps/tests/mochitest/test_bug995943.xul
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -27,16 +27,17 @@
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "nsError.h"
 #include "nsDOMCID.h"
 #include "nsIXPConnect.h"
 #include "nsTextFormatter.h"
 #include "nsIStringBundle.h"
 #include "nsNetUtil.h"
+#include "nsIEffectiveTLDService.h"
 #include "nsIProperties.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIFile.h"
 #include "nsIFileURL.h"
 #include "nsIZipReader.h"
 #include "nsIXPConnect.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsPIDOMWindow.h"
@@ -511,16 +512,45 @@ DenyAccessIfURIHasFlags(nsIURI* aURI, ui
 
     if (uriHasFlags) {
         return NS_ERROR_DOM_BAD_URI;
     }
 
     return NS_OK;
 }
 
+static bool
+EqualOrSubdomain(nsIURI* aProbeArg, nsIURI* aBase)
+{
+    // Make a clone of the incoming URI, because we're going to mutate it.
+    nsCOMPtr<nsIURI> probe;
+    nsresult rv = aProbeArg->Clone(getter_AddRefs(probe));
+    NS_ENSURE_SUCCESS(rv, false);
+
+    nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
+    NS_ENSURE_TRUE(tldService, false);
+    while (true) {
+        if (nsScriptSecurityManager::SecurityCompareURIs(probe, aBase)) {
+            return true;
+        }
+
+        nsAutoCString host, newHost;
+        nsresult rv = probe->GetHost(host);
+        NS_ENSURE_SUCCESS(rv, false);
+
+        rv = tldService->GetNextSubDomain(host, newHost);
+        if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
+            return false;
+        }
+        NS_ENSURE_SUCCESS(rv, false);
+        rv = probe->SetHost(newHost);
+        NS_ENSURE_SUCCESS(rv, false);
+    }
+}
+
 NS_IMETHODIMP
 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
                                                    nsIURI *aTargetURI,
                                                    uint32_t aFlags)
 {
     NS_PRECONDITION(aPrincipal, "CheckLoadURIWithPrincipal must have a principal");
     // If someone passes a flag that we don't understand, we should
     // fail, because they may need a security check that we don't
@@ -711,17 +741,17 @@ nsScriptSecurityManager::CheckLoadURIWit
     rv = NS_URIChainHasFlags(targetBaseURI,
                              nsIProtocolHandler::URI_IS_LOCAL_FILE,
                              &hasFlags);
     NS_ENSURE_SUCCESS(rv, rv);
     if (hasFlags) {
         // Allow domains that were whitelisted in the prefs. In 99.9% of cases,
         // this array is empty.
         for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) {
-            if (SecurityCompareURIs(mFileURIWhitelist[i], sourceURI)) {
+            if (EqualOrSubdomain(sourceURI, mFileURIWhitelist[i])) {
                 return NS_OK;
             }
         }
 
         // resource: and chrome: are equivalent, securitywise
         // That's bogus!!  Fix this.  But watch out for
         // the view-source stylesheet?
         bool sourceIsChrome;
--- a/caps/tests/mochitest/test_bug995943.xul
+++ b/caps/tests/mochitest/test_bug995943.xul
@@ -77,23 +77,28 @@ https://bugzilla.mozilla.org/show_bug.cg
                             ['capability.policy.somepolicy.sites', 'http://example.com']]))
     .then(checkLoadFileURI.bind(null, 'http://example.com', true))
     .then(popPrefs)
     .then(checkLoadFileURI.bind(null, 'http://example.com', false))
     .then(
       pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '],
                             ['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'],
                             ['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'],
-                            ['capability.policy.somepolicy.sites', ' http://example.org   https://example.com test1.example.com'],
+                            ['capability.policy.somepolicy.sites', ' http://example.org   test1.example.com https://test2.example.com '],
                             ['capability.policy.someotherpolicy.sites', 'http://example.net ']]))
     .then(checkLoadFileURI.bind(null, 'http://example.org', true))
-    .then(checkLoadFileURI.bind(null, 'http://example.com', false))
+    .then(checkLoadFileURI.bind(null, 'http://test2.example.com', false))
+    .then(checkLoadFileURI.bind(null, 'https://test2.example.com', true))
+    .then(checkLoadFileURI.bind(null, 'http://sub1.test2.example.com', false))
+    .then(checkLoadFileURI.bind(null, 'https://sub1.test2.example.com', true))
     .then(checkLoadFileURI.bind(null, 'http://example.net', false))
     .then(checkLoadFileURI.bind(null, 'http://test1.example.com', true))
     .then(checkLoadFileURI.bind(null, 'https://test1.example.com', true))
+    .then(checkLoadFileURI.bind(null, 'http://sub1.test1.example.com', true))
+    .then(checkLoadFileURI.bind(null, 'https://sub1.test1.example.com', true))
     .then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']]))
     .then(checkLoadFileURI.bind(null, 'http://example.net', true))
     .then(popPrefs)
     .then(popPrefs)
     .then(checkLoadFileURI.bind(null, 'http://example.net', false))
     .then(SimpleTest.finish.bind(SimpleTest));
 
   }