tor-browser

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

test_http2-proxy-failing.js (5248B)


      1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /* Test stream failure on the session to the proxy:
      8 *  - Test the case the error closes the affected stream only
      9 *  - Test the case the error closes the whole session and cancels existing
     10 *    streams.
     11 */
     12 
     13 /* eslint-env node */
     14 
     15 "use strict";
     16 
     17 const pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
     18 
     19 let filter;
     20 
     21 class ProxyFilter {
     22  constructor(type, host, port, flags) {
     23    this._type = type;
     24    this._host = host;
     25    this._port = port;
     26    this._flags = flags;
     27    this.QueryInterface = ChromeUtils.generateQI(["nsIProtocolProxyFilter"]);
     28  }
     29  applyFilter(uri, pi, cb) {
     30    cb.onProxyFilterResult(
     31      pps.newProxyInfo(
     32        this._type,
     33        this._host,
     34        this._port,
     35        null,
     36        null,
     37        this._flags,
     38        1000,
     39        null
     40      )
     41    );
     42  }
     43 }
     44 
     45 function createPrincipal(url) {
     46  var ssm = Services.scriptSecurityManager;
     47  try {
     48    return ssm.createContentPrincipal(Services.io.newURI(url), {});
     49  } catch (e) {
     50    return null;
     51  }
     52 }
     53 
     54 function make_channel(url) {
     55  return Services.io.newChannelFromURIWithProxyFlags(
     56    Services.io.newURI(url),
     57    null,
     58    16,
     59    null,
     60    createPrincipal(url),
     61    createPrincipal(url),
     62    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT,
     63    Ci.nsIContentPolicy.TYPE_OTHER
     64  );
     65 }
     66 
     67 function get_response(channel, flags = CL_ALLOW_UNKNOWN_CL, delay = 0) {
     68  return new Promise(resolve => {
     69    var listener = new ChannelListener(
     70      (request, data) => {
     71        request.QueryInterface(Ci.nsIHttpChannel);
     72        const status = request.status;
     73        const http_code = status ? undefined : request.responseStatus;
     74        request.QueryInterface(Ci.nsIProxiedChannel);
     75        const proxy_connect_response_code =
     76          request.httpProxyConnectResponseCode;
     77        resolve({ status, http_code, data, proxy_connect_response_code });
     78      },
     79      null,
     80      flags
     81    );
     82    if (delay > 0) {
     83      do_timeout(delay, function () {
     84        channel.asyncOpen(listener);
     85      });
     86    } else {
     87      channel.asyncOpen(listener);
     88    }
     89  });
     90 }
     91 
     92 add_task(async function setup() {
     93  // Set to allow the cert presented by our H2 server
     94  do_get_profile();
     95 
     96  // The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
     97  // so add that cert to the trust list as a signing cert.
     98  let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
     99    Ci.nsIX509CertDB
    100  );
    101  addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
    102 
    103  let proxy_port = Services.env.get("MOZHTTP2_PORT");
    104  Assert.notEqual(proxy_port, null);
    105 
    106  Services.prefs.setBoolPref("network.http.http2.enabled", true);
    107  // make all native resolve calls "secretly" resolve localhost instead
    108  Services.prefs.setBoolPref("network.dns.native-is-localhost", true);
    109 
    110  filter = new ProxyFilter("https", "localhost", proxy_port, 16);
    111  pps.registerFilter(filter, 10);
    112 });
    113 
    114 registerCleanupFunction(async () => {
    115  Services.prefs.clearUserPref("network.http.http2.enabled");
    116  Services.prefs.clearUserPref("network.dns.native-is-localhost");
    117 
    118  pps.unregisterFilter(filter);
    119 });
    120 
    121 add_task(
    122  async function proxy_server_stream_soft_failure_multiple_streams_not_affected() {
    123    let should_succeed = get_response(make_channel(`http://750.example.com`));
    124    const failed = await get_response(
    125      make_channel(`http://illegalhpacksoft.example.com`),
    126      CL_EXPECT_FAILURE,
    127      20
    128    );
    129 
    130    const succeeded = await should_succeed;
    131 
    132    Assert.equal(failed.status, Cr.NS_ERROR_ILLEGAL_VALUE);
    133    Assert.equal(failed.proxy_connect_response_code, 0);
    134    Assert.equal(failed.http_code, undefined);
    135    Assert.equal(succeeded.status, Cr.NS_OK);
    136    Assert.equal(succeeded.proxy_connect_response_code, 200);
    137    Assert.equal(succeeded.http_code, 200);
    138  }
    139 );
    140 
    141 add_task(
    142  async function proxy_server_stream_hard_failure_multiple_streams_affected() {
    143    let should_failed = get_response(
    144      make_channel(`http://750.example.com`),
    145      CL_EXPECT_FAILURE
    146    );
    147    const failed1 = await get_response(
    148      make_channel(`http://illegalhpackhard.example.com`),
    149      CL_EXPECT_FAILURE
    150    );
    151 
    152    const failed2 = await should_failed;
    153 
    154    Assert.equal(failed1.status, 0x804b0053);
    155    Assert.equal(failed1.proxy_connect_response_code, 0);
    156    Assert.equal(failed1.http_code, undefined);
    157    Assert.equal(failed2.status, 0x804b0053);
    158    Assert.equal(failed2.proxy_connect_response_code, 0);
    159    Assert.equal(failed2.http_code, undefined);
    160  }
    161 );
    162 
    163 add_task(async function test_http2_h11required_stream() {
    164  let should_failed = await get_response(
    165    make_channel(`http://h11required.com`),
    166    CL_EXPECT_FAILURE
    167  );
    168 
    169  // See HTTP/1.1 connect handler in moz-http2.js. The handler returns
    170  // "404 Not Found", so the expected error code is NS_ERROR_UNKNOWN_HOST.
    171  Assert.equal(should_failed.status, Cr.NS_ERROR_UNKNOWN_HOST);
    172  Assert.equal(should_failed.proxy_connect_response_code, 404);
    173  Assert.equal(should_failed.http_code, undefined);
    174 });