commit 59445b7baed58e712bd38c02e6dc75882ff0c997
Author: Arthur Edelstein <[email protected]>
Date:   Mon Jul 14 00:40:13 2014 -0700

    Bug #3455.3: Add DomainIsolator, for isolating circuit by domain.
    
    An XPCOM component that registers a ProtocolProxyChannelFilter
    which sets the username/password for each web request according to
    url bar domain.
---
 src/chrome.manifest               |    5 +-
 src/components/domain-isolator.js |  128 +++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/src/chrome.manifest b/src/chrome.manifest
index af44862..d211984 100644
--- a/src/chrome.manifest
+++ b/src/chrome.manifest
@@ -155,7 +155,10 @@ contract @torproject.org/torbutton-torCheckService;1 
{5d57312b-5d8c-4169-b4af-e8
 component {f36d72c9-9718-4134-b550-e109638331d7} components/torbutton-logger.js
 contract @torproject.org/torbutton-logger;1 
{f36d72c9-9718-4134-b550-e109638331d7}
 
+component {e33fd6d4-270f-475f-a96f-ff3140279f68} components/domain-isolator.js
+contract @torproject.org/domain-isolator;1 
{e33fd6d4-270f-475f-a96f-ff3140279f68}
+
 category profile-after-change CookieJarSelector 
@torproject.org/cookie-jar-selector;1
-# category profile-after-change RefSpoofer @torproject.org/torRefSpoofer;1
 category profile-after-change TBSessionBlocker 
@torproject.org/torbutton-ss-blocker;1
 category profile-after-change StartupObserver 
@torproject.org/startup-observer;1
+category profile-after-change DomainIsolator @torproject.org/domain-isolator;1
\ No newline at end of file
diff --git a/src/components/domain-isolator.js 
b/src/components/domain-isolator.js
new file mode 100644
index 0000000..e8e6bfa
--- /dev/null
+++ b/src/components/domain-isolator.js
@@ -0,0 +1,128 @@
+// # domain-isolator.js
+// A component for TorBrowser that puts requests from different
+// first party domains on separate tor circuits.
+
+// This file is written in call stack order (later functions
+// call earlier functions). The code file can be processed
+// with docco.js to provide clear documentation.
+
+/* jshint moz: true */
+/* global Components, console, XPCOMUtils */
+
+// ### Abbreviations
+const Cc = Components.classes, Ci = Components.interfaces, Cu = 
Components.utils;
+
+// Make the logger available.
+let logger = Cc["@torproject.org/torbutton-logger;1"]
+               .getService(Components.interfaces.nsISupports).wrappedJSObject;
+
+// ## mozilla namespace.
+// Useful functionality for interacting with Mozilla services.
+let mozilla = mozilla || {};
+
+// __mozilla.protocolProxyService__.
+// Mozilla's protocol proxy service, useful for managing proxy connections made
+// by the browser.
+mozilla.protocolProxyService = 
Cc["@mozilla.org/network/protocol-proxy-service;1"]
+                                 .getService(Ci.nsIProtocolProxyService);
+
+// __mozilla.thirdPartyUtil__.
+// Mozilla's Thirdy Party Utilities, for figuring out first party domain.
+mozilla.thirdPartyUtil = Cc["@mozilla.org/thirdpartyutil;1"]
+                           .getService(Ci.mozIThirdPartyUtil);
+                           
+// __mozilla.registerProxyChannelFilter(filterFunction, positionIndex)__.
+// Registers a proxy channel filter with the Mozilla Protocol Proxy Service,
+// which will help to decide the proxy to be used for a given channel.
+// The filterFunction should expect two arguments, (aChannel, aProxy),
+// where aProxy is the proxy or list of proxies that would be used by default
+// for the given channel, and should return a new Proxy or list of Proxies.
+mozilla.registerProxyChannelFilter = function (filterFunction, positionIndex) {
+  let proxyFilter = {
+    applyFilter : function (aProxyService, aChannel, aProxy) {
+      return filterFunction(aChannel, aProxy);
+    }
+  };
+  mozilla.protocolProxyService.registerChannelFilter(proxyFilter, 
positionIndex);
+};
+
+// ## tor functionality.
+let tor = tor || {};
+
+// __tor.noncesForDomains__.
+// A mutable map that records what nonce we are using for each domain.
+tor.noncesForDomains = {};
+
+// __tor.socksProxyCredentials(originalProxy, domain)__.
+// Takes a proxyInfo object (originalProxy) and returns a new proxyInfo
+// object with the same properties, except the username is set to the 
+// the domain, and the password is a nonce.
+tor.socksProxyCredentials = function (originalProxy, domain) {
+  // Check if we already have a nonce. If not, create
+  // one for this domain.
+  if (!tor.noncesForDomains.hasOwnProperty(domain)) {
+    tor.noncesForDomains[domain] = 0;
+  }
+  let proxy = originalProxy.QueryInterface(Ci.nsIProxyInfo);
+  return mozilla.protocolProxyService
+           .newSOCKSProxyInfo(proxy.host,
+                              proxy.port,
+                              domain, // username
+                              tor.noncesForDomains[domain].toString(), // 
password
+                              proxy.flags,
+                              proxy.failoverTimeout,
+                              proxy.failoverProxy);
+};
+
+// __tor.isolateCircuitsByDomain()__.
+// For every HTTPChannel, replaces the default SOCKS proxy with one that 
authenticates
+// to the SOCKS server (the tor client process) with a username (the first 
party domain)
+// and a nonce password. Tor provides a separate circuit for each 
username+password
+// combination.
+tor.isolateCircuitsByDomain = function () {
+  mozilla.registerProxyChannelFilter(function (aChannel, aProxy) {
+    try {
+      let channel = aChannel.QueryInterface(Ci.nsIHttpChannel),
+          firstPartyURI = 
mozilla.thirdPartyUtil.getFirstPartyURIFromChannel(channel, true)
+                            .QueryInterface(Ci.nsIURI),
+          firstPartyDomain = mozilla.thirdPartyUtil
+                               .getFirstPartyHostForIsolation(firstPartyURI),
+          proxy = aProxy.QueryInterface(Ci.nsIProxyInfo),
+          replacementProxy = tor.socksProxyCredentials(aProxy, 
firstPartyDomain);
+      logger.eclog(3, "tor SOCKS: " + channel.URI.spec + " via " +
+                      replacementProxy.username + ":" + 
replacementProxy.password); 
+      return replacementProxy;
+    } catch (err) {
+      // If we fail, then just use the default proxyInfo.
+      return aProxy;
+    }
+  }, 0);
+};
+
+// ## XPCOM component construction.
+// Module specific constants
+const kMODULE_NAME = "TorBrowser Domain Isolator";
+const kMODULE_CONTRACTID = "@torproject.org/domain-isolator;1";
+const kMODULE_CID = Components.ID("e33fd6d4-270f-475f-a96f-ff3140279f68");
+
+// Import XPCOMUtils object.
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+// DomainIsolator object. Constructor does nothing.
+function DomainIsolator() { }
+// Firefox component requirements
+DomainIsolator.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
+  classDescription: kMODULE_NAME,
+  classID: kMODULE_CID,
+  contractID: kMODULE_CONTRACTID,
+  observe: function (subject, topic, data) {
+    if (topic === "profile-after-change") {
+      logger.eclog(3, "domain isolator: set up isolating circuits by domain");
+      tor.isolateCircuitsByDomain();
+    }
+  }
+};
+
+// Assign factory to global object.
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([DomainIsolator]);



_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to