tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_trr_confirmation.js (12304B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const { TestUtils } = ChromeUtils.importESModule(
      8  "resource://testing-common/TestUtils.sys.mjs"
      9 );
     10 
     11 async function waitForConfirmationState(state, msToWait = 0) {
     12  await TestUtils.waitForCondition(
     13    () => Services.dns.currentTrrConfirmationState == state,
     14    `Timed out waiting for ${state}. Currently ${Services.dns.currentTrrConfirmationState}`,
     15    1,
     16    msToWait
     17  );
     18  equal(
     19    Services.dns.currentTrrConfirmationState,
     20    state,
     21    "expected confirmation state"
     22  );
     23 }
     24 
     25 const CONFIRM_OFF = 0;
     26 const CONFIRM_TRYING_OK = 1;
     27 const CONFIRM_OK = 2;
     28 const CONFIRM_FAILED = 3;
     29 const CONFIRM_TRYING_FAILED = 4;
     30 const CONFIRM_DISABLED = 5;
     31 
     32 function setup() {
     33  trr_test_setup();
     34  Services.prefs.setBoolPref("network.trr.skip-check-for-blocked-host", true);
     35 }
     36 
     37 setup();
     38 registerCleanupFunction(async () => {
     39  trr_clear_prefs();
     40  Services.prefs.clearUserPref("network.trr.skip-check-for-blocked-host");
     41 });
     42 
     43 let trrServer = null;
     44 add_task(async function start_trr_server() {
     45  trrServer = new TRRServer();
     46  registerCleanupFunction(async () => {
     47    await trrServer.stop();
     48  });
     49  await trrServer.start();
     50  dump(`port = ${trrServer.port()}\n`);
     51 
     52  await trrServer.registerDoHAnswers(`faily.com`, "NS", {
     53    answers: [
     54      {
     55        name: "faily.com",
     56        ttl: 55,
     57        type: "NS",
     58        flush: false,
     59        data: "ns.faily.com",
     60      },
     61    ],
     62  });
     63 
     64  for (let i = 0; i < 15; i++) {
     65    await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "A", {
     66      error: 600,
     67    });
     68    await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "AAAA", {
     69      error: 600,
     70    });
     71  }
     72 });
     73 
     74 function trigger15Failures() {
     75  // We need to clear the cache in case a previous call to this method
     76  // put the results in the DNS cache.
     77  Services.dns.clearCache(true);
     78 
     79  let dnsRequests = [];
     80  // There are actually two TRR requests sent for A and AAAA records, so doing
     81  // DNS query 10 times should be enough to trigger confirmation process.
     82  for (let i = 0; i < 10; i++) {
     83    dnsRequests.push(
     84      new TRRDNSListener(`failing-domain${i}.faily.com`, {
     85        expectedAnswer: "127.0.0.1",
     86      })
     87    );
     88  }
     89 
     90  return Promise.all(dnsRequests);
     91 }
     92 
     93 async function registerNS(delay) {
     94  return trrServer.registerDoHAnswers("confirm.example.com", "NS", {
     95    answers: [
     96      {
     97        name: "confirm.example.com",
     98        ttl: 55,
     99        type: "NS",
    100        flush: false,
    101        data: "test.com",
    102      },
    103    ],
    104    delay,
    105  });
    106 }
    107 
    108 add_task(async function confirm_off() {
    109  Services.prefs.setCharPref(
    110    "network.trr.confirmationNS",
    111    "confirm.example.com"
    112  );
    113  Services.prefs.setIntPref(
    114    "network.trr.mode",
    115    Ci.nsIDNSService.MODE_NATIVEONLY
    116  );
    117  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
    118  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRROFF);
    119  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
    120 });
    121 
    122 add_task(async function confirm_disabled() {
    123  Services.prefs.setCharPref(
    124    "network.trr.confirmationNS",
    125    "confirm.example.com"
    126  );
    127  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY);
    128  equal(Services.dns.currentTrrConfirmationState, CONFIRM_DISABLED);
    129  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
    130  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    131  equal(Services.dns.currentTrrConfirmationState, CONFIRM_DISABLED);
    132 });
    133 
    134 add_task(async function confirm_ok() {
    135  Services.dns.clearCache(true);
    136  Services.prefs.setCharPref(
    137    "network.trr.confirmationNS",
    138    "confirm.example.com"
    139  );
    140  await registerNS(0);
    141  await trrServer.registerDoHAnswers("example.com", "A", {
    142    answers: [
    143      {
    144        name: "example.com",
    145        ttl: 55,
    146        type: "A",
    147        flush: false,
    148        data: "1.2.3.4",
    149      },
    150    ],
    151  });
    152  Services.prefs.setCharPref(
    153    "network.trr.uri",
    154    `https://foo.example.com:${trrServer.port()}/dns-query`
    155  );
    156  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    157  equal(
    158    Services.dns.currentTrrConfirmationState,
    159    CONFIRM_TRYING_OK,
    160    "Should be CONFIRM_TRYING_OK"
    161  );
    162  await new TRRDNSListener("example.com", { expectedAnswer: "1.2.3.4" });
    163  equal(await trrServer.requestCount("example.com", "A"), 1);
    164  await waitForConfirmationState(CONFIRM_OK, 1000);
    165 
    166  await registerNS(500);
    167  Services.prefs.setIntPref(
    168    "network.trr.mode",
    169    Ci.nsIDNSService.MODE_NATIVEONLY
    170  );
    171  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    172  equal(
    173    Services.dns.currentTrrConfirmationState,
    174    CONFIRM_TRYING_OK,
    175    "Should be CONFIRM_TRYING_OK"
    176  );
    177  await new Promise(resolve => do_timeout(100, resolve));
    178  equal(
    179    Services.dns.currentTrrConfirmationState,
    180    CONFIRM_TRYING_OK,
    181    "Confirmation should still be pending"
    182  );
    183  await waitForConfirmationState(CONFIRM_OK, 1000);
    184 });
    185 
    186 add_task(async function confirm_timeout() {
    187  Services.prefs.setIntPref(
    188    "network.trr.mode",
    189    Ci.nsIDNSService.MODE_NATIVEONLY
    190  );
    191  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
    192  await registerNS(7000);
    193  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    194  equal(
    195    Services.dns.currentTrrConfirmationState,
    196    CONFIRM_TRYING_OK,
    197    "Should be CONFIRM_TRYING_OK"
    198  );
    199  await waitForConfirmationState(CONFIRM_FAILED, 7500);
    200  // After the confirmation fails, a timer will periodically trigger a retry
    201  // causing the state to go into CONFIRM_TRYING_FAILED.
    202  await waitForConfirmationState(CONFIRM_TRYING_FAILED, 500);
    203 });
    204 
    205 add_task(async function confirm_fail_fast() {
    206  Services.prefs.setIntPref(
    207    "network.trr.mode",
    208    Ci.nsIDNSService.MODE_NATIVEONLY
    209  );
    210  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
    211  await trrServer.registerDoHAnswers("confirm.example.com", "NS", {
    212    error: 404,
    213  });
    214  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    215  equal(
    216    Services.dns.currentTrrConfirmationState,
    217    CONFIRM_TRYING_OK,
    218    "Should be CONFIRM_TRYING_OK"
    219  );
    220  await waitForConfirmationState(CONFIRM_FAILED, 100);
    221 });
    222 
    223 add_task(async function multiple_failures() {
    224  Services.prefs.setIntPref(
    225    "network.trr.mode",
    226    Ci.nsIDNSService.MODE_NATIVEONLY
    227  );
    228  Services.prefs.setIntPref("network.trr.max-retry-timeout-ms", 8000);
    229  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
    230 
    231  await registerNS(100);
    232  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    233  equal(
    234    Services.dns.currentTrrConfirmationState,
    235    CONFIRM_TRYING_OK,
    236    "Should be CONFIRM_TRYING_OK"
    237  );
    238  await waitForConfirmationState(CONFIRM_OK, 1000);
    239  await registerNS(4000);
    240  let failures = trigger15Failures();
    241  await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
    242  await failures;
    243  // Check that failures during confirmation are ignored.
    244  await trigger15Failures();
    245  equal(
    246    Services.dns.currentTrrConfirmationState,
    247    CONFIRM_TRYING_OK,
    248    "Should be CONFIRM_TRYING_OK"
    249  );
    250  await waitForConfirmationState(CONFIRM_OK, 8500);
    251 });
    252 
    253 add_task(async function test_connectivity_change() {
    254  await registerNS(100);
    255  Services.prefs.setIntPref(
    256    "network.trr.mode",
    257    Ci.nsIDNSService.MODE_NATIVEONLY
    258  );
    259  let confirmationCount = await trrServer.requestCount(
    260    "confirm.example.com",
    261    "NS"
    262  );
    263  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
    264  equal(
    265    Services.dns.currentTrrConfirmationState,
    266    CONFIRM_TRYING_OK,
    267    "Should be CONFIRM_TRYING_OK"
    268  );
    269  await waitForConfirmationState(CONFIRM_OK, 1000);
    270  equal(
    271    await trrServer.requestCount("confirm.example.com", "NS"),
    272    confirmationCount + 1
    273  );
    274  Services.obs.notifyObservers(
    275    null,
    276    "network:captive-portal-connectivity",
    277    "clear"
    278  );
    279  // This means a CP check completed successfully. But no CP was previously
    280  // detected, so this is mostly a no-op.
    281  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
    282 
    283  Services.obs.notifyObservers(
    284    null,
    285    "network:captive-portal-connectivity",
    286    "captive"
    287  );
    288  // This basically a successful CP login event. Wasn't captive before.
    289  // Still treating as a no-op.
    290  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
    291 
    292  // This makes the TRR service set mCaptiveIsPassed=false
    293  Services.obs.notifyObservers(
    294    null,
    295    "captive-portal-login",
    296    "{type: 'captive-portal-login', id: 0, url: 'http://localhost/'}"
    297  );
    298 
    299  await registerNS(500);
    300  let failures = trigger15Failures();
    301  // The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req
    302  await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
    303  await failures;
    304 
    305  // The notification sets mCaptiveIsPassed=true then triggers an entirely new
    306  // confirmation.
    307  Services.obs.notifyObservers(
    308    null,
    309    "network:captive-portal-connectivity",
    310    "clear"
    311  );
    312  // The notification should cause us to send a new confirmation request
    313  equal(
    314    Services.dns.currentTrrConfirmationState,
    315    CONFIRM_TRYING_OK,
    316    "Should be CONFIRM_TRYING_OK"
    317  );
    318  await waitForConfirmationState(CONFIRM_OK, 1000);
    319  // two extra confirmation events should have been received by the server
    320  equal(
    321    await trrServer.requestCount("confirm.example.com", "NS"),
    322    confirmationCount + 3
    323  );
    324 });
    325 
    326 add_task(async function test_network_change() {
    327  let confirmationCount = await trrServer.requestCount(
    328    "confirm.example.com",
    329    "NS"
    330  );
    331  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
    332 
    333  Services.obs.notifyObservers(null, "network:link-status-changed", "up");
    334  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
    335  equal(
    336    await trrServer.requestCount("confirm.example.com", "NS"),
    337    confirmationCount
    338  );
    339 
    340  let failures = trigger15Failures();
    341  // The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req
    342  await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
    343  await failures;
    344  // The network up event should reset the confirmation to TRYING_OK and do
    345  // another NS req
    346  Services.obs.notifyObservers(null, "network:link-status-changed", "up");
    347  equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
    348  await waitForConfirmationState(CONFIRM_OK, 1000);
    349  // two extra confirmation events should have been received by the server
    350  equal(
    351    await trrServer.requestCount("confirm.example.com", "NS"),
    352    confirmationCount + 2
    353  );
    354 });
    355 
    356 add_task(async function test_uri_pref_change() {
    357  let confirmationCount = await trrServer.requestCount(
    358    "confirm.example.com",
    359    "NS"
    360  );
    361  equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
    362  Services.prefs.setCharPref(
    363    "network.trr.uri",
    364    `https://foo.example.com:${trrServer.port()}/dns-query?changed`
    365  );
    366  equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
    367  await waitForConfirmationState(CONFIRM_OK, 1000);
    368  equal(
    369    await trrServer.requestCount("confirm.example.com", "NS"),
    370    confirmationCount + 1
    371  );
    372 });
    373 
    374 add_task(async function test_autodetected_uri() {
    375  const defaultPrefBranch = Services.prefs.getDefaultBranch("");
    376  let defaultURI = defaultPrefBranch.getCharPref(
    377    "network.trr.default_provider_uri"
    378  );
    379  defaultPrefBranch.setCharPref(
    380    "network.trr.default_provider_uri",
    381    `https://foo.example.com:${trrServer.port()}/dns-query?changed`
    382  );
    383  // For setDetectedTrrURI to work we must pretend we are using the default.
    384  Services.prefs.clearUserPref("network.trr.uri");
    385  await waitForConfirmationState(CONFIRM_OK, 1000);
    386  let confirmationCount = await trrServer.requestCount(
    387    "confirm.example.com",
    388    "NS"
    389  );
    390  Services.dns.setDetectedTrrURI(
    391    `https://foo.example.com:${trrServer.port()}/dns-query?changed2`
    392  );
    393  equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
    394  await waitForConfirmationState(CONFIRM_OK, 1000);
    395  equal(
    396    await trrServer.requestCount("confirm.example.com", "NS"),
    397    confirmationCount + 1
    398  );
    399 
    400  // reset the default URI
    401  defaultPrefBranch.setCharPref("network.trr.default_provider_uri", defaultURI);
    402 });