Bug 1515863, r=ckerschb

Differential Revision: https://phabricator.services.mozilla.com/D15957

--HG--
extra : rebase_source : 748d4849050c3f2042f45f083cc7c99137963721
This commit is contained in:
Gijs Kruitbosch 2019-01-08 16:59:21 +01:00
parent ceecd61c16
commit 7de2c5899e
6 changed files with 130 additions and 2 deletions

View File

@ -23,6 +23,7 @@
#include "mozilla/dom/BlobURLProtocolHandler.h" #include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/ChromeUtils.h" #include "mozilla/dom/ChromeUtils.h"
#include "mozilla/dom/CSPDictionariesBinding.h" #include "mozilla/dom/CSPDictionariesBinding.h"
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/ToJSValue.h"
namespace mozilla { namespace mozilla {
@ -506,8 +507,20 @@ void BasePrincipal::FinishInit(BasePrincipal* aOther,
mOriginNoSuffix = aOther->mOriginNoSuffix; mOriginNoSuffix = aOther->mOriginNoSuffix;
mHasExplicitDomain = aOther->mHasExplicitDomain; mHasExplicitDomain = aOther->mHasExplicitDomain;
mCSP = aOther->mCSP;
mPreloadCSP = aOther->mPreloadCSP; if (aOther->mPreloadCSP) {
mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1");
nsCSPContext* preloadCSP = static_cast<nsCSPContext*>(mPreloadCSP.get());
preloadCSP->InitFromOther(
static_cast<nsCSPContext*>(aOther->mPreloadCSP.get()), nullptr, this);
}
if (aOther->mCSP) {
mCSP = do_CreateInstance("@mozilla.org/cspcontext;1");
nsCSPContext* csp = static_cast<nsCSPContext*>(mCSP.get());
csp->InitFromOther(static_cast<nsCSPContext*>(aOther->mCSP.get()), nullptr,
this);
}
} }
bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const { bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {

View File

@ -54,6 +54,7 @@ support-files =
browser_timelineMarkers-frame-05.js browser_timelineMarkers-frame-05.js
head.js head.js
frame-head.js frame-head.js
file_data_load_inherit_csp.html
file_click_link_within_view_source.html file_click_link_within_view_source.html
onload_message.html onload_message.html
onpageshow_message.html onpageshow_message.html
@ -92,6 +93,7 @@ skip-if = verify
[browser_bug852909.js] [browser_bug852909.js]
skip-if = (verify && debug && (os == 'win')) skip-if = (verify && debug && (os == 'win'))
[browser_bug92473.js] [browser_bug92473.js]
[browser_data_load_inherit_csp.js]
[browser_dataURI_unique_opaque_origin.js] [browser_dataURI_unique_opaque_origin.js]
[browser_uriFixupIntegration.js] [browser_uriFixupIntegration.js]
[browser_uriFixupAlternateRedirects.js] [browser_uriFixupAlternateRedirects.js]

View File

@ -0,0 +1,82 @@
"use strict";
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
const HTML_URI = TEST_PATH + "file_data_load_inherit_csp.html";
const DATA_URI = "data:text/html;html,<html><body>foo</body></html>";
function setDataHrefOnLink(aBrowser, aDataURI) {
return ContentTask.spawn(aBrowser, aDataURI, function(uri) {
let link = content.document.getElementById("testlink");
link.href = uri;
});
};
function verifyCSP(aTestName, aBrowser, aDataURI) {
return ContentTask.spawn(aBrowser, {aTestName, aDataURI}, async function ({aTestName, aDataURI}) {
let channel = content.docShell.currentDocumentChannel;
is(channel.URI.spec, aDataURI, "testing CSP for " + aTestName);
let principal = channel.loadInfo.triggeringPrincipal;
let cspJSON = principal.cspJSON;
let cspOBJ = JSON.parse(cspJSON);
let policies = cspOBJ["csp-policies"];
is(policies.length, 1, "should be one policy");
let policy = policies[0];
is(policy['script-src'], "'unsafe-inline'", "script-src directive matches");
});
};
add_task(async function setup() {
// allow top level data: URI navigations, otherwise clicking data: link fails
await SpecialPowers.pushPrefEnv({
"set": [["security.data_uri.block_toplevel_data_uri_navigations", false]],
});
});
add_task(async function test_data_csp_inheritance_regular_click() {
await BrowserTestUtils.withNewTab(HTML_URI, async function(browser) {
let loadPromise = BrowserTestUtils.browserLoaded(browser, false, DATA_URI);
// set the data href + simulate click
await setDataHrefOnLink(gBrowser.selectedBrowser, DATA_URI);
BrowserTestUtils.synthesizeMouseAtCenter("#testlink", {},
gBrowser.selectedBrowser);
await loadPromise;
await verifyCSP("click()", gBrowser.selectedBrowser, DATA_URI);
});
});
add_task(async function test_data_csp_inheritance_ctrl_click() {
await BrowserTestUtils.withNewTab(HTML_URI, async function(browser) {
let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, DATA_URI);
// set the data href + simulate ctrl+click
await setDataHrefOnLink(gBrowser.selectedBrowser, DATA_URI);
BrowserTestUtils.synthesizeMouseAtCenter("#testlink",
{ ctrlKey: true, metaKey: true },
gBrowser.selectedBrowser);
let tab = await loadPromise;
gBrowser.selectTabAtIndex(2);
await verifyCSP("ctrl-click()", gBrowser.selectedBrowser, DATA_URI);
await BrowserTestUtils.removeTab(tab);
});
});
add_task(async function test_data_csp_inheritance_right_click_open_link_in_new_tab() {
await BrowserTestUtils.withNewTab(HTML_URI, async function(browser) {
let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, DATA_URI);
// set the data href + simulate right-click open link in tab
await setDataHrefOnLink(gBrowser.selectedBrowser, DATA_URI);
BrowserTestUtils.waitForEvent(document, "popupshown", false, event => {
// These are operations that must be executed synchronously with the event.
document.getElementById("context-openlinkintab").doCommand();
event.target.hidePopup();
return true;
});
BrowserTestUtils.synthesizeMouseAtCenter("#testlink",
{ type: "contextmenu", button: 2 },
gBrowser.selectedBrowser);
let tab = await loadPromise;
gBrowser.selectTabAtIndex(2);
await verifyCSP("right-click-open-in-new-tab()", gBrowser.selectedBrowser, DATA_URI);
await BrowserTestUtils.removeTab(tab);
});
});

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1358009 - Inherit CSP into data URI</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline'">
</head>
<body>
<a id="testlink">testlink</a>
</body>
</html>

View File

@ -261,6 +261,22 @@ nsCSPContext::~nsCSPContext() {
} }
} }
nsresult nsCSPContext::InitFromOther(nsCSPContext* aOtherContext,
Document* aDoc, nsIPrincipal* aPrincipal) {
NS_ENSURE_ARG(aOtherContext);
nsresult rv = SetRequestContext(aDoc, aPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
for (auto policy : aOtherContext->mPolicies) {
nsAutoString policyStr;
policy->toString(policyStr);
AppendPolicy(policyStr, policy->getReportOnlyFlag(),
policy->getDeliveredViaMetaTagFlag());
}
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsCSPContext::GetPolicyString(uint32_t aIndex, nsAString& outStr) { nsCSPContext::GetPolicyString(uint32_t aIndex, nsAString& outStr) {
outStr.Truncate(); outStr.Truncate();

View File

@ -51,6 +51,10 @@ class nsCSPContext : public nsIContentSecurityPolicy {
public: public:
nsCSPContext(); nsCSPContext();
nsresult InitFromOther(nsCSPContext* otherContext,
mozilla::dom::Document* aDoc,
nsIPrincipal* aPrincipal);
/** /**
* SetRequestContext() needs to be called before the innerWindowID * SetRequestContext() needs to be called before the innerWindowID
* is initialized on the document. Use this function to call back to * is initialized on the document. Use this function to call back to