--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -647,47 +647,16 @@ EqualOrSubdomain(nsIURI* aProbeArg, nsIU
return false;
}
NS_ENSURE_SUCCESS(rv, false);
rv = probe->SetHost(newHost);
NS_ENSURE_SUCCESS(rv, false);
}
}
-static bool
-AllSchemesMatch(nsIURI* aURI, nsIURI* aOtherURI)
-{
- auto stringComparator = nsCaseInsensitiveCStringComparator();
- nsCOMPtr<nsIURI> currentURI = aURI;
- nsCOMPtr<nsIURI> currentOtherURI = aOtherURI;
- while (currentURI && currentOtherURI) {
- nsAutoCString scheme, otherScheme;
- currentURI->GetScheme(scheme);
- currentOtherURI->GetScheme(otherScheme);
- if (!scheme.Equals(otherScheme, stringComparator)) {
- return false;
- }
- nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(currentURI);
- nsCOMPtr<nsINestedURI> nestedOtherURI = do_QueryInterface(currentOtherURI);
- // If neither are nested and all schemes have matched so far
- // (or we would have bailed already), we're the same:
- if (!nestedURI && !nestedOtherURI) {
- return true;
- }
- // If one is nested and the other not, they're not equal:
- if (!nestedURI != !nestedOtherURI) {
- return false;
- }
- // At this stage, both are still nested URIs, so let's play again:
- nestedURI->GetInnerURI(getter_AddRefs(currentURI));
- nestedOtherURI->GetInnerURI(getter_AddRefs(currentOtherURI));
- }
- return 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
@@ -800,63 +769,60 @@ nsScriptSecurityManager::CheckLoadURIWit
bool targetIsViewSource = false;
if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
// A null principal can target its own URI.
if (sourceURI == aTargetURI) {
return NS_OK;
}
}
- else if (AllSchemesMatch(sourceURI, aTargetURI) ||
- (sViewSourceReachableFromInner &&
- sourceScheme.EqualsIgnoreCase(targetScheme.get()) &&
- NS_SUCCEEDED(aTargetURI->SchemeIs("view-source", &targetIsViewSource)) &&
- targetIsViewSource))
+ else if (sViewSourceReachableFromInner &&
+ sourceScheme.EqualsIgnoreCase(targetScheme.get()) &&
+ NS_SUCCEEDED(aTargetURI->SchemeIs("view-source", &targetIsViewSource)) &&
+ targetIsViewSource)
{
- // every scheme can access another URI from the same scheme,
- // as long as they don't represent null principals...
- // Or they don't require an special permission to do so
- // See bug#773886
- rv = NS_URIChainHasFlags(targetBaseURI,
- nsIProtocolHandler::URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM,
- &hasFlags);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (hasFlags) {
- // Let apps load the whitelisted theme resources even if they don't
- // have the webapps-manage permission but have the themeable one.
- // Resources from the theme origin are also allowed to load from
- // the theme origin (eg. stylesheets using images from the theme).
- auto themeOrigin = Preferences::GetCString("b2g.theme.origin");
- if (themeOrigin) {
- nsAutoCString targetOrigin;
- nsPrincipal::GetOriginForURI(targetBaseURI, targetOrigin);
- if (targetOrigin.Equals(themeOrigin)) {
- nsAutoCString pOrigin;
- aPrincipal->GetOrigin(pOrigin);
- return nsContentUtils::IsExactSitePermAllow(aPrincipal, "themeable") ||
- pOrigin.Equals(themeOrigin)
- ? NS_OK : NS_ERROR_DOM_BAD_URI;
- }
- }
- // In this case, we allow opening only if the source and target URIS
- // are on the same domain, or the opening URI has the webapps
- // permision granted
- if (!SecurityCompareURIs(sourceBaseURI, targetBaseURI) &&
- !nsContentUtils::IsExactSitePermAllow(aPrincipal, WEBAPPS_PERM_NAME)) {
- return NS_ERROR_DOM_BAD_URI;
- }
- }
+ // exception for foo: linking to view-source:foo for reftests...
return NS_OK;
}
- // If the schemes don't match, the policy is specified by the protocol
- // flags on the target URI.
- return CheckLoadURIFlags(sourceURI, aTargetURI, sourceBaseURI,
- targetBaseURI, aFlags);
+ // If we get here, check all the schemes can link to each other, from the top down:
+ auto stringComparator = nsCaseInsensitiveCStringComparator();
+ nsCOMPtr<nsIURI> currentURI = sourceURI;
+ nsCOMPtr<nsIURI> currentOtherURI = aTargetURI;
+ 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.
+ // The policy is specified by the protocol flags on both URIs.
+ if (!scheme.Equals(otherScheme, stringComparator)) {
+ 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.
+ if (!nestedURI && !nestedOtherURI) {
+ return NS_OK;
+ }
+ // If one is nested and the other isn't, something is wrong.
+ if (!nestedURI != !nestedOtherURI) {
+ return NS_ERROR_DOM_BAD_URI;
+ }
+ // Otherwise, both should be nested and we'll go through the loop again.
+ nestedURI->GetInnerURI(getter_AddRefs(currentURI));
+ nestedOtherURI->GetInnerURI(getter_AddRefs(currentOtherURI));
+ }
+
+ // We should never get here. We should always return from inside the loop.
+ return NS_ERROR_DOM_BAD_URI;
}
/**
* Helper method to check whether the target URI and its innermost ("base") URI
* has protocol flags that should stop it from being loaded by the source URI
* (and/or the source URI's innermost ("base") URI), taking into account any
* nsIScriptSecurityManager flags originally passed to
* CheckLoadURIWithPrincipal and friends.
--- a/caps/tests/mochitest/browser_checkloaduri.js
+++ b/caps/tests/mochitest/browser_checkloaduri.js
@@ -10,42 +10,45 @@ const URLs = new Map([
// - whether the URI can be created at all (some protocol handlers will
// refuse to create certain variants)
["http://www.example2.com", true, true, true],
["feed:http://www.example2.com", false, false, true],
["https://www.example2.com", true, true, true],
["chrome://foo/content/bar.xul", false, false, true],
["feed:chrome://foo/content/bar.xul", false, false, false],
["view-source:http://www.example2.com", false, false, true],
+ ["view-source:https://www.example2.com", false, false, true],
["view-source:feed:http://www.example2.com", false, false, true],
["feed:view-source:http://www.example2.com", false, false, false],
["data:text/html,Hi", true, false, true],
["javascript:alert('hi')", true, false, true],
]],
["feed:http://www.example.com", [
["http://www.example2.com", true, true, true],
["feed:http://www.example2.com", true, true, true],
["https://www.example2.com", true, true, true],
- ["feed:https://www.example2.com", false, false, true],
+ ["feed:https://www.example2.com", true, true, true],
["chrome://foo/content/bar.xul", false, false, true],
["feed:chrome://foo/content/bar.xul", false, false, false],
["view-source:http://www.example2.com", false, false, true],
+ ["view-source:https://www.example2.com", false, false, true],
["view-source:feed:http://www.example2.com", false, false, true],
["feed:view-source:http://www.example2.com", false, false, false],
["data:text/html,Hi", true, false, true],
["javascript:alert('hi')", true, false, true],
]],
["view-source:http://www.example.com", [
["http://www.example2.com", true, true, true],
["feed:http://www.example2.com", false, false, true],
["https://www.example2.com", true, true, true],
["feed:https://www.example2.com", false, false, true],
["chrome://foo/content/bar.xul", false, false, true],
["feed:chrome://foo/content/bar.xul", false, false, false],
["view-source:http://www.example2.com", true, true, true],
+ ["view-source:https://www.example2.com", true, true, true],
["view-source:feed:http://www.example2.com", false, false, true],
["feed:view-source:http://www.example2.com", false, false, false],
["data:text/html,Hi", true, false, true],
["javascript:alert('hi')", true, false, true],
]],
]);
function testURL(source, target, canLoad, canLoadWithoutInherit, canCreate, flags) {