tor-browser

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

browser_secure_transport_insecure_scheme.js (6501B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* Any copyright is dedicated to the Public Domain.
      4 * http://creativecommons.org/publicdomain/zero/1.0/ */
      5 
      6 // Test that an insecure resource routed over a secure transport is considered
      7 // insecure in terms of the site identity panel. We achieve this by running an
      8 // HTTP-over-TLS "proxy" and having Firefox request an http:// URI over it.
      9 
     10 const NOT_SECURE_LABEL = Services.prefs.getBoolPref(
     11  "security.insecure_connection_text.enabled"
     12 )
     13  ? "notSecure notSecureText"
     14  : "notSecure";
     15 
     16 /**
     17 * Tests that the page info dialog "security" section labels a
     18 * connection as unencrypted and does not show certificate.
     19 *
     20 * @param {string} uri - URI of the page to test with.
     21 */
     22 async function testPageInfoNotEncrypted(uri) {
     23  let pageInfo = BrowserCommands.pageInfo(uri, "securityTab");
     24  await BrowserTestUtils.waitForEvent(pageInfo, "load");
     25  let pageInfoDoc = pageInfo.document;
     26  let securityTab = pageInfoDoc.getElementById("securityTab");
     27  await TestUtils.waitForCondition(
     28    () => BrowserTestUtils.isVisible(securityTab),
     29    "Security tab should be visible."
     30  );
     31 
     32  let secLabel = pageInfoDoc.getElementById("security-technical-shortform");
     33  await TestUtils.waitForCondition(
     34    () => secLabel.value == "Connection Not Encrypted",
     35    "pageInfo 'Security Details' should show not encrypted"
     36  );
     37 
     38  let viewCertBtn = pageInfoDoc.getElementById("security-view-cert");
     39  ok(
     40    viewCertBtn.collapsed,
     41    "pageInfo 'View Cert' button should not be visible"
     42  );
     43  pageInfo.close();
     44 }
     45 
     46 // But first, a quick test that we don't incorrectly treat a
     47 // blob:https://example.com URI as secure.
     48 add_task(async function () {
     49  let uri =
     50    getRootDirectory(gTestPath).replace(
     51      "chrome://mochitests/content",
     52      "https://example.com"
     53    ) + "dummy_page.html";
     54  await BrowserTestUtils.withNewTab(uri, async browser => {
     55    await SpecialPowers.spawn(browser, [], async () => {
     56      let debug = { hello: "world" };
     57      let blob = new Blob([JSON.stringify(debug, null, 2)], {
     58        type: "application/json",
     59      });
     60      let blobUri = URL.createObjectURL(blob);
     61      content.document.location = blobUri;
     62    });
     63    await BrowserTestUtils.browserLoaded(browser);
     64    let identityMode = window.document.getElementById("identity-box").className;
     65    is(identityMode, "localResource", "identity should be 'localResource'");
     66    await testPageInfoNotEncrypted(uri);
     67  });
     68 });
     69 
     70 // This server pretends to be a HTTP over TLS proxy. It isn't really, but this
     71 // is sufficient for the purposes of this test.
     72 function startServer(cert) {
     73  let tlsServer = Cc["@mozilla.org/network/tls-server-socket;1"].createInstance(
     74    Ci.nsITLSServerSocket
     75  );
     76  tlsServer.init(-1, true, -1);
     77  tlsServer.serverCert = cert;
     78 
     79  let input, output;
     80 
     81  let listener = {
     82    onSocketAccepted(socket, transport) {
     83      let connectionInfo = transport.securityCallbacks.getInterface(
     84        Ci.nsITLSServerConnectionInfo
     85      );
     86      connectionInfo.setSecurityObserver(listener);
     87      input = transport.openInputStream(0, 0, 0);
     88      output = transport.openOutputStream(0, 0, 0);
     89    },
     90 
     91    onHandshakeDone() {
     92      input.asyncWait(
     93        {
     94          onInputStreamReady(readyInput) {
     95            try {
     96              let request = NetUtil.readInputStreamToString(
     97                readyInput,
     98                readyInput.available()
     99              );
    100              ok(
    101                request.startsWith("GET ") && request.includes("HTTP/1.1"),
    102                "expecting an HTTP/1.1 GET request"
    103              );
    104              let response =
    105                "HTTP/1.1 200 OK\r\nContent-Type:text/plain\r\n" +
    106                "Connection:Close\r\nContent-Length:2\r\n\r\nOK";
    107              output.write(response, response.length);
    108            } catch (e) {
    109              info(e);
    110            }
    111          },
    112        },
    113        0,
    114        0,
    115        Services.tm.currentThread
    116      );
    117    },
    118 
    119    onStopListening() {
    120      input.close();
    121      output.close();
    122    },
    123  };
    124 
    125  tlsServer.setSessionTickets(false);
    126  tlsServer.asyncListen(listener);
    127 
    128  return tlsServer;
    129 }
    130 
    131 add_task(async function () {
    132  await SpecialPowers.pushPrefEnv({
    133    // This test fails on some platforms if we leave IPv6 enabled.
    134    set: [["network.dns.disableIPv6", true]],
    135  });
    136 
    137  let certOverrideService = Cc[
    138    "@mozilla.org/security/certoverride;1"
    139  ].getService(Ci.nsICertOverrideService);
    140 
    141  let cert = getTestServerCertificate();
    142  // Start the proxy and configure Firefox to trust its certificate.
    143  let server = startServer(cert);
    144  certOverrideService.rememberValidityOverride(
    145    "localhost",
    146    server.port,
    147    {},
    148    cert,
    149    true
    150  );
    151  // Configure Firefox to use the proxy.
    152  let systemProxySettings = {
    153    QueryInterface: ChromeUtils.generateQI(["nsISystemProxySettings"]),
    154    mainThreadOnly: true,
    155    PACURI: null,
    156    getProxyForURI: () => {
    157      return `HTTPS localhost:${server.port}`;
    158    },
    159  };
    160  let oldProxyType = Services.prefs.getIntPref("network.proxy.type");
    161  Services.prefs.setIntPref(
    162    "network.proxy.type",
    163    Ci.nsIProtocolProxyService.PROXYCONFIG_SYSTEM
    164  );
    165  let { MockRegistrar } = ChromeUtils.importESModule(
    166    "resource://testing-common/MockRegistrar.sys.mjs"
    167  );
    168  let mockProxy = MockRegistrar.register(
    169    "@mozilla.org/system-proxy-settings;1",
    170    systemProxySettings
    171  );
    172  // Register cleanup to undo the configuration changes we've made.
    173  registerCleanupFunction(() => {
    174    certOverrideService.clearValidityOverride("localhost", server.port, {});
    175    Services.prefs.setIntPref("network.proxy.type", oldProxyType);
    176    MockRegistrar.unregister(mockProxy);
    177    server.close();
    178  });
    179 
    180  // Navigate to 'http://example.com'. Our proxy settings will route this via
    181  // the "proxy" we just started. Even though our connection to the proxy is
    182  // secure, in a real situation the connection from the proxy to
    183  // http://example.com won't be secure, so we treat it as not secure.
    184  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    185  await BrowserTestUtils.withNewTab("http://example.com/", async () => {
    186    let identityMode = window.document.getElementById("identity-box").className;
    187    is(
    188      identityMode,
    189      NOT_SECURE_LABEL,
    190      `identity should be '${NOT_SECURE_LABEL}'`
    191    );
    192 
    193    // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    194    await testPageInfoNotEncrypted("http://example.com");
    195  });
    196 });