tor-browser

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

test_websocket_fails.js (6854B)


      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 /* import-globals-from head_cache.js */
      8 /* import-globals-from head_cookies.js */
      9 /* import-globals-from head_channels.js */
     10 /* import-globals-from head_websocket.js */
     11 
     12 const {
     13  NodeWebSocketServer,
     14  NodeHTTPSProxyServer,
     15  WebSocketConnection,
     16  NodeProxyFilter,
     17 } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs");
     18 
     19 // We don't normally allow localhost channels to be proxied, but this
     20 // is easier than updating all the certs and/or domains.
     21 Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
     22 registerCleanupFunction(() => {
     23  Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
     24 });
     25 
     26 var CC = Components.Constructor;
     27 const ServerSocket = CC(
     28  "@mozilla.org/network/server-socket;1",
     29  "nsIServerSocket",
     30  "init"
     31 );
     32 
     33 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
     34  Ci.nsIX509CertDB
     35 );
     36 
     37 add_setup(() => {
     38  Services.prefs.setBoolPref("network.http.http2.websockets", true);
     39 });
     40 
     41 registerCleanupFunction(() => {
     42  Services.prefs.clearUserPref("network.http.http2.websockets");
     43 });
     44 
     45 // TLS handshake to the end server fails - no proxy
     46 async function test_tls_fail_on_direct_ws_server_handshake() {
     47  // no cert and no proxy
     48  let wss = new NodeWebSocketServer();
     49  wss._skipCert = true;
     50  await wss.start();
     51  registerCleanupFunction(async () => {
     52    await wss.stop();
     53  });
     54 
     55  Assert.notEqual(wss.port(), null);
     56 
     57  let chan = makeWebSocketChan();
     58  let url = `wss://localhost:${wss.port()}`;
     59  const msg = "test tls handshake with direct ws server fails";
     60  let [status] = await openWebSocketChannelPromise(chan, url, msg);
     61 
     62  // can be two errors, seems to be a race between:
     63  // * overwriting the WebSocketChannel status with NS_ERROR_NET_RESET and
     64  // * getting the original 805A1FF3 // SEC_ERROR_UNKNOWN_ISSUER
     65  if (status == 2152398930) {
     66    Assert.equal(status, 0x804b0052); // NS_ERROR_NET_INADEQUATE_SECURITY
     67  } else {
     68    // occasionally this happens
     69    Assert.equal(status, 0x804b0057); // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
     70  }
     71 }
     72 
     73 // TLS handshake to proxy fails
     74 async function test_tls_fail_on_proxy_handshake() {
     75  // we have ws cert, but no proxy cert
     76  let proxy = new NodeHTTPSProxyServer();
     77  proxy._skipCert = true;
     78  await proxy.start();
     79 
     80  let wss = new NodeWebSocketServer();
     81  await wss.start();
     82 
     83  registerCleanupFunction(async () => {
     84    await wss.stop();
     85    await proxy.stop();
     86  });
     87 
     88  Assert.notEqual(wss.port(), null);
     89 
     90  let chan = makeWebSocketChan();
     91  let url = `wss://localhost:${wss.port()}`;
     92  const msg = "test tls failure on proxy handshake";
     93  let [status] = await openWebSocketChannelPromise(chan, url, msg);
     94 
     95  // see above test for details on why 2 cases here
     96  if (status == 2152398930) {
     97    Assert.equal(status, 0x804b0052); // NS_ERROR_NET_INADEQUATE_SECURITY
     98  } else {
     99    Assert.equal(status, 0x804b0057); // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
    100  }
    101 
    102  await proxy.stop();
    103 }
    104 
    105 // the ws server does not respond (closed port)
    106 async function test_non_responsive_ws_server_closed_port() {
    107  // ws server cert already added in previous test
    108 
    109  // no ws server listening (closed port)
    110  let randomPort = 666; // "random" port
    111  let chan = makeWebSocketChan();
    112  let url = `wss://localhost:${randomPort}`;
    113  const msg = "test non-responsive ws server closed port";
    114  let [status] = await openWebSocketChannelPromise(chan, url, msg);
    115  Assert.equal(status, 0x804b0057); // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
    116 }
    117 
    118 // no ws response from server (ie. no ws server, use tcp server to open port)
    119 async function test_non_responsive_ws_server_open_port() {
    120  // we are expecting the timeout in this test, so lets shorten to 1s
    121  Services.prefs.setIntPref("network.websocket.timeout.open", 1);
    122 
    123  // ws server cert already added in previous test
    124 
    125  // use a tcp server to test open port, not a ws server
    126  var server = ServerSocket(-1, true, -1); // port, loopback, default-backlog
    127  var port = server.port;
    128  info("server: listening on " + server.port);
    129  server.asyncListen({});
    130 
    131  // queue cleanup after all tests
    132  registerCleanupFunction(() => {
    133    server.close();
    134    Services.prefs.clearUserPref("network.websocket.timeout.open");
    135  });
    136 
    137  // try ws connection
    138  let chan = makeWebSocketChan();
    139  let url = `wss://localhost:${port}`;
    140  const msg = "test non-responsive ws server open port";
    141  let [status] = await openWebSocketChannelPromise(chan, url, msg);
    142  Assert.equal(status, Cr.NS_ERROR_NET_TIMEOUT_EXTERNAL); // we will timeout
    143  Services.prefs.clearUserPref("network.websocket.timeout.open");
    144 }
    145 
    146 // proxy does not respond
    147 async function test_proxy_doesnt_respond() {
    148  Services.prefs.setIntPref("network.websocket.timeout.open", 1);
    149  Services.prefs.setBoolPref("network.http.http2.websockets", false);
    150  // ws cert added in previous test, add proxy cert
    151  addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
    152  addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u");
    153 
    154  info("spinning up proxy");
    155  let proxy = new NodeHTTPSProxyServer();
    156  await proxy.start();
    157 
    158  // route traffic through non-existant proxy
    159  const pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
    160  let randomPort = proxy.port() + 1;
    161  var filter = new NodeProxyFilter(
    162    proxy.protocol(),
    163    "localhost",
    164    randomPort,
    165    0
    166  );
    167  pps.registerFilter(filter, 10);
    168 
    169  registerCleanupFunction(async () => {
    170    await proxy.stop();
    171    Services.prefs.clearUserPref("network.websocket.timeout.open");
    172  });
    173 
    174  // setup the websocket server
    175  info("spinning up websocket server");
    176  let wss = new NodeWebSocketServer();
    177  await wss.start();
    178  registerCleanupFunction(() => {
    179    wss.stop();
    180  });
    181  Assert.notEqual(wss.port(), null);
    182  await wss.registerMessageHandler((data, ws) => {
    183    ws.send(data);
    184  });
    185 
    186  info("creating and connecting websocket");
    187  let url = `wss://localhost:${wss.port()}`;
    188  let conn = new WebSocketConnection();
    189  conn.open(url); // do not await, we don't expect a fully opened channel
    190 
    191  // check proxy info
    192  info("checking proxy info");
    193  let proxyInfoPromise = conn.getProxyInfo();
    194  let proxyInfo = await proxyInfoPromise;
    195  Assert.equal(proxyInfo.type, "https"); // let's be sure that failure is not "direct"
    196 
    197  // we fail to connect via proxy, as expected
    198  let { status } = await conn.finished();
    199  info("stats: " + status);
    200  Assert.equal(status, 0x804b0057); // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
    201 }
    202 
    203 add_task(test_tls_fail_on_direct_ws_server_handshake);
    204 add_task(test_tls_fail_on_proxy_handshake);
    205 add_task(test_non_responsive_ws_server_closed_port);
    206 add_task(test_non_responsive_ws_server_open_port);
    207 add_task(test_proxy_doesnt_respond);