tor-browser

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

test_trr_https_rr_with_cname.js (6199B)


      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 var { setTimeout } = ChromeUtils.importESModule(
      8  "resource://gre/modules/Timer.sys.mjs"
      9 );
     10 
     11 const { TestUtils } = ChromeUtils.importESModule(
     12  "resource://testing-common/TestUtils.sys.mjs"
     13 );
     14 
     15 let h2Port;
     16 let h3Port;
     17 let h3EchConfig;
     18 
     19 function makeChan(url) {
     20  let chan = NetUtil.newChannel({
     21    uri: url,
     22    loadUsingSystemPrincipal: true,
     23    contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
     24  }).QueryInterface(Ci.nsIHttpChannel);
     25  return chan;
     26 }
     27 
     28 function channelOpenPromise(chan, flags) {
     29  return new Promise(resolve => {
     30    function finish(req, buffer) {
     31      resolve([req, buffer]);
     32    }
     33    chan.asyncOpen(new ChannelListener(finish, null, flags));
     34  });
     35 }
     36 
     37 add_setup(async function setup() {
     38  if (mozinfo.socketprocess_networking) {
     39    Services.dns; // Needed to trigger socket process.
     40    await TestUtils.waitForCondition(() => Services.io.socketProcessLaunched);
     41  }
     42 
     43  Services.prefs.setBoolPref("network.dns.port_prefixed_qname_https_rr", false);
     44 
     45  trr_test_setup();
     46  registerCleanupFunction(async () => {
     47    trr_clear_prefs();
     48    Services.prefs.clearUserPref("network.dns.port_prefixed_qname_https_rr");
     49  });
     50 
     51  h2Port = Services.env.get("MOZHTTP2_PORT");
     52  Assert.notEqual(h2Port, null);
     53  Assert.notEqual(h2Port, "");
     54 
     55  h3Port = Services.env.get("MOZHTTP3_PORT_ECH");
     56  Assert.notEqual(h3Port, null);
     57  Assert.notEqual(h3Port, "");
     58 
     59  h3EchConfig = Services.env.get("MOZHTTP3_ECH");
     60  Assert.notEqual(h3EchConfig, null);
     61  Assert.notEqual(h3EchConfig, "");
     62 });
     63 
     64 async function do_test_https_rr_records(
     65  host,
     66  targetName1,
     67  port1,
     68  targetName2,
     69  port2,
     70  cname,
     71  expectedVersion
     72 ) {
     73  Services.obs.notifyObservers(null, "net:cancel-all-connections");
     74  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     75  await new Promise(resolve => setTimeout(resolve, 1000));
     76 
     77  Services.dns.clearCache(true);
     78 
     79  let trrServer = new TRRServer();
     80  registerCleanupFunction(async () => {
     81    await trrServer.stop();
     82  });
     83  await trrServer.start();
     84  Services.prefs.setIntPref("network.trr.mode", 3);
     85  Services.prefs.setCharPref(
     86    "network.trr.uri",
     87    `https://foo.example.com:${trrServer.port()}/dns-query`
     88  );
     89 
     90  await trrServer.registerDoHAnswers(host, "HTTPS", {
     91    answers: [
     92      {
     93        name: host,
     94        ttl: 55,
     95        type: "HTTPS",
     96        flush: false,
     97        data: {
     98          priority: 1,
     99          name: targetName1,
    100          values: [
    101            { key: "alpn", value: "h3" },
    102            { key: "port", value: port1 },
    103            {
    104              key: "echconfig",
    105              value: h3EchConfig,
    106              needBase64Decode: true,
    107            },
    108          ],
    109        },
    110      },
    111      {
    112        name: host,
    113        ttl: 55,
    114        type: "HTTPS",
    115        flush: false,
    116        data: {
    117          priority: 1,
    118          name: targetName2,
    119          values: [
    120            { key: "alpn", value: "h3" },
    121            { key: "port", value: port2 },
    122            {
    123              key: "echconfig",
    124              value: h3EchConfig,
    125              needBase64Decode: true,
    126            },
    127          ],
    128        },
    129      },
    130    ],
    131  });
    132 
    133  await trrServer.registerDoHAnswers(host, "A", {
    134    answers: [
    135      {
    136        name: host,
    137        ttl: 55,
    138        type: "CNAME",
    139        flush: false,
    140        data: cname,
    141      },
    142      {
    143        name: cname,
    144        ttl: 55,
    145        type: "A",
    146        flush: false,
    147        data: "127.0.0.1",
    148      },
    149    ],
    150  });
    151 
    152  await trrServer.registerDoHAnswers(cname, "A", {
    153    answers: [
    154      {
    155        name: cname,
    156        ttl: 55,
    157        type: "A",
    158        flush: false,
    159        data: "127.0.0.1",
    160      },
    161    ],
    162  });
    163 
    164  let { inRecord } = await new TRRDNSListener(host, {
    165    expectedAnswer: "127.0.0.1",
    166    flags: Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
    167  });
    168  equal(inRecord.QueryInterface(Ci.nsIDNSAddrRecord).canonicalName, cname);
    169 
    170  let chan = makeChan(`https://${host}:${h2Port}/`);
    171  let [req] = await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
    172  Assert.equal(req.protocolVersion, expectedVersion);
    173  await trrServer.stop();
    174 }
    175 
    176 // Test the case that the pref is off and the cname is not the same as the
    177 // targetName. The expected protocol version being "h3" means that the last
    178 // svcb record is used.
    179 add_task(async function test_https_rr_with_unmatched_cname() {
    180  Services.prefs.setBoolPref(
    181    "network.dns.https_rr.check_record_with_cname",
    182    false
    183  );
    184  await do_test_https_rr_records(
    185    "alt1.example.com",
    186    "alt1.example.com",
    187    h3Port,
    188    "not_used",
    189    h3Port,
    190    "test.cname1.com",
    191    "h3"
    192  );
    193 });
    194 
    195 // Test the case that the pref is on and the cname is not the same as the
    196 // targetName. Since there is no svcb record can be used, we fallback to "h2".
    197 add_task(async function test_https_rr_with_unmatched_cname_1() {
    198  Services.prefs.setBoolPref(
    199    "network.dns.https_rr.check_record_with_cname",
    200    true
    201  );
    202  await do_test_https_rr_records(
    203    "alt1.example.com",
    204    "alt1.example.com",
    205    h3Port,
    206    "not_used",
    207    h3Port,
    208    "test.cname1.com",
    209    "h2"
    210  );
    211 });
    212 
    213 // Test the case that the pref is on and the cname is matched. We failed to
    214 // connect to the first record, but we successfully connect with the second one.
    215 add_task(async function test_https_rr_with_matched_cname() {
    216  Services.prefs.setBoolPref(
    217    "network.dns.https_rr.check_record_with_cname",
    218    true
    219  );
    220  await do_test_https_rr_records(
    221    "alt1.example.com",
    222    "not_used",
    223    h3Port,
    224    "alt2.example.com",
    225    h3Port,
    226    "alt2.example.com",
    227    "h3"
    228  );
    229 });
    230 
    231 // Test the case that the pref is on and both records are failed to connect.
    232 // We can only fallback to "h2" when another pref is on.
    233 add_task(async function test_https_rr_with_matched_cname_1() {
    234  Services.prefs.setBoolPref(
    235    "network.dns.echconfig.fallback_to_origin_when_all_failed",
    236    true
    237  );
    238  await do_test_https_rr_records(
    239    "alt1.example.com",
    240    "not_used",
    241    h3Port,
    242    "alt2.example.com",
    243    h2Port,
    244    "alt2.example.com",
    245    "h2"
    246  );
    247 });