tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2016
- 18 participants
- 868 discussions

20 Oct '16
commit c07486bcd78cd9c40f2e1a62a0da5e613a6afd92
Author: Damian Johnson <atagar(a)torproject.org>
Date: Thu Oct 20 10:47:50 2016 -0700
Graph header continued to update when paused
When paused the top of the graph that shows the bandwidth numbers continued to
update.
---
nyx/panel/graph.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index 9c76673..59b201c 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -103,7 +103,7 @@ class GraphData(object):
self.tick = clone.tick
self.values = copy.deepcopy(clone.values)
- self._category = clone._category
+ self._category = category
self._is_primary = clone._is_primary
self._in_process_value = dict(clone._in_process_value)
self._max_value = dict(clone._max_value)
@@ -200,8 +200,8 @@ class GraphCategory(object):
def __init__(self, clone = None):
if clone:
- self.primary = GraphData(clone.primary)
- self.secondary = GraphData(clone.secondary)
+ self.primary = GraphData(clone.primary, category = self)
+ self.secondary = GraphData(clone.secondary, category = self)
self.start_time = clone.start_time
self._title_stats = list(clone._title_stats)
self._primary_header_stats = list(clone._primary_header_stats)
1
0
commit fa945a8c573db48607192498e728007de9d8cfbc
Author: Damian Johnson <atagar(a)torproject.org>
Date: Wed Oct 19 10:40:01 2016 -0700
Ignore setup.py's build directory
Running 'python setup.py build' creates a build directory. Might as well have
git ignore it. Thanks to Henrik for the patch.
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 2dd810d..e0ab993 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*.pyc
src/stem/
+build/
*.swp
1
0

[tor-launcher/maint-0.2.10] Bug 20111: use Unix domain sockets for SOCKS port by default
by gk@torproject.org 20 Oct '16
by gk@torproject.org 20 Oct '16
20 Oct '16
commit 239131f5747385e832d6d12f30382ce00056591b
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Thu Oct 20 09:59:20 2016 -0400
Bug 20111: use Unix domain sockets for SOCKS port by default
New preferences:
extensions.torlauncher.socks_port_use_ipc (Boolean; defaults to true)
extensions.torlauncher.socks_ipc_path (override default IPC path)
extensions.torlauncher.socks_port_flags (SocksPort flags)
Also added support for the TOR_SOCKS_IPC_PATH environment variable.
Consistently use IPC to refer to Unix domain sockets.
Renamed preferences:
extensions.torlauncher.control_port_use_socket is now
extensions.torlauncher.control_port_use_ipc
extensions.torlauncher.control_socket_path is now
extensions.torlauncher.control_ipc_path
Renamed the TOR_CONTROL_SOCKET env variable to TOR_CONTROL_IPC_PATH.
Change _strUnescape() to throw and fix hex and octal unescaping.
---
src/components/tl-process.js | 31 ++++-
src/components/tl-protocol.js | 248 ++++++++++++++++++++++++++++----------
src/defaults/preferences/prefs.js | 27 +++--
src/modules/tl-util.jsm | 30 +++--
4 files changed, 252 insertions(+), 84 deletions(-)
diff --git a/src/components/tl-process.js b/src/components/tl-process.js
index 1883013..166a8ae 100644
--- a/src/components/tl-process.js
+++ b/src/components/tl-process.js
@@ -334,8 +334,9 @@ TorProcessService.prototype =
var torrcDefaultsFile =
TorLauncherUtil.getTorFile("torrc-defaults", false);
var hashedPassword = this.mProtocolSvc.TorGetPassword(true);
- var controlSocketFile = this.mProtocolSvc.TorGetControlSocketFile();
+ var controlIPCFile = this.mProtocolSvc.TorGetControlIPCFile();
var controlPort = this.mProtocolSvc.TorGetControlPort();
+ var socksPortInfo = this.mProtocolSvc.TorGetSOCKSPortInfo();
var detailsKey;
if (!exeFile)
@@ -382,10 +383,10 @@ TorProcessService.prototype =
args.push(hashedPassword);
// Include a ControlPort argument to support switching between
- // a TCP port and a Unix domain socket.
+ // a TCP port and an IPC port (e.g., a Unix domain socket).
let controlPortArg;
- if (controlSocketFile)
- controlPortArg = "unix:" + controlSocketFile.path;
+ if (controlIPCFile)
+ controlPortArg = this._ipcPortArg(controlIPCFile);
else if (controlPort)
controlPortArg = "" + controlPort;
if (controlPortArg)
@@ -394,6 +395,21 @@ TorProcessService.prototype =
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 = (socksPortInfo.ipcFile)
+ ? this._ipcPortArg(socksPortInfo.ipcFile)
+ : socksPortInfo.host + ':' + socksPortInfo.port;
+ 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)
{
@@ -458,6 +474,13 @@ 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()
{
diff --git a/src/components/tl-protocol.js b/src/components/tl-protocol.js
index d394b53..12f3910 100644
--- a/src/components/tl-protocol.js
+++ b/src/components/tl-protocol.js
@@ -38,10 +38,10 @@ function TorProtocolService()
.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_SOCKET"))
+ if (!isWindows && env.exists("TOR_CONTROL_IPC_PATH"))
{
- let socketPath = env.get("TOR_CONTROL_SOCKET");
- this.mControlSocketFile = new FileUtils.File(socketPath);
+ let ipcPath = env.get("TOR_CONTROL_IPC_PATH");
+ this.mControlIPCFile = new FileUtils.File(ipcPath);
}
else
{
@@ -51,13 +51,10 @@ function TorProtocolService()
if (env.exists("TOR_CONTROL_PORT"))
this.mControlPort = parseInt(env.get("TOR_CONTROL_PORT"), 10);
- let useSocket = !isWindows && TorLauncherUtil.getBoolPref(
- "extensions.torlauncher.control_port_use_socket", true);
- if (!this.mControlHost && !this.mControlPort && useSocket)
- {
- this.mControlSocketFile = TorLauncherUtil.getTorFile("control_socket",
- false);
- }
+ 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)
@@ -75,7 +72,9 @@ function TorProtocolService()
// 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).
@@ -86,6 +85,117 @@ 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)
{
@@ -164,12 +274,12 @@ TorProtocolService.prototype =
kCmdStatusOK: 250,
kCmdStatusEventNotification: 650,
- TorGetControlSocketFile: function()
+ TorGetControlIPCFile: function()
{
- if (!this.mControlSocketFile)
+ if (!this.mControlIPCFile)
return undefined;
- return this.mControlSocketFile.clone();
+ return this.mControlIPCFile.clone();
},
TorGetControlPort: function()
@@ -184,6 +294,18 @@ 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
@@ -373,11 +495,13 @@ TorProtocolService.prototype =
else
{
token = tokenAndVal.substring(0, idx);
- var valObj = {};
- if (!this._strUnescape(tokenAndVal.substring(idx + 1), valObj))
- continue; // skip this token/value pair.
+ try
+ {
+ val = this._strUnescape(tokenAndVal.substring(idx + 1));
+ } catch (e) {}
- val = valObj.result;
+ if (!val)
+ continue; // skip this token/value pair.
}
if ("BOOTSTRAP" == token)
@@ -548,8 +672,9 @@ TorProtocolService.prototype =
mConsoleSvc: null,
mControlPort: null,
mControlHost: null,
- mControlSocketFile: null, // An nsIFile if using a UNIX domain socket.
+ 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,
@@ -600,27 +725,28 @@ TorProtocolService.prototype =
let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService);
let socket;
- if (this.mControlSocketFile)
+ if (this.mControlIPCFile)
{
- let exists = this.mControlSocketFile.exists();
+ let exists = this.mControlIPCFile.exists();
if (!exists)
{
- TorLauncherLogger.log(5, "Control port socket does not exist: " +
- this.mControlSocketFile.path);
+ TorLauncherLogger.log(5, "Control port IPC object does not exist: " +
+ this.mControlIPCFile.path);
}
else
{
- let isSpecial = this.mControlSocketFile.isSpecial();
+ let isSpecial = this.mControlIPCFile.isSpecial();
if (!isSpecial)
{
- TorLauncherLogger.log(5, "Control port socket is not a socket: " +
- this.mControlSocketFile.path);
+ TorLauncherLogger.log(5,
+ "Control port IPC object is not a special file: " +
+ this.mControlIPCFile.path);
}
else
{
- TorLauncherLogger.log(2, "Opening control connection to socket " +
- this.mControlSocketFile.path);
- socket = sts.createUnixDomainTransport(this.mControlSocketFile);
+ TorLauncherLogger.log(2, "Opening control connection to " +
+ this.mControlIPCFile.path);
+ socket = sts.createUnixDomainTransport(this.mControlIPCFile);
}
}
}
@@ -855,14 +981,16 @@ TorProtocolService.prototype =
}
else
{
- var valObj = {};
- if (!this._strUnescape(line.substring(prefixLen), valObj))
+ try
{
- TorLauncherLogger.safelog(4, "Invalid string within " + aCmd +
+ let s = this._strUnescape(line.substring(prefixLen));
+ tmpArray.push(s);
+ }
+ catch (e)
+ {
+ TorLauncherLogger.safelog(4, e + " within " + aCmd +
" response: ", line);
}
- else
- tmpArray.push(valObj.result);
}
}
@@ -954,25 +1082,20 @@ TorProtocolService.prototype =
// Unescape Tor Control string aStr (removing surrounding "" and \ escapes).
// Based on Vidalia's src/common/stringutil.cpp:string_unescape().
- // Returns true if successful and sets aResultObj.result.
- _strUnescape: function(aStr, aResultObj)
+ // Returns the unescaped string. Throws upon failure.
+ // Within Torbutton, the file modules/utils.js also contains a copy of
+ // _strUnescape().
+ _strUnescape: function(aStr)
{
- if (!aResultObj)
- return false;
-
if (!aStr)
- {
- aResultObj.result = aStr;
- return true;
- }
+ return aStr;
var len = aStr.length;
if ((len < 2) || ('"' != aStr.charAt(0)) || ('"' != aStr.charAt(len - 1)))
- {
- aResultObj.result = aStr;
- return true;
- }
+ return aStr;
+ const kHexRE = /[0-9A-Fa-f]{2}/;
+ const kOctalRE = /[0-7]{3}/;
var rv = "";
var i = 1;
var lastCharIndex = len - 2;
@@ -982,7 +1105,7 @@ TorProtocolService.prototype =
if ('\\' == c)
{
if (++i > lastCharIndex)
- return false; // error: \ without next character.
+ throw new Error("missing character after \\");
c = aStr.charAt(i);
if ('n' == c)
@@ -994,24 +1117,26 @@ TorProtocolService.prototype =
else if ('x' == c)
{
if ((i + 2) > lastCharIndex)
- return false; // error: not enough hex characters.
+ throw new Error("not enough hex characters");
- var val = parseInt(aStr.substr(i, 2), 16);
- if (isNaN(val))
- return false; // error: invalid hex characters.
+ let s = aStr.substr(i + 1, 2);
+ if (!kHexRE.test(s))
+ throw new Error("invalid hex character");
+ let val = parseInt(s, 16);
rv += String.fromCharCode(val);
- i += 2;
+ i += 3;
}
else if (this._isDigit(c))
{
- if ((i + 3) > lastCharIndex)
- return false; // error: not enough octal characters.
+ let s = aStr.substr(i, 3);
+ if ((i + 2) > lastCharIndex)
+ throw new Error("not enough octal characters");
- var val = parseInt(aStr.substr(i, 3), 8);
- if (isNaN(val))
- return false; // error: invalid octal characters.
+ if (!kOctalRE.test(s))
+ throw new Error("invalid octal character");
+ let val = parseInt(s, 8);
rv += String.fromCharCode(val);
i += 3;
}
@@ -1022,7 +1147,7 @@ TorProtocolService.prototype =
}
}
else if ('"' == c)
- return false; // error: unescaped double quote in middle of string.
+ throw new Error("unescaped \" within string");
else
{
rv += c;
@@ -1031,10 +1156,7 @@ TorProtocolService.prototype =
}
// Convert from UTF-8 to Unicode. TODO: is UTF-8 always used in protocol?
- rv = decodeURIComponent(escape(rv));
-
- aResultObj.result = rv;
- return true;
+ return decodeURIComponent(escape(rv));
}, // _strUnescape()
// Returns a random 16 character password, hex-encoded.
@@ -1188,6 +1310,8 @@ TorProtocolService.prototype =
return rv;
},
+ // Within Torbutton, the file modules/utils.js also contains a copy of
+ // _isDigit().
_isDigit: function(aChar)
{
const kRE = /^\d$/;
diff --git a/src/defaults/preferences/prefs.js b/src/defaults/preferences/prefs.js
index 0f197de..ea5ea80 100644
--- a/src/defaults/preferences/prefs.js
+++ b/src/defaults/preferences/prefs.js
@@ -5,17 +5,30 @@ pref("extensions.torlauncher.loglevel", 4); // 1=verbose, 2=debug, 3=info, 4=no
pref("extensions.torlauncher.logmethod", 1); // 0=stdout, 1=errorconsole, 2=debuglog
pref("extensions.torlauncher.max_tor_log_entries", 1000);
-// By default, a Unix domain socket at a default location is used for
-// the Tor control port.
-// Change control_port_use_socket to false to use a TCP connection
-// instead, as defined by control_host and control_port.
-// Modify control_socket_path to override the default socket location. If a
+// 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_socket", true);
-pref("extensions.torlauncher.control_socket_path", "");
+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");
+
// The tor_path is relative to the application directory. On Linux and
// Windows this is the Browser/ directory that contains the firefox
// executables, and on Mac OS it is the TorBrowser.app directory.
diff --git a/src/modules/tl-util.jsm b/src/modules/tl-util.jsm
index 9709e0e..a18f779 100644
--- a/src/modules/tl-util.jsm
+++ b/src/modules/tl-util.jsm
@@ -368,8 +368,8 @@ let TorLauncherUtil = // Public
},
// Returns an nsIFile.
- // If aTorFileType is "control_socket", aCreate is ignored and there is
- // no requirement that the socket exists.
+ // 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)
@@ -380,7 +380,9 @@ let TorLauncherUtil = // Public
let isRelativePath = true;
let isUserData = (aTorFileType != "tor") &&
(aTorFileType != "torrc-defaults");
- let isControlSocket = ("control_socket" == aTorFileType);
+ let isControlIPC = ("control_ipc" == aTorFileType);
+ let isSOCKSIPC = ("socks_ipc" == aTorFileType);
+ let isIPC = isControlIPC || isSOCKSIPC;
let prefName = "extensions.torlauncher." + aTorFileType + "_path";
let path = this.getCharPref(prefName);
if (path)
@@ -415,8 +417,10 @@ let TorLauncherUtil = // Public
path = "Tor/torrc";
else if ("tordatadir" == aTorFileType)
path = "Tor";
- else if (isControlSocket)
+ else if (isControlIPC)
path = "Tor/control.socket";
+ else if (isSOCKSIPC)
+ path = "Tor/socks.socket";
}
else // Linux and others.
{
@@ -428,8 +432,10 @@ let TorLauncherUtil = // Public
path = "Tor/torrc";
else if ("tordatadir" == aTorFileType)
path = "Tor";
- else if (isControlSocket)
+ else if (isControlIPC)
path = "Tor/control.socket";
+ else if (isSOCKSIPC)
+ path = "Tor/socks.socket";
}
}
else if (this.isWindows)
@@ -455,8 +461,10 @@ let TorLauncherUtil = // Public
path = "Data/Tor/torrc";
else if ("tordatadir" == aTorFileType)
path = "Data/Tor";
- else if (isControlSocket)
+ else if (isControlIPC)
path = "Data/Tor/control.socket";
+ else if (isSOCKSIPC)
+ path = "Data/Tor/socks.socket";
}
}
@@ -488,7 +496,7 @@ let TorLauncherUtil = // Public
f.initWithPath(path);
}
- if (!f.exists() && !isControlSocket && aCreate)
+ if (!f.exists() && !isIPC && aCreate)
{
try
{
@@ -504,10 +512,10 @@ let TorLauncherUtil = // Public
}
}
- // If the file exists or the control socket was requested, normalize
- // the path and return a file object. The control socket will be
+ // 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 (f.exists() || isControlSocket)
+ if (f.exists() || isIPC)
{
try { f.normalize(); } catch(e) {}
return f;
@@ -518,7 +526,7 @@ let TorLauncherUtil = // Public
catch(e)
{
TorLauncherLogger.safelog(4, "getTorFile " + aTorFileType +
- " failed for " + path + ": ", e);
+ " failed for " + path + ": ", e);
}
return null; // File not found or error (logged above).
1
0

