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

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-102.12.0esr-13.0-1] 12 commits: fixup! Bug 40933: Add tor-launcher functionality



Title: GitLab

richard pushed to branch tor-browser-102.12.0esr-13.0-1 at The Tor Project / Applications / Tor Browser

Commits:

  • 2bf330d2
    by Pier Angelo Vendrame at 2023-06-08T14:56:19+02:00
    fixup! Bug 40933: Add tor-launcher functionality
    
    Added a newnym function
    
  • ed24f026
    by Pier Angelo Vendrame at 2023-06-08T14:56:20+02:00
    fixup! Bug 10760: Integrate TorButton to TorBrowser core
    
    Bug 40938: Moving the domain isolator out of torbutton
    
  • 4e063afe
    by Arthur Edelstein at 2023-06-08T14:56:20+02:00
    Bug 3455: Add DomainIsolator, for isolating circuit by domain.
    
    Add an XPCOM component that registers a ProtocolProxyChannelFilter
    which sets the username/password for each web request according to
    url bar domain.
    
    Bug 9442: Add New Circuit button
    
    Bug 13766: Set a 10 minute circuit dirty timeout for the catch-all circ.
    
    Bug 19206: Include a 128 bit random tag as part of the domain isolator nonce.
    
    Bug 19206: Clear out the domain isolator state on `New Identity`.
    
    Bug 21201.2: Isolate by firstPartyDomain from OriginAttributes
    
    Bug 21745: Fix handling of catch-all circuit
    
    Bug 41741: Refactor the domain isolator and new circuit
    
  • 9018b2cd
    by Pier Angelo Vendrame at 2023-06-08T14:56:20+02:00
    fixup! Bug 3455: Add DomainIsolator, for isolating circuit by domain.
    
    Refactors to the old JS code.
    
  • 47c03bfc
    by Pier Angelo Vendrame at 2023-06-08T14:56:21+02:00
    fixup! Bug 3455: Add DomainIsolator, for isolating circuit by domain.
    
    Manage NEWNYM here.
    
  • d33564dd
    by Pier Angelo Vendrame at 2023-06-08T14:56:21+02:00
    fixup! Bug 3455: Add DomainIsolator, for isolating circuit by domain.
    
    Removed the XPCOM definition of the domain isolator.
    
  • ae68e4b5
    by Pier Angelo Vendrame at 2023-06-08T14:56:22+02:00
    fixup! Bug 10760: Integrate TorButton to TorBrowser core
    
    Extract the new identity button from torbutton
    
  • 322c6af1
    by Pier Angelo Vendrame at 2023-06-08T14:56:22+02:00
    fixup! Bug 3455: Add DomainIsolator, for isolating circuit by domain.
    
    Actually added the new circuit button.
    
  • 1ba65aa4
    by Pier Angelo Vendrame at 2023-06-08T14:56:22+02:00
    fixup! Bug 41600: Add a tor circuit display panel.
    
    Use the new domain isolator interface.
    
  • beec825e
    by Pier Angelo Vendrame at 2023-06-08T14:56:23+02:00
    fixup! Bug 40209: Implement Basic Crypto Safety
    
    Use the new domain isolator interface
    
  • e3478fc9
    by Pier Angelo Vendrame at 2023-06-08T14:56:23+02:00
    fixup! Bug 10760: Integrate TorButton to TorBrowser core
    
    Remove string changes from Torbutton.
    We will add them back in the TorStrings commit.
    
  • cf8bb1df
    by Pier Angelo Vendrame at 2023-06-08T14:56:24+02:00
    fixup! Add TorStrings module for localization
    
    Add our DTDs where needed.
    
    These changes were originally in the torbutton commit, but I think they
    are better fit here, with all the strings files.
    

15 changed files:

