mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-23 04:43:07 +09:00
308 lines
8.9 KiB
JavaScript
308 lines
8.9 KiB
JavaScript
/*
|
|
* Description of the tests:
|
|
* Check that HSTS priming occurs correctly with mixed content
|
|
*
|
|
* This test uses three hostnames, each of which treats an HSTS priming
|
|
* request differently.
|
|
* * no-ssl never returns an ssl response
|
|
* * reject-upgrade returns an ssl response, but with no STS header
|
|
* * prime-hsts returns an ssl response with the appropriate STS header
|
|
*
|
|
* For each server, test that it response appropriately when the we allow
|
|
* or block active or display content, as well as when we send an hsts priming
|
|
* request, but do not change the order of mixed-content and HSTS.
|
|
*
|
|
* Test use http-on-examine-response, so must be run in browser context.
|
|
*/
|
|
'use strict';
|
|
|
|
var TOP_URI = "https://example.com/browser/dom/security/test/hsts/file_priming-top.html";
|
|
|
|
var test_servers = {
|
|
// a test server that does not support TLS
|
|
'no-ssl': {
|
|
host: 'example.co.jp',
|
|
response: false,
|
|
id: 'no-ssl',
|
|
},
|
|
// a test server which does not support STS upgrade
|
|
'reject-upgrade': {
|
|
host: 'example.org',
|
|
response: true,
|
|
id: 'reject-upgrade',
|
|
},
|
|
// a test server when sends an STS header when priming
|
|
'prime-hsts': {
|
|
host: 'test1.example.com',
|
|
response: true,
|
|
id: 'prime-hsts'
|
|
},
|
|
};
|
|
|
|
var test_settings = {
|
|
// mixed active content is allowed, priming will upgrade
|
|
allow_active: {
|
|
block_active: false,
|
|
block_display: false,
|
|
use_hsts: true,
|
|
send_hsts_priming: true,
|
|
type: 'script',
|
|
result: {
|
|
'no-ssl': 'insecure',
|
|
'reject-upgrade': 'insecure',
|
|
'prime-hsts': 'secure',
|
|
},
|
|
},
|
|
// mixed active content is blocked, priming will upgrade
|
|
block_active: {
|
|
block_active: true,
|
|
block_display: false,
|
|
use_hsts: true,
|
|
send_hsts_priming: true,
|
|
type: 'script',
|
|
result: {
|
|
'no-ssl': 'blocked',
|
|
'reject-upgrade': 'blocked',
|
|
'prime-hsts': 'secure',
|
|
},
|
|
},
|
|
// keep the original order of mixed-content and HSTS, but send
|
|
// priming requests
|
|
hsts_after_mixed: {
|
|
block_active: true,
|
|
block_display: false,
|
|
use_hsts: false,
|
|
send_hsts_priming: true,
|
|
type: 'script',
|
|
result: {
|
|
'no-ssl': 'blocked',
|
|
'reject-upgrade': 'blocked',
|
|
'prime-hsts': 'blocked',
|
|
},
|
|
},
|
|
// mixed display content is allowed, priming will upgrade
|
|
allow_display: {
|
|
block_active: true,
|
|
block_display: false,
|
|
use_hsts: true,
|
|
send_hsts_priming: true,
|
|
type: 'img',
|
|
result: {
|
|
'no-ssl': 'insecure',
|
|
'reject-upgrade': 'insecure',
|
|
'prime-hsts': 'secure',
|
|
},
|
|
},
|
|
// mixed display content is blocked, priming will upgrade
|
|
block_display: {
|
|
block_active: true,
|
|
block_display: true,
|
|
use_hsts: true,
|
|
send_hsts_priming: true,
|
|
type: 'img',
|
|
result: {
|
|
'no-ssl': 'blocked',
|
|
'reject-upgrade': 'blocked',
|
|
'prime-hsts': 'secure',
|
|
},
|
|
},
|
|
// mixed active content is blocked, priming will upgrade (css)
|
|
block_active_css: {
|
|
block_active: true,
|
|
block_display: false,
|
|
use_hsts: true,
|
|
send_hsts_priming: true,
|
|
type: 'css',
|
|
result: {
|
|
'no-ssl': 'blocked',
|
|
'reject-upgrade': 'blocked',
|
|
'prime-hsts': 'secure',
|
|
},
|
|
},
|
|
// mixed active content is blocked, priming will upgrade
|
|
// redirect to the same host
|
|
block_active_with_redir_same: {
|
|
block_active: true,
|
|
block_display: false,
|
|
use_hsts: true,
|
|
send_hsts_priming: true,
|
|
type: 'script',
|
|
redir: 'same',
|
|
result: {
|
|
'no-ssl': 'blocked',
|
|
'reject-upgrade': 'blocked',
|
|
'prime-hsts': 'secure',
|
|
},
|
|
},
|
|
}
|
|
// track which test we are on
|
|
var which_test = "";
|
|
|
|
const Observer = {
|
|
observe: function (subject, topic, data) {
|
|
switch (topic) {
|
|
case 'console-api-log-event':
|
|
return Observer.console_api_log_event(subject, topic, data);
|
|
case 'http-on-examine-response':
|
|
return Observer.http_on_examine_response(subject, topic, data);
|
|
case 'http-on-modify-request':
|
|
return Observer.http_on_modify_request(subject, topic, data);
|
|
}
|
|
throw "Can't handle topic "+topic;
|
|
},
|
|
add_observers: function (services) {
|
|
services.obs.addObserver(Observer, "console-api-log-event", false);
|
|
services.obs.addObserver(Observer, "http-on-examine-response", false);
|
|
services.obs.addObserver(Observer, "http-on-modify-request", false);
|
|
},
|
|
// When a load is blocked which results in an error event within a page, the
|
|
// test logs to the console.
|
|
console_api_log_event: function (subject, topic, data) {
|
|
var message = subject.wrappedJSObject.arguments[0];
|
|
// when we are blocked, this will match the message we sent to the console,
|
|
// ignore everything else.
|
|
var re = RegExp(/^HSTS_PRIMING: Blocked ([-\w]+).*$/);
|
|
if (!re.test(message)) {
|
|
return;
|
|
}
|
|
|
|
let id = message.replace(re, '$1');
|
|
let curTest =test_servers[id];
|
|
|
|
if (!curTest) {
|
|
ok(false, "HSTS priming got a console message blocked, "+
|
|
"but doesn't match expectations "+id+" (msg="+message);
|
|
return;
|
|
}
|
|
|
|
is("blocked", test_settings[which_test].result[curTest.id], "HSTS priming "+
|
|
which_test+":"+curTest.id+" expected "+
|
|
test_settings[which_test].result[curTest.id]+", got blocked");
|
|
test_settings[which_test].finished[curTest.id] = "blocked";
|
|
},
|
|
get_current_test: function(uri) {
|
|
for (let item in test_servers) {
|
|
let re = RegExp('https?://'+test_servers[item].host);
|
|
if (re.test(uri)) {
|
|
return test_servers[item];
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
http_on_modify_request: function (subject, topic, data) {
|
|
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
|
|
if (channel.requestMethod != 'HEAD') {
|
|
return;
|
|
}
|
|
|
|
let curTest = this.get_current_test(channel.URI.asciiSpec);
|
|
|
|
if (!curTest) {
|
|
return;
|
|
}
|
|
|
|
ok(!(curTest.id in test_settings[which_test].priming), "Already saw a priming request for " + curTest.id);
|
|
test_settings[which_test].priming[curTest.id] = true;
|
|
},
|
|
// When we see a response come back, peek at the response and test it is secure
|
|
// or insecure as needed. Addtionally, watch the response for priming requests.
|
|
http_on_examine_response: function (subject, topic, data) {
|
|
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
|
|
let curTest = this.get_current_test(channel.URI.asciiSpec);
|
|
|
|
if (!curTest) {
|
|
return;
|
|
}
|
|
|
|
let result = (channel.URI.asciiSpec.startsWith('https:')) ? "secure" : "insecure";
|
|
|
|
// This is a priming request, go ahead and validate we were supposed to see
|
|
// a response from the server
|
|
if (channel.requestMethod == 'HEAD') {
|
|
is(true, curTest.response, "HSTS priming response found " + curTest.id);
|
|
return;
|
|
}
|
|
|
|
// This is the response to our query, make sure it matches
|
|
is(result, test_settings[which_test].result[curTest.id],
|
|
"HSTS priming result " + which_test + ":" + curTest.id);
|
|
test_settings[which_test].finished[curTest.id] = result;
|
|
},
|
|
};
|
|
|
|
// opens `uri' in a new tab and focuses it.
|
|
// returns the newly opened tab
|
|
function openTab(uri) {
|
|
let tab = gBrowser.addTab(uri);
|
|
|
|
// select tab and make sure its browser is focused
|
|
gBrowser.selectedTab = tab;
|
|
tab.ownerDocument.defaultView.focus();
|
|
|
|
return tab;
|
|
}
|
|
|
|
function clear_sts_data() {
|
|
for (let test in test_servers) {
|
|
SpecialPowers.cleanUpSTSData('http://'+test_servers[test].host);
|
|
}
|
|
}
|
|
|
|
function do_cleanup() {
|
|
clear_sts_data();
|
|
|
|
Services.obs.removeObserver(Observer, "console-api-log-event");
|
|
Services.obs.removeObserver(Observer, "http-on-examine-response");
|
|
}
|
|
|
|
function SetupPrefTestEnvironment(which, additional_prefs) {
|
|
which_test = which;
|
|
clear_sts_data();
|
|
|
|
var settings = test_settings[which];
|
|
// priming counts how many priming requests we saw
|
|
settings.priming = {};
|
|
// priming counts how many tests were finished
|
|
settings.finished= {};
|
|
|
|
var prefs = [["security.mixed_content.block_active_content",
|
|
settings.block_active],
|
|
["security.mixed_content.block_display_content",
|
|
settings.block_display],
|
|
["security.mixed_content.use_hsts",
|
|
settings.use_hsts],
|
|
["security.mixed_content.send_hsts_priming",
|
|
settings.send_hsts_priming]];
|
|
|
|
if (additional_prefs) {
|
|
for (let idx in additional_prefs) {
|
|
prefs.push(additional_prefs[idx]);
|
|
}
|
|
}
|
|
|
|
console.log("prefs=%s", prefs);
|
|
|
|
SpecialPowers.pushPrefEnv({'set': prefs});
|
|
}
|
|
|
|
// make the top-level test uri
|
|
function build_test_uri(base_uri, host, test_id, type) {
|
|
return base_uri +
|
|
"?host=" + escape(host) +
|
|
"&id=" + escape(test_id) +
|
|
"&type=" + escape(type);
|
|
}
|
|
|
|
// open a new tab, load the test, and wait for it to finish
|
|
function execute_test(test, mimetype) {
|
|
var src = build_test_uri(TOP_URI, test_servers[test].host,
|
|
test, test_settings[which_test].type);
|
|
|
|
let tab = openTab(src);
|
|
test_servers[test]['tab'] = tab;
|
|
|
|
let browser = gBrowser.getBrowserForTab(tab);
|
|
yield BrowserTestUtils.browserLoaded(browser);
|
|
|
|
yield BrowserTestUtils.removeTab(tab);
|
|
}
|