20 Oct '16
commit e7a9367be0b0b18c2cfbac774e4edcd7d3bcaaf8
Author: Georg Koppen <gk(a)torproject.org>
Date: Thu Sep 15 13:35:37 2016 +0000
Version bump for a better tag
---
src/install.rdf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/install.rdf b/src/install.rdf
index 96f9a66..06c3413 100644
--- a/src/install.rdf
+++ b/src/install.rdf
@@ -7,7 +7,7 @@
<em:creator>The Tor Project, Inc.</em:creator>
<em:contributor>Pearl Crescent, LLC</em:contributor>
<em:id>tor-launcher(a)torproject.org</em:id>
- <em:version>0.2.10</em:version>
+ <em:version>0.2.10.1</em:version>
<em:homepageURL>https://www.torproject.org/projects/torbrowser.html</em:homepageURL>
<em:updateURL>data:text/plain,</em:updateURL>
<em:updateKey>-</em:updateKey>
1
0

[tor-launcher/master] Bug 20111: use Unix domain sockets for SOCKS port by default
by gk@torproject.org 20 Oct '16
by gk@torproject.org 20 Oct '16
20 Oct '16
commit 8ca52414916c3d8bc2a2974017d759901ddc1736
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Thu Oct 20 09:59:20 2016 -0400
Bug 20111: use Unix domain sockets for SOCKS port by default
New preferences:
extensions.torlauncher.socks_port_use_ipc (Boolean; defaults to true)
extensions.torlauncher.socks_ipc_path (override default IPC path)
extensions.torlauncher.socks_port_flags (SocksPort flags)
Also added support for the TOR_SOCKS_IPC_PATH environment variable.
Consistently use IPC to refer to Unix domain sockets.
Renamed preferences:
extensions.torlauncher.control_port_use_socket is now
extensions.torlauncher.control_port_use_ipc
extensions.torlauncher.control_socket_path is now
extensions.torlauncher.control_ipc_path
Renamed the TOR_CONTROL_SOCKET env variable to TOR_CONTROL_IPC_PATH.
Change _strUnescape() to throw and fix hex and octal unescaping.
---
src/components/tl-process.js | 31 ++++-
src/components/tl-protocol.js | 248 ++++++++++++++++++++++++++++----------
src/defaults/preferences/prefs.js | 27 +++--
src/modules/tl-util.jsm | 30 +++--
4 files changed, 252 insertions(+), 84 deletions(-)
diff --git a/src/components/tl-process.js b/src/components/tl-process.js
index db074b4..844aba1 100644
--- a/src/components/tl-process.js
+++ b/src/components/tl-process.js
@@ -330,8 +330,9 @@ TorProcessService.prototype =
var torrcDefaultsFile =
TorLauncherUtil.getTorFile("torrc-defaults", false);
var hashedPassword = this.mProtocolSvc.TorGetPassword(true);
- var controlSocketFile = this.mProtocolSvc.TorGetControlSocketFile();
+ var controlIPCFile = this.mProtocolSvc.TorGetControlIPCFile();
var controlPort = this.mProtocolSvc.TorGetControlPort();
+ var socksPortInfo = this.mProtocolSvc.TorGetSOCKSPortInfo();
var detailsKey;
if (!exeFile)
@@ -378,10 +379,10 @@ TorProcessService.prototype =
args.push(hashedPassword);
// Include a ControlPort argument to support switching between
- // a TCP port and a Unix domain socket.
+ // a TCP port and an IPC port (e.g., a Unix domain socket).
let controlPortArg;
- if (controlSocketFile)
- controlPortArg = "unix:" + controlSocketFile.path;
+ if (controlIPCFile)
+ controlPortArg = this._ipcPortArg(controlIPCFile);
else if (controlPort)
controlPortArg = "" + controlPort;
if (controlPortArg)
@@ -390,6 +391,21 @@ TorProcessService.prototype =
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 = (socksPortInfo.ipcFile)
+ ? this._ipcPortArg(socksPortInfo.ipcFile)
+ : socksPortInfo.host + ':' + socksPortInfo.port;
+ 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)
{
@@ -454,6 +470,13 @@ 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()
{
diff --git a/src/components/tl-protocol.js b/src/components/tl-protocol.js
index d394b53..12f3910 100644
--- a/src/components/tl-protocol.js
+++ b/src/components/tl-protocol.js
@@ -38,10 +38,10 @@ function TorProtocolService()
.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_SOCKET"))
+ if (!isWindows && env.exists("TOR_CONTROL_IPC_PATH"))
{
- let socketPath = env.get("TOR_CONTROL_SOCKET");
- this.mControlSocketFile = new FileUtils.File(socketPath);
+ let ipcPath = env.get("TOR_CONTROL_IPC_PATH");
+ this.mControlIPCFile = new FileUtils.File(ipcPath);
}
else
{
@@ -51,13 +51,10 @@ function TorProtocolService()
if (env.exists("TOR_CONTROL_PORT"))
this.mControlPort = parseInt(env.get("TOR_CONTROL_PORT"), 10);
- let useSocket = !isWindows && TorLauncherUtil.getBoolPref(
- "extensions.torlauncher.control_port_use_socket", true);
- if (!this.mControlHost && !this.mControlPort && useSocket)
- {
- this.mControlSocketFile = TorLauncherUtil.getTorFile("control_socket",
- false);
- }
+ 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)
@@ -75,7 +72,9 @@ function TorProtocolService()
// 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).
@@ -86,6 +85,117 @@ 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)
{
@@ -164,12 +274,12 @@ TorProtocolService.prototype =
kCmdStatusOK: 250,
kCmdStatusEventNotification: 650,
- TorGetControlSocketFile: function()
+ TorGetControlIPCFile: function()
{
- if (!this.mControlSocketFile)
+ if (!this.mControlIPCFile)
return undefined;
- return this.mControlSocketFile.clone();
+ return this.mControlIPCFile.clone();
},
TorGetControlPort: function()
@@ -184,6 +294,18 @@ 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
@@ -373,11 +495,13 @@ TorProtocolService.prototype =
else
{
token = tokenAndVal.substring(0, idx);
- var valObj = {};
- if (!this._strUnescape(tokenAndVal.substring(idx + 1), valObj))
- continue; // skip this token/value pair.
+ try
+ {
+ val = this._strUnescape(tokenAndVal.substring(idx + 1));
+ } catch (e) {}
- val = valObj.result;
+ if (!val)
+ continue; // skip this token/value pair.
}
if ("BOOTSTRAP" == token)
@@ -548,8 +672,9 @@ TorProtocolService.prototype =
mConsoleSvc: null,
mControlPort: null,
mControlHost: null,
- mControlSocketFile: null, // An nsIFile if using a UNIX domain socket.
+ 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,
@@ -600,27 +725,28 @@ TorProtocolService.prototype =
let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService);
let socket;
- if (this.mControlSocketFile)
+ if (this.mControlIPCFile)
{
- let exists = this.mControlSocketFile.exists();
+ let exists = this.mControlIPCFile.exists();
if (!exists)
{
- TorLauncherLogger.log(5, "Control port socket does not exist: " +
- this.mControlSocketFile.path);
+ TorLauncherLogger.log(5, "Control port IPC object does not exist: " +
+ this.mControlIPCFile.path);
}
else
{
- let isSpecial = this.mControlSocketFile.isSpecial();
+ let isSpecial = this.mControlIPCFile.isSpecial();
if (!isSpecial)
{
- TorLauncherLogger.log(5, "Control port socket is not a socket: " +
- this.mControlSocketFile.path);
+ TorLauncherLogger.log(5,
+ "Control port IPC object is not a special file: " +
+ this.mControlIPCFile.path);
}
else
{
- TorLauncherLogger.log(2, "Opening control connection to socket " +
- this.mControlSocketFile.path);
- socket = sts.createUnixDomainTransport(this.mControlSocketFile);
+ TorLauncherLogger.log(2, "Opening control connection to " +
+ this.mControlIPCFile.path);
+ socket = sts.createUnixDomainTransport(this.mControlIPCFile);
}
}
}
@@ -855,14 +981,16 @@ TorProtocolService.prototype =
}
else
{
- var valObj = {};
- if (!this._strUnescape(line.substring(prefixLen), valObj))
+ try
{
- TorLauncherLogger.safelog(4, "Invalid string within " + aCmd +
+ let s = this._strUnescape(line.substring(prefixLen));
+ tmpArray.push(s);
+ }
+ catch (e)
+ {
+ TorLauncherLogger.safelog(4, e + " within " + aCmd +
" response: ", line);
}
- else
- tmpArray.push(valObj.result);
}
}
@@ -954,25 +1082,20 @@ TorProtocolService.prototype =
// Unescape Tor Control string aStr (removing surrounding "" and \ escapes).
// Based on Vidalia's src/common/stringutil.cpp:string_unescape().
- // Returns true if successful and sets aResultObj.result.
- _strUnescape: function(aStr, aResultObj)
+ // Returns the unescaped string. Throws upon failure.
+ // Within Torbutton, the file modules/utils.js also contains a copy of
+ // _strUnescape().
+ _strUnescape: function(aStr)
{
- if (!aResultObj)
- return false;
-
if (!aStr)
- {
- aResultObj.result = aStr;
- return true;
- }
+ return aStr;
var len = aStr.length;
if ((len < 2) || ('"' != aStr.charAt(0)) || ('"' != aStr.charAt(len - 1)))
- {
- aResultObj.result = aStr;
- return true;
- }
+ return aStr;
+ const kHexRE = /[0-9A-Fa-f]{2}/;
+ const kOctalRE = /[0-7]{3}/;
var rv = "";
var i = 1;
var lastCharIndex = len - 2;
@@ -982,7 +1105,7 @@ TorProtocolService.prototype =
if ('\\' == c)
{
if (++i > lastCharIndex)
- return false; // error: \ without next character.
+ throw new Error("missing character after \\");
c = aStr.charAt(i);
if ('n' == c)
@@ -994,24 +1117,26 @@ TorProtocolService.prototype =
else if ('x' == c)
{
if ((i + 2) > lastCharIndex)
- return false; // error: not enough hex characters.
+ throw new Error("not enough hex characters");
- var val = parseInt(aStr.substr(i, 2), 16);
- if (isNaN(val))
- return false; // error: invalid hex characters.
+ let s = aStr.substr(i + 1, 2);
+ if (!kHexRE.test(s))
+ throw new Error("invalid hex character");
+ let val = parseInt(s, 16);
rv += String.fromCharCode(val);
- i += 2;
+ i += 3;
}
else if (this._isDigit(c))
{
- if ((i + 3) > lastCharIndex)
- return false; // error: not enough octal characters.
+ let s = aStr.substr(i, 3);
+ if ((i + 2) > lastCharIndex)
+ throw new Error("not enough octal characters");
- var val = parseInt(aStr.substr(i, 3), 8);
- if (isNaN(val))
- return false; // error: invalid octal characters.
+ if (!kOctalRE.test(s))
+ throw new Error("invalid octal character");
+ let val = parseInt(s, 8);
rv += String.fromCharCode(val);
i += 3;
}
@@ -1022,7 +1147,7 @@ TorProtocolService.prototype =
}
}
else if ('"' == c)
- return false; // error: unescaped double quote in middle of string.
+ throw new Error("unescaped \" within string");
else
{
rv += c;
@@ -1031,10 +1156,7 @@ TorProtocolService.prototype =
}
// Convert from UTF-8 to Unicode. TODO: is UTF-8 always used in protocol?
- rv = decodeURIComponent(escape(rv));
-
- aResultObj.result = rv;
- return true;
+ return decodeURIComponent(escape(rv));
}, // _strUnescape()
// Returns a random 16 character password, hex-encoded.
@@ -1188,6 +1310,8 @@ TorProtocolService.prototype =
return rv;
},
+ // Within Torbutton, the file modules/utils.js also contains a copy of
+ // _isDigit().
_isDigit: function(aChar)
{
const kRE = /^\d$/;
diff --git a/src/defaults/preferences/prefs.js b/src/defaults/preferences/prefs.js
index 500fe2f..875c300 100644
--- a/src/defaults/preferences/prefs.js
+++ b/src/defaults/preferences/prefs.js
@@ -9,17 +9,30 @@ pref("extensions.torlauncher.loglevel", 4); // 1=verbose, 2=debug, 3=info, 4=no
pref("extensions.torlauncher.logmethod", 1); // 0=stdout, 1=errorconsole, 2=debuglog
pref("extensions.torlauncher.max_tor_log_entries", 1000);
-// By default, a Unix domain socket at a default location is used for
-// the Tor control port.
-// Change control_port_use_socket to false to use a TCP connection
-// instead, as defined by control_host and control_port.
-// Modify control_socket_path to override the default socket location. If a
+// 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_socket", true);
-pref("extensions.torlauncher.control_socket_path", "");
+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");
+
// The tor_path is relative to the application directory. On Linux and
// Windows this is the Browser/ directory that contains the firefox
// executables, and on Mac OS it is the TorBrowser.app directory.
diff --git a/src/modules/tl-util.jsm b/src/modules/tl-util.jsm
index 85b5fbe..a1256fd 100644
--- a/src/modules/tl-util.jsm
+++ b/src/modules/tl-util.jsm
@@ -388,8 +388,8 @@ let TorLauncherUtil = // Public
},
// Returns an nsIFile.
- // If aTorFileType is "control_socket", aCreate is ignored and there is
- // no requirement that the socket exists.
+ // 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)
@@ -400,7 +400,9 @@ let TorLauncherUtil = // Public
let isRelativePath = true;
let isUserData = (aTorFileType != "tor") &&
(aTorFileType != "torrc-defaults");
- let isControlSocket = ("control_socket" == aTorFileType);
+ let isControlIPC = ("control_ipc" == aTorFileType);
+ let isSOCKSIPC = ("socks_ipc" == aTorFileType);
+ let isIPC = isControlIPC || isSOCKSIPC;
let prefName = "extensions.torlauncher." + aTorFileType + "_path";
let path = this.getCharPref(prefName);
if (path)
@@ -435,8 +437,10 @@ let TorLauncherUtil = // Public
path = "Tor/torrc";
else if ("tordatadir" == aTorFileType)
path = "Tor";
- else if (isControlSocket)
+ else if (isControlIPC)
path = "Tor/control.socket";
+ else if (isSOCKSIPC)
+ path = "Tor/socks.socket";
}
else // Linux and others.
{
@@ -448,8 +452,10 @@ let TorLauncherUtil = // Public
path = "Tor/torrc";
else if ("tordatadir" == aTorFileType)
path = "Tor";
- else if (isControlSocket)
+ else if (isControlIPC)
path = "Tor/control.socket";
+ else if (isSOCKSIPC)
+ path = "Tor/socks.socket";
}
}
else if (this.isWindows)
@@ -475,8 +481,10 @@ let TorLauncherUtil = // Public
path = "Data/Tor/torrc";
else if ("tordatadir" == aTorFileType)
path = "Data/Tor";
- else if (isControlSocket)
+ else if (isControlIPC)
path = "Data/Tor/control.socket";
+ else if (isSOCKSIPC)
+ path = "Data/Tor/socks.socket";
}
}
@@ -508,7 +516,7 @@ let TorLauncherUtil = // Public
f.initWithPath(path);
}
- if (!f.exists() && !isControlSocket && aCreate)
+ if (!f.exists() && !isIPC && aCreate)
{
try
{
@@ -524,10 +532,10 @@ let TorLauncherUtil = // Public
}
}
- // If the file exists or the control socket was requested, normalize
- // the path and return a file object. The control socket will be
+ // 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 (f.exists() || isControlSocket)
+ if (f.exists() || isIPC)
{
try { f.normalize(); } catch(e) {}
return f;
@@ -538,7 +546,7 @@ let TorLauncherUtil = // Public
catch(e)
{
TorLauncherLogger.safelog(4, "getTorFile " + aTorFileType +
- " failed for " + path + ": ", e);
+ " failed for " + path + ": ", e);
}
return null; // File not found or error (logged above).
1
0

