зеркало из https://github.com/mozilla/gecko-dev.git
900 строки
27 KiB
JavaScript
900 строки
27 KiB
JavaScript
"use strict";
|
|
|
|
/* import-globals-from trr_common.js */
|
|
|
|
const gDefaultPref = Services.prefs.getDefaultBranch("");
|
|
|
|
SetParentalControlEnabled(false);
|
|
|
|
function setup() {
|
|
h2Port = trr_test_setup();
|
|
runningODoHTests = false;
|
|
}
|
|
|
|
setup();
|
|
registerCleanupFunction(async () => {
|
|
trr_clear_prefs();
|
|
});
|
|
|
|
async function waitForConfirmation(expectedResponseIP, confirmationShouldFail) {
|
|
// Check that the confirmation eventually completes.
|
|
let count = 100;
|
|
while (count > 0) {
|
|
if (count == 50 || count == 10) {
|
|
// At these two points we do a longer timeout to account for a slow
|
|
// response on the server side. This is usually a problem on the Android
|
|
// because of the increased delay between the emulator and host.
|
|
await new Promise(resolve => do_timeout(100 * (100 / count), resolve));
|
|
}
|
|
let { inRecord } = await new TRRDNSListener(
|
|
`ip${count}.example.org`,
|
|
undefined,
|
|
false
|
|
);
|
|
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
|
|
let responseIP = inRecord.getNextAddrAsString();
|
|
Assert.ok(true, responseIP);
|
|
if (responseIP == expectedResponseIP) {
|
|
break;
|
|
}
|
|
count--;
|
|
}
|
|
|
|
if (confirmationShouldFail) {
|
|
Assert.equal(count, 0, "Confirmation did not finish after 100 iterations");
|
|
return;
|
|
}
|
|
|
|
Assert.greater(count, 0, "Finished confirmation before 100 iterations");
|
|
}
|
|
|
|
function setModeAndURI(mode, path) {
|
|
Services.prefs.setIntPref("network.trr.mode", mode);
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://${TRR_Domain}:${h2Port}/${path}`
|
|
);
|
|
}
|
|
|
|
function makeChan(url, mode, bypassCache) {
|
|
let chan = NetUtil.newChannel({
|
|
uri: url,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
chan.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
|
chan.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
|
chan.setTRRMode(mode);
|
|
return chan;
|
|
}
|
|
|
|
add_task(async function test_server_up() {
|
|
// This test checks that moz-http2.js running in node is working.
|
|
// This should always be the first test in this file (except for setup)
|
|
// otherwise we may encounter random failures when the http2 server is down.
|
|
|
|
await NodeServer.execute("bad_id", `"hello"`)
|
|
.then(() => ok(false, "expecting to throw"))
|
|
.catch(e => equal(e.message, "Error: could not find id"));
|
|
});
|
|
|
|
add_task(async function test_trr_flags() {
|
|
Services.prefs.setBoolPref("network.trr.fallback-on-zero-response", true);
|
|
|
|
let httpserv = new HttpServer();
|
|
httpserv.registerPathHandler("/", function handler(metadata, response) {
|
|
let content = "ok";
|
|
response.setHeader("Content-Length", `${content.length}`);
|
|
response.bodyOutputStream.write(content, content.length);
|
|
});
|
|
httpserv.start(-1);
|
|
|
|
const URL = `http://example.com:${httpserv.identity.primaryPort}/`;
|
|
|
|
for (let mode of [0, 1, 2, 3, 4, 5]) {
|
|
setModeAndURI(mode, "doh?responseIP=127.0.0.1");
|
|
for (let flag of [
|
|
Ci.nsIRequest.TRR_DEFAULT_MODE,
|
|
Ci.nsIRequest.TRR_DISABLED_MODE,
|
|
Ci.nsIRequest.TRR_FIRST_MODE,
|
|
Ci.nsIRequest.TRR_ONLY_MODE,
|
|
]) {
|
|
dns.clearCache(true);
|
|
let chan = makeChan(URL, flag);
|
|
let expectTRR =
|
|
([2, 3].includes(mode) && flag != Ci.nsIRequest.TRR_DISABLED_MODE) ||
|
|
(mode == 0 &&
|
|
[Ci.nsIRequest.TRR_FIRST_MODE, Ci.nsIRequest.TRR_ONLY_MODE].includes(
|
|
flag
|
|
));
|
|
|
|
await new Promise(resolve =>
|
|
chan.asyncOpen(new ChannelListener(resolve))
|
|
);
|
|
|
|
equal(chan.getTRRMode(), flag);
|
|
equal(
|
|
expectTRR,
|
|
chan.QueryInterface(Ci.nsIHttpChannelInternal).isResolvedByTRR
|
|
);
|
|
}
|
|
}
|
|
|
|
await new Promise(resolve => httpserv.stop(resolve));
|
|
Services.prefs.clearUserPref("network.trr.fallback-on-zero-response");
|
|
});
|
|
|
|
add_task(test_A_record);
|
|
|
|
add_task(async function test_push() {
|
|
info("Verify DOH push");
|
|
dns.clearCache(true);
|
|
info("Asking server to push us a record");
|
|
setModeAndURI(3, "doh?responseIP=5.5.5.5&push=true");
|
|
|
|
await new TRRDNSListener("first.example.com", "5.5.5.5");
|
|
|
|
// At this point the second host name should've been pushed and we can resolve it using
|
|
// cache only. Set back the URI to a path that fails.
|
|
// Don't clear the cache, otherwise we lose the pushed record.
|
|
setModeAndURI(3, "404");
|
|
|
|
await new TRRDNSListener("push.example.org", "2018::2018");
|
|
});
|
|
|
|
add_task(test_AAAA_records);
|
|
|
|
add_task(test_RFC1918);
|
|
|
|
add_task(test_GET_ECS);
|
|
|
|
add_task(test_timeout_mode3);
|
|
|
|
add_task(test_trr_retry);
|
|
|
|
add_task(test_strict_native_fallback);
|
|
|
|
add_task(test_no_answers_fallback);
|
|
|
|
add_task(test_404_fallback);
|
|
|
|
add_task(test_mode_1_and_4);
|
|
|
|
add_task(test_CNAME);
|
|
|
|
add_task(test_name_mismatch);
|
|
|
|
add_task(test_mode_2);
|
|
|
|
add_task(test_excluded_domains);
|
|
|
|
add_task(test_captiveportal_canonicalURL);
|
|
|
|
add_task(test_parentalcontrols);
|
|
|
|
// TRR-first check that DNS result is used if domain is part of the builtin-excluded-domains pref
|
|
add_task(test_builtin_excluded_domains);
|
|
|
|
add_task(test_excluded_domains_mode3);
|
|
|
|
add_task(test25e);
|
|
|
|
add_task(test_parentalcontrols_mode3);
|
|
|
|
add_task(test_builtin_excluded_domains_mode3);
|
|
|
|
add_task(count_cookies);
|
|
|
|
add_task(test_connection_closed);
|
|
|
|
add_task(async function test_clearCacheOnURIChange() {
|
|
info("Check that the TRR cache should be cleared by a pref change.");
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", true);
|
|
setModeAndURI(2, "doh?responseIP=7.7.7.7");
|
|
|
|
await new TRRDNSListener("bar.example.com", "7.7.7.7");
|
|
|
|
// The TRR cache should be cleared by this pref change.
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://localhost:${h2Port}/doh?responseIP=8.8.8.8`
|
|
);
|
|
|
|
await new TRRDNSListener("bar.example.com", "8.8.8.8");
|
|
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
|
|
});
|
|
|
|
add_task(async function test_dnsSuffix() {
|
|
info("Checking that domains matching dns suffix list use Do53");
|
|
async function checkDnsSuffixInMode(mode) {
|
|
dns.clearCache(true);
|
|
setModeAndURI(mode, "doh?responseIP=1.2.3.4&push=true");
|
|
await new TRRDNSListener("example.org", "1.2.3.4");
|
|
await new TRRDNSListener("push.example.org", "2018::2018");
|
|
await new TRRDNSListener("test.com", "1.2.3.4");
|
|
|
|
let networkLinkService = {
|
|
dnsSuffixList: ["example.org"],
|
|
QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
|
|
};
|
|
Services.obs.notifyObservers(
|
|
networkLinkService,
|
|
"network:dns-suffix-list-updated"
|
|
);
|
|
await new TRRDNSListener("test.com", "1.2.3.4");
|
|
if (Services.prefs.getBoolPref("network.trr.split_horizon_mitigations")) {
|
|
await new TRRDNSListener("example.org", "127.0.0.1");
|
|
// Also test that we don't use the pushed entry.
|
|
await new TRRDNSListener("push.example.org", "127.0.0.1");
|
|
} else {
|
|
await new TRRDNSListener("example.org", "1.2.3.4");
|
|
await new TRRDNSListener("push.example.org", "2018::2018");
|
|
}
|
|
|
|
// Attempt to clean up, just in case
|
|
networkLinkService.dnsSuffixList = [];
|
|
Services.obs.notifyObservers(
|
|
networkLinkService,
|
|
"network:dns-suffix-list-updated"
|
|
);
|
|
}
|
|
|
|
Services.prefs.setBoolPref("network.trr.split_horizon_mitigations", true);
|
|
await checkDnsSuffixInMode(2);
|
|
Services.prefs.setCharPref("network.trr.bootstrapAddr", "127.0.0.1");
|
|
await checkDnsSuffixInMode(3);
|
|
Services.prefs.setBoolPref("network.trr.split_horizon_mitigations", false);
|
|
// Test again with mitigations off
|
|
await checkDnsSuffixInMode(2);
|
|
await checkDnsSuffixInMode(3);
|
|
Services.prefs.clearUserPref("network.trr.split_horizon_mitigations");
|
|
Services.prefs.clearUserPref("network.trr.bootstrapAddr");
|
|
});
|
|
|
|
add_task(async function test_async_resolve_with_trr_server() {
|
|
info("Checking asyncResolveWithTrrServer");
|
|
dns.clearCache(true);
|
|
Services.prefs.setIntPref("network.trr.mode", 0); // TRR-disabled
|
|
|
|
await new TRRDNSListener(
|
|
"bar_with_trr1.example.com",
|
|
"2.2.2.2",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=2.2.2.2`
|
|
);
|
|
|
|
// Test request without trr server, it should return a native dns response.
|
|
await new TRRDNSListener("bar_with_trr1.example.com", "127.0.0.1");
|
|
|
|
// Mode 2
|
|
dns.clearCache(true);
|
|
setModeAndURI(2, "doh?responseIP=2.2.2.2");
|
|
|
|
await new TRRDNSListener(
|
|
"bar_with_trr2.example.com",
|
|
"3.3.3.3",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
|
|
);
|
|
|
|
// Test request without trr server, it should return a response from trr server defined in the pref.
|
|
await new TRRDNSListener("bar_with_trr2.example.com", "2.2.2.2");
|
|
|
|
// Mode 3
|
|
dns.clearCache(true);
|
|
setModeAndURI(3, "doh?responseIP=2.2.2.2");
|
|
|
|
await new TRRDNSListener(
|
|
"bar_with_trr3.example.com",
|
|
"3.3.3.3",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
|
|
);
|
|
|
|
// Test request without trr server, it should return a response from trr server defined in the pref.
|
|
await new TRRDNSListener("bar_with_trr3.example.com", "2.2.2.2");
|
|
|
|
// Mode 5
|
|
dns.clearCache(true);
|
|
setModeAndURI(5, "doh?responseIP=2.2.2.2");
|
|
|
|
// When dns is resolved in socket process, we can't set |expectEarlyFail| to true.
|
|
let inSocketProcess = mozinfo.socketprocess_networking;
|
|
await new TRRDNSListener(
|
|
"bar_with_trr3.example.com",
|
|
undefined,
|
|
false,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`,
|
|
!inSocketProcess
|
|
);
|
|
|
|
// Call normal AsyncOpen, it will return result from the native resolver.
|
|
await new TRRDNSListener("bar_with_trr3.example.com", "127.0.0.1");
|
|
|
|
// Check that cache is ignored when server is different
|
|
dns.clearCache(true);
|
|
setModeAndURI(3, "doh?responseIP=2.2.2.2");
|
|
|
|
await new TRRDNSListener("bar_with_trr4.example.com", "2.2.2.2", true);
|
|
|
|
// The record will be fetch again.
|
|
await new TRRDNSListener(
|
|
"bar_with_trr4.example.com",
|
|
"3.3.3.3",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
|
|
);
|
|
|
|
// The record will be fetch again.
|
|
await new TRRDNSListener(
|
|
"bar_with_trr5.example.com",
|
|
"4.4.4.4",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=4.4.4.4`
|
|
);
|
|
|
|
// Check no fallback and no blocklisting upon failure
|
|
dns.clearCache(true);
|
|
setModeAndURI(2, "doh?responseIP=2.2.2.2");
|
|
|
|
let { inStatus } = await new TRRDNSListener(
|
|
"bar_with_trr6.example.com",
|
|
undefined,
|
|
false,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/404`
|
|
);
|
|
Assert.ok(
|
|
!Components.isSuccessCode(inStatus),
|
|
`${inStatus} should be an error code`
|
|
);
|
|
|
|
await new TRRDNSListener("bar_with_trr6.example.com", "2.2.2.2", true);
|
|
|
|
// Check that DoH push doesn't work
|
|
dns.clearCache(true);
|
|
setModeAndURI(2, "doh?responseIP=2.2.2.2");
|
|
|
|
await new TRRDNSListener(
|
|
"bar_with_trr7.example.com",
|
|
"3.3.3.3",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3&push=true`
|
|
);
|
|
|
|
// AsyncResoleWithTrrServer rejects server pushes and the entry for push.example.org
|
|
// shouldn't be neither in the default cache not in AsyncResoleWithTrrServer cache.
|
|
setModeAndURI(2, "404");
|
|
|
|
await new TRRDNSListener(
|
|
"push.example.org",
|
|
"3.3.3.3",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3&push=true`
|
|
);
|
|
|
|
await new TRRDNSListener("push.example.org", "127.0.0.1");
|
|
|
|
// Check confirmation is ignored
|
|
dns.clearCache(true);
|
|
setModeAndURI(2, "doh?responseIP=1::ffff");
|
|
Services.prefs.clearUserPref("network.trr.useGET");
|
|
Services.prefs.clearUserPref("network.trr.disable-ECS");
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
|
|
// AsyncResoleWithTrrServer will succeed
|
|
await new TRRDNSListener(
|
|
"bar_with_trr8.example.com",
|
|
"3.3.3.3",
|
|
true,
|
|
undefined,
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
|
|
);
|
|
|
|
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
|
|
|
|
// Bad port
|
|
dns.clearCache(true);
|
|
setModeAndURI(2, "doh?responseIP=2.2.2.2");
|
|
|
|
({ inStatus } = await new TRRDNSListener(
|
|
"only_once.example.com",
|
|
undefined,
|
|
false,
|
|
undefined,
|
|
`https://target.example.com:666/404`
|
|
));
|
|
Assert.ok(
|
|
!Components.isSuccessCode(inStatus),
|
|
`${inStatus} should be an error code`
|
|
);
|
|
|
|
// // MOZ_LOG=sync,timestamp,nsHostResolver:5 We should not keep resolving only_once.example.com
|
|
// // TODO: find a way of automating this
|
|
// await new Promise(resolve => {});
|
|
});
|
|
|
|
add_task(test_fetch_time);
|
|
|
|
add_task(async function test_content_encoding_gzip() {
|
|
info("Checking gzip content encoding");
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref(
|
|
"network.trr.send_empty_accept-encoding_headers",
|
|
false
|
|
);
|
|
setModeAndURI(3, "doh?responseIP=2.2.2.2");
|
|
|
|
await new TRRDNSListener("bar.example.com", "2.2.2.2");
|
|
Services.prefs.clearUserPref(
|
|
"network.trr.send_empty_accept-encoding_headers"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_redirect() {
|
|
info("Check handling of redirect");
|
|
|
|
// GET
|
|
dns.clearCache(true);
|
|
setModeAndURI(3, "doh?redirect=4.4.4.4{&dns}");
|
|
Services.prefs.setBoolPref("network.trr.useGET", true);
|
|
Services.prefs.setBoolPref("network.trr.disable-ECS", true);
|
|
|
|
await new TRRDNSListener("ecs.example.com", "4.4.4.4");
|
|
|
|
// POST
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.useGET", false);
|
|
setModeAndURI(3, "doh?redirect=4.4.4.4");
|
|
|
|
await new TRRDNSListener("bar.example.com", "4.4.4.4");
|
|
|
|
Services.prefs.clearUserPref("network.trr.useGET");
|
|
Services.prefs.clearUserPref("network.trr.disable-ECS");
|
|
});
|
|
|
|
// confirmationNS set without confirmed NS yet
|
|
// checks that we properly fall back to DNS is confirmation is not ready yet,
|
|
// and wait-for-confirmation pref is true
|
|
add_task(async function test_confirmation() {
|
|
info("Checking that we fall back correctly when confirmation is pending");
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.wait-for-confirmation", true);
|
|
setModeAndURI(2, "doh?responseIP=7.7.7.7&slowConfirm=true");
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
|
|
await new TRRDNSListener("example.org", "127.0.0.1");
|
|
await new Promise(resolve => do_timeout(1000, resolve));
|
|
await waitForConfirmation("7.7.7.7");
|
|
|
|
// Reset between each test to force re-confirm
|
|
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
|
|
|
|
info("Check that confirmation is skipped in mode 3");
|
|
// This is just a smoke test to make sure lookups succeed immediately
|
|
// in mode 3 without waiting for confirmation.
|
|
dns.clearCache(true);
|
|
setModeAndURI(3, "doh?responseIP=1::ffff&slowConfirm=true");
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
|
|
await new TRRDNSListener("skipConfirmationForMode3.example.com", "1::ffff");
|
|
|
|
// Reset between each test to force re-confirm
|
|
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
|
|
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.wait-for-confirmation", false);
|
|
setModeAndURI(2, "doh?responseIP=7.7.7.7&slowConfirm=true");
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
|
|
// DoH available immediately
|
|
await new TRRDNSListener("example.org", "7.7.7.7");
|
|
|
|
// Reset between each test to force re-confirm
|
|
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
|
|
|
|
// Fallback when confirmation fails
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.wait-for-confirmation", true);
|
|
setModeAndURI(2, "404");
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
|
|
await waitForConfirmation("7.7.7.7", true);
|
|
|
|
await new TRRDNSListener("example.org", "127.0.0.1");
|
|
|
|
// Reset
|
|
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
|
|
Services.prefs.clearUserPref("network.trr.wait-for-confirmation");
|
|
});
|
|
|
|
add_task(test_fqdn);
|
|
|
|
add_task(async function test_detected_uri() {
|
|
info("Test setDetectedTrrURI");
|
|
dns.clearCache(true);
|
|
Services.prefs.setIntPref("network.trr.mode", 3);
|
|
Services.prefs.clearUserPref("network.trr.uri");
|
|
let defaultURI = gDefaultPref.getCharPref("network.trr.default_provider_uri");
|
|
gDefaultPref.setCharPref(
|
|
"network.trr.default_provider_uri",
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.4.5.6`
|
|
);
|
|
await new TRRDNSListener("domainA.example.org.", "3.4.5.6");
|
|
dns.setDetectedTrrURI(
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
|
|
);
|
|
await new TRRDNSListener("domainB.example.org.", "1.2.3.4");
|
|
gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
|
|
|
|
// With a user-set doh uri this time.
|
|
dns.clearCache(true);
|
|
setModeAndURI(2, "doh?responseIP=4.5.6.7");
|
|
await new TRRDNSListener("domainA.example.org.", "4.5.6.7");
|
|
|
|
// This should be a no-op, since we have a user-set URI
|
|
dns.setDetectedTrrURI(
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
|
|
);
|
|
await new TRRDNSListener("domainB.example.org.", "4.5.6.7");
|
|
|
|
// Test network link status change
|
|
dns.clearCache(true);
|
|
Services.prefs.setIntPref("network.trr.mode", 3);
|
|
Services.prefs.clearUserPref("network.trr.uri");
|
|
gDefaultPref.setCharPref(
|
|
"network.trr.default_provider_uri",
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.4.5.6`
|
|
);
|
|
await new TRRDNSListener("domainA.example.org.", "3.4.5.6");
|
|
dns.setDetectedTrrURI(
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
|
|
);
|
|
await new TRRDNSListener("domainB.example.org.", "1.2.3.4");
|
|
|
|
let networkLinkService = {
|
|
platformDNSIndications: 0,
|
|
QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
|
|
};
|
|
|
|
Services.obs.notifyObservers(
|
|
networkLinkService,
|
|
"network:link-status-changed",
|
|
"changed"
|
|
);
|
|
|
|
await new TRRDNSListener("domainC.example.org.", "3.4.5.6");
|
|
|
|
gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
|
|
});
|
|
|
|
add_task(async function test_pref_changes() {
|
|
info("Testing pref change handling");
|
|
Services.prefs.clearUserPref("network.trr.uri");
|
|
let defaultURI = gDefaultPref.getCharPref("network.trr.default_provider_uri");
|
|
|
|
async function doThenCheckURI(closure, expectedURI, expectChange = true) {
|
|
let uriChanged;
|
|
if (expectChange) {
|
|
uriChanged = topicObserved("network:trr-uri-changed");
|
|
}
|
|
closure();
|
|
if (expectChange) {
|
|
await uriChanged;
|
|
}
|
|
equal(dns.currentTrrURI, expectedURI);
|
|
}
|
|
|
|
// setting the default value of the pref should be reflected in the URI
|
|
await doThenCheckURI(() => {
|
|
gDefaultPref.setCharPref(
|
|
"network.trr.default_provider_uri",
|
|
`https://foo.example.com:${h2Port}/doh?default`
|
|
);
|
|
}, `https://foo.example.com:${h2Port}/doh?default`);
|
|
|
|
// the user set value should be reflected in the URI
|
|
await doThenCheckURI(() => {
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://foo.example.com:${h2Port}/doh?user`
|
|
);
|
|
}, `https://foo.example.com:${h2Port}/doh?user`);
|
|
|
|
// A user set pref is selected, so it should be chosen instead of the rollout
|
|
await doThenCheckURI(
|
|
() => {
|
|
Services.prefs.setCharPref(
|
|
"doh-rollout.uri",
|
|
`https://foo.example.com:${h2Port}/doh?rollout`
|
|
);
|
|
},
|
|
`https://foo.example.com:${h2Port}/doh?user`,
|
|
false
|
|
);
|
|
|
|
// There is no user set pref, so we go to the rollout pref
|
|
await doThenCheckURI(() => {
|
|
Services.prefs.clearUserPref("network.trr.uri");
|
|
}, `https://foo.example.com:${h2Port}/doh?rollout`);
|
|
|
|
// When the URI is set by the rollout addon, detection is allowed
|
|
await doThenCheckURI(() => {
|
|
dns.setDetectedTrrURI(`https://foo.example.com:${h2Port}/doh?detected`);
|
|
}, `https://foo.example.com:${h2Port}/doh?detected`);
|
|
|
|
// Should switch back to the default provided by the rollout addon
|
|
await doThenCheckURI(() => {
|
|
let networkLinkService = {
|
|
platformDNSIndications: 0,
|
|
QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
|
|
};
|
|
Services.obs.notifyObservers(
|
|
networkLinkService,
|
|
"network:link-status-changed",
|
|
"changed"
|
|
);
|
|
}, `https://foo.example.com:${h2Port}/doh?rollout`);
|
|
|
|
// Again the user set pref should be chosen
|
|
await doThenCheckURI(() => {
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://foo.example.com:${h2Port}/doh?user`
|
|
);
|
|
}, `https://foo.example.com:${h2Port}/doh?user`);
|
|
|
|
// Detection should not work with a user set pref
|
|
await doThenCheckURI(
|
|
() => {
|
|
dns.setDetectedTrrURI(`https://foo.example.com:${h2Port}/doh?detected`);
|
|
},
|
|
`https://foo.example.com:${h2Port}/doh?user`,
|
|
false
|
|
);
|
|
|
|
// Should stay the same on network changes
|
|
await doThenCheckURI(
|
|
() => {
|
|
let networkLinkService = {
|
|
platformDNSIndications: 0,
|
|
QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
|
|
};
|
|
Services.obs.notifyObservers(
|
|
networkLinkService,
|
|
"network:link-status-changed",
|
|
"changed"
|
|
);
|
|
},
|
|
`https://foo.example.com:${h2Port}/doh?user`,
|
|
false
|
|
);
|
|
|
|
// Restore the pref
|
|
gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
|
|
});
|
|
|
|
add_task(async function test_dohrollout_mode() {
|
|
info("Testing doh-rollout.mode");
|
|
Services.prefs.clearUserPref("network.trr.mode");
|
|
Services.prefs.clearUserPref("doh-rollout.mode");
|
|
|
|
equal(dns.currentTrrMode, 0);
|
|
|
|
async function doThenCheckMode(trrMode, rolloutMode, expectedMode, message) {
|
|
let modeChanged;
|
|
if (dns.currentTrrMode != expectedMode) {
|
|
modeChanged = topicObserved("network:trr-mode-changed");
|
|
}
|
|
|
|
if (trrMode != undefined) {
|
|
Services.prefs.setIntPref("network.trr.mode", trrMode);
|
|
}
|
|
|
|
if (rolloutMode != undefined) {
|
|
Services.prefs.setIntPref("doh-rollout.mode", rolloutMode);
|
|
}
|
|
|
|
if (modeChanged) {
|
|
await modeChanged;
|
|
}
|
|
equal(dns.currentTrrMode, expectedMode, message);
|
|
}
|
|
|
|
await doThenCheckMode(2, undefined, 2);
|
|
await doThenCheckMode(3, undefined, 3);
|
|
await doThenCheckMode(5, undefined, 5);
|
|
await doThenCheckMode(2, undefined, 2);
|
|
await doThenCheckMode(0, undefined, 0);
|
|
await doThenCheckMode(1, undefined, 5);
|
|
await doThenCheckMode(6, undefined, 5);
|
|
|
|
await doThenCheckMode(2, 0, 2);
|
|
await doThenCheckMode(2, 1, 2);
|
|
await doThenCheckMode(2, 2, 2);
|
|
await doThenCheckMode(2, 3, 2);
|
|
await doThenCheckMode(2, 5, 2);
|
|
await doThenCheckMode(3, 2, 3);
|
|
await doThenCheckMode(5, 2, 5);
|
|
|
|
Services.prefs.clearUserPref("network.trr.mode");
|
|
Services.prefs.clearUserPref("doh-rollout.mode");
|
|
|
|
await doThenCheckMode(undefined, 2, 2);
|
|
await doThenCheckMode(undefined, 3, 3);
|
|
|
|
// All modes that are not 0,2,3 are treated as 5
|
|
await doThenCheckMode(undefined, 5, 5);
|
|
await doThenCheckMode(undefined, 4, 5);
|
|
await doThenCheckMode(undefined, 6, 5);
|
|
|
|
await doThenCheckMode(undefined, 2, 2);
|
|
await doThenCheckMode(3, undefined, 3);
|
|
|
|
Services.prefs.clearUserPref("network.trr.mode");
|
|
equal(dns.currentTrrMode, 2);
|
|
Services.prefs.clearUserPref("doh-rollout.mode");
|
|
equal(dns.currentTrrMode, 0);
|
|
});
|
|
|
|
add_task(test_ipv6_trr_fallback);
|
|
|
|
add_task(test_ipv4_trr_fallback);
|
|
|
|
add_task(test_no_retry_without_doh);
|
|
|
|
// This test checks that normally when the TRR mode goes from ON -> OFF
|
|
// we purge the DNS cache (including TRR), so the entries aren't used on
|
|
// networks where they shouldn't. For example - turning on a VPN.
|
|
add_task(async function test_purge_trr_cache_on_mode_change() {
|
|
info("Checking that we purge cache when TRR is turned off");
|
|
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", true);
|
|
|
|
Services.prefs.setIntPref("network.trr.mode", 0);
|
|
Services.prefs.setIntPref("doh-rollout.mode", 2);
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
|
|
);
|
|
|
|
await new TRRDNSListener("cached.example.com", "3.3.3.3");
|
|
Services.prefs.clearUserPref("doh-rollout.mode");
|
|
|
|
await new TRRDNSListener("cached.example.com", "127.0.0.1");
|
|
|
|
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
|
|
Services.prefs.clearUserPref("doh-rollout.mode");
|
|
});
|
|
|
|
add_task(async function test_old_bootstrap_pref() {
|
|
dns.clearCache(true);
|
|
// Note this is a remote address. Setting this pref should have no effect,
|
|
// as this is the old name for the bootstrap pref.
|
|
// If this were to be used, the test would crash when accessing a non-local
|
|
// IP address.
|
|
Services.prefs.setCharPref("network.trr.bootstrapAddress", "1.1.1.1");
|
|
setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh?responseIP=4.4.4.4`);
|
|
await new TRRDNSListener("testytest.com", "4.4.4.4");
|
|
});
|
|
|
|
add_task(async function test_padding() {
|
|
setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh`);
|
|
async function CheckPadding(
|
|
pad_length,
|
|
request,
|
|
none,
|
|
ecs,
|
|
padding,
|
|
ecsPadding
|
|
) {
|
|
Services.prefs.setIntPref("network.trr.padding.length", pad_length);
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.padding", false);
|
|
Services.prefs.setBoolPref("network.trr.disable-ECS", false);
|
|
await new TRRDNSListener(request, none);
|
|
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.padding", false);
|
|
Services.prefs.setBoolPref("network.trr.disable-ECS", true);
|
|
await new TRRDNSListener(request, ecs);
|
|
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.padding", true);
|
|
Services.prefs.setBoolPref("network.trr.disable-ECS", false);
|
|
await new TRRDNSListener(request, padding);
|
|
|
|
dns.clearCache(true);
|
|
Services.prefs.setBoolPref("network.trr.padding", true);
|
|
Services.prefs.setBoolPref("network.trr.disable-ECS", true);
|
|
await new TRRDNSListener(request, ecsPadding);
|
|
}
|
|
|
|
// short domain name
|
|
await CheckPadding(
|
|
16,
|
|
"a.pd",
|
|
"2.2.0.22",
|
|
"2.2.0.41",
|
|
"1.1.0.48",
|
|
"1.1.0.48"
|
|
);
|
|
await CheckPadding(256, "a.pd", "2.2.0.22", "2.2.0.41", "1.1.1.0", "1.1.1.0");
|
|
|
|
// medium domain name
|
|
await CheckPadding(
|
|
16,
|
|
"has-padding.pd",
|
|
"2.2.0.32",
|
|
"2.2.0.51",
|
|
"1.1.0.48",
|
|
"1.1.0.64"
|
|
);
|
|
await CheckPadding(
|
|
128,
|
|
"has-padding.pd",
|
|
"2.2.0.32",
|
|
"2.2.0.51",
|
|
"1.1.0.128",
|
|
"1.1.0.128"
|
|
);
|
|
await CheckPadding(
|
|
80,
|
|
"has-padding.pd",
|
|
"2.2.0.32",
|
|
"2.2.0.51",
|
|
"1.1.0.80",
|
|
"1.1.0.80"
|
|
);
|
|
|
|
// long domain name
|
|
await CheckPadding(
|
|
16,
|
|
"abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.pd",
|
|
"2.2.0.131",
|
|
"2.2.0.150",
|
|
"1.1.0.160",
|
|
"1.1.0.160"
|
|
);
|
|
await CheckPadding(
|
|
128,
|
|
"abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.pd",
|
|
"2.2.0.131",
|
|
"2.2.0.150",
|
|
"1.1.1.0",
|
|
"1.1.1.0"
|
|
);
|
|
await CheckPadding(
|
|
80,
|
|
"abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.pd",
|
|
"2.2.0.131",
|
|
"2.2.0.150",
|
|
"1.1.0.160",
|
|
"1.1.0.160"
|
|
);
|
|
});
|
|
|
|
add_task(test_connection_reuse_and_cycling);
|