Skip to content

Commit

Permalink
Bug 1515863, r=ckerschb
Browse files Browse the repository at this point in the history
  • Loading branch information
gijsk committed Dec 21, 2018
1 parent 575af9d commit 89ad488
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 4 deletions.
2 changes: 1 addition & 1 deletion browser/base/content/utilityOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ function openLinkIn(url, where, params) {
userContextId: aUserContextId,
privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)),
};
return Services.scriptSecurityManager.createCodebasePrincipal(principal.URI, attrs);
return Services.scriptSecurityManager.principalWithOA(principal, attrs);
}
return principal;
}
Expand Down
16 changes: 16 additions & 0 deletions caps/BasePrincipal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,22 @@ void BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
mOriginNoSuffix = NS_Atomize(aOriginNoSuffix);
}

void BasePrincipal::FinishInit(BasePrincipal* aOther,
const OriginAttributes& aOriginAttributes) {
mInitialized = true;
mOriginAttributes = aOriginAttributes;

// First compute the origin suffix since it's infallible.
nsAutoCString originSuffix;
mOriginAttributes.CreateSuffix(originSuffix);
mOriginSuffix = NS_Atomize(originSuffix);

mOriginNoSuffix = aOther->mOriginNoSuffix;
mHasExplicitDomain = aOther->mHasExplicitDomain;
mCSP = aOther->mCSP;
mPreloadCSP = aOther->mPreloadCSP;
}

bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
MOZ_ASSERT(IsInitialized());
MOZ_ASSERT(aOther.IsInitialized());
Expand Down
8 changes: 5 additions & 3 deletions caps/BasePrincipal.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,13 @@ class BasePrincipal : public nsJSPrincipals {

void SetHasExplicitDomain() { mHasExplicitDomain = true; }

// This function should be called as the last step of the initialization of
// the principal objects. It's typically called as the last step from the
// Init() method of the child classes.
// Either of these functions should be called as the last step of the
// initialization of the principal objects. It's typically called as the
// last step from the Init() method of the child classes.
void FinishInit(const nsACString& aOriginNoSuffix,
const OriginAttributes& aOriginAttributes);
void FinishInit(BasePrincipal* aOther,
const OriginAttributes& aOriginAttributes);

nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
Expand Down
12 changes: 12 additions & 0 deletions caps/ContentPrincipal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ nsresult ContentPrincipal::Init(nsIURI* aCodebase,
return NS_OK;
}

nsresult ContentPrincipal::Init(ContentPrincipal* aOther,
const OriginAttributes& aOriginAttributes) {
NS_ENSURE_ARG(aOther);

mCodebase = aOther->mCodebase;
FinishInit(aOther, aOriginAttributes);

mDomain = aOther->mDomain;
mAddon = aOther->mAddon;
return NS_OK;
}

nsresult ContentPrincipal::GetScriptLocation(nsACString& aStr) {
return mCodebase->GetSpec(aStr);
}
Expand Down
2 changes: 2 additions & 0 deletions caps/ContentPrincipal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ContentPrincipal final : public BasePrincipal {
// Init() must be called before the principal is in a usable state.
nsresult Init(nsIURI* aCodebase, const OriginAttributes& aOriginAttributes,
const nsACString& aOriginNoSuffix);
nsresult Init(ContentPrincipal* aOther,
const OriginAttributes& aOriginAttributes);

virtual nsresult GetScriptLocation(nsACString& aStr) override;

Expand Down
8 changes: 8 additions & 0 deletions caps/nsIScriptSecurityManager.idl
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ interface nsIScriptSecurityManager : nsISupports
nsIPrincipal getDocShellCodebasePrincipal(in nsIURI uri,
in nsIDocShell docShell);

/**
* If this is a codebase principal, return a copy with different
* origin attributes.
*/
[implicit_jscontext]
nsIPrincipal principalWithOA(in nsIPrincipal principal,
in jsval originAttributes);

/**
* Returns a principal whose origin is composed of |uri| and |originAttributes|.
* See nsIPrincipal.idl for a description of origin attributes, and
Expand Down
29 changes: 29 additions & 0 deletions caps/nsScriptSecurityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,35 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsScriptSecurityManager::PrincipalWithOA(
nsIPrincipal* aPrincipal, JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aReturnPrincipal) {
if (!aPrincipal) {
return NS_OK;
}
if (aPrincipal->GetIsCodebasePrincipal()) {
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
RefPtr<ContentPrincipal> copy = new ContentPrincipal();
ContentPrincipal* contentPrincipal =
static_cast<ContentPrincipal*>(aPrincipal);
nsresult rv = copy->Init(contentPrincipal, attrs);
NS_ENSURE_SUCCESS(rv, rv);
copy.forget(aReturnPrincipal);
} else {
// We do this for null principals, system principals (both fine)
// ... and expanded principals, where we should probably do something
// cleverer, but I also don't think we care too much.
nsCOMPtr<nsIPrincipal> prin = aPrincipal;
prin.forget(aReturnPrincipal);
}

return *aReturnPrincipal ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsScriptSecurityManager::CanCreateWrapper(JSContext* cx, const nsIID& aIID,
nsISupports* aObj,
Expand Down
3 changes: 3 additions & 0 deletions dom/security/test/csp/browser.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ support-files =
!/dom/security/test/csp/file_web_manifest_remote.html
[browser_test_web_manifest.js]
[browser_test_web_manifest_mixed_content.js]
[browser_test_uir_optional_clicks.js]
support-files =
file_csp_meta_uir.html
[browser_manifest-src-override-default-src.js]
14 changes: 14 additions & 0 deletions dom/security/test/csp/browser_test_uir_optional_clicks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use strict"

const TEST_PATH_HTTP = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
const TEST_PATH_HTTPS = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com");

add_task(async function() {
await BrowserTestUtils.withNewTab(TEST_PATH_HTTPS + "file_csp_meta_uir.html", async function(browser) {
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
BrowserTestUtils.synthesizeMouse("#mylink", 2, 2, {accelKey: true}, browser);
let tab = await newTabPromise;
is(tab.linkedBrowser.currentURI.scheme, "https", "Should have opened https page.");
BrowserTestUtils.removeTab(tab);
});
});
13 changes: 13 additions & 0 deletions dom/security/test/csp/file_csp_meta_uir.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
</head>
<body>
<script>
document.write("<a href='" + document.location.href.replace(/^https/, "http") + "' id='mylink'>Click me</a>");
</script>
</body>
</html>

0 comments on commit 89ad488

Please sign in to comment.