mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 16:22:00 +00:00
Bug 1725800 - Also check if the uri path is the same when doing upgrade and downgrade loop check, r=ckerschb
Differential Revision: https://phabricator.services.mozilla.com/D122847
This commit is contained in:
parent
360dba0b1c
commit
17d46e745c
@ -273,6 +273,25 @@ bool nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
|
||||
nsAutoCString uriHost;
|
||||
aURI->GetAsciiHost(uriHost);
|
||||
|
||||
auto uriAndPrincipalComparator = [&](nsIPrincipal* aPrincipal) {
|
||||
nsAutoCString principalHost;
|
||||
aPrincipal->GetAsciiHost(principalHost);
|
||||
bool checkPath = mozilla::StaticPrefs::
|
||||
dom_security_https_only_check_path_upgrade_downgrade_endless_loop();
|
||||
if (!checkPath) {
|
||||
return uriHost.Equals(principalHost);
|
||||
}
|
||||
|
||||
nsAutoCString uriPath;
|
||||
nsresult rv = aURI->GetFilePath(uriPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
nsAutoCString principalPath;
|
||||
aPrincipal->GetFilePath(principalPath);
|
||||
return uriHost.Equals(principalHost) && uriPath.Equals(principalPath);
|
||||
};
|
||||
|
||||
// 6. Check actual redirects. If the Principal that kicked off the
|
||||
// load/redirect is not https, then it's definitely not a redirect cause by
|
||||
// https-only. If the scheme of the principal however is https and the
|
||||
@ -283,12 +302,9 @@ bool nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
|
||||
nsCOMPtr<nsIPrincipal> redirectPrincipal;
|
||||
for (nsIRedirectHistoryEntry* entry : aLoadInfo->RedirectChain()) {
|
||||
entry->GetPrincipal(getter_AddRefs(redirectPrincipal));
|
||||
if (redirectPrincipal && redirectPrincipal->SchemeIs("https")) {
|
||||
nsAutoCString redirectHost;
|
||||
redirectPrincipal->GetAsciiHost(redirectHost);
|
||||
if (uriHost.Equals(redirectHost)) {
|
||||
return true;
|
||||
}
|
||||
if (redirectPrincipal && redirectPrincipal->SchemeIs("https") &&
|
||||
uriAndPrincipalComparator(redirectPrincipal)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -311,9 +327,8 @@ bool nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
|
||||
if (!triggeringPrincipal->SchemeIs("https")) {
|
||||
return false;
|
||||
}
|
||||
nsAutoCString triggeringHost;
|
||||
triggeringPrincipal->GetAsciiHost(triggeringHost);
|
||||
return uriHost.Equals(triggeringHost);
|
||||
|
||||
return uriAndPrincipalComparator(triggeringPrincipal);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const REDIRECT_URI = "http://example.com/tests/dom/security/test/https-first/file_break_endless_upgrade_downgrade_loop.sjs?verify";
|
||||
|
||||
const DOWNGRADE_URI = "http://example.com/tests/dom/security/test/https-first/file_downgrade_with_different_path.sjs";
|
||||
const RESPONSE_ERROR = "unexpected-query";
|
||||
|
||||
// An onload postmessage to window opener
|
||||
@ -27,6 +27,14 @@ function handleRequest(request, response) {
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
const query = request.queryString;
|
||||
|
||||
if (query == "downgrade") {
|
||||
// send same-origin downgrade from https: to http: with a different path.
|
||||
// we don't consider it's an endless upgrade downgrade loop in this case.
|
||||
response.setStatusLine(request.httpVersion, 302, "Found");
|
||||
response.setHeader("Location", DOWNGRADE_URI, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// handle the redirect case
|
||||
if ((query >= 301 && query <= 303) || query == 307) {
|
||||
// send same-origin downgrade from https: to http: again simluating
|
||||
|
@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
|
||||
// An onload postmessage to window opener
|
||||
const RESPONSE_HTTPS_SCHEME = `
|
||||
<html>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
window.opener.postMessage({result: 'scheme-https'}, '*');
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const RESPONSE_HTTP_SCHEME = `
|
||||
<html>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
window.opener.postMessage({result: 'scheme-http'}, '*');
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
function handleRequest(request, response) {
|
||||
let response_content = request.scheme === "https"
|
||||
? RESPONSE_HTTPS_SCHEME
|
||||
: RESPONSE_HTTP_SCHEME;
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.write(response_content);
|
||||
return;
|
||||
}
|
@ -26,6 +26,7 @@ support-files= file_referrer_policy.sjs
|
||||
[test_break_endless_upgrade_downgrade_loop.html]
|
||||
support-files =
|
||||
file_break_endless_upgrade_downgrade_loop.sjs
|
||||
file_downgrade_with_different_path.sjs
|
||||
[test_multiple_redirection.html]
|
||||
support-files =
|
||||
file_multiple_redirection.sjs
|
||||
|
@ -39,6 +39,17 @@ Test that same origin redirect does not cause endless loop with https-first enab
|
||||
return;
|
||||
}
|
||||
window.removeEventListener("message", receiveMessage);
|
||||
window.addEventListener("message", receiveMessageForDifferentPathTest);
|
||||
testDifferentPath();
|
||||
}
|
||||
|
||||
async function receiveMessageForDifferentPathTest(event) {
|
||||
is(event.data.result,
|
||||
"scheme-https",
|
||||
"scheme should be https when the path is different"
|
||||
);
|
||||
testWin.close();
|
||||
window.removeEventListener("message", receiveMessageForDifferentPathTest);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -50,11 +61,19 @@ Test that same origin redirect does not cause endless loop with https-first enab
|
||||
testWin = window.open(uri);
|
||||
}
|
||||
|
||||
async function testDifferentPath() {
|
||||
// Load an https:// window which gets downgraded to http://
|
||||
let uri =
|
||||
`https://example.com/tests/dom/security/test/https-first/file_break_endless_upgrade_downgrade_loop.sjs?downgrade`;
|
||||
testWin = window.open(uri);
|
||||
}
|
||||
|
||||
// Set preference and start test
|
||||
SpecialPowers.pushPrefEnv({ set: [
|
||||
["dom.security.https_first", true],
|
||||
["security.mixed_content.block_active_content", false],
|
||||
["security.mixed_content.block_display_content", false],
|
||||
["dom.security.https_only_check_path_upgrade_downgrade_endless_loop", true],
|
||||
]}, startTest);
|
||||
</script>
|
||||
</body>
|
||||
|
@ -25,6 +25,9 @@ const REDIRECT_JS = `
|
||||
const REDIRECT_302 =
|
||||
"http://example.com/tests/dom/security/test/https-only/file_break_endless_upgrade_downgrade_loop.sjs?test3b";
|
||||
|
||||
const REDIRECT_302_DIFFERENT_PATH =
|
||||
"http://example.com/tests/dom/security/test/https-only/file_user_gesture.html";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
// avoid confusing cache behaviour
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
@ -50,6 +53,12 @@ function handleRequest(request, response) {
|
||||
response.setHeader("Location", REDIRECT_302, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query === "test4a") {
|
||||
response.setStatusLine("1.1", 302, "Found");
|
||||
response.setHeader("Location", REDIRECT_302_DIFFERENT_PATH, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we should never get here, just in case,
|
||||
|
@ -18,7 +18,9 @@ support-files = file_http_background_request.sjs
|
||||
support-files = file_http_background_auth_request.sjs
|
||||
[test_break_endless_upgrade_downgrade_loop.html]
|
||||
skip-if = (toolkit == 'android') # no support for error pages, Bug 1697866
|
||||
support-files = file_break_endless_upgrade_downgrade_loop.sjs
|
||||
support-files =
|
||||
file_break_endless_upgrade_downgrade_loop.sjs
|
||||
file_user_gesture.html
|
||||
[test_user_suggestion_box.html]
|
||||
support-files = file_user_suggestion_box.sjs
|
||||
skip-if = toolkit == 'android' # no https-only errorpage support in android
|
||||
|
@ -39,18 +39,29 @@ async function verifyResult(aTestName) {
|
||||
ok(innerHTML.includes(errorPageL10nId), "the error page should be shown for " + aTestName);
|
||||
}
|
||||
|
||||
async function verifyTest4Result() {
|
||||
let pathname = content.document.location.pathname;
|
||||
ok(
|
||||
pathname === "/tests/dom/security/test/https-only/file_user_gesture.html",
|
||||
"the http:// page should be loaded"
|
||||
);
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["dom.security.https_only_mode", true],
|
||||
["dom.security.https_only_mode_break_upgrade_downgrade_endless_loop", true],
|
||||
["dom.security.https_only_check_path_upgrade_downgrade_endless_loop", true],
|
||||
]});
|
||||
|
||||
// Test 1: Meta Refresh Redirect
|
||||
let winTest1 = window.open(REQUEST_URL + "?test1a", "_blank");
|
||||
// Test 2: JS win.location Redirect
|
||||
let winTest2 = window.open(REQUEST_URL + "?test2a", "_blank");
|
||||
// Test 3: 302 Redirect
|
||||
// Test 3: 302 Redirect
|
||||
let winTest3 = window.open(REQUEST_URL + "?test3a", "_blank");
|
||||
// Test 4: 302 Redirect with a different path
|
||||
let winTest4 = window.open(REQUEST_URL + "?test4a", "_blank");
|
||||
|
||||
// provide enough time for:
|
||||
// the redirects to occur, and the error page to be displayed
|
||||
@ -65,6 +76,9 @@ async function runTests() {
|
||||
await SpecialPowers.spawn(winTest3, ["test3"], verifyResult);
|
||||
winTest3.close();
|
||||
|
||||
await SpecialPowers.spawn(winTest4, ["test4"], verifyTest4Result);
|
||||
winTest4.close();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -3086,6 +3086,13 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# If true, when checking if it's upgrade downgrade cycles, the URI path will be
|
||||
# also checked.
|
||||
- name: dom.security.https_only_check_path_upgrade_downgrade_endless_loop
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# If true and HTTPS-only mode is enabled, requests
|
||||
# to local IP addresses are also upgraded
|
||||
- name: dom.security.https_only_mode.upgrade_local
|
||||
|
Loading…
Reference in New Issue
Block a user