summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docshell/base/nsDocShell.cpp23
-rw-r--r--dom/security/test/csp/file_upgrade_insecure_navigation.sjs79
-rw-r--r--dom/security/test/csp/mochitest.ini2
-rw-r--r--dom/security/test/csp/test_upgrade_insecure_navigation.html103
-rw-r--r--netwerk/base/LoadInfo.cpp6
-rw-r--r--netwerk/base/LoadInfo.h1
6 files changed, 214 insertions, 0 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index ab119a016a..2e08e67207 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11025,6 +11025,29 @@ nsDocShell::DoURILoad(nsIURI* aURI,
}
}
+ // Navigational requests that are same origin need to be upgraded in case
+ // upgrade-insecure-requests is present. Please note that in that case
+ // the triggeringPrincipal is holding the CSP that potentially
+ // holds upgrade-insecure-requests.
+ nsCOMPtr<nsIContentSecurityPolicy> csp;
+ aTriggeringPrincipal->GetCsp(getter_AddRefs(csp));
+ if (csp) {
+ bool upgradeInsecureRequests = false;
+ csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
+ if (upgradeInsecureRequests) {
+ // only upgrade if the navigation is same origin
+ nsCOMPtr<nsIPrincipal> resultPrincipal;
+ rv = nsContentUtils::GetSecurityManager()->
+ GetChannelResultPrincipal(channel,
+ getter_AddRefs(resultPrincipal));
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (resultPrincipal->Equals(aTriggeringPrincipal)) {
+ static_cast<mozilla::LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests();
+ }
+ }
+ }
+
+
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel);
if (appCacheChannel) {
diff --git a/dom/security/test/csp/file_upgrade_insecure_navigation.sjs b/dom/security/test/csp/file_upgrade_insecure_navigation.sjs
new file mode 100644
index 0000000000..51afa39bf7
--- /dev/null
+++ b/dom/security/test/csp/file_upgrade_insecure_navigation.sjs
@@ -0,0 +1,79 @@
+// Custom *.sjs file specifically for the needs of
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1271173
+
+"use strict";
+Components.utils.importGlobalProperties(["URLSearchParams"]);
+
+const TEST_NAVIGATIONAL_UPGRADE = `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"></head>
+ <body>
+ <a href="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs?action=framenav" id="testlink">clickme</a>
+ <script type="text/javascript">
+ // before navigating the current frame we open the window and check that uir applies
+ var myWin = window.open("http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs?action=docnav");
+
+ window.addEventListener("message", receiveMessage, false);
+ function receiveMessage(event) {
+ myWin.close();
+ var link = document.getElementById('testlink');
+ link.click();
+ }
+ </script>
+ </body>
+ </html>`;
+
+const FRAME_NAV = `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"></head>
+ <body>
+ <script type="text/javascript">
+ parent.postMessage({result: document.documentURI}, "*");
+ </script>
+ </body>
+ </html>`;
+
+const DOC_NAV = `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"></head>
+ <body>
+ <script type="text/javascript">
+ // call back to the main testpage signaling whether the upgraded succeeded
+ window.opener.parent.postMessage({result: document.documentURI}, "*");
+ // let the opener (iframe) now that we can now close the window and move on with the test.
+ window.opener.postMessage({result: "readyToMoveOn"}, "*");
+ </script>
+ </body>
+ </html>`;
+
+function handleRequest(request, response) {
+ const query = new URLSearchParams(request.queryString);
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html", false);
+ if (query.get("csp")) {
+ response.setHeader("Content-Security-Policy", query.get("csp"), false);
+ }
+
+ if (query.get("action") === "perform_navigation") {
+ response.write(TEST_NAVIGATIONAL_UPGRADE);
+ return;
+ }
+
+ if (query.get("action") === "framenav") {
+ response.write(FRAME_NAV);
+ return;
+ }
+
+ if (query.get("action") === "docnav") {
+ response.write(DOC_NAV);
+ return;
+ }
+
+ // we should never get here, but just in case
+ // return something unexpected
+ response.write("do'h");
+}
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini
index 5351097521..04401b063d 100644
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -210,6 +210,7 @@ support-files =
file_ignore_xfo.html^headers^
file_ro_ignore_xfo.html
file_ro_ignore_xfo.html^headers^
+ file_upgrade_insecure_navigation.sjs
[test_base-uri.html]
[test_blob_data_schemes.html]
@@ -296,6 +297,7 @@ tags = mcb
[test_strict_dynamic.html]
[test_strict_dynamic_parser_inserted.html]
[test_strict_dynamic_default_src.html]
+[test_upgrade_insecure_navigation.html]
[test_iframe_sandbox_srcdoc.html]
[test_iframe_srcdoc.html]
[test_sandbox_allow_scripts.html]
diff --git a/dom/security/test/csp/test_upgrade_insecure_navigation.html b/dom/security/test/csp/test_upgrade_insecure_navigation.html
new file mode 100644
index 0000000000..db6a6a1bed
--- /dev/null
+++ b/dom/security/test/csp/test_upgrade_insecure_navigation.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1271173 - Missing spec on Upgrade Insecure Requests(Navigational Upgrades) </title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+<iframe style="width:100%;" id="sandboxedtestframe"
+ sandbox="allow-scripts allow-top-navigation allow-same-origin allow-pointer-lock allow-popups"></iframe>
+
+<script class="testbody" type="text/javascript">
+/*
+ * Description of the test:
+ * We load a page into an iframe that performs a navigational request.
+ * We make sure that upgrade-insecure-requests applies and the page
+ * gets upgraded to https if same origin.
+ * Please note that uir only applies to sandboxed iframes if
+ * the value 'allow-same-origin' is specified.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+var tests = [
+ {
+ csp: "upgrade-insecure-requests;",
+ result: "https",
+ origin: "http://example.com",
+ desc: "upgrade-insecure-requests same origin should upgrade"
+ },
+ {
+ csp: "",
+ result: "http",
+ origin: "http://example.com",
+ desc: "No upgrade-insecure-requests same origin should not upgrade"
+ },
+ {
+ csp: "upgrade-insecure-requests;",
+ result: "http",
+ origin: "http://mochi.test:8888",
+ desc: "upgrade-insecure-requests cross origin should not upgrade"
+ },
+ {
+ csp: "",
+ result: "http",
+ origin: "http://mochi.test:8888",
+ desc: "No upgrade-insecure-requests cross origin should not upgrade"
+ },
+];
+
+// initializing to -1 so we start at index 0 when we start the test
+var counter = -1;
+
+function finishTest() {
+ window.removeEventListener("message", receiveMessage, false);
+ SimpleTest.finish();
+}
+
+var subtests = 0;
+
+window.addEventListener("message", receiveMessage, false);
+function receiveMessage(event) {
+ var result = event.data.result;
+ // query the scheme from the URL before comparing the result
+ var scheme = result.substring(0, result.indexOf(":"));
+ is(scheme, tests[counter].result, tests[counter].desc);
+
+ // @hardcoded 4:
+ // each test run contains of two subtests (frame and top-level)
+ // and we load each test into a regular iframe and into a
+ // sandboxed iframe. only move on to the next test once all
+ // four results from the subtests have bubbled up.
+ subtests++;
+ if (subtests != 4) {
+ return;
+ }
+ subtests = 0;
+ loadNextTest();
+}
+
+function loadNextTest() {
+ counter++;
+ if (counter == tests.length) {
+ finishTest();
+ return;
+ }
+
+ var src = tests[counter].origin;
+ src += "/tests/dom/security/test/csp/file_upgrade_insecure_navigation.sjs";
+ src += "?csp=" + escape(tests[counter].csp);
+ src += "&action=perform_navigation";
+ document.getElementById("testframe").src = src;
+ document.getElementById("sandboxedtestframe").src = src;
+}
+
+// start running the tests
+loadNextTest();
+
+</script>
+</body>
+</html>
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index 216cf559cd..42fdea4a18 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -859,6 +859,12 @@ LoadInfo::SetIsPreflight()
mIsPreflight = true;
}
+void
+LoadInfo::SetUpgradeInsecureRequests()
+{
+ mUpgradeInsecureRequests = true;
+}
+
NS_IMETHODIMP
LoadInfo::GetIsPreflight(bool* aIsPreflight)
{
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index 261f85349d..3e1b92ff4c 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -78,6 +78,7 @@ public:
already_AddRefed<nsILoadInfo> CloneForNewRequest() const;
void SetIsPreflight();
+ void SetUpgradeInsecureRequests();
private:
// private constructor that is only allowed to be called from within