Bug 1402530 - Use IsOriginPotentiallyTrustworthy in ShouldLoad r=ckerschb
authorSebastian Streich <sstreich@mozilla.com>
Mon, 13 May 2019 14:40:40 +0000
changeset 535570 9abb460fe84149f3d6e6579a914c70ff50efe7dc
parent 535569 2c0de6646a6199e4558a4bf6279f7250302fc172
child 535571 91bc05242c6f02a5d30c71557693129303e7067e
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1402530
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1402530 - Use IsOriginPotentiallyTrustworthy in ShouldLoad r=ckerschb Differential Revision: https://phabricator.services.mozilla.com/D30917
browser/base/content/test/siteIdentity/test_no_mcb_for_loopback.html
build/pgo/server-locations.txt
dom/security/nsContentSecurityManager.cpp
dom/security/nsMixedContentBlocker.cpp
dom/security/nsMixedContentBlocker.h
--- a/browser/base/content/test/siteIdentity/test_no_mcb_for_loopback.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_for_loopback.html
@@ -1,14 +1,14 @@
 <!-- See browser_no_mcb_for_localhost.js -->
 <!DOCTYPE HTML>
 <html>
   <head>
     <meta charset="utf8">
-    <title>Bug 903966</title>
+    <title>Bug 903966, Bug 1402530</title>
   </head>
 
   <style>
     @font-face {
       font-family: "Font-IPv4";
       src: url("http://127.0.0.1:8/test.ttf");
     }
 
@@ -27,24 +27,29 @@
   </style>
 
   <body>
     <div id="ip-v4">test</div>
     <div id="ip-v6">test</div>
 
     <img src="http://127.0.0.1:8/test.png">
     <img src="http://[::1]:8/test.png">
+    <img src="http://localhost:8/test.png">
 
     <iframe src="http://127.0.0.1:8/test.html"></iframe>
     <iframe src="http://[::1]:8/test.html"></iframe>
+    <iframe src="http://localhost:8/test.html"></iframe>
   </body>
 
   <script src="http://127.0.0.1:8/test.js"></script>
   <script src="http://[::1]:8/test.js"></script>
-
+  <script src="http://localhost:8/test.js"></script>
+  
   <link href="http://127.0.0.1:8/test.css" rel="stylesheet"></link>
   <link href="http://[::1]:8/test.css" rel="stylesheet"></link>
+  <link href="http://localhost:8/test.css" rel="stylesheet"></link>
 
   <script>
     fetch("http://127.0.0.1:8");
+    fetch("http://localhost:8");
     fetch("http://[::1]:8");
   </script>
 </html>
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -293,10 +293,13 @@ https://ssl3rc4.example.com:443     priv
 https://tls1.example.com:443        privileged,tls1
 
 # Hosts for youtube rewrite tests
 https://mochitest.youtube.com:443
 
 # Host for U2F localhost tests
 https://localhost:443
 
+# Bug 1402530
+http://localhost:80                 privileged
+
 # Host for testing APIs whitelisted for mozilla.org
 https://www.mozilla.org:443
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -1074,98 +1074,23 @@ nsContentSecurityManager::IsOriginPotent
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_ARG_POINTER(aIsTrustWorthy);
 
   if (aPrincipal->IsSystemPrincipal()) {
     *aIsTrustWorthy = true;
     return NS_OK;
   }
-
-  // The following implements:
-  // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
-
   *aIsTrustWorthy = false;
