tor-browser

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

browser_auth_spoofing_protection.js (8063B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 ChromeUtils.defineESModuleGetters(this, {
      7  UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.sys.mjs",
      8 });
      9 
     10 let TEST_PATH = getRootDirectory(gTestPath).replace(
     11  "chrome://mochitests/content",
     12  "https://example.com"
     13 );
     14 
     15 let TEST_PATH_AUTH = getRootDirectory(gTestPath).replace(
     16  "chrome://mochitests/content",
     17  "https://example.org"
     18 );
     19 
     20 const CROSS_DOMAIN_URL = TEST_PATH + "redirect-crossDomain.html";
     21 
     22 const SAME_DOMAIN_URL = TEST_PATH + "redirect-sameDomain.html";
     23 
     24 const AUTH_URL = TEST_PATH_AUTH + "auth-route.sjs";
     25 
     26 /**
     27 * Opens a new tab with a url that ether redirects us cross or same domain
     28 *
     29 * @param {boolean} doConfirmPrompt - true if we want to test the case when the user accepts the prompt,
     30 *         false if we want to test the case when the user cancels the prompt.
     31 * @param {boolean} crossDomain - if true we will open a url that redirects us to a cross domain url,
     32 *        if false, we will open a url that redirects us to a same domain url
     33 * @param {boolean} prefEnabled true will enable "privacy.authPromptSpoofingProtection",
     34 *        false will disable the pref
     35 */
     36 async function trigger401AndHandle(doConfirmPrompt, crossDomain, prefEnabled) {
     37  await SpecialPowers.pushPrefEnv({
     38    set: [["privacy.authPromptSpoofingProtection", prefEnabled]],
     39  });
     40  let url = crossDomain ? CROSS_DOMAIN_URL : SAME_DOMAIN_URL;
     41  let dialogShown = waitForDialog(doConfirmPrompt, crossDomain, prefEnabled);
     42  await BrowserTestUtils.withNewTab(url, async function () {
     43    await dialogShown;
     44  });
     45  await new Promise(resolve => {
     46    Services.clearData.deleteData(
     47      Ci.nsIClearDataService.CLEAR_AUTH_CACHE,
     48      resolve
     49    );
     50  });
     51 }
     52 
     53 async function waitForDialog(doConfirmPrompt, crossDomain, prefEnabled) {
     54  await TestUtils.topicObserved("common-dialog-loaded");
     55  let dialog = gBrowser.getTabDialogBox(gBrowser.selectedBrowser)
     56    ._tabDialogManager._topDialog;
     57  let dialogDocument = dialog._frame.contentDocument;
     58  if (crossDomain) {
     59    if (prefEnabled) {
     60      Assert.equal(
     61        dialog._overlay.getAttribute("hideContent"),
     62        "true",
     63        "Dialog overlay hides the current sites content"
     64      );
     65      Assert.equal(
     66        window.gURLBar.value,
     67        UrlbarTestUtils.trimURL(AUTH_URL),
     68        "Correct location is provided by the prompt"
     69      );
     70      Assert.equal(
     71        window.gBrowser.selectedTab.label,
     72        "example.org",
     73        "Tab title is manipulated"
     74      );
     75      // switch to another tab and make sure we dont mess up this new tabs url bar and tab title
     76      let tab = await BrowserTestUtils.openNewForegroundTab(
     77        gBrowser,
     78        "https://example.org:443"
     79      );
     80      Assert.equal(
     81        window.gURLBar.value,
     82        UrlbarTestUtils.trimURL("https://example.org"),
     83        "No location is provided by the prompt, correct location is displayed"
     84      );
     85      Assert.equal(
     86        window.gBrowser.selectedTab.label,
     87        "mochitest index /",
     88        "Tab title is not manipulated"
     89      );
     90      // switch back to our tab with the prompt and make sure the url bar state and tab title is still there
     91      BrowserTestUtils.removeTab(tab);
     92      Assert.equal(
     93        window.gURLBar.value,
     94        UrlbarTestUtils.trimURL(AUTH_URL),
     95        "Correct location is provided by the prompt"
     96      );
     97      Assert.equal(
     98        window.gBrowser.selectedTab.label,
     99        "example.org",
    100        "Tab title is manipulated"
    101      );
    102      // make sure a value that the user types in has a higher priority than our prompts location
    103      gBrowser.selectedBrowser.userTypedValue = "user value";
    104      gURLBar.setURI();
    105      Assert.equal(
    106        window.gURLBar.value,
    107        "user value",
    108        "User typed value is shown"
    109      );
    110      // if the user clears the url bar we again fall back to the location of the prompt if we trigger setURI by a tab switch
    111      gBrowser.selectedBrowser.userTypedValue = "";
    112      gURLBar.setURI({ dueToTabSwitch: true });
    113      Assert.equal(
    114        window.gURLBar.value,
    115        UrlbarTestUtils.trimURL(AUTH_URL),
    116        "Correct location is provided by the prompt"
    117      );
    118      // Cross domain and pref is not enabled
    119    } else {
    120      Assert.equal(
    121        dialog._overlay.getAttribute("hideContent"),
    122        null,
    123        "Dialog overlay does not hide the current sites content"
    124      );
    125      Assert.equal(
    126        window.gURLBar.value,
    127        UrlbarTestUtils.trimURL(CROSS_DOMAIN_URL),
    128        "No location is provided by the prompt, correct location is displayed"
    129      );
    130      Assert.equal(
    131        window.gBrowser.selectedTab.label,
    132        "example.com",
    133        "Tab title is not manipulated"
    134      );
    135    }
    136    // same domain
    137  } else {
    138    Assert.equal(
    139      dialog._overlay.getAttribute("hideContent"),
    140      null,
    141      "Dialog overlay does not hide the current sites content"
    142    );
    143    Assert.equal(
    144      window.gURLBar.value,
    145      UrlbarTestUtils.trimURL(SAME_DOMAIN_URL),
    146      "No location is provided by the prompt, correct location is displayed"
    147    );
    148    Assert.equal(
    149      window.gBrowser.selectedTab.label,
    150      "example.com",
    151      "Tab title is not manipulated"
    152    );
    153  }
    154 
    155  let onDialogClosed = BrowserTestUtils.waitForEvent(
    156    window,
    157    "DOMModalDialogClosed"
    158  );
    159  if (doConfirmPrompt) {
    160    dialogDocument.getElementById("loginTextbox").value = "guest";
    161    dialogDocument.getElementById("password1Textbox").value = "guest";
    162    dialogDocument.getElementById("commonDialog").acceptDialog();
    163  } else {
    164    dialogDocument.getElementById("commonDialog").cancelDialog();
    165  }
    166 
    167  // wait for the dialog to be closed to check that the URLBar state is reset
    168  await onDialogClosed;
    169  // Due to bug 1812014, the url bar will be clear if we have set its value to "" while the prompt was open
    170  // so we trigger a tab switch again to have the uri displayed to be able to check its value
    171  gURLBar.setURI({ dueToTabSwitch: true });
    172  Assert.equal(
    173    window.gURLBar.value,
    174    UrlbarTestUtils.trimURL(crossDomain ? CROSS_DOMAIN_URL : SAME_DOMAIN_URL),
    175    "No location is provided by the prompt"
    176  );
    177  Assert.equal(
    178    window.gBrowser.selectedTab.label,
    179    "example.com",
    180    "Tab title is not manipulated"
    181  );
    182 }
    183 
    184 add_setup(async function () {
    185  await SpecialPowers.pushPrefEnv({
    186    set: [["privacy.authPromptSpoofingProtection", true]],
    187  });
    188 });
    189 
    190 /**
    191 * Tests that the 401 auth spoofing mechanisms apply if the 401 is from a different base domain than the current sites,
    192 * canceling the prompt
    193 */
    194 add_task(async function testCrossDomainCancelPrefEnabled() {
    195  await trigger401AndHandle(false, true, true);
    196 });
    197 
    198 /**
    199 * Tests that the 401 auth spoofing mechanisms apply if the 401 is from a different base domain than the current sites,
    200 * accepting the prompt
    201 */
    202 add_task(async function testCrossDomainAcceptPrefEnabled() {
    203  await trigger401AndHandle(true, true, true);
    204 });
    205 
    206 /**
    207 * Tests that the 401 auth spoofing mechanisms do not apply if "privacy.authPromptSpoofingProtection" is not set to true
    208 * canceling the prompt
    209 */
    210 add_task(async function testCrossDomainCancelPrefDisabled() {
    211  await trigger401AndHandle(false, true, false);
    212 });
    213 
    214 /**
    215 * Tests that the 401 auth spoofing mechanisms do not apply if "privacy.authPromptSpoofingProtection" is not set to true,
    216 * accepting the prompt
    217 */
    218 add_task(async function testCrossDomainAcceptPrefDisabled() {
    219  await trigger401AndHandle(true, true, false);
    220 });
    221 
    222 /**
    223 * Tests that the 401 auth spoofing mechanisms are not triggered by a 401 within the same base domain as the current sites,
    224 * canceling the prompt
    225 */
    226 add_task(async function testSameDomainCancelPrefEnabled() {
    227  await trigger401AndHandle(false, false, true);
    228 });
    229 
    230 /**
    231 * Tests that the 401 auth spoofing mechanisms are not triggered by a 401 within the same base domain as the current sites,
    232 * accepting the prompt
    233 */
    234 add_task(async function testSameDomainAcceptPrefEnabled() {
    235  await trigger401AndHandle(true, false, true);
    236 });