[torbutton/master] Bug 20111: use Unix domain sockets for SOCKS port by default
by gk@torproject.org 20 Oct '16
by gk@torproject.org 20 Oct '16
20 Oct '16
commit f4980a6c647ea780eacc922846e81c0d992cbd13
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Tue Oct 11 15:37:47 2016 -0400
Bug 20111: use Unix domain sockets for SOCKS port by default
Retrieve SOCKS port configuration from Tor Launcher if available.
Support the TOR_SOCKS_IPC_PATH environment variable.
Consistently use IPC to refer to Unix domain sockets.
Enhance torbutton_local_tor_check() to correctly handle spaces and
escaped characters within the 'GETINFO net/listeners/socks' response.
Within startup-observer.js, use Services.jsm, Cc and similar
constants, and remove unused code.
---
src/chrome/content/tor-circuit-display.js | 12 +--
src/chrome/content/torbutton.js | 64 +++++++++-------
src/components/startup-observer.js | 117 +++++++++++++++++++-----------
src/modules/tor-control-port.js | 51 +++++++------
src/modules/utils.js | 101 +++++++++++++++++++++++++-
5 files changed, 242 insertions(+), 103 deletions(-)
diff --git a/src/chrome/content/tor-circuit-display.js b/src/chrome/content/tor-circuit-display.js
index f1cf2aa..c58c6d7 100644
--- a/src/chrome/content/tor-circuit-display.js
+++ b/src/chrome/content/tor-circuit-display.js
@@ -6,7 +6,7 @@
// with docco.js to produce pretty documentation.
//
// This script is to be embedded in torbutton.xul. It defines a single global
-// function, createTorCircuitDisplay(socketFile, host, port, password), which
+// function, createTorCircuitDisplay(ipcFile, host, port, password), which
// activates the automatic Tor circuit display for the current tab and any
// future tabs.
//
@@ -16,9 +16,9 @@
/* global document, gBrowser, Components */
// ### Main function
-// __createTorCircuitDisplay(socketFile, host, port, password, enablePrefName)__.
+// __createTorCircuitDisplay(ipcFile, host, port, password, enablePrefName)__.
// The single function that prepares tor circuit display. Connects to a tor
-// control port with the given socketFile or host plus port, and password, and
+// control port with the given ipcFile or host plus port, and password, and
// binds to a named bool pref whose value determines whether the circuit display
// is enabled or disabled.
let createTorCircuitDisplay = (function () {
@@ -312,11 +312,11 @@ let syncDisplayWithSelectedTab = (function() {
// ## Main function
-// __setupDisplay(socketFile, host, port, password, enablePrefName)__.
+// __setupDisplay(ipcFile, host, port, password, enablePrefName)__.
// Once called, the Tor circuit display will be started whenever
// the "enablePref" is set to true, and stopped when it is set to false.
// A reference to this function (called createTorCircuitDisplay) is exported as a global.
-let setupDisplay = function (socketFile, host, port, password, enablePrefName) {
+let setupDisplay = function (ipcFile, host, port, password, enablePrefName) {
let myController = null,
stopCollectingIsolationData = null,
stop = function() {
@@ -330,7 +330,7 @@ let setupDisplay = function (socketFile, host, port, password, enablePrefName) {
},
start = function () {
if (!myController) {
- myController = controller(socketFile, host, port || 9151, password,
+ myController = controller(ipcFile, host, port || 9151, password,
function (err) {
// An error has occurred.
logger.eclog(5, err);
diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js
index d2824cb..9a8b9e2 100644
--- a/src/chrome/content/torbutton.js
+++ b/src/chrome/content/torbutton.js
@@ -10,6 +10,7 @@
let { LoadContextInfo } = Cu.import('resource://gre/modules/LoadContextInfo.jsm');
let { Services } = Cu.import("resource://gre/modules/Services.jsm");
let { showDialog } = Cu.import("resource://torbutton/modules/utils.js");
+let { unescapeTorString } = Cu.import("resource://torbutton/modules/utils.js");
const k_tb_last_browser_version_pref = "extensions.torbutton.lastBrowserVersion";
const k_tb_browser_update_needed_pref = "extensions.torbutton.updateNeeded";
@@ -33,9 +34,9 @@ var m_tb_window_width = window.outerWidth;
var m_tb_tbb = false;
-var m_tb_control_socket_file = null; // Set if using a UNIX domain socket.
-var m_tb_control_port = null; // Set if not using a socket.
-var m_tb_control_host = null; // Set if not using a socket.
+var m_tb_control_ipc_file = null; // Set if using IPC (UNIX domain socket).
+var m_tb_control_port = null; // Set if using TCP.
+var m_tb_control_host = null; // Set if using TCP.
var m_tb_control_pass = null;
var m_tb_control_desc = null; // For logging.
@@ -327,15 +328,15 @@ function torbutton_init() {
m_tb_control_pass = tlps.TorGetPassword(false);
} catch(e) {}
- // Try to get control port socket (an nsIFile) from Tor Launcher, since
- // Tor Launcher knows how to handle its own preferences and how to
+ // Try to get the control port IPC file (an nsIFile) from Tor Launcher,
+ // since Tor Launcher knows how to handle its own preferences and how to
// resolve relative paths.
try {
- m_tb_control_socket_file = tlps.TorGetControlSocketFile();
+ m_tb_control_ipc_file = tlps.TorGetControlIPCFile();
} catch(e) {}
- if (m_tb_control_socket_file) {
- m_tb_control_desc = m_tb_control_socket_file.path;
+ if (m_tb_control_ipc_file) {
+ m_tb_control_desc = m_tb_control_ipc_file.path;
} else {
if (environ.exists("TOR_CONTROL_PORT")) {
m_tb_control_port = environ.get("TOR_CONTROL_PORT");
@@ -438,7 +439,7 @@ function torbutton_init() {
torbutton_notify_if_update_needed();
torbutton_update_sync_ui();
- createTorCircuitDisplay(m_tb_control_socket_file, m_tb_control_host,
+ createTorCircuitDisplay(m_tb_control_ipc_file, m_tb_control_host,
m_tb_control_port, m_tb_control_pass,
"extensions.torbutton.display_circuit");
@@ -1009,8 +1010,8 @@ function torbutton_send_ctrl_cmd(command) {
let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService);
let socket;
- if (m_tb_control_socket_file) {
- socket = sts.createUnixDomainTransport(m_tb_control_socket_file);
+ if (m_tb_control_ipc_file) {
+ socket = sts.createUnixDomainTransport(m_tb_control_ipc_file);
} else {
socket = sts.createTransport(null, 0, m_tb_control_host,
m_tb_control_port, null);
@@ -1350,7 +1351,7 @@ function torbutton_do_new_identity() {
torbutton_log(3, "New Identity: Sending NEWNYM");
// We only support TBB for newnym.
- if (!m_tb_control_pass || (!m_tb_control_socket_file && !m_tb_control_port)) {
+ if (!m_tb_control_pass || (!m_tb_control_ipc_file && !m_tb_control_port)) {
var warning = torbutton_get_property_string("torbutton.popup.no_newnym");
torbutton_log(5, "Torbutton cannot safely newnym. It does not have access to the Tor Control Port.");
window.alert(warning);
@@ -1508,7 +1509,7 @@ function torbutton_do_tor_check()
const kEnvUseTransparentProxy = "TOR_TRANSPROXY";
var env = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment);
- if ((m_tb_control_socket_file || m_tb_control_port) &&
+ if ((m_tb_control_ipc_file || m_tb_control_port) &&
!env.exists(kEnvUseTransparentProxy) &&
!env.exists(kEnvSkipControlPortTest) &&
m_tb_prefs.getBoolPref("extensions.torbutton.local_tor_check")) {
@@ -1559,19 +1560,20 @@ function torbutton_local_tor_check()
}
// Sample response: net/listeners/socks="127.0.0.1:9149" "127.0.0.1:9150"
- // First, check for command argument prefix.
+ // First, check for and remove the command argument prefix.
if (0 != resp.indexOf(kCmdArg + '=')) {
logUnexpectedResponse();
return false;
}
+ resp = resp.substr(kCmdArg.length + 1);
// Retrieve configured proxy settings and check each listener against them.
- // When a Unix domain socket is configured, a file URL should be present in
- // network.proxy.socks.
+ // When the SOCKS prefs are set to use IPC (e.g., a Unix domain socket), a
+ // file URL should be present in network.proxy.socks.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1211567
let socksAddr = m_tb_prefs.getCharPref("network.proxy.socks");
let socksPort = m_tb_prefs.getIntPref("network.proxy.socks_port");
- let socketPath;
+ let socksIPCPath;
if (socksAddr && socksAddr.startsWith("file:")) {
// Convert the file URL to a file path.
try {
@@ -1579,19 +1581,29 @@ function torbutton_local_tor_check()
.getService(Ci.nsIIOService);
let fph = ioService.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler);
- socketPath = fph.getFileFromURLSpec(socksAddr).path;
+ socksIPCPath = fph.getFileFromURLSpec(socksAddr).path;
} catch (e) {
- torbutton_log(5, "Local Tor check: Unix domain socket error: " + e);
+ torbutton_log(5, "Local Tor check: IPC file error: " + e);
return false;
}
} else {
socksAddr = removeBrackets(socksAddr);
}
- let addrArray = resp.substr(kCmdArg.length + 1).split(' ');
+ // Split into quoted strings. This code is adapted from utils.splitAtSpaces()
+ // within tor-control-port.js; someday this code should use the entire
+ // tor-control-port.js framework.
+ let addrArray = [];
+ resp.replace(/((\S*?"(.*?)")+\S*|\S+)/g, function (a, captured) {
+ addrArray.push(captured);
+ });
+
let foundSocksListener = false;
for (let i = 0; !foundSocksListener && (i < addrArray.length); ++i) {
- let addr = addrArray[i];
+ let addr;
+ try { addr = unescapeTorString(addrArray[i]); } catch (e) {}
+ if (!addr)
+ continue;
// Remove double quotes if present.
let len = addr.length;
@@ -1599,14 +1611,14 @@ function torbutton_local_tor_check()
addr = addr.substring(1, len - 1);
if (addr.startsWith("unix:")) {
- if (!socketPath)
+ if (!socksIPCPath)
continue;
// Check against the configured UNIX domain socket proxy.
let path = addr.substring(5);
- torbutton_log(2, "Tor socks listener (socket): " + path);
- foundSocksListener = (socketPath === path);
- } else if (!socketPath) {
+ torbutton_log(2, "Tor socks listener (Unix domain socket): " + path);
+ foundSocksListener = (socksIPCPath === path);
+ } else if (!socksIPCPath) {
// Check against the configured TCP proxy. We expect addr:port where addr
// may be an IPv6 address; that is, it may contain colon characters.
// Also, we remove enclosing square brackets before comparing addresses
@@ -2088,7 +2100,7 @@ function torbutton_check_protections()
// See https://trac.torproject.org/projects/tor/ticket/10353 for more info.
document.getElementById("torbutton-cookie-protector").hidden = m_tb_prefs.getBoolPref("browser.privatebrowsing.autostart");
- if (!m_tb_control_pass || (!m_tb_control_socket_file && !m_tb_control_port)) {
+ if (!m_tb_control_pass || (!m_tb_control_ipc_file && !m_tb_control_port)) {
document.getElementById("torbutton-new-identity").disabled = true;
}
diff --git a/src/components/startup-observer.js b/src/components/startup-observer.js
index f083482..6698b0b 100644
--- a/src/components/startup-observer.js
+++ b/src/components/startup-observer.js
@@ -15,6 +15,13 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
+ "resource://gre/modules/FileUtils.jsm");
+
// Module specific constants
const kMODULE_NAME = "Startup";
@@ -22,10 +29,9 @@ const kMODULE_CONTRACTID = "@torproject.org/startup-observer;1";
const kMODULE_CID = Components.ID("06322def-6fde-4c06-aef6-47ae8e799629");
function StartupObserver() {
- this.logger = Components.classes["@torproject.org/torbutton-logger;1"]
- .getService(Components.interfaces.nsISupports).wrappedJSObject;
- this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
+ this.logger = Cc["@torproject.org/torbutton-logger;1"]
+ .getService(Ci.nsISupports).wrappedJSObject;
+ this._prefs = Services.prefs;
this.logger.log(3, "Startup Observer created");
var env = Cc["@mozilla.org/process/environment;1"]
@@ -61,41 +67,74 @@ StartupObserver.prototype = {
// some weird proxy caching code that showed up in FF15.
// Otherwise, homepage domain loads fail forever.
setProxySettings: function() {
+ if (!this.is_tbb)
+ return;
+
// Bug 1506: Still want to get these env vars
- var environ = Components.classes["@mozilla.org/process/environment;1"]
- .getService(Components.interfaces.nsIEnvironment);
-
- if (environ.exists("TOR_SOCKS_PORT")) {
- if (this.is_tbb) {
- this._prefs.setIntPref('network.proxy.socks_port',
- parseInt(environ.get("TOR_SOCKS_PORT")));
- this._prefs.setBoolPref('network.proxy.socks_remote_dns', true);
- this._prefs.setIntPref('network.proxy.type', 1);
+ let environ = Cc["@mozilla.org/process/environment;1"]
+ .getService(Ci.nsIEnvironment);
+ if (environ.exists("TOR_TRANSPROXY")) {
+ this.logger.log(3, "Resetting Tor settings to transproxy");
+ this._prefs.setBoolPref("network.proxy.socks_remote_dns", false);
+ this._prefs.setIntPref("network.proxy.type", 0);
+ this._prefs.setIntPref("network.proxy.socks_port", 0);
+ this._prefs.setCharPref("network.proxy.socks", "");
+ } else {
+ // Try to retrieve SOCKS proxy settings from Tor Launcher.
+ let socksPortInfo;
+ try {
+ let tlps = Cc["@torproject.org/torlauncher-protocol-service;1"]
+ .getService(Ci.nsISupports).wrappedJSObject;
+ socksPortInfo = tlps.TorGetSOCKSPortInfo();
+ } catch(e) {}
+
+ // If Tor Launcher is not available, check environment variables.
+ if (!socksPortInfo) {
+ socksPortInfo = { ipcFile: undefined, host: undefined, port: 0 };
+
+ let isWindows = Services.appinfo.OS === "WINNT";
+ if (!isWindows && environ.exists("TOR_SOCKS_IPC_PATH")) {
+ socksPortInfo.ipcFile = new FileUtils.File(
+ environ.get("TOR_SOCKS_IPC_PATH"));
+ }
+ else
+ {
+ if (environ.exists("TOR_SOCKS_HOST"))
+ socksPortInfo.host = environ.get("TOR_SOCKS_HOST");
+ if (environ.exists("TOR_SOCKS_PORT"))
+ socksPortInfo.port = parseInt(environ.get("TOR_SOCKS_PORT"));
+ }
}
- this.logger.log(3, "Reset socks port to "+environ.get("TOR_SOCKS_PORT"));
- }
- if (environ.exists("TOR_SOCKS_HOST")) {
- if (this.is_tbb) {
- this._prefs.setCharPref('network.proxy.socks', environ.get("TOR_SOCKS_HOST"));
+ // Adjust network.proxy prefs.
+ if (socksPortInfo.ipcFile) {
+ let fph = Services.io.getProtocolHandler("file")
+ .QueryInterface(Ci.nsIFileProtocolHandler);
+ let fileURI = fph.newFileURI(socksPortInfo.ipcFile);
+ this.logger.log(3, "Reset socks to "+fileURI.spec);
+ this._prefs.setCharPref("network.proxy.socks", fileURI.spec);
+ this._prefs.setIntPref("network.proxy.socks_port", 0);
+ } else {
+ if (socksPortInfo.host) {
+ this._prefs.setCharPref("network.proxy.socks", socksPortInfo.host);
+ this.logger.log(3, "Reset socks host to "+socksPortInfo.host);
+ }
+ if (socksPortInfo.port) {
+ this._prefs.setIntPref("network.proxy.socks_port",
+ socksPortInfo.port);
+ this.logger.log(3, "Reset socks port to "+socksPortInfo.port);
+ }
}
- }
- if (environ.exists("TOR_TRANSPROXY")) {
- this.logger.log(3, "Resetting Tor settings to transproxy");
- if (this.is_tbb) {
- this._prefs.setBoolPref('network.proxy.socks_remote_dns', false);
- this._prefs.setIntPref('network.proxy.type', 0);
- this._prefs.setIntPref('network.proxy.socks_port', 0);
- this._prefs.setCharPref('network.proxy.socks', "");
+ if (socksPortInfo.ipcFile || socksPortInfo.host || socksPortInfo.port) {
+ this._prefs.setBoolPref("network.proxy.socks_remote_dns", true);
+ this._prefs.setIntPref("network.proxy.type", 1);
}
}
// Force prefs to be synced to disk
- var prefService = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
- prefService.savePrefFile(null);
-
+ this._prefs.savePrefFile(null);
+
this.logger.log(3, "Synced network settings to environment.");
},
@@ -109,16 +148,14 @@ StartupObserver.prototype = {
}
// In all cases, force prefs to be synced to disk
- var prefService = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
- prefService.savePrefFile(null);
+ this._prefs.savePrefFile(null);
},
QueryInterface: function(iid) {
- if (iid.equals(Components.interfaces.nsISupports)) {
+ if (iid.equals(Ci.nsISupports)) {
return this;
}
- if(iid.equals(Components.interfaces.nsIClassInfo)) {
+ if(iid.equals(Ci.nsIClassInfo)) {
return this;
}
return this;
@@ -141,12 +178,4 @@ StartupObserver.prototype = {
};
-/**
-* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
-* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
-*/
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-if (XPCOMUtils.generateNSGetFactory)
- var NSGetFactory = XPCOMUtils.generateNSGetFactory([StartupObserver]);
-else
- var NSGetModule = XPCOMUtils.generateNSGetModule([StartupObserver]);
+var NSGetFactory = XPCOMUtils.generateNSGetFactory([StartupObserver]);
diff --git a/src/modules/tor-control-port.js b/src/modules/tor-control-port.js
index f23daed..a7f0434 100644
--- a/src/modules/tor-control-port.js
+++ b/src/modules/tor-control-port.js
@@ -10,7 +10,7 @@
// let { controller } = Components.utils.import("path/to/tor-control-port.js");
//
// See the last function defined in this file:
-// controller(socketFile, host, port, password, onError)
+// controller(ipcFile, host, port, password, onError)
// for usage of the controller function.
/* jshint esnext: true */
@@ -42,18 +42,18 @@ log("Loading tor-control-port.js\n");
// I/O utilities namespace
let io = {};
-// __io.asyncSocketStreams(socketFile, host, port)__.
+// __io.asyncSocketStreams(ipcFile, host, port)__.
// Creates a pair of asynchronous input and output streams for a socket at the
-// given socketFile or host and port.
-io.asyncSocketStreams = function (socketFile, host, port) {
+// given ipcFile or host and port.
+io.asyncSocketStreams = function (ipcFile, host, port) {
let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Components.interfaces.nsISocketTransportService),
UNBUFFERED = Ci.nsITransport.OPEN_UNBUFFERED;
// Create an instance of a socket transport.
let socketTransport;
- if (socketFile) {
- socketTransport = sts.createUnixDomainTransport(socketFile);
+ if (ipcFile) {
+ socketTransport = sts.createUnixDomainTransport(ipcFile);
} else {
socketTransport = sts.createTransport(null, 0, host, port, null);
}
@@ -99,16 +99,15 @@ io.pumpInputStream = function (inputStream, onInputData, onError) {
} }, null);
};
-// __io.asyncSocket(socketFile, host, port, onInputData, onError)__.
-// Creates an asynchronous, text-oriented UNIX domain socket (if socketFile
-// is defined) or TCP socket at host:port.
+// __io.asyncSocket(ipcFile, host, port, onInputData, onError)__.
+// Creates an asynchronous, text-oriented IPC socket (if ipcFile is defined)
+// or a TCP socket at host:port.
// The onInputData callback should accept a single argument, which will be called
// repeatedly, whenever incoming text arrives. Returns a socket object with two methods:
// socket.write(text) and socket.close(). onError will be passed the error object
// whenever a write fails.
-io.asyncSocket = function (socketFile, host, port, onInputData, onError) {
- let [inputStream, outputStream] = io.asyncSocketStreams(socketFile, host,
- port),
+io.asyncSocket = function (ipcFile, host, port, onInputData, onError) {
+ let [inputStream, outputStream] = io.asyncSocketStreams(ipcFile, host, port),
pendingWrites = [];
// Run an input stream pump to send incoming data to the onInputData callback.
io.pumpInputStream(inputStream, onInputData, onError);
@@ -253,8 +252,8 @@ io.matchRepliesToCommands = function (asyncSend, dispatcher) {
});
};
-// __io.controlSocket(socketFile, host, port, password, onError)__.
-// Instantiates and returns a socket to a tor ControlPort at socketFile or
+// __io.controlSocket(ipcFile, host, port, password, onError)__.
+// Instantiates and returns a socket to a tor ControlPort at ipcFile or
// host:port, authenticating with the given password. onError is called with an
// error object as its single argument whenever an error occurs. Example:
//
@@ -269,11 +268,11 @@ io.matchRepliesToCommands = function (asyncSend, dispatcher) {
// socket.removeNotificationCallback(callback);
// // Close the socket permanently
// socket.close();
-io.controlSocket = function (socketFile, host, port, password, onError) {
+io.controlSocket = function (ipcFile, host, port, password, onError) {
// Produce a callback dispatcher for Tor messages.
let mainDispatcher = io.callbackDispatcher(),
// Open the socket and convert format to Tor messages.
- socket = io.asyncSocket(socketFile, host, port,
+ socket = io.asyncSocket(ipcFile, host, port,
io.onDataFromOnLine(
io.onLineFromOnMessage(mainDispatcher.pushMessage)),
onError),
@@ -620,12 +619,12 @@ let tor = {};
// redundant instantiation of control sockets.
tor.controllerCache = {};
-// __tor.controller(socketFile, host, port, password, onError)__.
-// Creates a tor controller at the given socketFile or host and port, with the
+// __tor.controller(ipcFile, host, port, password, onError)__.
+// Creates a tor controller at the given ipcFile or host and port, with the
// given password.
// onError returns asynchronously whenever a connection error occurs.
-tor.controller = function (socketFile, host, port, password, onError) {
- let socket = io.controlSocket(socketFile, host, port, password, onError),
+tor.controller = function (ipcFile, host, port, password, onError) {
+ let socket = io.controlSocket(ipcFile, host, port, password, onError),
isOpen = true;
return { getInfo : key => info.getInfo(socket, key),
getConf : key => info.getConf(socket, key),
@@ -638,11 +637,11 @@ tor.controller = function (socketFile, host, port, password, onError) {
// ## Export
-// __controller(socketFile, host, port, password, onError)__.
+// __controller(ipcFile, host, port, password, onError)__.
// Instantiates and returns a controller object connected to a tor ControlPort
-// on socketFile or at host:port, authenticating with the given password, if
+// on ipcFile or at host:port, authenticating with the given password, if
// the controller doesn't yet exist. Otherwise returns the existing controller
-// to the given socketFile or host:port.
+// to the given ipcFile or host:port.
// onError is called with an error object as its single argument whenever
// an error occurs. Example:
//
@@ -653,13 +652,13 @@ tor.controller = function (socketFile, host, port, password, onError) {
// let replyPromise = c.getInfo("ip-to-country/16.16.16.16");
// // Close the controller permanently
// c.close();
-var controller = function (socketFile, host, port, password, onError) {
- let dest = (socketFile) ? "unix:" + socketFile.path : host + ":" + port,
+var controller = function (ipcFile, host, port, password, onError) {
+ let dest = (ipcFile) ? "unix:" + ipcFile.path : host + ":" + port,
maybeController = tor.controllerCache[dest];
return (tor.controllerCache[dest] =
(maybeController && maybeController.isOpen()) ?
maybeController :
- tor.controller(socketFile, host, port, password, onError));
+ tor.controller(ipcFile, host, port, password, onError));
};
// Export the controller function for external use.
diff --git a/src/modules/utils.js b/src/modules/utils.js
index 514ef51..b303485 100644
--- a/src/modules/utils.js
+++ b/src/modules/utils.js
@@ -74,5 +74,104 @@ var showDialog = function (parent, url, name, features) {
}
};
+// ## Tor control protocol utility functions
+
+let _torControl = {
+ // Unescape Tor Control string aStr (removing surrounding "" and \ escapes).
+ // Based on Vidalia's src/common/stringutil.cpp:string_unescape().
+ // Returns the unescaped string. Throws upon failure.
+ // Within Tor Launcher, the file components/tl-protocol.js also contains a
+ // copy of _strUnescape().
+ _strUnescape: function(aStr)
+ {
+ if (!aStr)
+ return aStr;
+
+ var len = aStr.length;
+ if ((len < 2) || ('"' != aStr.charAt(0)) || ('"' != aStr.charAt(len - 1)))
+ return aStr;
+
+ const kHexRE = /[0-9A-Fa-f]{2}/;
+ const kOctalRE = /[0-7]{3}/;
+ var rv = "";
+ var i = 1;
+ var lastCharIndex = len - 2;
+ while (i <= lastCharIndex)
+ {
+ var c = aStr.charAt(i);
+ if ('\\' == c)
+ {
+ if (++i > lastCharIndex)
+ throw new Error("missing character after \\");
+
+ c = aStr.charAt(i);
+ if ('n' == c)
+ rv += '\n';
+ else if ('r' == c)
+ rv += '\r';
+ else if ('t' == c)
+ rv += '\t';
+ else if ('x' == c)
+ {
+ if ((i + 2) > lastCharIndex)
+ throw new Error("not enough hex characters");
+
+ let s = aStr.substr(i + 1, 2);
+ if (!kHexRE.test(s))
+ throw new Error("invalid hex characters");
+
+ let val = parseInt(s, 16);
+ rv += String.fromCharCode(val);
+ i += 3;
+ }
+ else if (this._isDigit(c))
+ {
+ let s = aStr.substr(i, 3);
+ if ((i + 2) > lastCharIndex)
+ throw new Error("not enough octal characters");
+
+ if (!kOctalRE.test(s))
+ throw new Error("invalid octal characters");
+
+ let val = parseInt(s, 8);
+ rv += String.fromCharCode(val);
+ i += 3;
+ }
+ else // "\\" and others
+ {
+ rv += c;
+ ++i;
+ }
+ }
+ else if ('"' == c)
+ throw new Error("unescaped \" within string");
+ else
+ {
+ rv += c;
+ ++i;
+ }
+ }
+
+ // Convert from UTF-8 to Unicode. TODO: is UTF-8 always used in protocol?
+ return decodeURIComponent(escape(rv));
+ }, // _strUnescape()
+
+ // Within Tor Launcher, the file components/tl-protocol.js also contains a
+ // copy of _isDigit().
+ _isDigit: function(aChar)
+ {
+ const kRE = /^\d$/;
+ return aChar && kRE.test(aChar);
+ },
+}; // _torControl
+
+// __unescapeTorString(str, resultObj)__.
+// Unescape Tor Control string str (removing surrounding "" and \ escapes).
+// Returns the unescaped string. Throws upon failure.
+var unescapeTorString = function(str) {
+ return _torControl._strUnescape(str);
+};
+
// Export utility functions for external use.
-let EXPORTED_SYMBOLS = ["bindPrefAndInit", "getPrefValue", "getEnv", "showDialog"];
+let EXPORTED_SYMBOLS = ["bindPrefAndInit", "getPrefValue", "getEnv",
+ "showDialog", "unescapeTorString"];
1
0

[collector/master] Finishes task-20162: removed six configuration properties:
by karsten@torproject.org 20 Oct '16
by karsten@torproject.org 20 Oct '16
20 Oct '16
commit 8bb7de37ad100b7517b3810dd021a9e301d16bdc
Author: iwakeh <iwakeh(a)torproject.org>
Date: Tue Oct 18 15:59:07 2016 +0200
Finishes task-20162: removed six configuration properties:
DownloadCurrentConsensus,
DownloadCurrentMicrodescConsensus,
DownloadCurrentVotes,
DownloadMissingServerDescriptors,
DownloadMissingExtraInfoDescriptors,
and DownloadMissingMicrodescriptors
Each was replaced by hard-coded 'true'.
---
CHANGELOG.md | 2 ++
.../java/org/torproject/collector/conf/Key.java | 6 ------
.../collector/relaydescs/ArchiveWriter.java | 8 ++------
src/main/resources/collector.properties | 22 ----------------------
.../collector/conf/ConfigurationTest.java | 2 +-
5 files changed, 5 insertions(+), 35 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e1b7eb..af3a620 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
descriptors by a single 'OutPath' property.
- Introduced *Sources and *Origins properties to simplify
data source definition.
+ - Remove six properties for specifying what relay descriptors to
+ download and replace them with hard-coded 'true' values.
# Changes in version 1.0.2 - 2016-10-07
diff --git a/src/main/java/org/torproject/collector/conf/Key.java b/src/main/java/org/torproject/collector/conf/Key.java
index d06fe0c..4b924c7 100644
--- a/src/main/java/org/torproject/collector/conf/Key.java
+++ b/src/main/java/org/torproject/collector/conf/Key.java
@@ -49,12 +49,6 @@ public enum Key {
CompressRelayDescriptorDownloads(Boolean.class),
DirectoryAuthoritiesAddresses(String[].class),
DirectoryAuthoritiesFingerprintsForVotes(String[].class),
- DownloadCurrentConsensus(Boolean.class),
- DownloadCurrentMicrodescConsensus(Boolean.class),
- DownloadCurrentVotes(Boolean.class),
- DownloadMissingServerDescriptors(Boolean.class),
- DownloadMissingExtraInfoDescriptors(Boolean.class),
- DownloadMissingMicrodescriptors(Boolean.class),
DownloadAllServerDescriptors(Boolean.class),
DownloadAllExtraInfoDescriptors(Boolean.class),
KeepDirectoryArchiveImportHistory(Boolean.class),
diff --git a/src/main/java/org/torproject/collector/relaydescs/ArchiveWriter.java b/src/main/java/org/torproject/collector/relaydescs/ArchiveWriter.java
index cdf6506..b2ed0db 100644
--- a/src/main/java/org/torproject/collector/relaydescs/ArchiveWriter.java
+++ b/src/main/java/org/torproject/collector/relaydescs/ArchiveWriter.java
@@ -154,12 +154,8 @@ public class ArchiveWriter extends CollecTorMain {
config.getStringArray(Key.DirectoryAuthoritiesAddresses);
rdd = new RelayDescriptorDownloader(rdp, dirSources,
config.getStringArray(Key.DirectoryAuthoritiesFingerprintsForVotes),
- config.getBool(Key.DownloadCurrentConsensus),
- config.getBool(Key.DownloadCurrentMicrodescConsensus),
- config.getBool(Key.DownloadCurrentVotes),
- config.getBool(Key.DownloadMissingServerDescriptors),
- config.getBool(Key.DownloadMissingExtraInfoDescriptors),
- config.getBool(Key.DownloadMissingMicrodescriptors),
+ true, true, true, // download current consensus, microcons, and votes
+ true, true, true, // download missing serverdesc, extrainfo, and micro
config.getBool(Key.DownloadAllServerDescriptors),
config.getBool(Key.DownloadAllExtraInfoDescriptors),
config.getBool(Key.CompressRelayDescriptorDownloads));
diff --git a/src/main/resources/collector.properties b/src/main/resources/collector.properties
index c8a9e2f..00f4d50 100644
--- a/src/main/resources/collector.properties
+++ b/src/main/resources/collector.properties
@@ -95,28 +95,6 @@ DirectoryAuthoritiesAddresses = 128.31.0.39:9131,86.59.21.38,194.109.206.212,131
## votes
DirectoryAuthoritiesFingerprintsForVotes = 0232AF901C31A04EE9848595AF9BB7620D4C5B2E,14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4,23D15D965BC35114467363C165C4F724B64B4F66,49015F787433103580E3B66A1707A00E60F2D15B,D586D18309DED4CD6D57C18FDB97EFA96D330566,E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58,ED03BB616EB2F60BEC80151114BB25CEF515B226,EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97
#
-## Download the current consensus (only if DownloadRelayDescriptors is 1)
-DownloadCurrentConsensus = true
-#
-## Download the current microdesc consensus (only if
-## DownloadRelayDescriptors is true)
-DownloadCurrentMicrodescConsensus = true
-#
-## Download current votes (only if DownloadRelayDescriptors is true)
-DownloadCurrentVotes = true
-#
-## Download missing server descriptors (only if DownloadRelayDescriptors
-## is true)
-DownloadMissingServerDescriptors = true
-#
-## Download missing extra-info descriptors (only if
-## DownloadRelayDescriptors is true)
-DownloadMissingExtraInfoDescriptors = true
-#
-## Download missing microdescriptors (only if
-## DownloadRelayDescriptors is true)
-DownloadMissingMicrodescriptors = true
-#
## Download all server descriptors from the directory authorities at most
## once a day (only if DownloadRelayDescriptors is true)
DownloadAllServerDescriptors = false
diff --git a/src/test/java/org/torproject/collector/conf/ConfigurationTest.java b/src/test/java/org/torproject/collector/conf/ConfigurationTest.java
index 3f9c231..019c481 100644
--- a/src/test/java/org/torproject/collector/conf/ConfigurationTest.java
+++ b/src/test/java/org/torproject/collector/conf/ConfigurationTest.java
@@ -41,7 +41,7 @@ public class ConfigurationTest {
public void testKeyCount() throws Exception {
assertEquals("The number of properties keys in enum Key changed."
+ "\n This test class should be adapted.",
- 50, Key.values().length);
+ 44, Key.values().length);
}
@Test()
1
0

20 Oct '16
commit d1bcba19a9790a37680b711e910152a293961d82
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Oct 20 11:02:04 2016 -0400
Turn scheduler.c documentation into doxygen.
---
src/or/scheduler.c | 107 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 69 insertions(+), 38 deletions(-)
diff --git a/src/or/scheduler.c b/src/or/scheduler.c
index 49ac1b9..ae2e950 100644
--- a/src/or/scheduler.c
+++ b/src/or/scheduler.c
@@ -1,11 +1,6 @@
/* * Copyright (c) 2013-2016, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-/**
- * \file scheduler.c
- * \brief Relay scheduling system
- **/
-
#include "or.h"
#define TOR_CHANNEL_INTERNAL_ /* For channel_flush_some_cells() */
@@ -32,66 +27,102 @@ static uint32_t sched_q_high_water = 32768;
static uint32_t sched_max_flush_cells = 16;
-/*
- * Write scheduling works by keeping track of which channels can
+/**
+ * \file scheduler.c
+ * \brief Channel scheduling system: decides which channels should send and
+ * receive when.
+ *
+ * This module implements a scheduler algorithm, to decide
+ * which channels should send/receive when.
+ *
+ * The earliest versions of Tor approximated a kind of round-robin system among
+ * active connections, but only approximated it.
+ *
+ * Now, write scheduling works by keeping track of which channels can
* accept cells, and have cells to write. From the scheduler's perspective,
* a channel can be in four possible states:
*
- * 1.) Not open for writes, no cells to send
- * - Not much to do here, and the channel will have scheduler_state ==
+ * <ol>
+ * <li>
+ * Not open for writes, no cells to send .
+ * <ul><li> Not much to do here, and the channel will have scheduler_state ==
* SCHED_CHAN_IDLE
- * - Transitions from:
- * - Open for writes/has cells by simultaneously draining all circuit
+ * <li> Transitions from:
+ * <ul>
+ * <li>Open for writes/has cells by simultaneously draining all circuit
* queues and filling the output buffer.
- * - Transitions to:
- * - Not open for writes/has cells by arrival of cells on an attached
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li> Not open for writes/has cells by arrival of cells on an attached
* circuit (this would be driven from append_cell_to_circuit_queue())
- * - Open for writes/no cells by a channel type specific path;
+ * <li> Open for writes/no cells by a channel type specific path;
* driven from connection_or_flushed_some() for channel_tls_t.
+ * </ul>
+ * </ul>
*
- * 2.) Open for writes, no cells to send
- * - Not much here either; this will be the state an idle but open channel
+ * <li> Open for writes, no cells to send
+ * <ul>
+ * <li>Not much here either; this will be the state an idle but open channel
* can be expected to settle in. It will have scheduler_state ==
* SCHED_CHAN_WAITING_FOR_CELLS
- * - Transitions from:
- * - Not open for writes/no cells by flushing some of the output
+ * <li> Transitions from:
+ * <ul>
+ * <li>Not open for writes/no cells by flushing some of the output
* buffer.
- * - Open for writes/has cells by the scheduler moving cells from
+ * <li>Open for writes/has cells by the scheduler moving cells from
* circuit queues to channel output queue, but not having enough
* to fill the output queue.
- * - Transitions to:
- * - Open for writes/has cells by arrival of new cells on an attached
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li>Open for writes/has cells by arrival of new cells on an attached
* circuit, in append_cell_to_circuit_queue()
+ * </ul>
+ * </ul>
*
- * 3.) Not open for writes, cells to send
- * - This is the state of a busy circuit limited by output bandwidth;
+ * <li>Not open for writes, cells to send
+ * <ul>
+ * <li>This is the state of a busy circuit limited by output bandwidth;
* cells have piled up in the circuit queues waiting to be relayed.
* The channel will have scheduler_state == SCHED_CHAN_WAITING_TO_WRITE.
- * - Transitions from:
- * - Not open for writes/no cells by arrival of cells on an attached
+ * <li> Transitions from:
+ * <ul>
+ * <li>Not open for writes/no cells by arrival of cells on an attached
* circuit
- * - Open for writes/has cells by filling an output buffer without
+ * <li> Open for writes/has cells by filling an output buffer without
* draining all cells from attached circuits
- * - Transitions to:
- * - Opens for writes/has cells by draining some of the output buffer
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li>Opens for writes/has cells by draining some of the output buffer
* via the connection_or_flushed_some() path (for channel_tls_t).
+ * </ul>
+ * </ul>
*
- * 4.) Open for writes, cells to send
- * - This connection is ready to relay some cells and waiting for
+ * <li>Open for writes, cells to send
+ * <ul>
+ * <li>This connection is ready to relay some cells and waiting for
* the scheduler to choose it. The channel will have scheduler_state ==
* SCHED_CHAN_PENDING.
- * - Transitions from:
- * - Not open for writes/has cells by the connection_or_flushed_some()
+ * <li>Transitions from:
+ * <ul>
+ * <li> Not open for writes/has cells by the connection_or_flushed_some()
* path
- * - Open for writes/no cells by the append_cell_to_circuit_queue()
+ * <li> Open for writes/no cells by the append_cell_to_circuit_queue()
* path
- * - Transitions to:
- * - Not open for writes/no cells by draining all circuit queues and
- * simultaneously filling the output buffer.
- * - Not open for writes/has cells by writing enough cells to fill the
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li>Not open for writes/no cells by draining all circuit queues and
+ * simultaneously filling the output buffer.
+ * <li>Not open for writes/has cells by writing enough cells to fill the
* output buffer
- * - Open for writes/no cells by draining all attached circuit queues
+ * <li>Open for writes/no cells by draining all attached circuit queues
* without also filling the output buffer
+ * </ul>
+ * </ul>
+ * </ol>
*
* Other event-driven parts of the code move channels between these scheduling
* states by calling scheduler functions; the scheduler only runs on open-for-
1
0
commit fb74059ae3b658f28bb4e5fffa81c0b89a0c4553
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Wed Oct 19 21:21:48 2016 +0200
Prepare for 1.5.0 release.
---
CHANGELOG.md | 2 +-
build.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f4f2eb..a62c987 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-# Changes in version 1.?.? - 2016-1?-??
+# Changes in version 1.5.0 - 2016-10-19
* Major changes
- Make the DescriptorCollector implementation that uses CollecTor's
diff --git a/build.xml b/build.xml
index c1e3296..ad23f31 100644
--- a/build.xml
+++ b/build.xml
@@ -1,5 +1,5 @@
<project default="jar" name="descriptor" basedir=".">
- <property name="release.version" value="1.4.0-dev" />
+ <property name="release.version" value="1.5.0" />
<property name="allsources" value="src"/>
<property name="sources" value="src/main/java"/>
<property name="resources" value="src/main/resources"/>
1
0
commit dd4b395357000f3f8d901693f4046c13c6921080
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Thu Oct 20 11:01:16 2016 +0200
Bump version to 1.5.0-dev.
---
build.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.xml b/build.xml
index ad23f31..794188f 100644
--- a/build.xml
+++ b/build.xml
@@ -1,5 +1,5 @@
<project default="jar" name="descriptor" basedir=".">
- <property name="release.version" value="1.5.0" />
+ <property name="release.version" value="1.5.0-dev" />
<property name="allsources" value="src"/>
<property name="sources" value="src/main/java"/>
<property name="resources" value="src/main/resources"/>
1
0