-
   if (aPrincipal->GetIsNullPrincipal()) {
     return NS_OK;
   }
 
   MOZ_ASSERT(aPrincipal->GetIsCodebasePrincipal(),
              "Nobody is expected to call us with an nsIExpandedPrincipal");
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
-  if (NS_FAILED(rv)) {
-    return NS_OK;
-  }
-
-  nsAutoCString scheme;
-  rv = uri->GetScheme(scheme);
-  if (NS_FAILED(rv)) {
-    return NS_OK;
-  }
-
-  // Blobs are expected to inherit their principal so we don't expect to have
-  // a codebase principal with scheme 'blob' here.  We can't assert that though
-  // since someone could mess with a non-blob URI to give it that scheme.
-  NS_WARNING_ASSERTION(!scheme.EqualsLiteral("blob"),
-                       "IsOriginPotentiallyTrustworthy ignoring blob scheme");
-
-  // According to the specification, the user agent may choose to extend the
-  // trust to other, vendor-specific URL schemes. We use this for "resource:",
-  // which is technically a substituting protocol handler that is not limited to
-  // local resource mapping, but in practice is never mapped remotely as this
-  // would violate assumptions a lot of code makes.
-  // We use nsIProtocolHandler flags to determine which protocols we consider a
-  // priori authenticated.
-  bool aPrioriAuthenticated = false;
-  if (NS_FAILED(NS_URIChainHasFlags(
-          uri, nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY,
-          &aPrioriAuthenticated))) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (aPrioriAuthenticated) {
-    *aIsTrustWorthy = true;
-    return NS_OK;
-  }
-
-  nsAutoCString host;
-  rv = uri->GetHost(host);
-  if (NS_FAILED(rv)) {
-    return NS_OK;
-  }
-
-  if (host.EqualsLiteral("127.0.0.1") || host.EqualsLiteral("localhost") ||
-      host.EqualsLiteral("::1")) {
-    *aIsTrustWorthy = true;
-    return NS_OK;
-  }
-
-  // If a host is not considered secure according to the default algorithm, then
-  // check to see if it has been whitelisted by the user.  We only apply this
-  // whitelist for network resources, i.e., those with scheme "http" or "ws".
-  // The pref should contain a comma-separated list of hostnames.
-  if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("ws")) {
-    nsAutoCString whitelist;
-    nsresult rv =
-        Preferences::GetCString("dom.securecontext.whitelist", whitelist);
-    if (NS_SUCCEEDED(rv)) {
-      nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
-      while (tokenizer.hasMoreTokens()) {
-        const nsACString& allowedHost = tokenizer.nextToken();
-        if (host.Equals(allowedHost)) {
-          *aIsTrustWorthy = true;
-          return NS_OK;
-        }
-      }
-    }
-    // Maybe we have a .onion URL. Treat it as whitelisted as well if
-    // `dom.securecontext.whitelist_onions` is `true`.
-    if (nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(uri)) {
-      *aIsTrustWorthy = true;
-      return NS_OK;
-    }
-  }
+  NS_ENSURE_SUCCESS(rv, rv);
+  *aIsTrustWorthy = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
 
   return NS_OK;
 }
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -373,17 +373,19 @@ nsMixedContentBlocker::ShouldLoad(nsIURI
 bool nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(nsIURI* aURL) {
   nsAutoCString host;
   nsresult rv = aURL->GetHost(host);
   NS_ENSURE_SUCCESS(rv, false);
 
   // We could also allow 'localhost' (if we can guarantee that it resolves
   // to a loopback address), but Chrome doesn't support it as of writing. For
   // web compat, lets only allow what Chrome allows.
-  return host.EqualsLiteral("127.0.0.1") || host.EqualsLiteral("::1");
+  // see also https://bugzilla.mozilla.org/show_bug.cgi?id=1220810
+  return host.EqualsLiteral("127.0.0.1") || host.EqualsLiteral("::1") ||
+         host.EqualsLiteral("localhost");
 }
 
 /* Maybe we have a .onion URL. Treat it as whitelisted as well if
  * `dom.securecontext.whitelist_onions` is `true`.
  */
 bool nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(nsIURI* aURL) {
   static bool sInited = false;
   static bool sWhiteListOnions = false;
@@ -397,16 +399,88 @@ bool nsMixedContentBlocker::IsPotentiall
   }
 
   nsAutoCString host;
   nsresult rv = aURL->GetHost(host);
   NS_ENSURE_SUCCESS(rv, false);
   return StringEndsWith(host, NS_LITERAL_CSTRING(".onion"));
 }
 
