"use strict"; /* import-globals-from trr_common.js */ const gDefaultPref = Services.prefs.getDefaultBranch(""); SetParentalControlEnabled(false); function setup() { Services.prefs.setBoolPref("network.dns.get-ttl", false); h2Port = trr_test_setup(); } setup(); registerCleanupFunction(async () => { trr_clear_prefs(); Services.prefs.clearUserPref("network.dns.get-ttl"); }); 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) { 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); Services.prefs.setIntPref("network.trr.request_timeout_ms", 10000); Services.prefs.setIntPref( "network.trr.request_timeout_mode_trronly_ms", 10000 ); 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, ]) { Services.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"); Services.prefs.clearUserPref("network.trr.request_timeout_ms"); Services.prefs.clearUserPref("network.trr.request_timeout_mode_trronly_ms"); }); add_task(test_A_record); add_task(async function test_push() { info("Verify DOH push"); Services.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."); Services.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) { Services.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"); Services.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 Services.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 Services.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 Services.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 Services.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 Services.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 Services.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 Services.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 Services.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"); Services.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 Services.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 Services.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"); Services.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. Services.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"); Services.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 Services.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"); Services.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"); Services.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. Services.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 Services.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 Services.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"); Services.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(Services.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(() => { Services.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( () => { Services.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(Services.dns.currentTrrMode, 0); async function doThenCheckMode(trrMode, rolloutMode, expectedMode, message) { let modeChanged; if (Services.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(Services.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(Services.dns.currentTrrMode, 2); Services.prefs.clearUserPref("doh-rollout.mode"); equal(Services.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() { Services.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); Services.dns.clearCache(true); Services.prefs.setBoolPref("network.trr.padding", false); Services.prefs.setBoolPref("network.trr.disable-ECS", false); await new TRRDNSListener(request, none); Services.dns.clearCache(true); Services.prefs.setBoolPref("network.trr.padding", false); Services.prefs.setBoolPref("network.trr.disable-ECS", true); await new TRRDNSListener(request, ecs); Services.dns.clearCache(true); Services.prefs.setBoolPref("network.trr.padding", true); Services.prefs.setBoolPref("network.trr.disable-ECS", false); await new TRRDNSListener(request, padding); Services.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); // Can't test for socket process since telemetry is captured in different process. add_task( { skip_if: () => mozinfo.socketprocess_networking }, async function test_trr_pb_telemetry() { setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh`); Services.dns.clearCache(true); Services.fog.initializeFOG(); Services.fog.testResetFOG(); await new TRRDNSListener("testytest.com", { expectedAnswer: "5.5.5.5" }); Assert.equal( await Glean.networking.trrRequestCount.regular.testGetValue(), 2 ); // One for IPv4 and one for IPv6. Assert.equal( await Glean.networking.trrRequestCount.private.testGetValue(), null ); await new TRRDNSListener("testytest.com", { expectedAnswer: "5.5.5.5", originAttributes: { privateBrowsingId: 1 }, }); Assert.equal( await Glean.networking.trrRequestCount.regular.testGetValue(), 2 ); Assert.equal( await Glean.networking.trrRequestCount.private.testGetValue(), 2 ); } );