commit d99650b338f23d824cbd9d3cc91559ba607a465e Author: Kathy Brade brade@pearlcrescent.com Date: Tue Jan 10 12:03:41 2017 -0500
Bug 20951: Back out Unix domain socket related patches for Tor Browser 6.5
Revert the following commits, preserving the _strUnescape() fixes that were made as part of Bug 20111: 8871259c966755233b134a5ddb2b4926539d25c6 Bug 14272: Make Tor Launcher work with Unix Domain Socket option
32ddac7015be571c336be686b4f901103d0d36f6 Fix typo
fa4e114a20067810af0c5cc6a57aa6e849386418 fixup! Bug 14272: Make Tor Launcher work with Unix Domain Socket option
8ca52414916c3d8bc2a2974017d759901ddc1736 Bug 20111: use Unix domain sockets for SOCKS port by default
4dd8f6130f931616cf014e0ded444c30e04c8bad Bug 20185: Avoid using Unix domain socket paths that are too long --- src/components/tl-process.js | 290 +++++++++++++++++++++----- src/components/tl-protocol.js | 222 ++------------------ src/defaults/preferences/prefs.js | 25 +-- src/modules/tl-util.jsm | 415 +------------------------------------- 4 files changed, 254 insertions(+), 698 deletions(-)
diff --git a/src/components/tl-process.js b/src/components/tl-process.js index 717c338..48be93d 100644 --- a/src/components/tl-process.js +++ b/src/components/tl-process.js @@ -16,6 +16,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "TorLauncherUtil", "resource://torlauncher/modules/tl-util.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "TorLauncherLogger", "resource://torlauncher/modules/tl-logger.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", + "resource://gre/modules/FileUtils.jsm");
function TorProcessService() { @@ -29,6 +31,8 @@ TorProcessService.prototype = { kContractID : "@torproject.org/torlauncher-process-service;1", kServiceName : "Tor Launcher Process Service", + kThunderbirdID: "{3550f703-e582-4d05-9a08-453d09bdfdc6}", + kInstantbirdID: "{33cb9019-c295-46dd-be21-8c4936574bee}", kClassID: Components.ID("{FE7B4CAF-BCF4-4848-8BFF-EFA66C9AFDA1}"), kTorLauncherExtPath: "tor-launcher@torproject.org", // This could vary.
@@ -142,11 +146,7 @@ TorProcessService.prototype =
this.mObsSvc.notifyObservers(null, "TorProcessExited", null);
- if (this.mIsQuitting) - { - TorLauncherUtil.cleanupTempDirectories(); - } - else + if (!this.mIsQuitting) { this.mProtocolSvc.TorCleanupConnection();
@@ -311,6 +311,11 @@ TorProcessService.prototype = mProtocolSvc: null, mTorProcess: null, // nsIProcess mTorProcessStartTime: null, // JS Date.now() + // mIsUserDataOutsideOfAppDir is true when TorBrowser-Data is used. + // (cached; access via this._isUserDataOutsideOfAppDir) + mIsUserDataOutsideOfAppDir: undefined, + mAppDir: null, // nsIFile (cached; access via this._appDir) + mDataDir: null, // nsIFile (cached; access via this._dataDir) mControlConnTimer: null, mControlConnDelayMS: 0, mQuitSoon: false, // Quit was requested by the user; do so soon. @@ -332,15 +337,11 @@ TorProcessService.prototype =
// Get the Tor data directory first so it is created before we try to // construct paths to files that will be inside it. - var dataDir = TorLauncherUtil.getTorFile("tordatadir", true); - var exeFile = TorLauncherUtil.getTorFile("tor", false); - var torrcFile = TorLauncherUtil.getTorFile("torrc", true); - var torrcDefaultsFile = - TorLauncherUtil.getTorFile("torrc-defaults", false); + var dataDir = this._getTorFile("tordatadir", true); + var exeFile = this._getTorFile("tor", false); + var torrcFile = this._getTorFile("torrc", true); + var torrcDefaultsFile = this._getTorFile("torrc-defaults", false); var hashedPassword = this.mProtocolSvc.TorGetPassword(true); - var controlIPCFile = this.mProtocolSvc.TorGetControlIPCFile(); - var controlPort = this.mProtocolSvc.TorGetControlPort(); - var socksPortInfo = this.mProtocolSvc.TorGetSOCKSPortInfo();
var detailsKey; if (!exeFile) @@ -362,6 +363,7 @@ TorProcessService.prototype = return; }
+ // The geoip and geoip6 files are in the same directory as torrc-defaults. var geoipFile = torrcDefaultsFile.clone(); geoipFile.leafName = "geoip"; @@ -386,40 +388,6 @@ TorProcessService.prototype = args.push("HashedControlPassword"); args.push(hashedPassword);
- // Include a ControlPort argument to support switching between - // a TCP port and an IPC port (e.g., a Unix domain socket). - let controlPortArg; - if (controlIPCFile) - controlPortArg = this._ipcPortArg(controlIPCFile); - else if (controlPort) - controlPortArg = "" + controlPort; - if (controlPortArg) - { - args.push("ControlPort"); - args.push(controlPortArg); - } - - // Include a SocksPort argument to support switching between - // a TCP port and an IPC port (e.g., a Unix domain socket). - if (socksPortInfo) - { - let socksPortArg; - if (socksPortInfo.ipcFile) - socksPortArg = this._ipcPortArg(socksPortInfo.ipcFile) - else if (socksPortInfo.host && (socksPortInfo.port != 0)) - socksPortArg = socksPortInfo.host + ':' + socksPortInfo.port; - - if (socksPortArg) - { - let socksPortFlags = TorLauncherUtil.getCharPref( - "extensions.torlauncher.socks_port_flags"); - if (socksPortFlags) - socksPortArg += ' ' + socksPortFlags; - args.push("SocksPort"); - args.push(socksPortArg); - } - } - var pid = this._getpid(); if (0 != pid) { @@ -489,13 +457,6 @@ TorProcessService.prototype = } }, // _startTor()
- // Return a ControlPort or SocksPort argument for aIPCFile (an nsIFile). - // The result is unix:/path or unix:"/path with spaces" with appropriate - // C-style escaping within the path portion. - _ipcPortArg: function(aIPCFile) - { - return "unix:" + this.mProtocolSvc.TorEscapeString(aIPCFile.path); - },
_controlTor: function() { @@ -715,6 +676,227 @@ TorProcessService.prototype = return argsArray; },
+ // Returns an nsIFile. + // If aCreate is true and the file doesn't exist, it is created. + _getTorFile: function(aTorFileType, aCreate) + { + if (!aTorFileType) + return null; + + let isRelativePath = true; + let isUserData = (aTorFileType != "tor") && + (aTorFileType != "torrc-defaults"); + let prefName = "extensions.torlauncher." + aTorFileType + "_path"; + let path = TorLauncherUtil.getCharPref(prefName); + if (path) + { + let re = (TorLauncherUtil.isWindows) ? /^[A-Za-z]:\/ : /^//; + isRelativePath = !re.test(path); + } + else + { + // Get default path. + if (this._isUserDataOutsideOfAppDir) + { + // This block is used for the TorBrowser-Data/ case. + if (TorLauncherUtil.isWindows) + { + if ("tor" == aTorFileType) + path = "TorBrowser\Tor\tor.exe"; + else if ("torrc-defaults" == aTorFileType) + path = "TorBrowser\Tor\torrc-defaults"; + else if ("torrc" == aTorFileType) + path = "Tor\torrc"; + else if ("tordatadir" == aTorFileType) + path = "Tor"; + } + else if (TorLauncherUtil.isMac) + { + if ("tor" == aTorFileType) + path = "Contents/Resources/TorBrowser/Tor/tor"; + else if ("torrc-defaults" == aTorFileType) + path = "Contents/Resources/TorBrowser/Tor/torrc-defaults"; + else if ("torrc" == aTorFileType) + path = "Tor/torrc"; + else if ("tordatadir" == aTorFileType) + path = "Tor"; + } + else // Linux and others. + { + if ("tor" == aTorFileType) + path = "TorBrowser/Tor/tor"; + else if ("torrc-defaults" == aTorFileType) + path = "TorBrowser/Tor/torrc-defaults"; + else if ("torrc" == aTorFileType) + path = "Tor/torrc"; + else if ("tordatadir" == aTorFileType) + path = "Tor"; + } + } + else if (TorLauncherUtil.isWindows) + { + // This block is used for the non-TorBrowser-Data/ case. + if ("tor" == aTorFileType) + path = "Tor\tor.exe"; + else if ("torrc-defaults" == aTorFileType) + path = "Data\Tor\torrc-defaults"; + else if ("torrc" == aTorFileType) + path = "Data\Tor\torrc"; + else if ("tordatadir" == aTorFileType) + path = "Data\Tor"; + } + else // Linux, Mac OS and others. + { + // This block is also used for the non-TorBrowser-Data/ case. + if ("tor" == aTorFileType) + path = "Tor/tor"; + else if ("torrc-defaults" == aTorFileType) + path = "Data/Tor/torrc-defaults"; + else if ("torrc" == aTorFileType) + path = "Data/Tor/torrc"; + else if ("tordatadir" == aTorFileType) + path = "Data/Tor"; + } + } + + if (!path) + return null; + + try + { + let f; + if (isRelativePath) + { + // Turn 'path' into an absolute path. + if (this._isUserDataOutsideOfAppDir) + { + let baseDir = isUserData ? this._dataDir : this._appDir; + f = baseDir.clone(); + } + else + { + f = this._appDir.clone(); + f.append("TorBrowser"); + } + f.appendRelativePath(path); + } + else + { + f = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); + f.initWithPath(path); + } + + if (!f.exists() && aCreate) + { + try + { + if ("tordatadir" == aTorFileType) + f.create(f.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + else + f.create(f.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + } + catch (e) + { + TorLauncherLogger.safelog(4, "unable to create " + f.path + ": ", e); + return null; + } + } + + if (f.exists()) + { + try { f.normalize(); } catch(e) {} + + return f; + } + + TorLauncherLogger.log(4, aTorFileType + " file not found: " + f.path); + } + catch(e) + { + TorLauncherLogger.safelog(4, "_getTorFile " + aTorFileType + + " failed for " + path + ": ", e); + } + + return null; // File not found or error (logged above). + }, // _getTorFile() + + get _isUserDataOutsideOfAppDir() + { + if (this.mIsUserDataOutsideOfAppDir == undefined) + { + // Determine if we are using a "side-by-side" data model by checking + // whether the user profile is outside of the app directory. + try + { + let ds = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties); + let profDir = ds.get("ProfD", Ci.nsIFile); + this.mIsUserDataOutsideOfAppDir = !this._appDir.contains(profDir); + } + catch (e) + { + this.mIsUserDataOutsideOfAppDir = false; + } + } + + return this.mIsUserDataOutsideOfAppDir; + }, // get _isUserDataOutsideOfAppDir + + // Returns an nsIFile that points to the application directory. + // May throw. + get _appDir() + { + if (!this.mAppDir) + { + let topDir = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile); + let appInfo = Cc["@mozilla.org/xre/app-info;1"] + .getService(Ci.nsIXULAppInfo); + // On Linux and Windows, we want to return the Browser/ directory. + // Because topDir ("CurProcD") points to Browser/browser on those + // platforms, we need to go up one level. + // On Mac OS, we want to return the TorBrowser.app/ directory. + // Because topDir points to Contents/Resources/browser on Mac OS, + // we need to go up 3 levels. + let tbbBrowserDepth = (TorLauncherUtil.isMac) ? 3 : 1; + if ((appInfo.ID == this.kThunderbirdID) || + (appInfo.ID == this.kInstantbirdID)) + { + // On Thunderbird/Instantbird, the topDir is the root dir and not + // browser/, so we need to iterate one level less than Firefox. + --tbbBrowserDepth; + } + + while (tbbBrowserDepth > 0) + { + let didRemove = (topDir.leafName != "."); + topDir = topDir.parent; + if (didRemove) + tbbBrowserDepth--; + } + + this.mAppDir = topDir; + } + + return this.mAppDir; + }, // get _appDir + + // Returns an nsIFile that points to the TorBrowser-Data/ directory. + // This function is only used when this._isUserDataOutsideOfAppDir == true. + // May throw. + get _dataDir() + { + if (!this.mDataDir) + { + let ds = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties); + let profDir = ds.get("ProfD", Ci.nsIFile); + this.mDataDir = profDir.parent.parent; + } + + return this.mDataDir; + }, // get _dataDir + _getpid: function() { // Use nsIXULRuntime.processID if it is available. diff --git a/src/components/tl-protocol.js b/src/components/tl-protocol.js index 12f3910..581327e 100644 --- a/src/components/tl-protocol.js +++ b/src/components/tl-protocol.js @@ -17,8 +17,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "TorLauncherUtil", "resource://torlauncher/modules/tl-util.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "TorLauncherLogger", "resource://torlauncher/modules/tl-logger.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm");
function TorProtocolService() @@ -33,48 +31,28 @@ function TorProtocolService()
try { - let isWindows = TorLauncherUtil.isWindows; - let env = Cc["@mozilla.org/process/environment;1"] + var env = Cc["@mozilla.org/process/environment;1"] .getService(Ci.nsIEnvironment); - // Determine how Tor Launcher will connect to the Tor control port. - // Environment variables get top priority followed by preferences. - if (!isWindows && env.exists("TOR_CONTROL_IPC_PATH")) + + if (env.exists("TOR_CONTROL_HOST")) + this.mControlHost = env.get("TOR_CONTROL_HOST"); + else { - let ipcPath = env.get("TOR_CONTROL_IPC_PATH"); - this.mControlIPCFile = new FileUtils.File(ipcPath); + this.mControlHost = TorLauncherUtil.getCharPref( + "extensions.torlauncher.control_host", "127.0.0.1"); } + + if (env.exists("TOR_CONTROL_PORT")) + this.mControlPort = parseInt(env.get("TOR_CONTROL_PORT"), 10); else { - // Check for TCP host and port environment variables. - if (env.exists("TOR_CONTROL_HOST")) - this.mControlHost = env.get("TOR_CONTROL_HOST"); - if (env.exists("TOR_CONTROL_PORT")) - this.mControlPort = parseInt(env.get("TOR_CONTROL_PORT"), 10); - - let useIPC = !isWindows && TorLauncherUtil.getBoolPref( - "extensions.torlauncher.control_port_use_ipc", true); - if (!this.mControlHost && !this.mControlPort && useIPC) - this.mControlIPCFile = TorLauncherUtil.getTorFile("control_ipc", false); - else - { - if (!this.mControlHost) - { - this.mControlHost = TorLauncherUtil.getCharPref( - "extensions.torlauncher.control_host", "127.0.0.1"); - } - if (!this.mControlPort) - { - this.mControlPort = TorLauncherUtil.getIntPref( + this.mControlPort = TorLauncherUtil.getIntPref( "extensions.torlauncher.control_port", 9151); - } - } }
// Populate mControlPassword so it is available when starting tor. if (env.exists("TOR_CONTROL_PASSWD")) - { this.mControlPassword = env.get("TOR_CONTROL_PASSWD"); - } else if (env.exists("TOR_CONTROL_COOKIE_AUTH_FILE")) { // TODO: test this code path (TOR_CONTROL_COOKIE_AUTH_FILE). @@ -85,117 +63,6 @@ function TorProtocolService()
if (!this.mControlPassword) this.mControlPassword = this._generateRandomPassword(); - - // Determine what kind of SOCKS port Tor and the browser will use. - // On Windows (where Unix domain sockets are not supported), TCP is - // always used. - // - // The following environment variables are supported and take - // precedence over preferences: - // TOR_SOCKS_IPC_PATH (file system path; ignored on Windows) - // TOR_SOCKS_HOST - // TOR_SOCKS_PORT - // - // The following preferences are consulted: - // network.proxy.socks - // network.proxy.socks_port - // extensions.torlauncher.socks_port_use_ipc (Boolean) - // extensions.torlauncher.socks_ipc_path (file system path) - // If extensions.torlauncher.socks_ipc_path is empty, a default - // path is used (<tor-data-directory>/socks.socket). - // - // When using TCP, if a value is not defined via an env variable it is - // taken from the corresponding browser preference if possible. The - // exceptions are: - // If network.proxy.socks contains a file: URL, a default value of - // "127.0.0.1" is used instead. - // If the network.proxy.socks_port value is 0, a default value of - // 9150 is used instead. - // - // Supported scenarios: - // 1. By default, an IPC object at a default path is used. - // 2. If extensions.torlauncher.socks_port_use_ipc is set to false, - // a TCP socket at 127.0.0.1:9150 is used, unless different values - // are set in network.proxy.socks and network.proxy.socks_port. - // 3. If the TOR_SOCKS_IPC_PATH env var is set, an IPC object at that - // path is used (e.g., a Unix domain socket). - // 4. If the TOR_SOCKS_HOST and/or TOR_SOCKS_PORT env vars are set, TCP - // is used. Values not set via env vars will be taken from the - // network.proxy.socks and network.proxy.socks_port prefs as described - // above. - // 5. If extensions.torlauncher.socks_port_use_ipc is true and - // extensions.torlauncher.socks_ipc_path is set, an IPC object at - // the specified path is used. - // 6. Tor Launcher is disabled. Torbutton will respect the env vars if - // present; if not, the values in network.proxy.socks and - // network.proxy.socks_port are used without modification. - - let useIPC; - this.mSOCKSPortInfo = { ipcFile: undefined, host: undefined, port: 0 }; - if (!isWindows && env.exists("TOR_SOCKS_IPC_PATH")) - { - let ipcPath = env.get("TOR_SOCKS_IPC_PATH"); - this.mSOCKSPortInfo.ipcFile = new FileUtils.File(ipcPath); - useIPC = true; - } - else - { - // Check for TCP host and port environment variables. - if (env.exists("TOR_SOCKS_HOST")) - { - this.mSOCKSPortInfo.host = env.get("TOR_SOCKS_HOST"); - useIPC = false; - } - if (env.exists("TOR_SOCKS_PORT")) - { - this.mSOCKSPortInfo.port = parseInt(env.get("TOR_SOCKS_PORT"), 10); - useIPC = false; - } - } - - if (useIPC === undefined) - { - useIPC = !isWindows && TorLauncherUtil.getBoolPref( - "extensions.torlauncher.socks_port_use_ipc", true); - } - - // Fill in missing SOCKS info from prefs. - if (useIPC) - { - if (!this.mSOCKSPortInfo.ipcFile) - { - this.mSOCKSPortInfo.ipcFile = - TorLauncherUtil.getTorFile("socks_ipc", false); - } - } - else - { - if (!this.mSOCKSPortInfo.host) - { - let socksAddr = TorLauncherUtil.getCharPref("network.proxy.socks", - "127.0.0.1"); - let socksAddrHasHost = (socksAddr && !socksAddr.startsWith("file:")); - this.mSOCKSPortInfo.host = socksAddrHasHost ? socksAddr : "127.0.0.1"; - } - - if (!this.mSOCKSPortInfo.port) - { - let socksPort = TorLauncherUtil.getIntPref("network.proxy.socks_port", - 0); - this.mSOCKSPortInfo.port = (socksPort != 0) ? socksPort : 9150; - } - } - - TorLauncherLogger.log(3, "SOCKS port type: " + (useIPC ? "IPC" : "TCP")); - if (useIPC) - { - TorLauncherLogger.log(3, "ipcFile: " + this.mSOCKSPortInfo.ipcFile.path); - } - else - { - TorLauncherLogger.log(3, "SOCKS host: " + this.mSOCKSPortInfo.host); - TorLauncherLogger.log(3, "SOCKS port: " + this.mSOCKSPortInfo.port); - } } catch(e) { @@ -274,19 +141,6 @@ TorProtocolService.prototype = kCmdStatusOK: 250, kCmdStatusEventNotification: 650,
- TorGetControlIPCFile: function() - { - if (!this.mControlIPCFile) - return undefined; - - return this.mControlIPCFile.clone(); - }, - - TorGetControlPort: function() - { - return this.mControlPort; - }, - // Returns Tor password string or null if an error occurs. TorGetPassword: function(aPleaseHash) { @@ -294,18 +148,6 @@ TorProtocolService.prototype = return (aPleaseHash) ? this._hashPassword(pw) : pw; },
- TorGetSOCKSPortInfo: function() - { - return this.mSOCKSPortInfo; - }, - - // Escape non-ASCII characters for use within the Tor Control protocol. - // Returns a string. - TorEscapeString: function(aStr) - { - return this._strEscape(aStr); - }, - // NOTE: Many Tor protocol functions return a reply object, which is a // a JavaScript object that has the following fields: // reply.statusCode -- integer, e.g., 250 @@ -672,9 +514,7 @@ TorProtocolService.prototype = mConsoleSvc: null, mControlPort: null, mControlHost: null, - mControlIPCFile: null, // An nsIFile if using IPC for control port. mControlPassword: null, // JS string that contains hex-encoded password. - mSOCKSPortInfo: null, // An object that contains ipcFile, host, port. mControlConnection: null, // This is cached and reused. mEventMonitorConnection: null, mEventMonitorBuffer: null, @@ -722,44 +562,12 @@ TorProtocolService.prototype = var conn; try { - let sts = Cc["@mozilla.org/network/socket-transport-service;1"] + var sts = Cc["@mozilla.org/network/socket-transport-service;1"] .getService(Ci.nsISocketTransportService); - let socket; - if (this.mControlIPCFile) - { - let exists = this.mControlIPCFile.exists(); - if (!exists) - { - TorLauncherLogger.log(5, "Control port IPC object does not exist: " + - this.mControlIPCFile.path); - } - else - { - let isSpecial = this.mControlIPCFile.isSpecial(); - if (!isSpecial) - { - TorLauncherLogger.log(5, - "Control port IPC object is not a special file: " + - this.mControlIPCFile.path); - } - else - { - TorLauncherLogger.log(2, "Opening control connection to " + - this.mControlIPCFile.path); - socket = sts.createUnixDomainTransport(this.mControlIPCFile); - } - } - } - else - { - TorLauncherLogger.log(2, "Opening control connection to " + + TorLauncherLogger.log(2, "Opening control connection to " + this.mControlHost + ":" + this.mControlPort); - socket = sts.createTransport(null, 0, this.mControlHost, - this.mControlPort, null); - } - - if (!socket) - return null; + var socket = sts.createTransport(null, 0, this.mControlHost, + this.mControlPort, null);
// Our event monitor connection is non-blocking and unbuffered (an // asyncWait() call is used so we only read data when we know that diff --git a/src/defaults/preferences/prefs.js b/src/defaults/preferences/prefs.js index ea5ea80..ac1af21 100644 --- a/src/defaults/preferences/prefs.js +++ b/src/defaults/preferences/prefs.js @@ -1,33 +1,12 @@ -pref("extensions.torlauncher.start_tor", true); -pref("extensions.torlauncher.prompt_at_startup", true); - pref("extensions.torlauncher.loglevel", 4); // 1=verbose, 2=debug, 3=info, 4=note, 5=warn pref("extensions.torlauncher.logmethod", 1); // 0=stdout, 1=errorconsole, 2=debuglog pref("extensions.torlauncher.max_tor_log_entries", 1000);
-// By default, an IPC object (e.g., a Unix domain socket) at a default -// location is used for the Tor control port. -// Change control_port_use_ipc to false to use a TCP connection instead, as -// defined by control_host and control_port. -// Modify control_ipc_path to override the default IPC object location. If a -// relative path is used, it is handled like torrc_path (see below). -pref("extensions.torlauncher.control_port_use_ipc", true); -pref("extensions.torlauncher.control_ipc_path", ""); pref("extensions.torlauncher.control_host", "127.0.0.1"); pref("extensions.torlauncher.control_port", 9151);
-// By default, an IPC object (e.g., a Unix domain socket) at a default -// location is used for the Tor SOCKS port. -// Change socks_port_use_ipc to false to use a TCP connection. When a -// TCP connection is used, the host is taken from the network.proxy.socks -// pref and the port is taken from the network.proxy.socks_port pref. -// Modify socks_ipc_path to override the default IPC object location. If a -// relative path is used, it is handled like torrc_path (see below). -// Modify socks_port_flags to use a different set of SocksPort flags (but be -// careful). -pref("extensions.torlauncher.socks_port_use_ipc", true); -pref("extensions.torlauncher.socks_ipc_path", ""); -pref("extensions.torlauncher.socks_port_flags", "IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"); +pref("extensions.torlauncher.start_tor", true); +pref("extensions.torlauncher.prompt_at_startup", true);
// The tor_path is relative to the application directory. On Linux and // Windows this is the Browser/ directory that contains the firefox diff --git a/src/modules/tl-util.jsm b/src/modules/tl-util.jsm index 313a51b..3c7d80b 100644 --- a/src/modules/tl-util.jsm +++ b/src/modules/tl-util.jsm @@ -11,19 +11,14 @@ let EXPORTED_SYMBOLS = [ "TorLauncherUtil" ];
const Cc = Components.classes; const Ci = Components.interfaces; -const Cu = Components.utils; const kPropBundleURI = "chrome://torlauncher/locale/torlauncher.properties"; const kPropNamePrefix = "torlauncher.";
-Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "TorLauncherLogger", - "resource://torlauncher/modules/tl-logger.jsm"); - let TorLauncherUtil = // Public { get isMac() { - return TLUtilInternal._isMac; + return ("Darwin" == TLUtilInternal._OS); },
get isWindows() @@ -247,14 +242,6 @@ let TorLauncherUtil = // Public } catch (e) {} },
- clearUserPref: function(aPrefName) - { - try - { - TLUtilInternal.mPrefsSvc.clearUserPref(aPrefName); - } catch (e) {} - }, - // Currently, this returns a random permutation of an array, bridgeArray. // Later, we might want to change this function to weight based on the // bridges' bandwidths. @@ -374,281 +361,6 @@ let TorLauncherUtil = // Public
return undefined; }, - - // Returns an nsIFile. - // If aTorFileType is "control_ipc" or "socks_ipc", aCreate is ignored - // and there is no requirement that the IPC object exists. - // For all other file types, null is returned if the file does not exist - // and it cannot be created (it will be created if aCreate is true). - getTorFile: function(aTorFileType, aCreate) - { - if (!aTorFileType) - return null; - - let torFile; // an nsIFile to be returned - let path; // a relative or absolute path that will determine torFile - - let isRelativePath = false; - let isUserData = (aTorFileType != "tor") && - (aTorFileType != "torrc-defaults"); - let isControlIPC = ("control_ipc" == aTorFileType); - let isSOCKSIPC = ("socks_ipc" == aTorFileType); - let isIPC = isControlIPC || isSOCKSIPC; - let checkIPCPathLen = true; - - const kControlIPCFileName = "control.socket"; - const kSOCKSIPCFileName = "socks.socket"; - let extraIPCPathLen = (isSOCKSIPC) ? 2 : 0; - let ipcFileName; - if (isControlIPC) - ipcFileName = kControlIPCFileName; - else if (isSOCKSIPC) - ipcFileName = kSOCKSIPCFileName; - - // If this is the first request for an IPC path during this browser - // session, remove the old temporary directory. This helps to keep /tmp - // clean if the browser crashes or is killed. - let ipcDirPath; - if (isIPC && TLUtilInternal.mIsFirstIPCPathRequest) - { - this.cleanupTempDirectories(); - TLUtilInternal.mIsFirstIPCPathRequest = false; - } - else - { - // Retrieve path for IPC objects (it may have already been determined). - ipcDirPath = this.getCharPref(TLUtilInternal.kIPCDirPrefName); - } - - // First, check the _path preference for this file type. - let prefName = "extensions.torlauncher." + aTorFileType + "_path"; - path = this.getCharPref(prefName); - if (path) - { - let re = (this.isWindows) ? /^[A-Za-z]:\/ : /^//; - isRelativePath = !re.test(path); - checkIPCPathLen = false; // always try to use path if provided in pref - } - else if (isIPC) - { - if (ipcDirPath) - { - // We have already determined where IPC objects will be placed. - torFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); - torFile.initWithPath(ipcDirPath); - torFile.append(ipcFileName); - checkIPCPathLen = false; // already checked. - } - else - { - // If XDG_RUNTIME_DIR is set, use it as the base directory for IPC - // objects (e.g., Unix domain sockets) -- assuming it is not too long. - let env = Cc["@mozilla.org/process/environment;1"] - .getService(Ci.nsIEnvironment); - if (env.exists("XDG_RUNTIME_DIR")) - { - let ipcDir = TLUtilInternal._createUniqueIPCDir( - env.get("XDG_RUNTIME_DIR")); - if (ipcDir) - { - let f = ipcDir.clone(); - f.append(ipcFileName); - if (TLUtilInternal._isIPCPathLengthOK(f.path, extraIPCPathLen)) - { - torFile = f; - checkIPCPathLen = false; // no need to check again. - - // Store directory path so it can be reused for other IPC objects - // and so it can be removed during exit. - this.setCharPref(TLUtilInternal.kIPCDirPrefName, ipcDir.path); - } - else - { - // too long; remove the directory that we just created. - ipcDir.remove(false); - } - } - } - } - } - - if (!path && !torFile) - { - // No preference and no pre-determined IPC path: use a default path. - isRelativePath = true; - if (TLUtilInternal._isUserDataOutsideOfAppDir) - { - // This block is used for the TorBrowser-Data/ case. - if (this.isWindows) - { - if ("tor" == aTorFileType) - path = "TorBrowser\Tor\tor.exe"; - else if ("torrc-defaults" == aTorFileType) - path = "TorBrowser\Tor\torrc-defaults"; - else if ("torrc" == aTorFileType) - path = "Tor\torrc"; - else if ("tordatadir" == aTorFileType) - path = "Tor"; - } - else if (this.isMac) - { - if ("tor" == aTorFileType) - path = "Contents/Resources/TorBrowser/Tor/tor"; - else if ("torrc-defaults" == aTorFileType) - path = "Contents/Resources/TorBrowser/Tor/torrc-defaults"; - else if ("torrc" == aTorFileType) - path = "Tor/torrc"; - else if ("tordatadir" == aTorFileType) - path = "Tor"; - else if (isIPC) - path = "Tor/" + ipcFileName; - } - else // Linux and others. - { - if ("tor" == aTorFileType) - path = "TorBrowser/Tor/tor"; - else if ("torrc-defaults" == aTorFileType) - path = "TorBrowser/Tor/torrc-defaults"; - else if ("torrc" == aTorFileType) - path = "Tor/torrc"; - else if ("tordatadir" == aTorFileType) - path = "Tor"; - else if (isIPC) - path = "Tor/" + ipcFileName; - } - } - else if (this.isWindows) - { - // This block is used for the non-TorBrowser-Data/ case. - if ("tor" == aTorFileType) - path = "Tor\tor.exe"; - else if ("torrc-defaults" == aTorFileType) - path = "Data\Tor\torrc-defaults"; - else if ("torrc" == aTorFileType) - path = "Data\Tor\torrc"; - else if ("tordatadir" == aTorFileType) - path = "Data\Tor"; - } - else // Linux, Mac OS and others. - { - // This block is also used for the non-TorBrowser-Data/ case. - if ("tor" == aTorFileType) - path = "Tor/tor"; - else if ("torrc-defaults" == aTorFileType) - path = "Data/Tor/torrc-defaults"; - else if ("torrc" == aTorFileType) - path = "Data/Tor/torrc"; - else if ("tordatadir" == aTorFileType) - path = "Data/Tor"; - else if (isIPC) - path = "Data/Tor/" + ipcFileName; - } - - if (!path) - return null; - } - - try - { - if (path) - { - if (isRelativePath) - { - // Turn 'path' into an absolute path. - if (TLUtilInternal._isUserDataOutsideOfAppDir) - { - let baseDir = isUserData ? TLUtilInternal._dataDir - : TLUtilInternal._appDir; - torFile = baseDir.clone(); - } - else - { - torFile = TLUtilInternal._appDir.clone(); - torFile.append("TorBrowser"); - } - torFile.appendRelativePath(path); - } - else - { - torFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); - torFile.initWithPath(path); - } - - if (!torFile.exists() && !isIPC && aCreate) - { - try - { - if ("tordatadir" == aTorFileType) - torFile.create(torFile.DIRECTORY_TYPE, 0700); - else - torFile.create(torFile.NORMAL_FILE_TYPE, 0600); - } - catch (e) - { - TorLauncherLogger.safelog(4, - "unable to create " + torFile.path + ": ", e); - return null; - } - } - } - - // If the file exists or an IPC object was requested, normalize the path - // and return a file object. The control and SOCKS IPC objects will be - // created by tor. - if (torFile.exists() || isIPC) - { - try { torFile.normalize(); } catch(e) {} - - // Ensure that the IPC path length is short enough for use by the - // operating system. If not, create and use a unique directory under - // /tmp for all IPC objects. The created directory path is stored in - // a preference so it can be reused for other IPC objects and so it - // can be removed during exit. - if (isIPC && checkIPCPathLen && - !TLUtilInternal._isIPCPathLengthOK(torFile.path, extraIPCPathLen)) - { - torFile = TLUtilInternal._createUniqueIPCDir("/tmp"); - if (!torFile) - { - TorLauncherLogger.log(4, - "failed to create unique directory under /tmp"); - return null; - } - - this.setCharPref(TLUtilInternal.kIPCDirPrefName, torFile.path); - torFile.append(ipcFileName); - } - - return torFile; - } - - TorLauncherLogger.log(4, aTorFileType + " file not found: " - + torFile.path); - } - catch(e) - { - TorLauncherLogger.safelog(4, "getTorFile " + aTorFileType + - " failed for " + path + ": ", e); - } - - return null; // File not found or error (logged above). - }, // getTorFile() - - cleanupTempDirectories: function() - { - try - { - let dirPath = this.getCharPref(TLUtilInternal.kIPCDirPrefName); - this.clearUserPref(TLUtilInternal.kIPCDirPrefName); - if (dirPath) - { - let f = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); - f.initWithPath(dirPath); - if (f.exists()) - f.remove(false); // Remove directory if it is empty - } - } catch(e) {} - }, };
@@ -657,19 +369,9 @@ Object.freeze(TorLauncherUtil);
let TLUtilInternal = // Private { - kThunderbirdID: "{3550f703-e582-4d05-9a08-453d09bdfdc6}", - kInstantbirdID: "{33cb9019-c295-46dd-be21-8c4936574bee}", - kIPCDirPrefName: "extensions.torlauncher.tmp_ipc_dir", - mPrefsSvc : null, mStringBundle : null, mOS : "", - // mIsUserDataOutsideOfAppDir is true when TorBrowser-Data is used. - mIsUserDataOutsideOfAppDir: undefined, // Boolean (cached; access via - // this._isUserDataOutsideOfAppDir) - mAppDir: null, // nsIFile (cached; access via this._appDir) - mDataDir: null, // nsIFile (cached; access via this._dataDir) - mIsFirstIPCPathRequest : true,
_init: function() { @@ -699,121 +401,6 @@ let TLUtilInternal = // Private
return this.mOS; }, - - get _isMac() - { - return ("Darwin" == this._OS); - }, - - get _isUserDataOutsideOfAppDir() - { - if (this.mIsUserDataOutsideOfAppDir == undefined) - { - // Determine if we are using a "side-by-side" data model by checking - // whether the user profile is outside of the app directory. - try - { - let ds = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - let profDir = ds.get("ProfD", Ci.nsIFile); - this.mIsUserDataOutsideOfAppDir = !this._appDir.contains(profDir); - } - catch (e) - { - this.mIsUserDataOutsideOfAppDir = false; - } - } - - return this.mIsUserDataOutsideOfAppDir; - }, // get _isUserDataOutsideOfAppDir - - // Returns an nsIFile that points to the application directory. - // May throw. - get _appDir() - { - if (!this.mAppDir) - { - let topDir = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile); - let appInfo = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULAppInfo); - // On Linux and Windows, we want to return the Browser/ directory. - // Because topDir ("CurProcD") points to Browser/browser on those - // platforms, we need to go up one level. - // On Mac OS, we want to return the TorBrowser.app/ directory. - // Because topDir points to Contents/Resources/browser on Mac OS, - // we need to go up 3 levels. - let tbbBrowserDepth = (this._isMac) ? 3 : 1; - if ((appInfo.ID == this.kThunderbirdID) || - (appInfo.ID == this.kInstantbirdID)) - { - // On Thunderbird/Instantbird, the topDir is the root dir and not - // browser/, so we need to iterate one level less than Firefox. - --tbbBrowserDepth; - } - - while (tbbBrowserDepth > 0) - { - let didRemove = (topDir.leafName != "."); - topDir = topDir.parent; - if (didRemove) - tbbBrowserDepth--; - } - - this.mAppDir = topDir; - } - - return this.mAppDir; - }, // get _appDir - - // Returns an nsIFile that points to the TorBrowser-Data/ directory. - // This function is only used when this._isUserDataOutsideOfAppDir == true. - // May throw. - get _dataDir() - { - if (!this.mDataDir) - { - let ds = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - let profDir = ds.get("ProfD", Ci.nsIFile); - this.mDataDir = profDir.parent.parent; - } - - return this.mDataDir; - }, // get _dataDir - - // Return true if aPath is short enough to be used as an IPC object path, - // e.g., for a Unix domain socket path. aExtraLen is the "delta" necessary - // to accommodate other IPC objects that have longer names; it is used to - // account for "control.socket" vs. "socks.socket" (we want to ensure that - // all IPC objects are placed in the same parent directory unless the user - // has set prefs or env vars to explicitly specify the path for an object). - // We enforce a maximum length of 100 because all operating systems allow - // at least 100 characters for Unix domain socket paths. - _isIPCPathLengthOK: function(aPath, aExtraLen) - { - const kMaxIPCPathLen = 100; - return aPath && ((aPath.length + aExtraLen) <= kMaxIPCPathLen); - }, - - // Returns an nsIFile or null if a unique directory could not be created. - _createUniqueIPCDir: function(aBasePath) - { - try - { - let d = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); - d.initWithPath(aBasePath); - d.append("Tor"); - d.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700); - return d; - } - catch (e) - { - TorLauncherLogger.safelog(4, "_createUniqueIPCDir failed for " - + aBasePath + ": ", e); - return null; - } - }, };