[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-115.1.0esr-13.0-1] 9 commits: fixup! Add TorStrings module for localization



Title: GitLab

Pier Angelo Vendrame pushed to branch tor-browser-115.1.0esr-13.0-1 at The Tor Project / Applications / Tor Browser

Commits:

  • c3d2496b
    by Pier Angelo Vendrame at 2023-07-27T21:07:52+02:00
    fixup! Add TorStrings module for localization
    
    Move the `getLocale` function here from TorButton util.js and stop
    importing it.
    
  • 642df684
    by Pier Angelo Vendrame at 2023-07-27T21:07:53+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Fix a couple of problems in TorLauncherUtil and TorParsers.
    
    Also, moved the function to parse bridges in TorParsers.
    
  • 9e825b61
    by Pier Angelo Vendrame at 2023-07-27T21:07:53+02:00
    fixup! Bug 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection
    
    Use the bridge line parser from TorParsers.
    
  • 8061f810
    by Pier Angelo Vendrame at 2023-07-27T21:07:53+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Use actual private members for TorProcess.
    
  • f5a3f4af
    by Pier Angelo Vendrame at 2023-07-27T21:07:54+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Group arg pushes in one line (keys and values together).
    
  • 71b08c4e
    by Pier Angelo Vendrame at 2023-07-27T21:07:54+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    TorProcess: use real private properties instead of _, and removed the
    dependency on TorProtocolService (temporarily moved it to
    TorMonitorService, but eventually we should unify TorProtocolService
    and TorMonitorService, to then split them again in a smarter way).
    
  • e1a69b4e
    by Pier Angelo Vendrame at 2023-07-27T21:07:55+02:00
    fixup! Bug 10760: Integrate TorButton to TorBrowser core
    
    Move the SOCKS preference updater to TorProtocolService.
    We will need to refactor all this kind of stuff, but at least let's get
    it in a single place.
    
    Also, since this was the last bit of the startup service, remove the
    file, the component and what else was needed to add them.
    
  • d457b6f8
    by Pier Angelo Vendrame at 2023-07-31T20:42:54+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Hashing the control port password is needed only on the process, so move
    this function to TorProcess.
    
  • c4e8cd0f
    by Pier Angelo Vendrame at 2023-07-31T20:42:57+02:00
    fixup! Bug 10760: Integrate TorButton to TorBrowser core
    
    The hashpassword parameter has been removed.
    

13 changed files:

