Bug 1309310, r=bz
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 09 Nov 2016 18:25:11 +0000
changeset 322173 fb5ae665310e4f60464ccd43b2626fdfc2087a67
parent 322172 d728a7fdade20d7fbfd8c18e46974abd7fd150e6
child 322174 3f1ec7d616d64068b447ede8d6fe2d59d2cf09b2
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersbz
bugs1309310
milestone52.0a1
Bug 1309310, r=bz MozReview-Commit-ID: KLaMv6zfxR8
caps/nsScriptSecurityManager.cpp
netwerk/base/nsIProtocolHandler.idl
netwerk/protocol/about/nsAboutProtocolHandler.cpp
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -798,25 +798,37 @@ nsScriptSecurityManager::CheckLoadURIWit
         // exception for foo: linking to view-source:foo for reftests...
         return NS_OK;
     }
 
     // If we get here, check all the schemes can link to each other, from the top down:
     nsCaseInsensitiveCStringComparator stringComparator;
     nsCOMPtr<nsIURI> currentURI = sourceURI;
     nsCOMPtr<nsIURI> currentOtherURI = aTargetURI;
+
+    bool denySameSchemeLinks = false;
+    rv = NS_URIChainHasFlags(aTargetURI, nsIProtocolHandler::URI_SCHEME_NOT_SELF_LINKABLE,
+                             &denySameSchemeLinks);
+    if (NS_FAILED(rv)) return rv;
+
     while (currentURI && currentOtherURI) {
         nsAutoCString scheme, otherScheme;
         currentURI->GetScheme(scheme);
         currentOtherURI->GetScheme(otherScheme);
 
-        // If schemes are not equal, check if the URI flags of the current
-        // target URI allow the current source URI to link to it.
+        // If schemes are not equal, or they're equal but the target URI
+        // is different from the source URI and doesn't always allow linking
+        // from the same scheme, check if the URI flags of the current target
+        // URI allow the current source URI to link to it.
         // The policy is specified by the protocol flags on both URIs.
-        if (!scheme.Equals(otherScheme, stringComparator)) {
+        bool equalExceptRef = false;
+        if (!scheme.Equals(otherScheme, stringComparator) ||
+            (denySameSchemeLinks &&
+             (!NS_SUCCEEDED(currentURI->EqualsExceptRef(currentOtherURI, &equalExceptRef)) ||
+              !equalExceptRef))) {
             return CheckLoadURIFlags(currentURI, currentOtherURI,
                                      sourceBaseURI, targetBaseURI, aFlags);
         }
         // Otherwise... check if we can nest another level:
         nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(currentURI);
         nsCOMPtr<nsINestedURI> nestedOtherURI = do_QueryInterface(currentOtherURI);
 
         // If schemes match and neither URI is nested further, we're OK.
--- a/netwerk/base/nsIProtocolHandler.idl
+++ b/netwerk/base/nsIProtocolHandler.idl
@@ -295,16 +295,22 @@ interface nsIProtocolHandler : nsISuppor
      */
     const unsigned long URI_FETCHABLE_BY_ANYONE = (1 << 19);
 
     /**
      * If this flag is set, then the origin for this protocol is the full URI
      * spec, not just the scheme + host + port.
      */
     const unsigned long ORIGIN_IS_FULL_SPEC = (1 << 20);
+
+    /**
+     * If this flag is set, the URI does not always allow content using the same
+     * protocol to link to it.
+     */
+    const unsigned long URI_SCHEME_NOT_SELF_LINKABLE = (1 << 21);
 };
 
 %{C++
 /**
  * Protocol handlers are registered with XPCOM under the following CONTRACTID prefix:
  */
 #define NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "@mozilla.org/network/protocol;1?name="
 /**
--- a/netwerk/protocol/about/nsAboutProtocolHandler.cpp
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.cpp
@@ -62,17 +62,17 @@ nsAboutProtocolHandler::GetDefaultPort(i
 {
     *result = -1;        // no port for about: URLs
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAboutProtocolHandler::GetProtocolFlags(uint32_t *result)
 {
-    *result = URI_NORELATIVE | URI_NOAUTH | URI_DANGEROUS_TO_LOAD;
+    *result = URI_NORELATIVE | URI_NOAUTH | URI_DANGEROUS_TO_LOAD | URI_SCHEME_NOT_SELF_LINKABLE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAboutProtocolHandler::GetFlagsForURI(nsIURI* aURI, uint32_t* aFlags)
 {
     // First use the default (which is "unsafe for content"):
     GetProtocolFlags(aFlags);