+bool nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(nsIURI* aURI) {
+  // The following implements:
+  // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
+
+  nsAutoCString scheme;
+  nsresult rv = aURI->GetScheme(scheme);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  // Blobs are expected to inherit their principal so we don't expect to have
+  // a codebase principal with scheme 'blob' here.  We can't assert that though
+  // since someone could mess with a non-blob URI to give it that scheme.
+  NS_WARNING_ASSERTION(!scheme.EqualsLiteral("blob"),
+                       "IsOriginPotentiallyTrustworthy ignoring blob scheme");
+
+  // According to the specification, the user agent may choose to extend the
+  // trust to other, vendor-specific URL schemes. We use this for "resource:",
+  // which is technically a substituting protocol handler that is not limited to
+  // local resource mapping, but in practice is never mapped remotely as this
+  // would violate assumptions a lot of code makes.
+  // We use nsIProtocolHandler flags to determine which protocols we consider a
+  // priori authenticated.
+  bool aPrioriAuthenticated = false;
+  if (NS_FAILED(NS_URIChainHasFlags(
+          aURI, nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY,
+          &aPrioriAuthenticated))) {
+    return false;
+  }
+
+  if (aPrioriAuthenticated) {
+    return true;
+  }
+
+  nsAutoCString host;
+  rv = aURI->GetHost(host);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  if (IsPotentiallyTrustworthyLoopbackURL(aURI)) {
+    return true;
+  }
+
+  // If a host is not considered secure according to the default algorithm, then
+  // check to see if it has been whitelisted by the user.  We only apply this
+  // whitelist for network resources, i.e., those with scheme "http" or "ws".
+  // The pref should contain a comma-separated list of hostnames.
+
+  if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("ws")) {
+    return false;
+  }
+
+  nsAutoCString whitelist;
+  rv = Preferences::GetCString("dom.securecontext.whitelist", whitelist);
+  if (NS_SUCCEEDED(rv)) {
+    nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
+    while (tokenizer.hasMoreTokens()) {
+      const nsACString& allowedHost = tokenizer.nextToken();
+      if (host.Equals(allowedHost)) {
+        return true;
+      }
+    }
+  }
+  // Maybe we have a .onion URL. Treat it as whitelisted as well if
+  // `dom.securecontext.whitelist_onions` is `true`.
+  if (nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(aURI)) {
+    return true;
+  }
+  return false;
+}
+
 /* Static version of ShouldLoad() that contains all the Mixed Content Blocker
  * logic.  Called from non-static ShouldLoad().
  */
 nsresult nsMixedContentBlocker::ShouldLoad(
     bool aHadInsecureImageRedirect, uint32_t aContentType,
     nsIURI* aContentLocation, nsIURI* aRequestingLocation,
     nsISupports* aRequestingContext, const nsACString& aMimeGuess,
     nsIPrincipal* aRequestPrincipal, int16_t* aDecision) {
@@ -696,27 +770,17 @@ nsresult nsMixedContentBlocker::ShouldLo
     *aDecision = REJECT_REQUEST;
     return NS_OK;
   }
 
   bool isHttpScheme = false;
   rv = innerContentLocation->SchemeIs("http", &isHttpScheme);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Loopback origins are not considered mixed content even over HTTP. See:
-  // https://w3c.github.io/webappsec-mixed-content/#should-block-fetch
-  if (isHttpScheme &&
-      IsPotentiallyTrustworthyLoopbackURL(innerContentLocation)) {
-    *aDecision = ACCEPT;
-    return NS_OK;
-  }
-
-  // .onion URLs are encrypted and authenticated. Don't treat them as mixed
-  // content if potentially trustworthy (i.e. whitelisted).
-  if (isHttpScheme && IsPotentiallyTrustworthyOnion(innerContentLocation)) {
+  if (isHttpScheme && IsPotentiallyTrustworthyOrigin(innerContentLocation)) {
     *aDecision = ACCEPT;
     return NS_OK;
   }
 
   // The page might have set the CSP directive 'upgrade-insecure-requests'. In
   // such a case allow the http: load to succeed with the promise that the
   // channel will get upgraded to https before fetching any data from the
   // netwerk. Please see: nsHttpChannel::Connect()
--- a/dom/security/nsMixedContentBlocker.h
+++ b/dom/security/nsMixedContentBlocker.h
@@ -46,16 +46,17 @@ class nsMixedContentBlocker : public nsI
   NS_DECL_NSICHANNELEVENTSINK
 
   nsMixedContentBlocker();
 
   // See:
   // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
   static bool IsPotentiallyTrustworthyLoopbackURL(nsIURI* aURL);
   static bool IsPotentiallyTrustworthyOnion(nsIURI* aURL);
+  static bool IsPotentiallyTrustworthyOrigin(nsIURI* aURI);
 
   /* Static version of ShouldLoad() that contains all the Mixed Content Blocker
    * logic.  Called from non-static ShouldLoad().
    * Called directly from imageLib when an insecure redirect exists in a cached
    * image load.
    * @param aHadInsecureImageRedirect
    *        boolean flag indicating that an insecure redirect through http
    *        occured when this image was initially loaded and cached.