tor-browser

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

test_essential_domain_fallback.js (6892B)


      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 const lazy = {};
      6 ChromeUtils.defineESModuleGetters(lazy, {
      7  AddonSettings: "resource://gre/modules/addons/AddonSettings.sys.mjs",
      8  CertUtils: "resource://gre/modules/CertUtils.sys.mjs",
      9  ServiceRequest: "resource://gre/modules/ServiceRequest.sys.mjs",
     10 });
     11 
     12 const { NodeHTTPSServer } = ChromeUtils.importESModule(
     13  "resource://testing-common/NodeServer.sys.mjs"
     14 );
     15 
     16 function waitForNotificationPromise(notification) {
     17  return new Promise(resolve => {
     18    function observer(aSubject, _aTopic, _aData) {
     19      info(aSubject);
     20      Services.obs.removeObserver(observer, notification);
     21      resolve(aSubject);
     22    }
     23    Services.obs.addObserver(observer, notification);
     24  });
     25 }
     26 
     27 function openChannelPromise(url, options = { loadUsingSystemPrincipal: true }) {
     28  let uri = Services.io.newURI(url);
     29  options.uri = uri;
     30  let chan = NetUtil.newChannel(options);
     31  let flags = CL_ALLOW_UNKNOWN_CL;
     32  if (options.expectFailure) {
     33    flags |= CL_EXPECT_FAILURE;
     34  }
     35  return new Promise(resolve => {
     36    chan.asyncOpen(
     37      new ChannelListener((req, buf) => resolve({ req, buf }), null, flags)
     38    );
     39  });
     40 }
     41 
     42 let backupServer;
     43 const override = Cc["@mozilla.org/network/native-dns-override;1"].getService(
     44  Ci.nsINativeDNSResolverOverride
     45 );
     46 
     47 add_setup(async function setup() {
     48  let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
     49    Ci.nsIX509CertDB
     50  );
     51  addCertFromFile(certdb, "../unit/http2-ca.pem", "CTu,u,u");
     52  Services.prefs.setBoolPref("network.essential_domains_fallback", true);
     53 
     54  backupServer = new NodeHTTPSServer();
     55  await backupServer.start();
     56  registerCleanupFunction(async () => {
     57    await backupServer.stop();
     58  });
     59  await backupServer.registerPathHandler("/stuff", (req, res) => {
     60    res.end("Good stuff");
     61  });
     62 
     63  // Just so we can simulate mapping the default HTTPS port and domain.
     64  Services.prefs.setStringPref(
     65    "network.socket.forcePort",
     66    `443=${backupServer.port()}`
     67  );
     68 
     69  Services.io.addEssentialDomainMapping("aus5.mozilla.org", "foo.example.com");
     70 
     71  let ncs = Cc[
     72    "@mozilla.org/network/network-connectivity-service;1"
     73  ].getService(Ci.nsINetworkConnectivityService);
     74  ncs.IPv4 = Ci.nsINetworkConnectivityService.OK;
     75 });
     76 
     77 add_task(async function test_fallback_on_dns_failure() {
     78  Services.fog.testResetFOG();
     79  Services.obs.notifyObservers(null, "net:cancel-all-connections");
     80  Services.dns.clearCache(true);
     81  override.addIPOverride("aus5.mozilla.org", "N/A");
     82  override.addIPOverride("foo.example.com", "127.0.0.1");
     83 
     84  let { buf } = await openChannelPromise("https://aus5.mozilla.org/stuff");
     85  equal(buf, "Good stuff");
     86 
     87  equal(
     88    await Glean.network.systemChannelUpdateStatus.dns.testGetValue(),
     89    1,
     90    "Expecting one failed request due to DNS"
     91  );
     92  equal(
     93    await Glean.network.retriedSystemChannelUpdateStatus.ok.testGetValue(),
     94    1,
     95    "Expecting retried update request to succeed"
     96  );
     97 });
     98 
     99 add_task(async function test_dns_xhr() {
    100  Services.dns.clearCache(true);
    101  override.clearOverrides();
    102  override.addIPOverride("aus5.mozilla.org", "N/A");
    103  override.addIPOverride("foo.example.com", "127.0.0.1");
    104 
    105  let text = await new Promise((resolve, reject) => {
    106    let request = new XMLHttpRequest({ mozAnon: true, mozSystem: true });
    107    request.open("GET", `https://aus5.mozilla.org/stuff`, true);
    108    request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
    109    // Prevent the request from writing to cache.
    110    request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
    111    request.overrideMimeType("text/plain");
    112    request.timeout = 5000;
    113    request.addEventListener("load", () => resolve(request.responseText));
    114    request.addEventListener("error", reject);
    115    request.addEventListener("timeout", reject);
    116    request.send(null);
    117  });
    118  equal(text, "Good stuff");
    119 });
    120 
    121 add_task(async function test_dns_service_request() {
    122  Services.dns.clearCache(true);
    123  override.clearOverrides();
    124  override.addIPOverride("aus5.mozilla.org", "N/A");
    125  override.addIPOverride("foo.example.com", "127.0.0.1");
    126 
    127  let text = await new Promise((resolve, reject) => {
    128    let request = new lazy.ServiceRequest({ mozAnon: true });
    129    request.open("GET", `https://aus5.mozilla.org/stuff`, true);
    130    request.channel.notificationCallbacks = new lazy.CertUtils.BadCertHandler(
    131      !lazy.AddonSettings.UPDATE_REQUIREBUILTINCERTS
    132    );
    133    request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
    134    // Prevent the request from writing to cache.
    135    request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
    136    request.overrideMimeType("text/plain");
    137    request.timeout = 5000;
    138    request.addEventListener("load", () => resolve(request.responseText));
    139    request.addEventListener("error", reject);
    140    request.addEventListener("timeout", reject);
    141    request.send(null);
    142  });
    143  equal(text, "Good stuff");
    144 });
    145 
    146 add_task(async function test_fallback_on_tls_failure() {
    147  Services.obs.notifyObservers(null, "net:cancel-all-connections");
    148  Services.dns.clearCache(true);
    149 
    150  override.clearOverrides();
    151  override.addIPOverride("aus5.mozilla.org", "127.0.0.1");
    152  override.addIPOverride("foo.example.com", "127.0.0.1");
    153  let { buf } = await openChannelPromise("https://aus5.mozilla.org/stuff");
    154  equal(buf, "Good stuff");
    155 });
    156 
    157 add_task(async function test_no_fallback_with_content_principal() {
    158  Services.obs.notifyObservers(null, "net:cancel-all-connections");
    159  Services.dns.clearCache(true);
    160 
    161  let { req } = await openChannelPromise("https://aus5.mozilla.org/stuff", {
    162    loadingPrincipal: Services.scriptSecurityManager.createContentPrincipal(
    163      Services.io.newURI("https://aus5.mozilla.org"),
    164      {}
    165    ),
    166    securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT,
    167    contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
    168    expectFailure: true,
    169  });
    170  // "NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, SSL_ERROR_BAD_CERT_DOMAIN)"
    171  equal(req.status, 0x805a2ff4);
    172 });
    173 
    174 add_task(async function test_fallback_on_connection_failure() {
    175  Services.obs.notifyObservers(null, "net:cancel-all-connections");
    176  Services.dns.clearCache(true);
    177 
    178  Services.prefs.setIntPref("network.http.connection-timeout", 1);
    179  override.clearOverrides();
    180  override.addIPOverride("aus5.mozilla.org", "10.99.99.99"); // Local IP that doesn't exist (hopefully).
    181  override.addIPOverride("foo.example.com", "127.0.0.1");
    182 
    183  await new Promise(resolve => do_timeout(100, resolve));
    184  let chanNotif = waitForNotificationPromise("httpchannel-fallback");
    185  let chanPromise = openChannelPromise("https://aus5.mozilla.org/stuff");
    186  let chan = await chanNotif;
    187  equal(chan.status, Cr.NS_ERROR_NET_TIMEOUT);
    188  let { buf } = await chanPromise;
    189  equal(buf, "Good stuff");
    190 });