Changes:

  • browser/actors/CryptoSafetyParent.jsm
    ... ... @@ -12,6 +12,12 @@ const { XPCOMUtils } = ChromeUtils.import(
    12 12
       "resource://gre/modules/XPCOMUtils.jsm"
    
    13 13
     );
    
    14 14
     
    
    15
    +ChromeUtils.defineModuleGetter(
    
    16
    +  this,
    
    17
    +  "TorDomainIsolator",
    
    18
    +  "resource://gre/modules/TorDomainIsolator.jsm"
    
    19
    +);
    
    20
    +
    
    15 21
     XPCOMUtils.defineLazyGetter(this, "cryptoSafetyBundle", () => {
    
    16 22
       return Services.strings.createBundle(
    
    17 23
         "chrome://browser/locale/cryptoSafetyPrompt.properties"
    
    ... ... @@ -75,7 +81,11 @@ class CryptoSafetyParent extends JSWindowActorParent {
    75 81
         );
    
    76 82
     
    
    77 83
         if (buttonPressed === 0) {
    
    78
    -      this.browsingContext.topChromeWindow.torbutton_new_circuit();
    
    84
    +      const { browsingContext } = this.manager;
    
    85
    +      const browser = browsingContext.embedderElement;
    
    86
    +      if (browser) {
    
    87
    +        TorDomainIsolator.newCircuitForBrowser(browser.ownerGlobal.gBrowser);
    
    88
    +      }
    
    79 89
         }
    
    80 90
       }
    
    81 91
     }

  • browser/base/content/appmenu-viewcache.inc.xhtml
    ... ... @@ -63,9 +63,9 @@
    63 63
                          key="new-identity-key"/>
    
    64 64
           <toolbarbutton id="appMenuNewCircuit"
    
    65 65
                          class="subviewbutton"
    
    66
    -                     key="torbutton-new-circuit-key"
    
    66
    +                     key="new-circuit-key"
    
    67 67
                          label="&torbutton.context_menu.new_circuit_sentence_case;"
    
    68
    -                     _oncommand_="torbutton_new_circuit();"/>
    
    68
    +                     _oncommand_="TorDomainIsolator.newCircuitForBrowser(gBrowser);"/>
    
    69 69
           <toolbarseparator/>
    
    70 70
           <toolbarbutton id="appMenu-bookmarks-button"
    
    71 71
                          class="subviewbutton subviewbutton-nav"
    

  • browser/base/content/browser-menubar.inc
    ... ... @@ -33,9 +33,9 @@
    33 33
                               key="new-identity-key"/>
    
    34 34
                     <menuitem id="menu_newCircuit"
    
    35 35
                               accesskey="&torbutton.context_menu.new_circuit_key;"
    
    36
    -                          key="torbutton-new-circuit-key"
    
    36
    +                          key="new-circuit-key"
    
    37 37
                               label="&torbutton.context_menu.new_circuit;"
    
    38
    -                          oncommand="torbutton_new_circuit();"/>
    
    38
    +                          oncommand="TorDomainIsolator.newCircuitForBrowser(gBrowser);"/>
    
    39 39
                     <menuseparator/>
    
    40 40
                     <menuitem id="menu_openLocation"
    
    41 41
                               hidden="true"
    

  • browser/base/content/browser-sets.inc
    ... ... @@ -389,5 +389,5 @@
    389 389
              internal="true"/>
    
    390 390
     #endif
    
    391 391
         <key id="new-identity-key" modifiers="accel shift" key="U" oncommand="NewIdentityButton.onCommand(event)"/>
    
    392
    -    <key id="torbutton-new-circuit-key" modifiers="accel shift" key="L" oncommand="torbutton_new_circuit()"/>
    
    392
    +    <key id="new-circuit-key" modifiers="accel shift" key="L" oncommand="TorDomainIsolator.newCircuitForBrowser(gBrowser)"/>
    
    393 393
       </keyset>

  • browser/base/content/browser.js
    ... ... @@ -82,6 +82,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
    82 82
       TorConnect: "resource:///modules/TorConnect.jsm",
    
    83 83
       TorConnectState: "resource:///modules/TorConnect.jsm",
    
    84 84
       TorConnectTopics: "resource:///modules/TorConnect.jsm",
    
    85
    +  TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.jsm",
    
    85 86
       Translation: "resource:///modules/translation/TranslationParent.jsm",
    
    86 87
       UITour: "resource:///modules/UITour.jsm",
    
    87 88
       UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
    

  • browser/base/content/navigator-toolbox.inc.xhtml
    ... ... @@ -569,7 +569,7 @@
    569 569
     
    
    570 570
         <toolbarbutton id="new-circuit-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
    
    571 571
                        label="&torbutton.context_menu.new_circuit;"
    
    572
    -                   _oncommand_="torbutton_new_circuit();"
    
    572
    +                   _oncommand_="TorDomainIsolator.newCircuitForBrowser(gBrowser);"
    
    573 573
                        tooltiptext="&torbutton.context_menu.new_circuit;"/>
    
    574 574
     
    
    575 575
         <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
    

  • browser/components/torcircuit/content/torCircuitPanel.js
    ... ... @@ -193,7 +193,7 @@ var gTorCircuitPanel = {
    193 193
         document
    
    194 194
           .getElementById("tor-circuit-new-circuit")
    
    195 195
           .addEventListener("command", () => {
    
    196
    -        torbutton_new_circuit();
    
    196
    +        TorDomainIsolator.newCircuitForBrowser(gBrowser);
    
    197 197
             // And hide.
    
    198 198
             // NOTE: focus should return to the toolbar button, which we expect to
    
    199 199
             // remain visible during reload.
    
    ... ... @@ -415,20 +415,14 @@ var gTorCircuitPanel = {
    415 415
        */
    
    416 416
       _updateCurrentBrowser(matchingCredentials = null) {
    
    417 417
         const browser = gBrowser.selectedBrowser;
    
    418
    -    const { getDomainForBrowser } = ChromeUtils.import(
    
    419
    -      "resource://torbutton/modules/utils.js"
    
    420
    -    );
    
    421
    -    const domain = getDomainForBrowser(browser);
    
    418
    +    const domain = TorDomainIsolator.getDomainForBrowser(browser);
    
    422 419
         // We choose the currentURI, which matches what is shown in the URL bar and
    
    423 420
         // will match up with the domain.
    
    424 421
         // In contrast, documentURI corresponds to the shown page. E.g. it could
    
    425 422
         // point to "about:certerror".
    
    426 423
         const scheme = browser.currentURI?.scheme;
    
    427 424
     
    
    428
    -    const domainIsolator = Cc["@torproject.org/domain-isolator;1"].getService(
    
    429
    -      Ci.nsISupports
    
    430
    -    ).wrappedJSObject;
    
    431
    -    let credentials = domainIsolator.getSocksProxyCredentials(
    
    425
    +    let credentials = TorDomainIsolator.getSocksProxyCredentials(
    
    432 426
           domain,
    
    433 427
           browser.contentPrincipal.originAttributes.userContextId
    
    434 428
         );
    

  • toolkit/components/tor-launcher/TorDomainIsolator.jsm
    1
    +// A component for Tor Browser that puts requests from different
    
    2
    +// first party domains on separate Tor circuits.
    
    3
    +
    
    4
    +var EXPORTED_SYMBOLS = ["TorDomainIsolator"];
    
    5
    +
    
    6
    +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
    
    7
    +const { XPCOMUtils } = ChromeUtils.import(
    
    8
    +  "resource://gre/modules/XPCOMUtils.jsm"
    
    9
    +);
    
    10
    +const { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm");
    
    11
    +
    
    12
    +Cu.importGlobalProperties(["crypto"]);
    
    13
    +
    
    14
    +XPCOMUtils.defineLazyServiceGetters(this, {
    
    15
    +  ProtocolProxyService: [
    
    16
    +    "@mozilla.org/network/protocol-proxy-service;1",
    
    17
    +    "nsIProtocolProxyService",
    
    18
    +  ],
    
    19
    +});
    
    20
    +
    
    21
    +ChromeUtils.defineModuleGetter(
    
    22
    +  this,
    
    23
    +  "TorProtocolService",
    
    24
    +  "resource://gre/modules/TorProtocolService.jsm"
    
    25
    +);
    
    26
    +
    
    27
    +const logger = new ConsoleAPI({
    
    28
    +  prefix: "TorDomainIsolator",
    
    29
    +  maxLogLevel: "warn",
    
    30
    +  maxLogLevelPref: "browser.tordomainisolator.loglevel",
    
    31
    +});
    
    32
    +
    
    33
    +// The string to use instead of the domain when it is not known.
    
    34
    +const CATCHALL_DOMAIN = "--unknown--";
    
    35
    +
    
    36
    +// The preference to observe, to know whether isolation should be enabled or
    
    37
    +// disabled.
    
    38
    +const NON_TOR_PROXY_PREF = "extensions.torbutton.use_nontor_proxy";
    
    39
    +
    
    40
    +// The topic of new identity, to observe to cleanup all the nonces.
    
    41
    +const NEW_IDENTITY_TOPIC = "new-identity-requested";
    
    42
    +
    
    43
    +class TorDomainIsolatorImpl {
    
    44
    +  // A mutable map that records what nonce we are using for each domain.
    
    45
    +  #noncesForDomains = new Map();
    
    46
    +
    
    47
    +  // A mutable map that records what nonce we are using for each tab container.
    
    48
    +  #noncesForUserContextId = new Map();
    
    49
    +
    
    50
    +  // A bool that controls if we use SOCKS auth for isolation or not.
    
    51
    +  #isolationEnabled = true;
    
    52
    +
    
    53
    +  // Specifies when the current catch-all circuit was first used
    
    54
    +  #catchallDirtySince = Date.now();
    
    55
    +
    
    56
    +  /**
    
    57
    +   * Initialize the domain isolator.
    
    58
    +   * This function will setup the proxy filter that injects the credentials and
    
    59
    +   * register some observers.
    
    60
    +   */
    
    61
    +  init() {
    
    62
    +    logger.info("Setup circuit isolation by domain and user context");
    
    63
    +
    
    64
    +    if (Services.prefs.getBoolPref(NON_TOR_PROXY_PREF)) {
    
    65
    +      this.#isolationEnabled = false;
    
    66
    +    }
    
    67
    +    this.#setupProxyFilter();
    
    68
    +
    
    69
    +    Services.prefs.addObserver(NON_TOR_PROXY_PREF, this);
    
    70
    +    Services.obs.addObserver(this, NEW_IDENTITY_TOPIC);
    
    71
    +  }
    
    72
    +
    
    73
    +  /**
    
    74
    +   * Removes the observers added in the initialization.
    
    75
    +   */
    
    76
    +  uninit() {
    
    77
    +    Services.prefs.removeObserver(NON_TOR_PROXY_PREF, this);
    
    78
    +    Services.obs.removeObserver(this, NEW_IDENTITY_TOPIC);
    
    79
    +  }
    
    80
    +
    
    81
    +  enable() {
    
    82
    +    logger.trace("Domain isolation enabled");
    
    83
    +    this.#isolationEnabled = true;
    
    84
    +  }
    
    85
    +
    
    86
    +  disable() {
    
    87
    +    logger.trace("Domain isolation disabled");
    
    88
    +    this.#isolationEnabled = false;
    
    89
    +  }
    
    90
    +
    
    91
    +  /**
    
    92
    +   * Return the credentials to use as username and password for the SOCKS proxy,
    
    93
    +   * given a certain domain and userContextId. Optionally, create them.
    
    94
    +   *
    
    95
    +   * @param firstPartyDomain The first party domain associated to the requests
    
    96
    +   * @param userContextId The context ID associated to the request
    
    97
    +   * @param create Whether to create the nonce, if it is not available
    
    98
    +   * @return Either the credential, or null if we do not have them and create is
    
    99
    +   * false.
    
    100
    +   */
    
    101
    +  getSocksProxyCredentials(firstPartyDomain, userContextId, create = false) {
    
    102
    +    if (!this.#noncesForDomains.has(firstPartyDomain)) {
    
    103
    +      if (!create) {
    
    104
    +        return null;
    
    105
    +      }
    
    106
    +      const nonce = this.#nonce();
    
    107
    +      logger.info(`New nonce for first party ${firstPartyDomain}: ${nonce}`);
    
    108
    +      this.#noncesForDomains.set(firstPartyDomain, nonce);
    
    109
    +    }
    
    110
    +    if (!this.#noncesForUserContextId.has(userContextId)) {
    
    111
    +      if (!create) {
    
    112
    +        return null;
    
    113
    +      }
    
    114
    +      const nonce = this.#nonce();
    
    115
    +      logger.info(`New nonce for userContextId ${userContextId}: ${nonce}`);
    
    116
    +      this.#noncesForUserContextId.set(userContextId, nonce);
    
    117
    +    }
    
    118
    +    return {
    
    119
    +      username: this.#makeUsername(firstPartyDomain, userContextId),
    
    120
    +      password:
    
    121
    +        this.#noncesForDomains.get(firstPartyDomain) +
    
    122
    +        this.#noncesForUserContextId.get(userContextId),
    
    123
    +    };
    
    124
    +  }
    
    125
    +
    
    126
    +  /**
    
    127
    +   * Create a new nonce for the FP domain of the selected browser and reload the
    
    128
    +   * tab with a new circuit.
    
    129
    +   *
    
    130
    +   * @param browser Should be the gBrowser from the context of the caller
    
    131
    +   */
    
    132
    +  newCircuitForBrowser(browser) {
    
    133
    +    const firstPartyDomain = getDomainForBrowser(browser.selectedBrowser);
    
    134
    +    this.#newCircuitForDomain(firstPartyDomain);
    
    135
    +    // TODO: How to properly handle the user context? Should we use
    
    136
    +    // (domain, userContextId) pairs, instead of concatenating nonces?
    
    137
    +    browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
    
    138
    +  }
    
    139
    +
    
    140
    +  /**
    
    141
    +   * Clear the isolation state cache, forcing new circuits to be used for all
    
    142
    +   * subsequent requests.
    
    143
    +   */
    
    144
    +  clearIsolation() {
    
    145
    +    logger.trace("Clearing isolation nonces.");
    
    146
    +
    
    147
    +    // Per-domain and per contextId nonces are stored in maps, so simply clear
    
    148
    +    // them.
    
    149
    +    this.#noncesForDomains.clear();
    
    150
    +    this.#noncesForUserContextId.clear();
    
    151
    +
    
    152
    +    // Force a rotation on the next catch-all circuit use by setting the
    
    153
    +    // creation time to the epoch.
    
    154
    +    this.#catchallDirtySince = 0;
    
    155
    +  }
    
    156
    +
    
    157
    +  async observe(subject, topic, data) {
    
    158
    +    if (topic === "nsPref:changed" && data ="" NON_TOR_PROXY_PREF) {
    
    159
    +      if (Services.prefs.getBoolPref(NON_TOR_PROXY_PREF)) {
    
    160
    +        this.disable();
    
    161
    +      } else {
    
    162
    +        this.enable();
    
    163
    +      }
    
    164
    +    } else if (topic === NEW_IDENTITY_TOPIC) {
    
    165
    +      logger.info(
    
    166
    +        "New identity has been requested, clearing isolation tokens."
    
    167
    +      );
    
    168
    +      this.clearIsolation();
    
    169
    +      try {
    
    170
    +        await TorProtocolService.newnym();
    
    171
    +      } catch (e) {
    
    172
    +        logger.error("Could not send the newnym command", e);
    
    173
    +        // TODO: What UX to use here? See tor-browser#41708
    
    174
    +      }
    
    175
    +    }
    
    176
    +  }
    
    177
    +
    
    178
    +  /**
    
    179
    +   * Setup a filter that for every HTTPChannel, replaces the default SOCKS proxy
    
    180
    +   * with one that authenticates to the SOCKS server (the tor client process)
    
    181
    +   * with a username (the first party domain and userContextId) and a nonce
    
    182
    +   * password.
    
    183
    +   * Tor provides a separate circuit for each username+password combination.
    
    184
    +   */
    
    185
    +  #setupProxyFilter() {
    
    186
    +    const filterFunction = (aChannel, aProxy) => {
    
    187
    +      if (!this.#isolationEnabled) {
    
    188
    +        return aProxy;
    
    189
    +      }
    
    190
    +      try {
    
    191
    +        const channel = aChannel.QueryInterface(Ci.nsIChannel);
    
    192
    +        let firstPartyDomain =
    
    193
    +          channel.loadInfo.originAttributes.firstPartyDomain;
    
    194
    +        const userContextId = channel.loadInfo.originAttributes.userContextId;
    
    195
    +        if (firstPartyDomain === "") {
    
    196
    +          firstPartyDomain = CATCHALL_DOMAIN;
    
    197
    +          if (Date.now() - this.#catchallDirtySince > 1000 * 10 * 60) {
    
    198
    +            logger.info(
    
    199
    +              "tor catchall circuit has been dirty for over 10 minutes. Rotating."
    
    200
    +            );
    
    201
    +            this.#newCircuitForDomain(CATCHALL_DOMAIN);
    
    202
    +            this.#catchallDirtySince = Date.now();
    
    203
    +          }
    
    204
    +        }
    
    205
    +        const replacementProxy = this.#applySocksProxyCredentials(
    
    206
    +          aProxy,
    
    207
    +          firstPartyDomain,
    
    208
    +          userContextId
    
    209
    +        );
    
    210
    +        logger.debug(
    
    211
    +          `Requested ${channel.URI.spec} via ${replacementProxy.username}:${replacementProxy.password}`
    
    212
    +        );
    
    213
    +        return replacementProxy;
    
    214
    +      } catch (e) {
    
    215
    +        logger.error("Error while setting a new proxy", e);
    
    216
    +        return null;
    
    217
    +      }
    
    218
    +    };
    
    219
    +
    
    220
    +    ProtocolProxyService.registerChannelFilter(
    
    221
    +      {
    
    222
    +        applyFilter(aChannel, aProxy, aCallback) {
    
    223
    +          aCallback.onProxyFilterResult(filterFunction(aChannel, aProxy));
    
    224
    +        },
    
    225
    +      },
    
    226
    +      0
    
    227
    +    );
    
    228
    +  }
    
    229
    +
    
    230
    +  /**
    
    231
    +   * Takes a proxyInfo object (originalProxy) and returns a new proxyInfo
    
    232
    +   * object with the same properties, except the username is set to the
    
    233
    +   * the domain and userContextId, and the password is a nonce.
    
    234
    +   */
    
    235
    +  #applySocksProxyCredentials(originalProxy, domain, userContextId) {
    
    236
    +    const proxy = originalProxy.QueryInterface(Ci.nsIProxyInfo);
    
    237
    +    const { username, password } = this.getSocksProxyCredentials(
    
    238
    +      domain,
    
    239
    +      userContextId,
    
    240
    +      true
    
    241
    +    );
    
    242
    +    return ProtocolProxyService.newProxyInfoWithAuth(
    
    243
    +      "socks",
    
    244
    +      proxy.host,
    
    245
    +      proxy.port,
    
    246
    +      username,
    
    247
    +      password,
    
    248
    +      "", // aProxyAuthorizationHeader
    
    249
    +      "", // aConnectionIsolationKey
    
    250
    +      proxy.flags,
    
    251
    +      proxy.failoverTimeout,
    
    252
    +      proxy.failoverProxy
    
    253
    +    );
    
    254
    +  }
    
    255
    +
    
    256
    +  /**
    
    257
    +   * Combine the needed data into a username for the proxy.
    
    258
    +   */
    
    259
    +  #makeUsername(domain, userContextId) {
    
    260
    +    if (!domain) {
    
    261
    +      domain = CATCHALL_DOMAIN;
    
    262
    +    }
    
    263
    +    return `${domain}:${userContextId}`;
    
    264
    +  }
    
    265
    +
    
    266
    +  /**
    
    267
    +   * Generate a new 128 bit random tag.
    
    268
    +   *
    
    269
    +   * Strictly speaking both using a cryptographic entropy source and using 128
    
    270
    +   * bits of entropy for the tag are likely overkill, as correct behavior only
    
    271
    +   * depends on how unlikely it is for there to be a collision.
    
    272
    +   */
    
    273
    +  #nonce() {
    
    274
    +    return Array.from(crypto.getRandomValues(new Uint8Array(16)), byte =>
    
    275
    +      byte.toString(16).padStart(2, "0")
    
    276
    +    ).join("");
    
    277
    +  }
    
    278
    +
    
    279
    +  /**
    
    280
    +   * Re-generate the nonce for a certain domain.
    
    281
    +   */
    
    282
    +  #newCircuitForDomain(domain) {
    
    283
    +    if (!domain) {
    
    284
    +      domain = CATCHALL_DOMAIN;
    
    285
    +    }
    
    286
    +    this.#noncesForDomains.set(domain, this.#nonce());
    
    287
    +    logger.info(
    
    288
    +      `New domain isolation for ${domain}: ${this.#noncesForDomains.get(
    
    289
    +        domain
    
    290
    +      )}`
    
    291
    +    );
    
    292
    +  }
    
    293
    +
    
    294
    +  /**
    
    295
    +   * Re-generate the nonce for a userContextId.
    
    296
    +   *
    
    297
    +   * Currently, this function is not hooked to anything.
    
    298
    +   */
    
    299
    +  #newCircuitForUserContextId(userContextId) {
    
    300
    +    this.#noncesForUserContextId.set(userContextId, this.#nonce());
    
    301
    +    logger.info(
    
    302
    +      `New container isolation for ${userContextId}: ${this.#noncesForUserContextId.get(
    
    303
    +        userContextId
    
    304
    +      )}`
    
    305
    +    );
    
    306
    +  }
    
    307
    +}
    
    308
    +
    
    309
    +/**
    
    310
    + * Get the first party domain for a certain browser.
    
    311
    + *
    
    312
    + * @param browser The browser to get the FP-domain for.
    
    313
    + *
    
    314
    + * Please notice that it should be gBrowser.selectedBrowser, because
    
    315
    + * browser.documentURI is the actual shown page, and might be an error page.
    
    316
    + * In this case, we rely on currentURI, which for gBrowser is an alias of
    
    317
    + * gBrowser.selectedBrowser.currentURI.
    
    318
    + * See browser/base/content/tabbrowser.js and tor-browser#31562.
    
    319
    + */
    
    320
    +function getDomainForBrowser(browser) {
    
    321
    +  let fpd = browser.contentPrincipal.originAttributes.firstPartyDomain;
    
    322
    +
    
    323
    +  // Bug 31562: For neterror or certerror, get the original URL from
    
    324
    +  // browser.currentURI and use it to calculate the firstPartyDomain.
    
    325
    +  const knownErrors = [
    
    326
    +    "about:neterror",
    
    327
    +    "about:certerror",
    
    328
    +    "about:httpsonlyerror",
    
    329
    +  ];
    
    330
    +  const { documentURI } = browser;
    
    331
    +  if (
    
    332
    +    documentURI &&
    
    333
    +    documentURI.schemeIs("about") &&
    
    334
    +    knownErrors.some(x => documentURI.spec.startsWith(x))
    
    335
    +  ) {
    
    336
    +    const knownSchemes = ["http", "https"];
    
    337
    +    const currentURI = browser.currentURI;
    
    338
    +    if (currentURI && knownSchemes.some(x => currentURI.schemeIs(x))) {
    
    339
    +      try {
    
    340
    +        fpd = Services.eTLD.getBaseDomainFromHost(currentURI.host);
    
    341
    +      } catch (e) {
    
    342
    +        if (
    
    343
    +          e.result === Cr.NS_ERROR_HOST_IS_IP_ADDRESS ||
    
    344
    +          e.result === Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
    
    345
    +        ) {
    
    346
    +          fpd = currentURI.host;
    
    347
    +        } else {
    
    348
    +          logger.error(
    
    349
    +            `Failed to get first party domain for host ${currentURI.host}`,
    
    350
    +            e
    
    351
    +          );
    
    352
    +        }
    
    353
    +      }
    
    354
    +    }
    
    355
    +  }
    
    356
    +
    
    357
    +  return fpd;
    
    358
    +}
    
    359
    +
    
    360
    +const TorDomainIsolator = new TorDomainIsolatorImpl();
    
    361
    +// Reduce global vars pollution
    
    362
    +TorDomainIsolator.getDomainForBrowser = getDomainForBrowser;

  • toolkit/components/tor-launcher/TorProtocolService.jsm
    ... ... @@ -4,6 +4,7 @@
    4 4
     
    
    5 5
     var EXPORTED_SYMBOLS = ["TorProtocolService"];
    
    6 6
     
    
    7
    +const { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm");
    
    7 8
     const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
    
    8 9
     const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
    
    9 10
     ChromeUtils.defineModuleGetter(
    
    ... ... @@ -11,9 +12,6 @@ ChromeUtils.defineModuleGetter(
    11 12
       "FileUtils",
    
    12 13
       "resource://gre/modules/FileUtils.jsm"
    
    13 14
     );
    
    14
    -const { XPCOMUtils } = ChromeUtils.import(
    
    15
    -  "resource://gre/modules/XPCOMUtils.jsm"
    
    16
    -);
    
    17 15
     
    
    18 16
     Cu.importGlobalProperties(["crypto"]);
    
    19 17
     
    
    ... ... @@ -45,18 +43,9 @@ const TorTopics = Object.freeze({
    45 43
       ProcessRestarted: "TorProcessRestarted",
    
    46 44
     });
    
    47 45
     
    
    48
    -// Logger adapted from CustomizableUI.jsm
    
    49
    -XPCOMUtils.defineLazyGetter(this, "logger", () => {
    
    50
    -  const { ConsoleAPI } = ChromeUtils.import(
    
    51
    -    "resource://gre/modules/Console.jsm"
    
    52
    -  );
    
    53
    -  // TODO: Use a preference to set the log level.
    
    54
    -  const consoleOptions = {
    
    55
    -    // maxLogLevel: "warn",
    
    56
    -    maxLogLevel: "all",
    
    57
    -    prefix: "TorProtocolService",
    
    58
    -  };
    
    59
    -  return new ConsoleAPI(consoleOptions);
    
    46
    +const logger = new ConsoleAPI({
    
    47
    +  maxLogLevel: "warn",
    
    48
    +  prefix: "TorProtocolService",
    
    60 49
     });
    
    61 50
     
    
    62 51
     // Manage the connection to tor's control port, to update its settings and query
    
    ... ... @@ -194,6 +183,10 @@ const TorProtocolService = {
    194 183
         TorMonitorService.retrieveBootstrapStatus();
    
    195 184
       },
    
    196 185
     
    
    186
    +  async newnym() {
    
    187
    +    return this.sendCommand("SIGNAL NEWNYM");
    
    188
    +  },
    
    189
    +
    
    197 190
       // TODO: transform the following 4 functions in getters. At the moment they
    
    198 191
       // are also used in torbutton.
    
    199 192
     
    

  • toolkit/components/tor-launcher/TorStartupService.jsm
    ... ... @@ -33,6 +33,12 @@ ChromeUtils.defineModuleGetter(
    33 33
       "resource:///modules/TorSettings.jsm"
    
    34 34
     );
    
    35 35
     
    
    36
    +ChromeUtils.defineModuleGetter(
    
    37
    +  this,
    
    38
    +  "TorDomainIsolator",
    
    39
    +  "resource://gre/modules/TorDomainIsolator.jsm"
    
    40
    +);
    
    41
    +
    
    36 42
     /* Browser observer topis */
    
    37 43
     const BrowserTopics = Object.freeze({
    
    38 44
       ProfileAfterChange: "profile-after-change",
    
    ... ... @@ -67,12 +73,16 @@ class TorStartupService {
    67 73
         TorSettings.init();
    
    68 74
         TorConnect.init();
    
    69 75
     
    
    76
    +    TorDomainIsolator.init();
    
    77
    +
    
    70 78
         gInited = true;
    
    71 79
       }
    
    72 80
     
    
    73 81
       _uninit() {
    
    74 82
         Services.obs.removeObserver(this, BrowserTopics.QuitApplicationGranted);
    
    75 83
     
    
    84
    +    TorDomainIsolator.uninit();
    
    85
    +
    
    76 86
         // Close any helper connection first...
    
    77 87
         TorProtocolService.uninit();
    
    78 88
         // ... and only then closes the event monitor connection, which will cause
    

  • toolkit/components/tor-launcher/moz.build
    1 1
     EXTRA_JS_MODULES += [
    
    2 2
         "TorBootstrapRequest.jsm",
    
    3
    +    "TorDomainIsolator.jsm",
    
    3 4
         "TorLauncherUtil.jsm",
    
    4 5
         "TorMonitorService.jsm",
    
    5 6
         "TorParsers.jsm",
    

  • toolkit/torbutton/chrome/content/torbutton.js
    1 1
     // window globals
    
    2 2
     var torbutton_init;
    
    3
    -var torbutton_new_circuit;
    
    4 3
     
    
    5 4
     (() => {
    
    6 5
       // Bug 1506 P1-P5: This is the main Torbutton overlay file. Much needs to be
    
    ... ... @@ -16,9 +15,7 @@ var torbutton_new_circuit;
    16 15
     
    
    17 16
       let {
    
    18 17
         unescapeTorString,
    
    19
    -    getDomainForBrowser,
    
    20 18
         torbutton_log,
    
    21
    -    torbutton_get_property_string,
    
    22 19
       } = ChromeUtils.import("resource://torbutton/modules/utils.js");
    
    23 20
       let { configureControlPortModule, wait_for_controller } = ChromeUtils.import(
    
    24 21
         "resource://torbutton/modules/tor-control-port.js"
    
    ... ... @@ -46,32 +43,22 @@ var torbutton_new_circuit;
    46 43
       // in a component, not the XUL overlay.
    
    47 44
       var torbutton_unique_pref_observer = {
    
    48 45
         register() {
    
    49
    -      this.forced_ua = false;
    
    50
    -      m_tb_prefs.addObserver("extensions.torbutton", this);
    
    51
    -      m_tb_prefs.addObserver("browser.privatebrowsing.autostart", this);
    
    52
    -      m_tb_prefs.addObserver("_javascript_", this);
    
    46
    +      Services.prefs.addObserver("browser.privatebrowsing.autostart", this);
    
    53 47
         },
    
    54 48
     
    
    55 49
         unregister() {
    
    56
    -      m_tb_prefs.removeObserver("extensions.torbutton", this);
    
    57
    -      m_tb_prefs.removeObserver("browser.privatebrowsing.autostart", this);
    
    58
    -      m_tb_prefs.removeObserver("_javascript_", this);
    
    50
    +      Services.prefs.removeObserver("browser.privatebrowsing.autostart", this);
    
    59 51
         },
    
    60 52
     
    
    61 53
         // topic:   what event occurred
    
    62 54
         // subject: what nsIPrefBranch we're observing
    
    63 55
         // data:    which pref has been changed (relative to subject)
    
    64 56
         observe(subject, topic, data) {
    
    65
    -      if (topic !== "nsPref:changed") {
    
    66
    -        return;
    
    67
    -      }
    
    68
    -      switch (data) {
    
    69
    -        case "browser.privatebrowsing.autostart":
    
    70
    -          torbutton_update_disk_prefs();
    
    71
    -          break;
    
    72
    -        case "extensions.torbutton.use_nontor_proxy":
    
    73
    -          torbutton_use_nontor_proxy();
    
    74
    -          break;
    
    57
    +      if (
    
    58
    +        topic === "nsPref:changed" &&
    
    59
    +        data === "browser.privatebrowsing.autostart"
    
    60
    +      ) {
    
    61
    +        torbutton_update_disk_prefs();
    
    75 62
           }
    
    76 63
         },
    
    77 64
       };
    
    ... ... @@ -113,62 +100,6 @@ var torbutton_new_circuit;
    113 100
         },
    
    114 101
       };
    
    115 102
     
    
    116
    -  var torbutton_new_identity_observers = {
    
    117
    -    register() {
    
    118
    -      Services.obs.addObserver(this, "new-identity-requested");
    
    119
    -    },
    
    120
    -
    
    121
    -    observe(aSubject, aTopic, aData) {
    
    122
    -      if (aTopic !== "new-identity-requested") {
    
    123
    -        return;
    
    124
    -      }
    
    125
    -
    
    126
    -      // Clear the domain isolation state.
    
    127
    -      torbutton_log(3, "Clearing domain isolator");
    
    128
    -      const domainIsolator = Cc["@torproject.org/domain-isolator;1"].getService(
    
    129
    -        Ci.nsISupports
    
    130
    -      ).wrappedJSObject;
    
    131
    -      domainIsolator.clearIsolation();
    
    132
    -
    
    133
    -      torbutton_log(3, "New Identity: Sending NEWNYM");
    
    134
    -      // We only support TBB for newnym.
    
    135
    -      if (
    
    136
    -        !m_tb_control_pass ||
    
    137
    -        (!m_tb_control_ipc_file && !m_tb_control_port)
    
    138
    -      ) {
    
    139
    -        const warning = torbutton_get_property_string(
    
    140
    -          "torbutton.popup.no_newnym"
    
    141
    -        );
    
    142
    -        torbutton_log(
    
    143
    -          5,
    
    144
    -          "Torbutton cannot safely newnym. It does not have access to the Tor Control Port."
    
    145
    -        );
    
    146
    -        window.alert(warning);
    
    147
    -      } else {
    
    148
    -        const warning = torbutton_get_property_string(
    
    149
    -          "torbutton.popup.no_newnym"
    
    150
    -        );
    
    151
    -        torbutton_send_ctrl_cmd("SIGNAL NEWNYM")
    
    152
    -          .then(res => {
    
    153
    -            if (!res) {
    
    154
    -              torbutton_log(
    
    155
    -                5,
    
    156
    -                "Torbutton was unable to request a new circuit from Tor"
    
    157
    -              );
    
    158
    -              window.alert(warning);
    
    159
    -            }
    
    160
    -          })
    
    161
    -          .catch(e => {
    
    162
    -            torbutton_log(
    
    163
    -              5,
    
    164
    -              "Torbutton was unable to request a new circuit from Tor " + e
    
    165
    -            );
    
    166
    -            window.alert(warning);
    
    167
    -          });
    
    168
    -      }
    
    169
    -    },
    
    170
    -  };
    
    171
    -
    
    172 103
       // Bug 1506 P2-P4: This code sets some version variables that are irrelevant.
    
    173 104
       // It does read out some important environment variables, though. It is
    
    174 105
       // called once per browser window.. This might belong in a component.
    
    ... ... @@ -258,8 +189,6 @@ var torbutton_new_circuit;
    258 189
           true
    
    259 190
         );
    
    260 191
     
    
    261
    -    torbutton_new_identity_observers.register();
    
    262
    -
    
    263 192
         torbutton_log(3, "init completed");
    
    264 193
       };
    
    265 194
     
    
    ... ... @@ -374,36 +303,6 @@ var torbutton_new_circuit;
    374 303
         return response;
    
    375 304
       }
    
    376 305
     
    
    377
    -  // Bug 1506 P4: Needed for New IP Address
    
    378
    -  torbutton_new_circuit = function() {
    
    379
    -    let firstPartyDomain = getDomainForBrowser(gBrowser.selectedBrowser);
    
    380
    -
    
    381
    -    let domainIsolator = Cc["@torproject.org/domain-isolator;1"].getService(
    
    382
    -      Ci.nsISupports
    
    383
    -    ).wrappedJSObject;
    
    384
    -
    
    385
    -    domainIsolator.newCircuitForDomain(firstPartyDomain);
    
    386
    -
    
    387
    -    gBrowser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
    
    388
    -  };
    
    389
    -
    
    390
    -  /* Called when we switch the use_nontor_proxy pref in either direction.
    
    391
    -   *
    
    392
    -   * Enables/disables domain isolation and then does new identity
    
    393
    -   */
    
    394
    -  function torbutton_use_nontor_proxy() {
    
    395
    -    let domainIsolator = Cc["@torproject.org/domain-isolator;1"].getService(
    
    396
    -      Ci.nsISupports
    
    397
    -    ).wrappedJSObject;
    
    398
    -
    
    399
    -    if (m_tb_prefs.getBoolPref("extensions.torbutton.use_nontor_proxy")) {
    
    400
    -      // Disable domain isolation
    
    401
    -      domainIsolator.disableIsolation();
    
    402
    -    } else {
    
    403
    -      domainIsolator.enableIsolation();
    
    404
    -    }
    
    405
    -  }
    
    406
    -
    
    407 306
       async function torbutton_do_tor_check() {
    
    408 307
         let checkSvc = Cc["@torproject.org/torbutton-torCheckService;1"].getService(
    
    409 308
           Ci.nsISupports
    

  • toolkit/torbutton/components/domain-isolator.js deleted
    1
    -// # domain-isolator.js
    
    2
    -// A component for TorBrowser that puts requests from different
    
    3
    -// first party domains on separate tor circuits.
    
    4
    -
    
    5
    -// This file is written in call stack order (later functions
    
    6
    -// call earlier functions). The code file can be processed
    
    7
    -// with docco.js to provide clear documentation.
    
    8
    -
    
    9
    -// ### Abbreviations
    
    10
    -
    
    11
    -const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
    
    12
    -const { XPCOMUtils } = ChromeUtils.import(
    
    13
    -  "resource://gre/modules/XPCOMUtils.jsm"
    
    14
    -);
    
    15
    -
    
    16
    -XPCOMUtils.defineLazyModuleGetters(this, {
    
    17
    -  ComponentUtils: "resource://gre/modules/ComponentUtils.jsm",
    
    18
    -});
    
    19
    -
    
    20
    -// Make the logger available.
    
    21
    -let logger = Cc["@torproject.org/torbutton-logger;1"].getService(Ci.nsISupports)
    
    22
    -  .wrappedJSObject;
    
    23
    -
    
    24
    -// Import crypto object (FF 37+).
    
    25
    -Cu.importGlobalProperties(["crypto"]);
    
    26
    -
    
    27
    -// ## mozilla namespace.
    
    28
    -// Useful functionality for interacting with Mozilla services.
    
    29
    -let mozilla = {};
    
    30
    -
    
    31
    -// __mozilla.protocolProxyService__.
    
    32
    -// Mozilla's protocol proxy service, useful for managing proxy connections made
    
    33
    -// by the browser.
    
    34
    -mozilla.protocolProxyService = Cc[
    
    35
    -  "@mozilla.org/network/protocol-proxy-service;1"
    
    36
    -].getService(Ci.nsIProtocolProxyService);
    
    37
    -
    
    38
    -// __mozilla.registerProxyChannelFilter(filterFunction, positionIndex)__.
    
    39
    -// Registers a proxy channel filter with the Mozilla Protocol Proxy Service,
    
    40
    -// which will help to decide the proxy to be used for a given channel.
    
    41
    -// The filterFunction should expect two arguments, (aChannel, aProxy),
    
    42
    -// where aProxy is the proxy or list of proxies that would be used by default
    
    43
    -// for the given channel, and should return a new Proxy or list of Proxies.
    
    44
    -mozilla.registerProxyChannelFilter = function(filterFunction, positionIndex) {
    
    45
    -  let proxyFilter = {
    
    46
    -    applyFilter(aChannel, aProxy, aCallback) {
    
    47
    -      aCallback.onProxyFilterResult(filterFunction(aChannel, aProxy));
    
    48
    -    },
    
    49
    -  };
    
    50
    -  mozilla.protocolProxyService.registerChannelFilter(
    
    51
    -    proxyFilter,
    
    52
    -    positionIndex
    
    53
    -  );
    
    54
    -};
    
    55
    -
    
    56
    -// ## tor functionality.
    
    57
    -let tor = {};
    
    58
    -
    
    59
    -// __tor.noncesForDomains__.
    
    60
    -// A mutable map that records what nonce we are using for each domain.
    
    61
    -tor.noncesForDomains = new Map();
    
    62
    -
    
    63
    -// __tor.noncesForUserContextId__.
    
    64
    -// A mutable map that records what nonce we are using for each tab container.
    
    65
    -tor.noncesForUserContextId = new Map();
    
    66
    -
    
    67
    -// __tor.isolationEabled__.
    
    68
    -// A bool that controls if we use SOCKS auth for isolation or not.
    
    69
    -tor.isolationEnabled = true;
    
    70
    -
    
    71
    -// __tor.unknownDirtySince__.
    
    72
    -// Specifies when the current catch-all circuit was first used
    
    73
    -tor.unknownDirtySince = Date.now();
    
    74
    -
    
    75
    -tor.passwordForDomainAndUserContextId = function(
    
    76
    -  domain,
    
    77
    -  userContextId,
    
    78
    -  create
    
    79
    -) {
    
    80
    -  // Check if we already have a nonce. If not, possibly create one for this
    
    81
    -  // domain and userContextId.
    
    82
    -  if (!tor.noncesForDomains.has(domain)) {
    
    83
    -    if (!create) {
    
    84
    -      return null;
    
    85
    -    }
    
    86
    -    tor.noncesForDomains.set(domain, tor.nonce());
    
    87
    -  }
    
    88
    -  if (!tor.noncesForUserContextId.has(userContextId)) {
    
    89
    -    if (!create) {
    
    90
    -      return null;
    
    91
    -    }
    
    92
    -    tor.noncesForUserContextId.set(userContextId, tor.nonce());
    
    93
    -  }
    
    94
    -  return (
    
    95
    -    tor.noncesForDomains.get(domain) +
    
    96
    -    tor.noncesForUserContextId.get(userContextId)
    
    97
    -  );
    
    98
    -};
    
    99
    -
    
    100
    -tor.usernameForDomainAndUserContextId = function(domain, userContextId) {
    
    101
    -  return `${domain}:${userContextId}`;
    
    102
    -};
    
    103
    -
    
    104
    -// __tor.socksProxyCredentials(originalProxy, domain, userContextId)__.
    
    105
    -// Takes a proxyInfo object (originalProxy) and returns a new proxyInfo
    
    106
    -// object with the same properties, except the username is set to the
    
    107
    -// the domain and userContextId, and the password is a nonce.
    
    108
    -tor.socksProxyCredentials = function(originalProxy, domain, userContextId) {
    
    109
    -  let proxy = originalProxy.QueryInterface(Ci.nsIProxyInfo);
    
    110
    -  let proxyUsername = tor.usernameForDomainAndUserContextId(
    
    111
    -    domain,
    
    112
    -    userContextId
    
    113
    -  );
    
    114
    -  let proxyPassword = tor.passwordForDomainAndUserContextId(
    
    115
    -    domain,
    
    116
    -    userContextId,
    
    117
    -    true
    
    118
    -  );
    
    119
    -  return mozilla.protocolProxyService.newProxyInfoWithAuth(
    
    120
    -    "socks",
    
    121
    -    proxy.host,
    
    122
    -    proxy.port,
    
    123
    -    proxyUsername,
    
    124
    -    proxyPassword,
    
    125
    -    "", // aProxyAuthorizationHeader
    
    126
    -    "", // aConnectionIsolationKey
    
    127
    -    proxy.flags,
    
    128
    -    proxy.failoverTimeout,
    
    129
    -    proxy.failoverProxy
    
    130
    -  );
    
    131
    -};
    
    132
    -
    
    133
    -tor.nonce = function() {
    
    134
    -  // Generate a new 128 bit random tag.  Strictly speaking both using a
    
    135
    -  // cryptographic entropy source and using 128 bits of entropy for the
    
    136
    -  // tag are likely overkill, as correct behavior only depends on how
    
    137
    -  // unlikely it is for there to be a collision.
    
    138
    -  let tag = new Uint8Array(16);
    
    139
    -  crypto.getRandomValues(tag);
    
    140
    -
    
    141
    -  // Convert the tag to a hex string.
    
    142
    -  let tagStr = "";
    
    143
    -  for (let i = 0; i < tag.length; i++) {
    
    144
    -    tagStr += (tag[i] >>> 4).toString(16);
    
    145
    -    tagStr += (tag[i] & 0x0f).toString(16);
    
    146
    -  }
    
    147
    -
    
    148
    -  return tagStr;
    
    149
    -};
    
    150
    -
    
    151
    -tor.newCircuitForDomain = function(domain) {
    
    152
    -  // Re-generate the nonce for the domain.
    
    153
    -  if (domain === "") {
    
    154
    -    domain = "--unknown--";
    
    155
    -  }
    
    156
    -  tor.noncesForDomains.set(domain, tor.nonce());
    
    157
    -  logger.eclog(
    
    158
    -    3,
    
    159
    -    `New domain isolation for ${domain}: ${tor.noncesForDomains.get(domain)}`
    
    160
    -  );
    
    161
    -};
    
    162
    -
    
    163
    -tor.newCircuitForUserContextId = function(userContextId) {
    
    164
    -  // Re-generate the nonce for the context.
    
    165
    -  tor.noncesForUserContextId.set(userContextId, tor.nonce());
    
    166
    -  logger.eclog(
    
    167
    -    3,
    
    168
    -    `New container isolation for ${userContextId}: ${tor.noncesForUserContextId.get(
    
    169
    -      userContextId
    
    170
    -    )}`
    
    171
    -  );
    
    172
    -};
    
    173
    -
    
    174
    -// __tor.clearIsolation()_.
    
    175
    -// Clear the isolation state cache, forcing new circuits to be used for all
    
    176
    -// subsequent requests.
    
    177
    -tor.clearIsolation = function() {
    
    178
    -  // Per-domain and per contextId nonces are stored in maps, so simply clear them.
    
    179
    -  tor.noncesForDomains.clear();
    
    180
    -  tor.noncesForUserContextId.clear();
    
    181
    -
    
    182
    -  // Force a rotation on the next catch-all circuit use by setting the creation
    
    183
    -  // time to the epoch.
    
    184
    -  tor.unknownDirtySince = 0;
    
    185
    -};
    
    186
    -
    
    187
    -// __tor.isolateCircuitsByDomain()__.
    
    188
    -// For every HTTPChannel, replaces the default SOCKS proxy with one that authenticates
    
    189
    -// to the SOCKS server (the tor client process) with a username (the first party domain
    
    190
    -// and userContextId) and a nonce password. Tor provides a separate circuit for each
    
    191
    -// username+password combination.
    
    192
    -tor.isolateCircuitsByDomain = function() {
    
    193
    -  mozilla.registerProxyChannelFilter(function(aChannel, aProxy) {
    
    194
    -    if (!tor.isolationEnabled) {
    
    195
    -      return aProxy;
    
    196
    -    }
    
    197
    -    try {
    
    198
    -      let channel = aChannel.QueryInterface(Ci.nsIChannel),
    
    199
    -        firstPartyDomain = channel.loadInfo.originAttributes.firstPartyDomain,
    
    200
    -        userContextId = channel.loadInfo.originAttributes.userContextId;
    
    201
    -      if (firstPartyDomain === "") {
    
    202
    -        firstPartyDomain = "--unknown--";
    
    203
    -        if (Date.now() - tor.unknownDirtySince > 1000 * 10 * 60) {
    
    204
    -          logger.eclog(
    
    205
    -            3,
    
    206
    -            "tor catchall circuit has been dirty for over 10 minutes. Rotating."
    
    207
    -          );
    
    208
    -          tor.newCircuitForDomain("--unknown--");
    
    209
    -          tor.unknownDirtySince = Date.now();
    
    210
    -        }
    
    211
    -      }
    
    212
    -      let replacementProxy = tor.socksProxyCredentials(
    
    213
    -        aProxy,
    
    214
    -        firstPartyDomain,
    
    215
    -        userContextId
    
    216
    -      );
    
    217
    -      logger.eclog(
    
    218
    -        3,
    
    219
    -        `tor SOCKS: ${channel.URI.spec} via
    
    220
    -                       ${replacementProxy.username}:${replacementProxy.password}`
    
    221
    -      );
    
    222
    -      return replacementProxy;
    
    223
    -    } catch (e) {
    
    224
    -      logger.eclog(4, `tor domain isolator error: ${e.message}`);
    
    225
    -      return null;
    
    226
    -    }
    
    227
    -  }, 0);
    
    228
    -};
    
    229
    -
    
    230
    -// ## XPCOM component construction.
    
    231
    -// Module specific constants
    
    232
    -const kMODULE_NAME = "TorBrowser Domain Isolator";
    
    233
    -const kMODULE_CONTRACTID = "@torproject.org/domain-isolator;1";
    
    234
    -const kMODULE_CID = Components.ID("e33fd6d4-270f-475f-a96f-ff3140279f68");
    
    235
    -
    
    236
    -// DomainIsolator object.
    
    237
    -function DomainIsolator() {
    
    238
    -  this.wrappedJSObject = this;
    
    239
    -}
    
    240
    -
    
    241
    -// Firefox component requirements
    
    242
    -DomainIsolator.prototype = {
    
    243
    -  QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
    
    244
    -  classDescription: kMODULE_NAME,
    
    245
    -  classID: kMODULE_CID,
    
    246
    -  contractID: kMODULE_CONTRACTID,
    
    247
    -  observe(subject, topic, data) {
    
    248
    -    if (topic === "profile-after-change") {
    
    249
    -      logger.eclog(3, "domain isolator: set up isolating circuits by domain");
    
    250
    -
    
    251
    -      if (Services.prefs.getBoolPref("extensions.torbutton.use_nontor_proxy")) {
    
    252
    -        tor.isolationEnabled = false;
    
    253
    -      }
    
    254
    -      tor.isolateCircuitsByDomain();
    
    255
    -    }
    
    256
    -  },
    
    257
    -
    
    258
    -  newCircuitForDomain(domain) {
    
    259
    -    tor.newCircuitForDomain(domain);
    
    260
    -  },
    
    261
    -
    
    262
    -  /**
    
    263
    -   * Return the stored SOCKS proxy username and password for the given domain
    
    264
    -   * and user context ID.
    
    265
    -   *
    
    266
    -   * @param {string} firstPartyDomain - The domain to lookup credentials for.
    
    267
    -   * @param {integer} userContextId - The ID for the user context.
    
    268
    -   *
    
    269
    -   * @return {{ username: string, password: string }?} - The SOCKS credentials,
    
    270
    -   *   or null if none are found.
    
    271
    -   */
    
    272
    -  getSocksProxyCredentials(firstPartyDomain, userContextId) {
    
    273
    -    if (firstPartyDomain == "") {
    
    274
    -      firstPartyDomain = "--unknown--";
    
    275
    -    }
    
    276
    -    let proxyPassword = tor.passwordForDomainAndUserContextId(
    
    277
    -      firstPartyDomain,
    
    278
    -      userContextId,
    
    279
    -      // Do not create a new entry if it does not exist.
    
    280
    -      false
    
    281
    -    );
    
    282
    -    if (!proxyPassword) {
    
    283
    -      return null;
    
    284
    -    }
    
    285
    -    return {
    
    286
    -      username: tor.usernameForDomainAndUserContextId(
    
    287
    -        firstPartyDomain,
    
    288
    -        userContextId
    
    289
    -      ),
    
    290
    -      password: proxyPassword,
    
    291
    -    };
    
    292
    -  },
    
    293
    -
    
    294
    -  enableIsolation() {
    
    295
    -    tor.isolationEnabled = true;
    
    296
    -  },
    
    297
    -
    
    298
    -  disableIsolation() {
    
    299
    -    tor.isolationEnabled = false;
    
    300
    -  },
    
    301
    -
    
    302
    -  clearIsolation() {
    
    303
    -    tor.clearIsolation();
    
    304
    -  },
    
    305
    -
    
    306
    -  wrappedJSObject: null,
    
    307
    -};
    
    308
    -
    
    309
    -// Assign factory to global object.
    
    310
    -const NSGetFactory = XPCOMUtils.generateNSGetFactory
    
    311
    -  ? XPCOMUtils.generateNSGetFactory([DomainIsolator])
    
    312
    -  : ComponentUtils.generateNSGetFactory([DomainIsolator]);

  • toolkit/torbutton/jar.mn
    ... ... @@ -43,9 +43,5 @@ torbutton.jar:
    43 43
     % component {f36d72c9-9718-4134-b550-e109638331d7} %components/torbutton-logger.js
    
    44 44
     % contract @torproject.org/torbutton-logger;1 {f36d72c9-9718-4134-b550-e109638331d7}
    
    45 45
     
    
    46
    -% component {e33fd6d4-270f-475f-a96f-ff3140279f68} %components/domain-isolator.js
    
    47
    -% contract @torproject.org/domain-isolator;1 {e33fd6d4-270f-475f-a96f-ff3140279f68}
    
    48
    -
    
    49 46
     % category profile-after-change StartupObserver @torproject.org/startup-observer;1
    
    50
    -% category profile-after-change DomainIsolator @torproject.org/domain-isolator;1
    
    51 47
     % category profile-after-change DragDropFilter @torproject.org/torbutton-dragDropFilter;1

  • toolkit/torbutton/modules/utils.js
    ... ... @@ -213,45 +213,6 @@ var unescapeTorString = function(str) {
    213 213
       return _torControl._strUnescape(str);
    
    214 214
     };
    
    215 215
     
    
    216
    -var getFPDFromHost = hostname => {
    
    217
    -  try {
    
    218
    -    return Services.eTLD.getBaseDomainFromHost(hostname);
    
    219
    -  } catch (e) {
    
    220
    -    if (
    
    221
    -      e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS ||
    
    222
    -      e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
    
    223
    -    ) {
    
    224
    -      return hostname;
    
    225
    -    }
    
    226
    -  }
    
    227
    -  return null;
    
    228
    -};
    
    229
    -
    
    230
    -// Assuming this is called with gBrowser.selectedBrowser
    
    231
    -var getDomainForBrowser = browser => {
    
    232
    -  let fpd = browser.contentPrincipal.originAttributes.firstPartyDomain;
    
    233
    -  // Bug 31562: For neterror or certerror, get the original URL from
    
    234
    -  // browser.currentURI and use it to calculate the firstPartyDomain.
    
    235
    -  let knownErrors = [
    
    236
    -    "about:neterror",
    
    237
    -    "about:certerror",
    
    238
    -    "about:httpsonlyerror",
    
    239
    -  ];
    
    240
    -  let documentURI = browser.documentURI;
    
    241
    -  if (
    
    242
    -    documentURI &&
    
    243
    -    documentURI.schemeIs("about") &&
    
    244
    -    knownErrors.some(x => documentURI.spec.startsWith(x))
    
    245
    -  ) {
    
    246
    -    let knownSchemes = ["http", "https", "ftp"];
    
    247
    -    let currentURI = browser.currentURI;
    
    248
    -    if (currentURI && knownSchemes.some(x => currentURI.schemeIs(x))) {
    
    249
    -      fpd = getFPDFromHost(currentURI.host) || fpd;
    
    250
    -    }
    
    251
    -  }
    
    252
    -  return fpd;
    
    253
    -};
    
    254
    -
    
    255 216
     var m_tb_torlog = Cc["@torproject.org/torbutton-logger;1"].getService(
    
    256 217
       Ci.nsISupports
    
    257 218
     ).wrappedJSObject;
    
    ... ... @@ -310,7 +271,6 @@ let EXPORTED_SYMBOLS = [
    310 271
       "bindPrefAndInit",
    
    311 272
       "getEnv",
    
    312 273
       "getLocale",
    
    313
    -  "getDomainForBrowser",
    
    314 274
       "getPrefValue",
    
    315 275
       "observe",
    
    316 276
       "showDialog",
    

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