Changes:

  • browser/components/torpreferences/content/connectionPane.js
    ... ... @@ -14,8 +14,11 @@ const { setTimeout, clearTimeout } = ChromeUtils.import(
    14 14
     const { TorSettings, TorSettingsTopics, TorSettingsData, TorBridgeSource } =
    
    15 15
       ChromeUtils.import("resource:///modules/TorSettings.jsm");
    
    16 16
     
    
    17
    -const { TorProtocolService } = ChromeUtils.import(
    
    18
    -  "resource://gre/modules/TorProtocolService.jsm"
    
    17
    +const { TorParsers } = ChromeUtils.importESModule(
    
    18
    +  "resource://gre/modules/TorParsers.sys.mjs"
    
    19
    +);
    
    20
    +const { TorProtocolService } = ChromeUtils.importESModule(
    
    21
    +  "resource://gre/modules/TorProtocolService.sys.mjs"
    
    19 22
     );
    
    20 23
     const { TorMonitorService, TorMonitorTopics } = ChromeUtils.import(
    
    21 24
       "resource://gre/modules/TorMonitorService.jsm"
    
    ... ... @@ -495,7 +498,7 @@ const gConnectionPane = (function () {
    495 498
             });
    
    496 499
             const idString = TorStrings.settings.bridgeId;
    
    497 500
             const id = card.querySelector(selectors.bridges.cardId);
    
    498
    -        const details = parseBridgeLine(bridgeString);
    
    501
    +        const details = TorParsers.parseBridgeLine(bridgeString);
    
    499 502
             if (details && details.id !== undefined) {
    
    500 503
               card.setAttribute("data-bridge-id", details.id);
    
    501 504
             }
    
    ... ... @@ -1111,23 +1114,3 @@ function makeBridgeId(bridgeString) {
    1111 1114
         hash & 0x000000ff,
    
    1112 1115
       ];
    
    1113 1116
     }
    1114
    -
    
    1115
    -function parseBridgeLine(line) {
    
    1116
    -  const re =
    
    1117
    -    /^\s*(\S+\s+)?([0-9a-fA-F\.\[\]\:]+:\d{1,5})(\s+[0-9a-fA-F]{40})?(\s+.+)?/;
    
    1118
    -  const matches = line.match(re);
    
    1119
    -  if (!matches) {
    
    1120
    -    return null;
    
    1121
    -  }
    
    1122
    -  let bridge = { addr: matches[2] };
    
    1123
    -  if (matches[1] !== undefined) {
    
    1124
    -    bridge.transport = matches[1].trim();
    
    1125
    -  }
    
    1126
    -  if (matches[3] !== undefined) {
    
    1127
    -    bridge.id = matches[3].trim().toUpperCase();
    
    1128
    -  }
    
    1129
    -  if (matches[4] !== undefined) {
    
    1130
    -    bridge.args = matches[4].trim();
    
    1131
    -  }
    
    1132
    -  return bridge;
    
    1133
    -}

  • browser/installer/package-manifest.in
    ... ... @@ -228,7 +228,6 @@
    228 228
     @RESPATH@/components/tor-launcher.manifest
    
    229 229
     @RESPATH@/chrome/torbutton.manifest
    
    230 230
     @RESPATH@/chrome/torbutton/*
    
    231
    -@RESPATH@/components/torbutton.manifest
    
    232 231
     @RESPATH@/chrome/toolkit@JAREXT@
    
    233 232
     @RESPATH@/chrome/toolkit.manifest
    
    234 233
     #ifdef MOZ_GTK
    

  • browser/modules/TorStrings.jsm
    ... ... @@ -11,9 +11,11 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
    11 11
     const { AppConstants } = ChromeUtils.import(
    
    12 12
       "resource://gre/modules/AppConstants.jsm"
    
    13 13
     );
    
    14
    -const { getLocale } = ChromeUtils.import(
    
    15
    -  "resource://torbutton/modules/utils.js"
    
    16
    -);
    
    14
    +
    
    15
    +function getLocale() {
    
    16
    +  const locale = Services.locale.appLocaleAsBCP47;
    
    17
    +  return locale === "ja-JP-macos" ? "ja" : locale;
    
    18
    +}
    
    17 19
     
    
    18 20
     /*
    
    19 21
       Tor Property String Bundle
    

  • toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs
    ... ... @@ -5,6 +5,12 @@
    5 5
      * Tor Launcher Util JS Module
    
    6 6
      *************************************************************************/
    
    7 7
     
    
    8
    +const lazy = {};
    
    9
    +
    
    10
    +ChromeUtils.defineESModuleGetters(lazy, {
    
    11
    +  FileUtils: "resource://gre/modules/FileUtils.sys.jsm",
    
    12
    +});
    
    13
    +
    
    8 14
     const kPropBundleURI = "chrome://torbutton/locale/torlauncher.properties";
    
    9 15
     const kPropNamePrefix = "torlauncher.";
    
    10 16
     const kIPCDirPrefName = "extensions.torlauncher.tmp_ipc_dir";
    
    ... ... @@ -209,14 +215,15 @@ class TorFile {
    209 215
       // and return a file object. The control and SOCKS IPC objects will be
    
    210 216
       // created by tor.
    
    211 217
       normalize() {
    
    212
    -    if (!this.file.exists() && !this.isIPC) {
    
    218
    +    if (this.file.exists()) {
    
    219
    +      try {
    
    220
    +        this.file.normalize();
    
    221
    +      } catch (e) {
    
    222
    +        console.warn("Normalization of the path failed", e);
    
    223
    +      }
    
    224
    +    } else if (!this.isIPC) {
    
    213 225
           throw new Error(`${this.fileType} file not found: ${this.file.path}`);
    
    214 226
         }
    
    215
    -    try {
    
    216
    -      this.file.normalize();
    
    217
    -    } catch (e) {
    
    218
    -      console.warn("Normalization of the path failed", e);
    
    219
    -    }
    
    220 227
     
    
    221 228
         // Ensure that the IPC path length is short enough for use by the
    
    222 229
         // operating system. If not, create and use a unique directory under
    
    ... ... @@ -452,6 +459,154 @@ export const TorLauncherUtil = Object.freeze({
    452 459
         return result ? result : "";
    
    453 460
       },
    
    454 461
     
    
    462
    +  /**
    
    463
    +   * Determine what kind of SOCKS port has been requested for this session or
    
    464
    +   * the browser has been configured for.
    
    465
    +   * On Windows (where Unix domain sockets are not supported), TCP is always
    
    466
    +   * used.
    
    467
    +   *
    
    468
    +   * The following environment variables are supported and take precedence over
    
    469
    +   * preferences:
    
    470
    +   *    TOR_TRANSPROXY (do not use a proxy)
    
    471
    +   *    TOR_SOCKS_IPC_PATH (file system path; ignored on Windows)
    
    472
    +   *    TOR_SOCKS_HOST
    
    473
    +   *    TOR_SOCKS_PORT
    
    474
    +   *
    
    475
    +   * The following preferences are consulted:
    
    476
    +   *    network.proxy.socks
    
    477
    +   *    network.proxy.socks_port
    
    478
    +   *    extensions.torlauncher.socks_port_use_ipc (Boolean)
    
    479
    +   *    extensions.torlauncher.socks_ipc_path (file system path)
    
    480
    +   * If extensions.torlauncher.socks_ipc_path is empty, a default path is used.
    
    481
    +   *
    
    482
    +   * When using TCP, if a value is not defined via an env variable it is
    
    483
    +   * taken from the corresponding browser preference if possible. The
    
    484
    +   * exceptions are:
    
    485
    +   *   If network.proxy.socks contains a file: URL, a default value of
    
    486
    +   *     "127.0.0.1" is used instead.
    
    487
    +   *   If the network.proxy.socks_port value is not valid (outside the
    
    488
    +   *     (0; 65535] range), a default value of 9150 is used instead.
    
    489
    +   *
    
    490
    +   * The SOCKS configuration will not influence the launch of a tor daemon and
    
    491
    +   * the configuration of the control port in any way.
    
    492
    +   * When a SOCKS configuration is required without TOR_SKIP_LAUNCH, the browser
    
    493
    +   * will try to configure the tor instance to use the required configuration.
    
    494
    +   * This also applies to TOR_TRANSPROXY (at least for now): tor will be
    
    495
    +   * launched with its defaults.
    
    496
    +   *
    
    497
    +   * TODO: add a preference to ignore the current configuration, and let tor
    
    498
    +   * listen on any free port. Then, the browser will prompt the daemon the port
    
    499
    +   * to use through the control port (even though this is quite dangerous at the
    
    500
    +   * moment, because with network disabled tor will disable also the SOCKS
    
    501
    +   * listeners, so it means that we will have to check it every time we change
    
    502
    +   * the network status).
    
    503
    +   */
    
    504
    +  getPreferredSocksConfiguration() {
    
    505
    +    if (Services.env.exists("TOR_TRANSPROXY")) {
    
    506
    +      Services.prefs.setBoolPref("network.proxy.socks_remote_dns", false);
    
    507
    +      Services.prefs.setIntPref("network.proxy.type", 0);
    
    508
    +      Services.prefs.setIntPref("network.proxy.socks_port", 0);
    
    509
    +      Services.prefs.setCharPref("network.proxy.socks", "");
    
    510
    +      return { transproxy: true };
    
    511
    +    }
    
    512
    +
    
    513
    +    let useIPC;
    
    514
    +    const socksPortInfo = {
    
    515
    +      transproxy: false,
    
    516
    +    };
    
    517
    +
    
    518
    +    if (!this.isWindows && Services.env.exists("TOR_SOCKS_IPC_PATH")) {
    
    519
    +      useIPC = true;
    
    520
    +      const ipcPath = Services.env.get("TOR_SOCKS_IPC_PATH");
    
    521
    +      if (ipcPath) {
    
    522
    +        socksPortInfo.ipcFile = new lazy.FileUtils.File(ipcPath);
    
    523
    +      }
    
    524
    +    } else {
    
    525
    +      // Check for TCP host and port environment variables.
    
    526
    +      if (Services.env.exists("TOR_SOCKS_HOST")) {
    
    527
    +        socksPortInfo.host = Services.env.get("TOR_SOCKS_HOST");
    
    528
    +        useIPC = false;
    
    529
    +      }
    
    530
    +      if (Services.env.exists("TOR_SOCKS_PORT")) {
    
    531
    +        const port = parseInt(Services.env.get("TOR_SOCKS_PORT"), 10);
    
    532
    +        if (Number.isInteger(port) && port > 0 && port <= 65535) {
    
    533
    +          socksPortInfo.port = port;
    
    534
    +          useIPC = false;
    
    535
    +        }
    
    536
    +      }
    
    537
    +    }
    
    538
    +
    
    539
    +    if (useIPC === undefined) {
    
    540
    +      socksPortInfo.useIPC =
    
    541
    +        !this.isWindows &&
    
    542
    +        Services.prefs.getBoolPref(
    
    543
    +          "extensions.torlauncher.socks_port_use_ipc",
    
    544
    +          false
    
    545
    +        );
    
    546
    +    }
    
    547
    +
    
    548
    +    // Fill in missing SOCKS info from prefs.
    
    549
    +    if (socksPortInfo.useIPC) {
    
    550
    +      if (!socksPortInfo.ipcFile) {
    
    551
    +        socksPortInfo.ipcFile = TorLauncherUtil.getTorFile("socks_ipc", false);
    
    552
    +      }
    
    553
    +    } else {
    
    554
    +      if (!socksPortInfo.host) {
    
    555
    +        let socksAddr = Services.prefs.getCharPref(
    
    556
    +          "network.proxy.socks",
    
    557
    +          "127.0.0.1"
    
    558
    +        );
    
    559
    +        let socksAddrHasHost = socksAddr && !socksAddr.startsWith("file:");
    
    560
    +        socksPortInfo.host = socksAddrHasHost ? socksAddr : "127.0.0.1";
    
    561
    +      }
    
    562
    +
    
    563
    +      if (!socksPortInfo.port) {
    
    564
    +        let socksPort = Services.prefs.getIntPref(
    
    565
    +          "network.proxy.socks_port",
    
    566
    +          0
    
    567
    +        );
    
    568
    +        // This pref is set as 0 by default in Firefox, use 9150 if we get 0.
    
    569
    +        socksPortInfo.port =
    
    570
    +          socksPort > 0 && socksPort <= 65535 ? socksPort : 9150;
    
    571
    +      }
    
    572
    +    }
    
    573
    +
    
    574
    +    return socksPortInfo;
    
    575
    +  },
    
    576
    +
    
    577
    +  setProxyConfiguration(socksPortInfo) {
    
    578
    +    if (socksPortInfo.transproxy) {
    
    579
    +      return;
    
    580
    +    }
    
    581
    +
    
    582
    +    if (socksPortInfo.useIPC) {
    
    583
    +      const fph = Services.io
    
    584
    +        .getProtocolHandler("file")
    
    585
    +        .QueryInterface(Ci.nsIFileProtocolHandler);
    
    586
    +      const fileURI = fph.newFileURI(socksPortInfo.ipcFile);
    
    587
    +      Services.prefs.setCharPref("network.proxy.socks", fileURI.spec);
    
    588
    +      Services.prefs.setIntPref("network.proxy.socks_port", 0);
    
    589
    +    } else {
    
    590
    +      if (socksPortInfo.host) {
    
    591
    +        Services.prefs.setCharPref("network.proxy.socks", socksPortInfo.host);
    
    592
    +      }
    
    593
    +      if (socksPortInfo.port) {
    
    594
    +        Services.prefs.setIntPref(
    
    595
    +          "network.proxy.socks_port",
    
    596
    +          socksPortInfo.port
    
    597
    +        );
    
    598
    +      }
    
    599
    +    }
    
    600
    +
    
    601
    +    if (socksPortInfo.ipcFile || socksPortInfo.host || socksPortInfo.port) {
    
    602
    +      Services.prefs.setBoolPref("network.proxy.socks_remote_dns", true);
    
    603
    +      Services.prefs.setIntPref("network.proxy.type", 1);
    
    604
    +    }
    
    605
    +
    
    606
    +    // Force prefs to be synced to disk
    
    607
    +    Services.prefs.savePrefFile(null);
    
    608
    +  },
    
    609
    +
    
    455 610
       get shouldStartAndOwnTor() {
    
    456 611
         const kPrefStartTor = "extensions.torlauncher.start_tor";
    
    457 612
         try {
    

  • toolkit/components/tor-launcher/TorMonitorService.sys.mjs
    ... ... @@ -13,6 +13,10 @@ import { TorLauncherUtil } from "resource://gre/modules/TorLauncherUtil.sys.mjs"
    13 13
     
    
    14 14
     const lazy = {};
    
    15 15
     
    
    16
    +ChromeUtils.defineESModuleGetters(lazy, {
    
    17
    +  TorProtocolService: "resource://gre/modules/TorProtocolService.sys.mjs",
    
    18
    +});
    
    19
    +
    
    16 20
     ChromeUtils.defineModuleGetter(
    
    17 21
       lazy,
    
    18 22
       "controller",
    
    ... ... @@ -233,7 +237,10 @@ export const TorMonitorService = {
    233 237
         // TorProcess should be instanced once, then always reused and restarted
    
    234 238
         // only through the prompt it exposes when the controlled process dies.
    
    235 239
         if (!this._torProcess) {
    
    236
    -      this._torProcess = new TorProcess();
    
    240
    +      this._torProcess = new TorProcess(
    
    241
    +        lazy.TorProtocolService.torControlPortInfo,
    
    242
    +        lazy.TorProtocolService.torSOCKSPortInfo
    
    243
    +      );
    
    237 244
           this._torProcess.onExit = () => {
    
    238 245
             this._shutDownEventMonitor();
    
    239 246
             Services.obs.notifyObservers(null, TorTopics.ProcessExited);
    
    ... ... @@ -254,6 +261,7 @@ export const TorMonitorService = {
    254 261
           await this._torProcess.start();
    
    255 262
           if (this._torProcess.isRunning) {
    
    256 263
             logger.info("tor started");
    
    264
    +        this._torProcessStartTime = Date.now();
    
    257 265
           }
    
    258 266
         } catch (e) {
    
    259 267
           // TorProcess already logs the error.
    

  • toolkit/components/tor-launcher/TorParsers.sys.mjs
    ... ... @@ -267,4 +267,18 @@ export const TorParsers = Object.freeze({
    267 267
         rv += aStr.substring(lastAdded, aStr.length - 1);
    
    268 268
         return rv;
    
    269 269
       },
    
    270
    +
    
    271
    +  parseBridgeLine(line) {
    
    272
    +    const re =
    
    273
    +      /\s*(?:(?<transport>\S+)\s+)?(?<addr>[0-9a-fA-F\.\[\]\:]+:\d{1,5})(?:\s+(?<id>[0-9a-fA-F]{40}))?(?:\s+(?<args>.+))?/;
    
    274
    +    const match = re.exec(line);
    
    275
    +    if (!match) {
    
    276
    +      throw new Error("Invalid bridge line.");
    
    277
    +    }
    
    278
    +    const bridge = match.groups;
    
    279
    +    if (!bridge.transport) {
    
    280
    +      bridge.transport = "vanilla";
    
    281
    +    }
    
    282
    +    return bridge;
    
    283
    +  },
    
    270 284
     });

  • toolkit/components/tor-launcher/TorProcess.sys.mjs
    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
    +
    
    1 5
     import { setTimeout } from "resource://gre/modules/Timer.sys.mjs";
    
    2 6
     import { ConsoleAPI } from "resource://gre/modules/Console.sys.mjs";
    
    3 7
     import { Subprocess } from "resource://gre/modules/Subprocess.sys.mjs";
    
    4 8
     
    
    5 9
     const lazy = {};
    
    6 10
     
    
    7
    -ChromeUtils.defineModuleGetter(
    
    8
    -  lazy,
    
    9
    -  "TorProtocolService",
    
    10
    -  "resource://gre/modules/TorProtocolService.jsm"
    
    11
    -);
    
    12
    -const { TorLauncherUtil } = ChromeUtils.import(
    
    13
    -  "resource://gre/modules/TorLauncherUtil.jsm"
    
    14
    -);
    
    15
    -
    
    16
    -const { TorParsers } = ChromeUtils.import(
    
    17
    -  "resource://gre/modules/TorParsers.jsm"
    
    18
    -);
    
    11
    +ChromeUtils.defineESModuleGetters(lazy, {
    
    12
    +  TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs",
    
    13
    +  TorParsers: "resource://gre/modules/TorParsers.sys.mjs",
    
    14
    +});
    
    19 15
     
    
    20 16
     const TorProcessStatus = Object.freeze({
    
    21 17
       Unknown: 0,
    
    ... ... @@ -30,53 +26,86 @@ const logger = new ConsoleAPI({
    30 26
     });
    
    31 27
     
    
    32 28
     export class TorProcess {
    
    33
    -  _exeFile = null;
    
    34
    -  _dataDir = null;
    
    35
    -  _args = [];
    
    36
    -  _subprocess = null;
    
    37
    -  _status = TorProcessStatus.Unknown;
    
    38
    -  _torProcessStartTime = null; // JS Date.now()
    
    39
    -  _didConnectToTorControlPort = false; // Have we ever made a connection?
    
    29
    +  #controlSettings;
    
    30
    +  #socksSettings;
    
    31
    +  #exeFile = null;
    
    32
    +  #dataDir = null;
    
    33
    +  #args = [];
    
    34
    +  #subprocess = null;
    
    35
    +  #status = TorProcessStatus.Unknown;
    
    36
    +  // Have we ever made a connection on the control port?
    
    37
    +  #didConnectToTorControlPort = false;
    
    38
    +
    
    39
    +  onExit = exitCode => {};
    
    40
    +  onRestart = () => {};
    
    41
    +
    
    42
    +  constructor(controlSettings, socksSettings) {
    
    43
    +    if (
    
    44
    +      controlSettings &&
    
    45
    +      !controlSettings.password &&
    
    46
    +      !controlSettings.cookieFilePath
    
    47
    +    ) {
    
    48
    +      throw new Error("Unauthenticated control port is not supported");
    
    49
    +    }
    
    40 50
     
    
    41
    -  onExit = null;
    
    42
    -  onRestart = null;
    
    51
    +    const checkPort = port =>
    
    52
    +      port === undefined ||
    
    53
    +      (Number.isInteger(controlSettings.port) &&
    
    54
    +        controlSettings.port > 0 &&
    
    55
    +        controlSettings.port < 65535);
    
    56
    +    if (!checkPort(controlSettings?.port)) {
    
    57
    +      throw new Error("Invalid control port");
    
    58
    +    }
    
    59
    +    if (!checkPort(socksSettings.port)) {
    
    60
    +      throw new Error("Invalid port specified for the SOCKS port");
    
    61
    +    }
    
    62
    +
    
    63
    +    this.#controlSettings = { ...controlSettings };
    
    64
    +    const ipcFileToString = file =>
    
    65
    +      "unix:" + lazy.TorParsers.escapeString(file.path);
    
    66
    +    if (controlSettings.ipcFile) {
    
    67
    +      this.#controlSettings.ipcFile = ipcFileToString(controlSettings.ipcFile);
    
    68
    +    }
    
    69
    +    this.#socksSettings = { ...socksSettings };
    
    70
    +    if (socksSettings.ipcFile) {
    
    71
    +      this.#socksSettings.ipcFile = ipcFileToString(socksSettings.ipcFile);
    
    72
    +    }
    
    73
    +  }
    
    43 74
     
    
    44 75
       get status() {
    
    45
    -    return this._status;
    
    76
    +    return this.#status;
    
    46 77
       }
    
    47 78
     
    
    48 79
       get isRunning() {
    
    49 80
         return (
    
    50
    -      this._status === TorProcessStatus.Starting ||
    
    51
    -      this._status === TorProcessStatus.Running
    
    81
    +      this.#status === TorProcessStatus.Starting ||
    
    82
    +      this.#status === TorProcessStatus.Running
    
    52 83
         );
    
    53 84
       }
    
    54 85
     
    
    55 86
       async start() {
    
    56
    -    if (this._subprocess) {
    
    87
    +    if (this.#subprocess) {
    
    57 88
           return;
    
    58 89
         }
    
    59 90
     
    
    60
    -    this._status = TorProcessStatus.Unknown;
    
    91
    +    this.#status = TorProcessStatus.Unknown;
    
    61 92
     
    
    62 93
         try {
    
    63
    -      this._makeArgs();
    
    64
    -      this._addControlPortArg();
    
    65
    -      this._addSocksPortArg();
    
    94
    +      this.#makeArgs();
    
    95
    +      this.#addControlPortArgs();
    
    96
    +      this.#addSocksPortArg();
    
    66 97
     
    
    67 98
           const pid = Services.appinfo.processID;
    
    68 99
           if (pid !== 0) {
    
    69
    -        this._args.push("__OwningControllerProcess");
    
    70
    -        this._args.push("" + pid);
    
    100
    +        this.#args.push("__OwningControllerProcess", pid.toString());
    
    71 101
           }
    
    72 102
     
    
    73
    -      if (TorLauncherUtil.shouldShowNetworkSettings) {
    
    74
    -        this._args.push("DisableNetwork");
    
    75
    -        this._args.push("1");
    
    103
    +      if (lazy.TorLauncherUtil.shouldShowNetworkSettings) {
    
    104
    +        this.#args.push("DisableNetwork", "1");
    
    76 105
           }
    
    77 106
     
    
    78
    -      this._status = TorProcessStatus.Starting;
    
    79
    -      this._didConnectToTorControlPort = false;
    
    107
    +      this.#status = TorProcessStatus.Starting;
    
    108
    +      this.#didConnectToTorControlPort = false;
    
    80 109
     
    
    81 110
           // useful for simulating slow tor daemon launch
    
    82 111
           const kPrefTorDaemonLaunchDelay = "extensions.torlauncher.launch_delay";
    
    ... ... @@ -88,29 +117,31 @@ export class TorProcess {
    88 117
             await new Promise(resolve => setTimeout(() => resolve(), launchDelay));
    
    89 118
           }
    
    90 119
     
    
    91
    -      logger.debug(`Starting ${this._exeFile.path}`, this._args);
    
    120
    +      logger.debug(`Starting ${this.#exeFile.path}`, this.#args);
    
    92 121
           const options = {
    
    93
    -        command: this._exeFile.path,
    
    94
    -        arguments: this._args,
    
    122
    +        command: this.#exeFile.path,
    
    123
    +        arguments: this.#args,
    
    95 124
             stderr: "stdout",
    
    96
    -        workdir: TorLauncherUtil.getTorFile("pt-startup-dir", false).path,
    
    125
    +        workdir: lazy.TorLauncherUtil.getTorFile("pt-startup-dir", false).path,
    
    97 126
           };
    
    98
    -      this._subprocess = await Subprocess.call(options);
    
    99
    -      this._dumpStdout();
    
    100
    -      this._watchProcess();
    
    101
    -      this._status = TorProcessStatus.Running;
    
    102
    -      this._torProcessStartTime = Date.now();
    
    127
    +      this.#subprocess = await Subprocess.call(options);
    
    128
    +      this.#status = TorProcessStatus.Running;
    
    103 129
         } catch (e) {
    
    104
    -      this._status = TorProcessStatus.Exited;
    
    105
    -      this._subprocess = null;
    
    130
    +      this.#status = TorProcessStatus.Exited;
    
    131
    +      this.#subprocess = null;
    
    106 132
           logger.error("startTor error:", e);
    
    107 133
           throw e;
    
    108 134
         }
    
    135
    +
    
    136
    +    // Do not await the following functions, as they will return only when the
    
    137
    +    // process exits.
    
    138
    +    this.#dumpStdout();
    
    139
    +    this.#watchProcess();
    
    109 140
       }
    
    110 141
     
    
    111 142
       // Forget about a process.
    
    112 143
       //
    
    113
    -  // Instead of killing the tor process, we  rely on the TAKEOWNERSHIP feature
    
    144
    +  // Instead of killing the tor process, we rely on the TAKEOWNERSHIP feature
    
    114 145
       // to shut down tor when we close the control port connection.
    
    115 146
       //
    
    116 147
       // Previously, we sent a SIGNAL HALT command to the tor control port,
    
    ... ... @@ -123,36 +154,38 @@ export class TorProcess {
    123 154
       // Still, before closing the owning connection, this class should forget about
    
    124 155
       // the process, so that future notifications will be ignored.
    
    125 156
       forget() {
    
    126
    -    this._subprocess = null;
    
    127
    -    this._status = TorProcessStatus.Exited;
    
    157
    +    this.#subprocess = null;
    
    158
    +    this.#status = TorProcessStatus.Exited;
    
    128 159
       }
    
    129 160
     
    
    130 161
       // The owner of the process can use this function to tell us that they
    
    131 162
       // successfully connected to the control port. This information will be used
    
    132 163
       // only to decide which text to show in the confirmation dialog if tor exits.
    
    133 164
       connectionWorked() {
    
    134
    -    this._didConnectToTorControlPort = true;
    
    165
    +    this.#didConnectToTorControlPort = true;
    
    135 166
       }
    
    136 167
     
    
    137
    -  async _dumpStdout() {
    
    168
    +  async #dumpStdout() {
    
    138 169
         let string;
    
    139 170
         while (
    
    140
    -      this._subprocess &&
    
    141
    -      (string = await this._subprocess.stdout.readString())
    
    171
    +      this.#subprocess &&
    
    172
    +      (string = await this.#subprocess.stdout.readString())
    
    142 173
         ) {
    
    143 174
           dump(string);
    
    144 175
         }
    
    145 176
       }
    
    146 177
     
    
    147
    -  async _watchProcess() {
    
    148
    -    const watched = this._subprocess;
    
    178
    +  async #watchProcess() {
    
    179
    +    const watched = this.#subprocess;
    
    149 180
         if (!watched) {
    
    150 181
           return;
    
    151 182
         }
    
    183
    +    let processExitCode;
    
    152 184
         try {
    
    153 185
           const { exitCode } = await watched.wait();
    
    186
    +      processExitCode = exitCode;
    
    154 187
     
    
    155
    -      if (watched !== this._subprocess) {
    
    188
    +      if (watched !== this.#subprocess) {
    
    156 189
             logger.debug(`A Tor process exited with code ${exitCode}.`);
    
    157 190
           } else if (exitCode) {
    
    158 191
             logger.warn(`The watched Tor process exited with code ${exitCode}.`);
    
    ... ... @@ -163,30 +196,31 @@ export class TorProcess {
    163 196
           logger.error("Failed to watch the tor process", e);
    
    164 197
         }
    
    165 198
     
    
    166
    -    if (watched === this._subprocess) {
    
    167
    -      this._processExitedUnexpectedly();
    
    199
    +    if (watched === this.#subprocess) {
    
    200
    +      this.#processExitedUnexpectedly(processExitCode);
    
    168 201
         }
    
    169 202
       }
    
    170 203
     
    
    171
    -  _processExitedUnexpectedly() {
    
    172
    -    this._subprocess = null;
    
    173
    -    this._status = TorProcessStatus.Exited;
    
    204
    +  #processExitedUnexpectedly(exitCode) {
    
    205
    +    this.#subprocess = null;
    
    206
    +    this.#status = TorProcessStatus.Exited;
    
    174 207
     
    
    175 208
         // TODO: Move this logic somewhere else?
    
    176 209
         let s;
    
    177
    -    if (!this._didConnectToTorControlPort) {
    
    210
    +    if (!this.#didConnectToTorControlPort) {
    
    178 211
           // tor might be misconfigured, becauser we could never connect to it
    
    179 212
           const key = "tor_exited_during_startup";
    
    180
    -      s = TorLauncherUtil.getLocalizedString(key);
    
    213
    +      s = lazy.TorLauncherUtil.getLocalizedString(key);
    
    181 214
         } else {
    
    182 215
           // tor exited suddenly, so configuration should be okay
    
    183 216
           s =
    
    184
    -        TorLauncherUtil.getLocalizedString("tor_exited") +
    
    217
    +        lazy.TorLauncherUtil.getLocalizedString("tor_exited") +
    
    185 218
             "\n\n" +
    
    186
    -        TorLauncherUtil.getLocalizedString("tor_exited2");
    
    219
    +        lazy.TorLauncherUtil.getLocalizedString("tor_exited2");
    
    187 220
         }
    
    188 221
         logger.info(s);
    
    189
    -    const defaultBtnLabel = TorLauncherUtil.getLocalizedString("restart_tor");
    
    222
    +    const defaultBtnLabel =
    
    223
    +      lazy.TorLauncherUtil.getLocalizedString("restart_tor");
    
    190 224
         let cancelBtnLabel = "OK";
    
    191 225
         try {
    
    192 226
           const kSysBundleURI = "chrome://global/locale/commonDialogs.properties";
    
    ... ... @@ -196,51 +230,43 @@ export class TorProcess {
    196 230
           logger.warn("Could not localize the cancel button", e);
    
    197 231
         }
    
    198 232
     
    
    199
    -    const restart = TorLauncherUtil.showConfirm(
    
    233
    +    const restart = lazy.TorLauncherUtil.showConfirm(
    
    200 234
           null,
    
    201 235
           s,
    
    202 236
           defaultBtnLabel,
    
    203 237
           cancelBtnLabel
    
    204 238
         );
    
    205 239
         if (restart) {
    
    206
    -      this.start().then(() => {
    
    207
    -        if (this.onRestart) {
    
    208
    -          this.onRestart();
    
    209
    -        }
    
    210
    -      });
    
    211
    -    } else if (this.onExit) {
    
    212
    -      this.onExit();
    
    240
    +      this.start().then(this.onRestart);
    
    241
    +    } else {
    
    242
    +      this.onExit(exitCode);
    
    213 243
         }
    
    214 244
       }
    
    215 245
     
    
    216
    -  _makeArgs() {
    
    217
    -    // Ideally, we would cd to the Firefox application directory before
    
    218
    -    // starting tor (but we don't know how to do that). Instead, we
    
    219
    -    // rely on the TBB launcher to start Firefox from the right place.
    
    220
    -
    
    246
    +  #makeArgs() {
    
    247
    +    this.#exeFile = lazy.TorLauncherUtil.getTorFile("tor", false);
    
    248
    +    const torrcFile = lazy.TorLauncherUtil.getTorFile("torrc", true);
    
    221 249
         // Get the Tor data directory first so it is created before we try to
    
    222 250
         // construct paths to files that will be inside it.
    
    223
    -    this._exeFile = TorLauncherUtil.getTorFile("tor", false);
    
    224
    -    const torrcFile = TorLauncherUtil.getTorFile("torrc", true);
    
    225
    -    this._dataDir = TorLauncherUtil.getTorFile("tordatadir", true);
    
    226
    -    const onionAuthDir = TorLauncherUtil.getTorFile("toronionauthdir", true);
    
    227
    -    const hashedPassword = lazy.TorProtocolService.torGetPassword(true);
    
    251
    +    this.#dataDir = lazy.TorLauncherUtil.getTorFile("tordatadir", true);
    
    252
    +    const onionAuthDir = lazy.TorLauncherUtil.getTorFile(
    
    253
    +      "toronionauthdir",
    
    254
    +      true
    
    255
    +    );
    
    228 256
         let detailsKey;
    
    229
    -    if (!this._exeFile) {
    
    257
    +    if (!this.#exeFile) {
    
    230 258
           detailsKey = "tor_missing";
    
    231 259
         } else if (!torrcFile) {
    
    232 260
           detailsKey = "torrc_missing";
    
    233
    -    } else if (!this._dataDir) {
    
    261
    +    } else if (!this.#dataDir) {
    
    234 262
           detailsKey = "datadir_missing";
    
    235 263
         } else if (!onionAuthDir) {
    
    236 264
           detailsKey = "onionauthdir_missing";
    
    237
    -    } else if (!hashedPassword) {
    
    238
    -      detailsKey = "password_hash_missing";
    
    239 265
         }
    
    240 266
         if (detailsKey) {
    
    241
    -      const details = TorLauncherUtil.getLocalizedString(detailsKey);
    
    267
    +      const details = lazy.TorLauncherUtil.getLocalizedString(detailsKey);
    
    242 268
           const key = "unable_to_start_tor";
    
    243
    -      const err = TorLauncherUtil.getFormattedLocalizedString(
    
    269
    +      const err = lazy.TorLauncherUtil.getFormattedLocalizedString(
    
    244 270
             key,
    
    245 271
             [details],
    
    246 272
             1
    
    ... ... @@ -248,7 +274,7 @@ export class TorProcess {
    248 274
           throw new Error(err);
    
    249 275
         }
    
    250 276
     
    
    251
    -    const torrcDefaultsFile = TorLauncherUtil.getTorFile(
    
    277
    +    const torrcDefaultsFile = lazy.TorLauncherUtil.getTorFile(
    
    252 278
           "torrc-defaults",
    
    253 279
           false
    
    254 280
         );
    
    ... ... @@ -258,77 +284,131 @@ export class TorProcess {
    258 284
         const geoip6File = torrcDefaultsFile.clone();
    
    259 285
         geoip6File.leafName = "geoip6";
    
    260 286
     
    
    261
    -    this._args = [];
    
    287
    +    this.#args = [];
    
    262 288
         if (torrcDefaultsFile) {
    
    263
    -      this._args.push("--defaults-torrc");
    
    264
    -      this._args.push(torrcDefaultsFile.path);
    
    289
    +      this.#args.push("--defaults-torrc", torrcDefaultsFile.path);
    
    265 290
         }
    
    266
    -    this._args.push("-f");
    
    267
    -    this._args.push(torrcFile.path);
    
    268
    -    this._args.push("DataDirectory");
    
    269
    -    this._args.push(this._dataDir.path);
    
    270
    -    this._args.push("ClientOnionAuthDir");
    
    271
    -    this._args.push(onionAuthDir.path);
    
    272
    -    this._args.push("GeoIPFile");
    
    273
    -    this._args.push(geoipFile.path);
    
    274
    -    this._args.push("GeoIPv6File");
    
    275
    -    this._args.push(geoip6File.path);
    
    276
    -    this._args.push("HashedControlPassword");
    
    277
    -    this._args.push(hashedPassword);
    
    291
    +    this.#args.push("-f", torrcFile.path);
    
    292
    +    this.#args.push("DataDirectory", this.#dataDir.path);
    
    293
    +    this.#args.push("ClientOnionAuthDir", onionAuthDir.path);
    
    294
    +    this.#args.push("GeoIPFile", geoipFile.path);
    
    295
    +    this.#args.push("GeoIPv6File", geoip6File.path);
    
    278 296
       }
    
    279 297
     
    
    280
    -  _addControlPortArg() {
    
    281
    -    // Include a ControlPort argument to support switching between
    
    282
    -    // a TCP port and an IPC port (e.g., a Unix domain socket). We
    
    283
    -    // include a "+__" prefix so that (1) this control port is added
    
    284
    -    // to any control ports that the user has defined in their torrc
    
    285
    -    // file and (2) it is never written to torrc.
    
    298
    +  /**
    
    299
    +   * Add all the arguments related to the control port.
    
    300
    +   * We use the + prefix so that the the port is added to any other port already
    
    301
    +   * defined in the torrc, and the __ prefix so that it is never written to
    
    302
    +   * torrc.
    
    303
    +   */
    
    304
    +  #addControlPortArgs() {
    
    305
    +    if (!this.#controlSettings) {
    
    306
    +      return;
    
    307
    +    }
    
    308
    +
    
    286 309
         let controlPortArg;
    
    287
    -    const controlIPCFile = lazy.TorProtocolService.torGetControlIPCFile();
    
    288
    -    const controlPort = lazy.TorProtocolService.torGetControlPort();
    
    289
    -    if (controlIPCFile) {
    
    290
    -      controlPortArg = this._ipcPortArg(controlIPCFile);
    
    291
    -    } else if (controlPort) {
    
    292
    -      controlPortArg = "" + controlPort;
    
    310
    +    if (this.#controlSettings.ipcFile) {
    
    311
    +      controlPortArg = this.#controlSettings.ipcFile;
    
    312
    +    } else if (this.#controlSettings.port) {
    
    313
    +      controlPortArg = this.#controlSettings.host
    
    314
    +        ? `${this.#controlSettings.host}:${this.#controlSettings.port}`
    
    315
    +        : this.#controlSettings.port.toString();
    
    293 316
         }
    
    294 317
         if (controlPortArg) {
    
    295
    -      this._args.push("+__ControlPort");
    
    296
    -      this._args.push(controlPortArg);
    
    318
    +      this.#args.push("+__ControlPort", controlPortArg);
    
    319
    +    }
    
    320
    +
    
    321
    +    if (this.#controlSettings.password) {
    
    322
    +      this.#args.push(
    
    323
    +        "HashedControlPassword",
    
    324
    +        this.#hashPassword(this.#controlSettings.password)
    
    325
    +      );
    
    326
    +    }
    
    327
    +    if (this.#controlSettings.cookieFilePath) {
    
    328
    +      this.#args.push("CookieAuthentication", "1");
    
    329
    +      this.#args.push("CookieAuthFile", this.#controlSettings.cookieFilePath);
    
    297 330
         }
    
    298 331
       }
    
    299 332
     
    
    300
    -  _addSocksPortArg() {
    
    301
    -    // Include a SocksPort argument to support switching between
    
    302
    -    // a TCP port and an IPC port (e.g., a Unix domain socket). We
    
    303
    -    // include a "+__" prefix so that (1) this SOCKS port is added
    
    304
    -    // to any SOCKS ports that the user has defined in their torrc
    
    305
    -    // file and (2) it is never written to torrc.
    
    306
    -    const socksPortInfo = lazy.TorProtocolService.torGetSOCKSPortInfo();
    
    307
    -    if (socksPortInfo) {
    
    308
    -      let socksPortArg;
    
    309
    -      if (socksPortInfo.ipcFile) {
    
    310
    -        socksPortArg = this._ipcPortArg(socksPortInfo.ipcFile);
    
    311
    -      } else if (socksPortInfo.host && socksPortInfo.port != 0) {
    
    312
    -        socksPortArg = socksPortInfo.host + ":" + socksPortInfo.port;
    
    313
    -      }
    
    314
    -      if (socksPortArg) {
    
    315
    -        let socksPortFlags = Services.prefs.getCharPref(
    
    316
    -          "extensions.torlauncher.socks_port_flags",
    
    317
    -          "IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"
    
    318
    -        );
    
    319
    -        if (socksPortFlags) {
    
    320
    -          socksPortArg += " " + socksPortFlags;
    
    321
    -        }
    
    322
    -        this._args.push("+__SocksPort");
    
    323
    -        this._args.push(socksPortArg);
    
    333
    +  /**
    
    334
    +   * Add the argument related to the control port.
    
    335
    +   * We use the + prefix so that the the port is added to any other port already
    
    336
    +   * defined in the torrc, and the __ prefix so that it is never written to
    
    337
    +   * torrc.
    
    338
    +   */
    
    339
    +  #addSocksPortArg() {
    
    340
    +    let socksPortArg;
    
    341
    +    if (this.#socksSettings.ipcFile) {
    
    342
    +      socksPortArg = this.#socksSettings.ipcFile;
    
    343
    +    } else if (this.#socksSettings.port != 0) {
    
    344
    +      socksPortArg = this.#socksSettings.host
    
    345
    +        ? `${this.#socksSettings.host}:${this.#socksSettings.port}`
    
    346
    +        : this.#socksSettings.port.toString();
    
    347
    +    }
    
    348
    +    if (socksPortArg) {
    
    349
    +      const socksPortFlags = Services.prefs.getCharPref(
    
    350
    +        "extensions.torlauncher.socks_port_flags",
    
    351
    +        "IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"
    
    352
    +      );
    
    353
    +      if (socksPortFlags) {
    
    354
    +        socksPortArg += " " + socksPortFlags;
    
    324 355
           }
    
    356
    +      this.#args.push("+__SocksPort", socksPortArg);
    
    357
    +    }
    
    358
    +  }
    
    359
    +
    
    360
    +  // Based on Vidalia's TorSettings::hashPassword().
    
    361
    +  #hashPassword(aHexPassword) {
    
    362
    +    if (!aHexPassword) {
    
    363
    +      return null;
    
    325 364
         }
    
    365
    +
    
    366
    +    // Generate a random, 8 byte salt value.
    
    367
    +    const salt = Array.from(crypto.getRandomValues(new Uint8Array(8)));
    
    368
    +
    
    369
    +    // Convert hex-encoded password to an array of bytes.
    
    370
    +    const password = [];
    
    371
    +    for (let i = 0; i < aHexPassword.length; i += 2) {
    
    372
    +      password.push(parseInt(aHexPassword.substring(i, i + 2), 16));
    
    373
    +    }
    
    374
    +
    
    375
    +    // Run through the S2K algorithm and convert to a string.
    
    376
    +    const toHex = v => v.toString(16).padStart(2, "0");
    
    377
    +    const arrayToHex = aArray => aArray.map(toHex).join("");
    
    378
    +    const kCodedCount = 96;
    
    379
    +    const hashVal = this.#cryptoSecretToKey(password, salt, kCodedCount);
    
    380
    +    return "16:" + arrayToHex(salt) + toHex(kCodedCount) + arrayToHex(hashVal);
    
    326 381
       }
    
    327 382
     
    
    328
    -  // Return a ControlPort or SocksPort argument for aIPCFile (an nsIFile).
    
    329
    -  // The result is unix:/path or unix:"/path with spaces" with appropriate
    
    330
    -  // C-style escaping within the path portion.
    
    331
    -  _ipcPortArg(aIPCFile) {
    
    332
    -    return "unix:" + TorParsers.escapeString(aIPCFile.path);
    
    383
    +  // #cryptoSecretToKey() is similar to Vidalia's crypto_secret_to_key().
    
    384
    +  // It generates and returns a hash of aPassword by following the iterated
    
    385
    +  // and salted S2K algorithm (see RFC 2440 section 3.6.1.3).
    
    386
    +  // See also https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/control-spec.txt#L3824.
    
    387
    +  // Returns an array of bytes.
    
    388
    +  #cryptoSecretToKey(aPassword, aSalt, aCodedCount) {
    
    389
    +    const inputArray = aSalt.concat(aPassword);
    
    390
    +
    
    391
    +    // Subtle crypto only has the final digest, and does not allow incremental
    
    392
    +    // updates.
    
    393
    +    const hasher = Cc["@mozilla.org/security/hash;1"].createInstance(
    
    394
    +      Ci.nsICryptoHash
    
    395
    +    );
    
    396
    +    hasher.init(hasher.SHA1);
    
    397
    +    const kEXPBIAS = 6;
    
    398
    +    let count = (16 + (aCodedCount & 15)) << ((aCodedCount >> 4) + kEXPBIAS);
    
    399
    +    while (count > 0) {
    
    400
    +      if (count > inputArray.length) {
    
    401
    +        hasher.update(inputArray, inputArray.length);
    
    402
    +        count -= inputArray.length;
    
    403
    +      } else {
    
    404
    +        const finalArray = inputArray.slice(0, count);
    
    405
    +        hasher.update(finalArray, finalArray.length);
    
    406
    +        count = 0;
    
    407
    +      }
    
    408
    +    }
    
    409
    +    return hasher
    
    410
    +      .finish(false)
    
    411
    +      .split("")
    
    412
    +      .map(b => b.charCodeAt(0));
    
    333 413
       }
    
    334 414
     }

  • toolkit/components/tor-launcher/TorProtocolService.sys.mjs
    ... ... @@ -289,9 +289,8 @@ export const TorProtocolService = {
    289 289
       // are also used in torbutton.
    
    290 290
     
    
    291 291
       // Returns Tor password string or null if an error occurs.
    
    292
    -  torGetPassword(aPleaseHash) {
    
    293
    -    const pw = this._controlPassword;
    
    294
    -    return aPleaseHash ? this._hashPassword(pw) : pw;
    
    292
    +  torGetPassword() {
    
    293
    +    return this._controlPassword;
    
    295 294
       },
    
    296 295
     
    
    297 296
       torGetControlIPCFile() {
    
    ... ... @@ -306,6 +305,24 @@ export const TorProtocolService = {
    306 305
         return this._SOCKSPortInfo;
    
    307 306
       },
    
    308 307
     
    
    308
    +  get torControlPortInfo() {
    
    309
    +    const info = {
    
    310
    +      password: this._controlPassword,
    
    311
    +    };
    
    312
    +    if (this._controlIPCFile) {
    
    313
    +      info.ipcFile = this._controlIPCFile?.clone();
    
    314
    +    }
    
    315
    +    if (this._controlPort) {
    
    316
    +      info.host = this._controlHost;
    
    317
    +      info.port = this._controlPort;
    
    318
    +    }
    
    319
    +    return info;
    
    320
    +  },
    
    321
    +
    
    322
    +  get torSOCKSPortInfo() {
    
    323
    +    return this._SOCKSPortInfo;
    
    324
    +  },
    
    325
    +
    
    309 326
       // Public, but called only internally
    
    310 327
     
    
    311 328
       // Executes a command on the control port.
    
    ... ... @@ -469,115 +486,8 @@ export const TorProtocolService = {
    469 486
             this._controlPassword = this._generateRandomPassword();
    
    470 487
           }
    
    471 488
     
    
    472
    -      // Determine what kind of SOCKS port Tor and the browser will use.
    
    473
    -      // On Windows (where Unix domain sockets are not supported), TCP is
    
    474
    -      // always used.
    
    475
    -      //
    
    476
    -      // The following environment variables are supported and take
    
    477
    -      // precedence over preferences:
    
    478
    -      //    TOR_SOCKS_IPC_PATH  (file system path; ignored on Windows)
    
    479
    -      //    TOR_SOCKS_HOST
    
    480
    -      //    TOR_SOCKS_PORT
    
    481
    -      //
    
    482
    -      // The following preferences are consulted:
    
    483
    -      //    network.proxy.socks
    
    484
    -      //    network.proxy.socks_port
    
    485
    -      //    extensions.torlauncher.socks_port_use_ipc (Boolean)
    
    486
    -      //    extensions.torlauncher.socks_ipc_path (file system path)
    
    487
    -      // If extensions.torlauncher.socks_ipc_path is empty, a default
    
    488
    -      // path is used (<tor-data-directory>/socks.socket).
    
    489
    -      //
    
    490
    -      // When using TCP, if a value is not defined via an env variable it is
    
    491
    -      // taken from the corresponding browser preference if possible. The
    
    492
    -      // exceptions are:
    
    493
    -      //   If network.proxy.socks contains a file: URL, a default value of
    
    494
    -      //     "127.0.0.1" is used instead.
    
    495
    -      //   If the network.proxy.socks_port value is 0, a default value of
    
    496
    -      //     9150 is used instead.
    
    497
    -      //
    
    498
    -      // Supported scenarios:
    
    499
    -      // 1. By default, an IPC object at a default path is used.
    
    500
    -      // 2. If extensions.torlauncher.socks_port_use_ipc is set to false,
    
    501
    -      //    a TCP socket at 127.0.0.1:9150 is used, unless different values
    
    502
    -      //    are set in network.proxy.socks and network.proxy.socks_port.
    
    503
    -      // 3. If the TOR_SOCKS_IPC_PATH env var is set, an IPC object at that
    
    504
    -      //    path is used (e.g., a Unix domain socket).
    
    505
    -      // 4. If the TOR_SOCKS_HOST and/or TOR_SOCKS_PORT env vars are set, TCP
    
    506
    -      //    is used. Values not set via env vars will be taken from the
    
    507
    -      //    network.proxy.socks and network.proxy.socks_port prefs as described
    
    508
    -      //    above.
    
    509
    -      // 5. If extensions.torlauncher.socks_port_use_ipc is true and
    
    510
    -      //    extensions.torlauncher.socks_ipc_path is set, an IPC object at
    
    511
    -      //    the specified path is used.
    
    512
    -      // 6. Tor Launcher is disabled. Torbutton will respect the env vars if
    
    513
    -      //    present; if not, the values in network.proxy.socks and
    
    514
    -      //    network.proxy.socks_port are used without modification.
    
    515
    -
    
    516
    -      let useIPC;
    
    517
    -      this._SOCKSPortInfo = { ipcFile: undefined, host: undefined, port: 0 };
    
    518
    -      if (!isWindows && Services.env.exists("TOR_SOCKS_IPC_PATH")) {
    
    519
    -        let ipcPath = Services.env.get("TOR_SOCKS_IPC_PATH");
    
    520
    -        this._SOCKSPortInfo.ipcFile = new lazy.FileUtils.File(ipcPath);
    
    521
    -        useIPC = true;
    
    522
    -      } else {
    
    523
    -        // Check for TCP host and port environment variables.
    
    524
    -        if (Services.env.exists("TOR_SOCKS_HOST")) {
    
    525
    -          this._SOCKSPortInfo.host = Services.env.get("TOR_SOCKS_HOST");
    
    526
    -          useIPC = false;
    
    527
    -        }
    
    528
    -        if (Services.env.exists("TOR_SOCKS_PORT")) {
    
    529
    -          this._SOCKSPortInfo.port = parseInt(
    
    530
    -            Services.env.get("TOR_SOCKS_PORT"),
    
    531
    -            10
    
    532
    -          );
    
    533
    -          useIPC = false;
    
    534
    -        }
    
    535
    -      }
    
    536
    -
    
    537
    -      if (useIPC === undefined) {
    
    538
    -        useIPC =
    
    539
    -          !isWindows &&
    
    540
    -          Services.prefs.getBoolPref(
    
    541
    -            "extensions.torlauncher.socks_port_use_ipc",
    
    542
    -            false
    
    543
    -          );
    
    544
    -      }
    
    545
    -
    
    546
    -      // Fill in missing SOCKS info from prefs.
    
    547
    -      if (useIPC) {
    
    548
    -        if (!this._SOCKSPortInfo.ipcFile) {
    
    549
    -          this._SOCKSPortInfo.ipcFile = TorLauncherUtil.getTorFile(
    
    550
    -            "socks_ipc",
    
    551
    -            false
    
    552
    -          );
    
    553
    -        }
    
    554
    -      } else {
    
    555
    -        if (!this._SOCKSPortInfo.host) {
    
    556
    -          let socksAddr = Services.prefs.getCharPref(
    
    557
    -            "network.proxy.socks",
    
    558
    -            "127.0.0.1"
    
    559
    -          );
    
    560
    -          let socksAddrHasHost = socksAddr && !socksAddr.startsWith("file:");
    
    561
    -          this._SOCKSPortInfo.host = socksAddrHasHost ? socksAddr : "127.0.0.1";
    
    562
    -        }
    
    563
    -
    
    564
    -        if (!this._SOCKSPortInfo.port) {
    
    565
    -          let socksPort = Services.prefs.getIntPref(
    
    566
    -            "network.proxy.socks_port",
    
    567
    -            0
    
    568
    -          );
    
    569
    -          // This pref is set as 0 by default in Firefox, use 9150 if we get 0.
    
    570
    -          this._SOCKSPortInfo.port = socksPort != 0 ? socksPort : 9150;
    
    571
    -        }
    
    572
    -      }
    
    573
    -
    
    574
    -      logger.info("SOCKS port type: " + (useIPC ? "IPC" : "TCP"));
    
    575
    -      if (useIPC) {
    
    576
    -        logger.info(`ipcFile: ${this._SOCKSPortInfo.ipcFile.path}`);
    
    577
    -      } else {
    
    578
    -        logger.info(`SOCKS host: ${this._SOCKSPortInfo.host}`);
    
    579
    -        logger.info(`SOCKS port: ${this._SOCKSPortInfo.port}`);
    
    580
    -      }
    
    489
    +      this._SOCKSPortInfo = TorLauncherUtil.getPreferredSocksConfiguration();
    
    490
    +      TorLauncherUtil.setProxyConfiguration(this._SOCKSPortInfo);
    
    581 491
     
    
    582 492
           // Set the global control port info parameters.
    
    583 493
           // These values may be overwritten by torbutton when it initializes, but
    
    ... ... @@ -781,38 +691,6 @@ export const TorProtocolService = {
    781 691
         return pwd;
    
    782 692
       },
    
    783 693
     
    
    784
    -  // Based on Vidalia's TorSettings::hashPassword().
    
    785
    -  _hashPassword(aHexPassword) {
    
    786
    -    if (!aHexPassword) {
    
    787
    -      return null;
    
    788
    -    }
    
    789
    -
    
    790
    -    // Generate a random, 8 byte salt value.
    
    791
    -    const salt = Array.from(crypto.getRandomValues(new Uint8Array(8)));
    
    792
    -
    
    793
    -    // Convert hex-encoded password to an array of bytes.
    
    794
    -    const password = [];
    
    795
    -    for (let i = 0; i < aHexPassword.length; i += 2) {
    
    796
    -      password.push(parseInt(aHexPassword.substring(i, i + 2), 16));
    
    797
    -    }
    
    798
    -
    
    799
    -    // Run through the S2K algorithm and convert to a string.
    
    800
    -    const kCodedCount = 96;
    
    801
    -    const hashVal = this._cryptoSecretToKey(password, salt, kCodedCount);
    
    802
    -    if (!hashVal) {
    
    803
    -      logger.error("_cryptoSecretToKey() failed");
    
    804
    -      return null;
    
    805
    -    }
    
    806
    -
    
    807
    -    const arrayToHex = aArray =>
    
    808
    -      aArray.map(item => this._toHex(item, 2)).join("");
    
    809
    -    let rv = "16:";
    
    810
    -    rv += arrayToHex(salt);
    
    811
    -    rv += this._toHex(kCodedCount, 2);
    
    812
    -    rv += arrayToHex(hashVal);
    
    813
    -    return rv;
    
    814
    -  },
    
    815
    -
    
    816 694
       // Returns -1 upon failure.
    
    817 695
       _cryptoRandInt(aMax) {
    
    818 696
         // Based on tor's crypto_rand_int().
    
    ... ... @@ -831,43 +709,6 @@ export const TorProtocolService = {
    831 709
         return val % aMax;
    
    832 710
       },
    
    833 711
     
    
    834
    -  // _cryptoSecretToKey() is similar to Vidalia's crypto_secret_to_key().
    
    835
    -  // It generates and returns a hash of aPassword by following the iterated
    
    836
    -  // and salted S2K algorithm (see RFC 2440 section 3.6.1.3).
    
    837
    -  // Returns an array of bytes.
    
    838
    -  _cryptoSecretToKey(aPassword, aSalt, aCodedCount) {
    
    839
    -    if (!aPassword || !aSalt) {
    
    840
    -      return null;
    
    841
    -    }
    
    842
    -
    
    843
    -    const inputArray = aSalt.concat(aPassword);
    
    844
    -
    
    845
    -    // Subtle crypto only has the final digest, and does not allow incremental
    
    846
    -    // updates. Also, it is async, so we should hash and keep the hash in a
    
    847
    -    // variable if we wanted to switch to getters.
    
    848
    -    // So, keeping this implementation should be okay for now.
    
    849
    -    const hasher = Cc["@mozilla.org/security/hash;1"].createInstance(
    
    850
    -      Ci.nsICryptoHash
    
    851
    -    );
    
    852
    -    hasher.init(hasher.SHA1);
    
    853
    -    const kEXPBIAS = 6;
    
    854
    -    let count = (16 + (aCodedCount & 15)) << ((aCodedCount >> 4) + kEXPBIAS);
    
    855
    -    while (count > 0) {
    
    856
    -      if (count > inputArray.length) {
    
    857
    -        hasher.update(inputArray, inputArray.length);
    
    858
    -        count -= inputArray.length;
    
    859
    -      } else {
    
    860
    -        const finalArray = inputArray.slice(0, count);
    
    861
    -        hasher.update(finalArray, finalArray.length);
    
    862
    -        count = 0;
    
    863
    -      }
    
    864
    -    }
    
    865
    -    return hasher
    
    866
    -      .finish(false)
    
    867
    -      .split("")
    
    868
    -      .map(b => b.charCodeAt(0));
    
    869
    -  },
    
    870
    -
    
    871 712
       _toHex(aValue, aMinLen) {
    
    872 713
         return aValue.toString(16).padStart(aMinLen, "0");
    
    873 714
       },
    

  • toolkit/torbutton/chrome/content/torbutton.js
    ... ... @@ -60,7 +60,7 @@ var torbutton_init;
    60 60
         } else {
    
    61 61
           try {
    
    62 62
             // Try to get password from Tor Launcher.
    
    63
    -        m_tb_control_pass = TorProtocolService.torGetPassword(false);
    
    63
    +        m_tb_control_pass = TorProtocolService.torGetPassword();
    
    64 64
           } catch (e) {}
    
    65 65
         }
    
    66 66
     
    

  • toolkit/torbutton/components.conf
    1 1
     Classes = [
    
    2
    -    {
    
    3
    -        "cid": "{06322def-6fde-4c06-aef6-47ae8e799629}",
    
    4
    -        "contract_ids": [
    
    5
    -            "@torproject.org/startup-observer;1"
    
    6
    -        ],
    
    7
    -        "jsm": "resource://torbutton/modules/TorbuttonStartupObserver.jsm",
    
    8
    -        "constructor": "StartupObserver",
    
    9
    -    },
    
    10 2
         {
    
    11 3
             "cid": "{f36d72c9-9718-4134-b550-e109638331d7}",
    
    12 4
             "contract_ids": [
    

  • toolkit/torbutton/modules/TorbuttonStartupObserver.jsm deleted
    1
    -// Bug 1506 P1-3: This code is mostly hackish remnants of session store
    
    2
    -// support. There are a couple of observer events that *might* be worth
    
    3
    -// listening to. Search for 1506 in the code.
    
    4
    -
    
    5
    -/*************************************************************************
    
    6
    - * Startup observer (_javascript_ XPCOM component)
    
    7
    - *
    
    8
    - * Cases tested (each during Tor and Non-Tor, FF4 and FF3.6)
    
    9
    - *    1. Crash
    
    10
    - *    2. Upgrade
    
    11
    - *    3. Fresh install
    
    12
    - *
    
    13
    - *************************************************************************/
    
    14
    -
    
    15
    -var EXPORTED_SYMBOLS = ["StartupObserver"];
    
    16
    -
    
    17
    -const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
    
    18
    -const { XPCOMUtils } = ChromeUtils.import(
    
    19
    -  "resource://gre/modules/XPCOMUtils.jsm"
    
    20
    -);
    
    21
    -
    
    22
    -const { TorProtocolService } = ChromeUtils.import(
    
    23
    -  "resource://gre/modules/TorProtocolService.jsm"
    
    24
    -);
    
    25
    -
    
    26
    -const lazy = {};
    
    27
    -
    
    28
    -XPCOMUtils.defineLazyModuleGetters(lazy, {
    
    29
    -  FileUtils: "resource://gre/modules/FileUtils.jsm",
    
    30
    -});
    
    31
    -
    
    32
    -function StartupObserver() {
    
    33
    -  this.logger = Cc["@torproject.org/torbutton-logger;1"].getService(
    
    34
    -    Ci.nsISupports
    
    35
    -  ).wrappedJSObject;
    
    36
    -  this._prefs = Services.prefs;
    
    37
    -  this.logger.log(3, "Startup Observer created");
    
    38
    -
    
    39
    -  try {
    
    40
    -    // XXX: We're in a race with HTTPS-Everywhere to update our proxy settings
    
    41
    -    // before the initial SSL-Observatory test... If we lose the race, Firefox
    
    42
    -    // caches the old proxy settings for check.tp.o somehwere, and it never loads :(
    
    43
    -    this.setProxySettings();
    
    44
    -  } catch (e) {
    
    45
    -    this.logger.log(
    
    46
    -      4,
    
    47
    -      "Early proxy change failed. Will try again at profile load. Error: " + e
    
    48
    -    );
    
    49
    -  }
    
    50
    -}
    
    51
    -
    
    52
    -StartupObserver.prototype = {
    
    53
    -  // Bug 6803: We need to get the env vars early due to
    
    54
    -  // some weird proxy caching code that showed up in FF15.
    
    55
    -  // Otherwise, homepage domain loads fail forever.
    
    56
    -  setProxySettings() {
    
    57
    -    // Bug 1506: Still want to get these env vars
    
    58
    -    if (Services.env.exists("TOR_TRANSPROXY")) {
    
    59
    -      this.logger.log(3, "Resetting Tor settings to transproxy");
    
    60
    -      this._prefs.setBoolPref("network.proxy.socks_remote_dns", false);
    
    61
    -      this._prefs.setIntPref("network.proxy.type", 0);
    
    62
    -      this._prefs.setIntPref("network.proxy.socks_port", 0);
    
    63
    -      this._prefs.setCharPref("network.proxy.socks", "");
    
    64
    -    } else {
    
    65
    -      // Try to retrieve SOCKS proxy settings from Tor Launcher.
    
    66
    -      let socksPortInfo;
    
    67
    -      try {
    
    68
    -        socksPortInfo = TorProtocolService.torGetSOCKSPortInfo();
    
    69
    -      } catch (e) {
    
    70
    -        this.logger.log(3, "tor launcher failed " + e);
    
    71
    -      }
    
    72
    -
    
    73
    -      // If Tor Launcher is not available, check environment variables.
    
    74
    -      if (!socksPortInfo) {
    
    75
    -        socksPortInfo = { ipcFile: undefined, host: undefined, port: 0 };
    
    76
    -
    
    77
    -        let isWindows = Services.appinfo.OS === "WINNT";
    
    78
    -        if (!isWindows && Services.env.exists("TOR_SOCKS_IPC_PATH")) {
    
    79
    -          socksPortInfo.ipcFile = new lazy.FileUtils.File(
    
    80
    -            Services.env.get("TOR_SOCKS_IPC_PATH")
    
    81
    -          );
    
    82
    -        } else {
    
    83
    -          if (Services.env.exists("TOR_SOCKS_HOST")) {
    
    84
    -            socksPortInfo.host = Services.env.get("TOR_SOCKS_HOST");
    
    85
    -          }
    
    86
    -          if (Services.env.exists("TOR_SOCKS_PORT")) {
    
    87
    -            socksPortInfo.port = parseInt(Services.env.get("TOR_SOCKS_PORT"));
    
    88
    -          }
    
    89
    -        }
    
    90
    -      }
    
    91
    -
    
    92
    -      // Adjust network.proxy prefs.
    
    93
    -      if (socksPortInfo.ipcFile) {
    
    94
    -        let fph = Services.io
    
    95
    -          .getProtocolHandler("file")
    
    96
    -          .QueryInterface(Ci.nsIFileProtocolHandler);
    
    97
    -        let fileURI = fph.newFileURI(socksPortInfo.ipcFile);
    
    98
    -        this.logger.log(3, "Reset socks to " + fileURI.spec);
    
    99
    -        this._prefs.setCharPref("network.proxy.socks", fileURI.spec);
    
    100
    -        this._prefs.setIntPref("network.proxy.socks_port", 0);
    
    101
    -      } else {
    
    102
    -        if (socksPortInfo.host) {
    
    103
    -          this._prefs.setCharPref("network.proxy.socks", socksPortInfo.host);
    
    104
    -          this.logger.log(3, "Reset socks host to " + socksPortInfo.host);
    
    105
    -        }
    
    106
    -        if (socksPortInfo.port) {
    
    107
    -          this._prefs.setIntPref(
    
    108
    -            "network.proxy.socks_port",
    
    109
    -            socksPortInfo.port
    
    110
    -          );
    
    111
    -          this.logger.log(3, "Reset socks port to " + socksPortInfo.port);
    
    112
    -        }
    
    113
    -      }
    
    114
    -
    
    115
    -      if (socksPortInfo.ipcFile || socksPortInfo.host || socksPortInfo.port) {
    
    116
    -        this._prefs.setBoolPref("network.proxy.socks_remote_dns", true);
    
    117
    -        this._prefs.setIntPref("network.proxy.type", 1);
    
    118
    -      }
    
    119
    -    }
    
    120
    -
    
    121
    -    // Force prefs to be synced to disk
    
    122
    -    Services.prefs.savePrefFile(null);
    
    123
    -
    
    124
    -    this.logger.log(3, "Synced network settings to environment.");
    
    125
    -  },
    
    126
    -
    
    127
    -  observe(subject, topic, data) {
    
    128
    -    if (topic == "profile-after-change") {
    
    129
    -      this.setProxySettings();
    
    130
    -    }
    
    131
    -
    
    132
    -    // In all cases, force prefs to be synced to disk
    
    133
    -    Services.prefs.savePrefFile(null);
    
    134
    -  },
    
    135
    -
    
    136
    -  // Hack to get us registered early to observe recovery
    
    137
    -  _xpcom_categories: [{ category: "profile-after-change" }],
    
    138
    -};

  • toolkit/torbutton/moz.build
    ... ... @@ -8,7 +8,3 @@ JAR_MANIFESTS += ['jar.mn']
    8 8
     XPCOM_MANIFESTS += [
    
    9 9
         "components.conf",
    
    10 10
     ]
    11
    -
    
    12
    -EXTRA_COMPONENTS += [
    
    13
    -    "torbutton.manifest",
    
    14
    -]

  • toolkit/torbutton/torbutton.manifest deleted
    1
    -category profile-after-change StartupObserver @torproject.org/startup-observer;1

  • _______________________________________________
    tor-commits mailing list
    tor-commits@xxxxxxxxxxxxxxxxxxxx
    https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits