commit 1875ef7416f9f6108e1bb2a2eea7d6e4a972a988 Author: Yawning Angel yawning@schwanenlied.me Date: Tue May 12 11:39:52 2015 +0000
Add automatic per process isolation (IsolatePID)
IsolatePID will have torsocks automatically derive a unique SOCKS5 username/password pair of the form:
'torsocks-' PID ':' unixTime / '42'
To provide automatic per-process isolation (Disabled by default). This behavior may be better for certain users/applications, and may also be controlled via the `TORSOCKS_ISOLATE_PID` env var.
Option -i/--isolate to torsocks is added that automatically export the TORSOCKS_ISOLATE_PID variable.
Implements #16006.
Signed-off-by: Yawning Angel yawning@schwanenlied.me Signed-off-by: David Goulet dgoulet@ev0ke.net --- doc/torsocks.1 | 5 +++ doc/torsocks.8 | 6 +++ doc/torsocks.conf | 7 +++ doc/torsocks.conf.5 | 8 ++++ src/bin/torsocks.in | 4 ++ src/common/config-file.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++ src/common/config-file.h | 10 +++++ src/common/defaults.h | 3 ++ src/lib/torsocks.c | 16 ++++++- 9 files changed, 165 insertions(+), 1 deletion(-)
diff --git a/doc/torsocks.1 b/doc/torsocks.1 index 9fc4361..0e3c341 100644 --- a/doc/torsocks.1 +++ b/doc/torsocks.1 @@ -47,6 +47,11 @@ Set password for the SOCKS5 authentication. Use for circuit isolation in Tor. Note that you MUST have a username set either by the command line, environment variable or configuration file (torsocks.conf(5)). .TP +.BR "-i, --isolate" +Automatic tor isolation. Set the username and password for the SOCKS5 +authentication method to a PID/current time based value automatically. Username +and Password MUST NOT be set. +.TP .BR "-d, --debug" Activate the debug mode. Output will be written on stderr. .TP diff --git a/doc/torsocks.8 b/doc/torsocks.8 index 4a14703..ac3863a 100644 --- a/doc/torsocks.8 +++ b/doc/torsocks.8 @@ -99,6 +99,12 @@ also with the variable above. Allow inbound connections so the application can accept and listen for connections.
+.PP +.IP TORSOCKS_ISOLATE_PID +Set the username and password for the SOCKS5 authentication method to a +PID/current time based value automatically. Username and Password MUST NOT +be set. + .SH KNOWN ISSUES
.SS DNS diff --git a/doc/torsocks.conf b/doc/torsocks.conf index 7e82a27..5dd9df6 100644 --- a/doc/torsocks.conf +++ b/doc/torsocks.conf @@ -33,3 +33,10 @@ OnionAddrRange 127.42.42.0/24 # If set to 1, connect() will be allowed to be used to the loopback interface # bypassing Tor. This option should not be used by most users. (Default: 0) #AllowOutboundLocalhost 1 + +# Set Torsocks to use an automatically generated SOCKS5 username/password based +# on the process ID and current time, that makes the connections to Tor use a +# different circuit from other existing streams in Tor on a per-process basis. +# If set, the SOCKS5Username and SOCKS5Password options must not be set. +# (Default: 0) +#IsolatePID 1 diff --git a/doc/torsocks.conf.5 b/doc/torsocks.conf.5 index 13ac7b9..33fba3e 100644 --- a/doc/torsocks.conf.5 +++ b/doc/torsocks.conf.5 @@ -83,6 +83,14 @@ Allow outbound connections to the loopback interface meaning that connect() will be allowed to connect to localhost addresses bypassing Tor. This option should not be used by most users. (Default: 0)
+.TP +.I IsolatePID 0|1 +Set Torsocks to use an automatically generated SOCKS5 username/password +based on the process ID and current time, that makes the connections to Tor +use a different circuit from other existing streams in Tor on a per-process +basis. If set, the SOCKS5Username and SOCKS5Password options must not be +set. (Default: 0) + .SH EXAMPLE $ export TORSOCKS_CONF_FILE=$PWD/torsocks.conf $ torsocks ssh account@sshserver.com diff --git a/src/bin/torsocks.in b/src/bin/torsocks.in index 7fd43d6..2a459b3 100644 --- a/src/bin/torsocks.in +++ b/src/bin/torsocks.in @@ -131,6 +131,7 @@ usage () echo " -d, --debug Set debug mode." echo " -u, --user NAME Username for the SOCKS5 authentication" echo " -p, --pass NAME Password for the SOCKS5 authentication" + echo " -i, --isolate Automatic tor isolation. Can't be used with -u/-p" echo " on, off Set/Unset your shell to use Torsocks by default" echo " Make sure to source the call when using this option. (See Examples)" echo " show, sh Show the current value of the LD_PRELOAD" @@ -214,6 +215,9 @@ do export TORSOCKS_PASSWORD=$2 shift ;; + -i|--isolate) + export TORSOCKS_ISOLATE_PID=1 + ;; -d|--debug) # Set full DEBUG with 5 being the highest possible level. export TORSOCKS_LOG_LEVEL=5 diff --git a/src/common/config-file.c b/src/common/config-file.c index 64b3d42..2f145fb 100644 --- a/src/common/config-file.c +++ b/src/common/config-file.c @@ -39,6 +39,7 @@ static const char *conf_socks5_user_str = "SOCKS5Username"; static const char *conf_socks5_pass_str = "SOCKS5Password"; static const char *conf_allow_inbound_str = "AllowInbound"; static const char *conf_allow_outbound_localhost_str = "AllowOutboundLocalhost"; +static const char *conf_isolate_pid_str = "IsolatePID";
/* * Once this value reaches 2, it means both user and password for a SOCKS5 @@ -47,6 +48,14 @@ static const char *conf_allow_outbound_localhost_str = "AllowOutboundLocalhost"; static unsigned int both_socks5_pass_user_set;
/* + * Username format for the IsolatePID option. Format is: + * 'torsocks-' PID ':' TIME + */ +static const char *isolate_username_fmt = "torsocks-%ld:%lld"; +/* Default password for the IsolatePID option. */ +static const char *isolate_password = "42"; + +/* * Set the onion pool address range in the configuration object using the value * found in the conf file. * @@ -233,6 +242,11 @@ static int parse_config_line(const char *line, struct configuration *config) if (ret < 0) { goto error; } + } else if (!strcmp(tokens[0], conf_isolate_pid_str)) { + ret = conf_file_set_isolate_pid(tokens[1], config); + if (ret < 0) { + goto error; + } } else { WARN("Config file contains unknown value: %s", line); } @@ -402,6 +416,99 @@ int conf_file_set_allow_outbound_localhost(const char *val, }
/* + * Set the isolate PID option for the given config. + * + * Return 0 if optiuon is off, 1 if on and negative value on error. + */ +ATTR_HIDDEN +int conf_file_set_isolate_pid(const char *val, struct configuration *config) +{ + int ret; + + assert(val); + assert(config); + + ret = atoi(val); + if (ret == 0) { + config->isolate_pid = 0; + DBG("[config] PID isolation disabled."); + } else if (ret == 1) { + config->isolate_pid = 1; + DBG("[config] PID isolation enabled."); + } else { + ERR("[config] Invalid %s value for %s", val, + conf_isolate_pid_str); + ret = -EINVAL; + } + + return ret; +} + +/* + * Applies the SOCKS authentication configuration and sets the final SOCKS + * username and password. + * + * Return 0 if successful, and negative value on error. + */ +ATTR_HIDDEN +int conf_apply_socks_auth(struct configuration *config) +{ + int ret; + pid_t pid; + time_t now; + + assert(config); + + if (!config->socks5_use_auth && !config->isolate_pid) { + /* No auth specified at all. */ + ret = 0; + goto end; + } else if (config->socks5_use_auth && !config->isolate_pid) { + /* SOCKS5 auth specified by user, already setup. */ + ret = 0; + goto end; + } else if (config->socks5_use_auth && config->isolate_pid) { + ERR("[config] %s and SOCKS5 auth both set.", conf_isolate_pid_str); + ret = -EINVAL; + goto end; + } + + + /* PID based isolation requested. + * Username: 'torsocks-' PID ':' TIME + * Password: '42' + */ + + pid = getpid(); + now = time(NULL); + + ret = snprintf(config->conf_file.socks5_username, + sizeof(config->conf_file.socks5_username), isolate_username_fmt, + (long) pid, (long long int) now); + if (ret < 0 || ret >= (int) sizeof(config->conf_file.socks5_username)) { + ret = -ENOBUFS; + goto end; + } + + ret = snprintf(config->conf_file.socks5_password, + sizeof(config->conf_file.socks5_password), "%s", isolate_password); + if (ret < 0 || ret >= (int) sizeof(config->conf_file.socks5_password)) { + ret = -ENOBUFS; + goto end; + } + + DBG("[config]: %s: '%s'/'%s'", conf_isolate_pid_str, + config->conf_file.socks5_username, + config->conf_file.socks5_password); + + config->socks5_use_auth = 1; + ret = 0; + +end: + return ret; +} + +/* * Read and populate the given config parsed data structure. * * Return 0 on success or else a negative value. diff --git a/src/common/config-file.h b/src/common/config-file.h index da3d507..23dd842 100644 --- a/src/common/config-file.h +++ b/src/common/config-file.h @@ -83,6 +83,13 @@ struct configuration { * Allow outbound connections to localhost that bypass Tor. */ unsigned int allow_outbound_localhost:1; + + /* + * Automatically set the SOCKS5 authentication to a unique per-process + * value. If this value is set, the user MUST NOT have provided a + * username or password. + */ + unsigned int isolate_pid:1; };
int config_file_read(const char *filename, struct configuration *config); @@ -94,5 +101,8 @@ int conf_file_set_socks5_user(const char *username, int conf_file_set_allow_inbound(const char *val, struct configuration *config); int conf_file_set_allow_outbound_localhost(const char *val, struct configuration *config); +int conf_file_set_isolate_pid(const char *val, struct configuration *config); + +int conf_apply_socks_auth(struct configuration *config);
#endif /* CONFIG_FILE_H */ diff --git a/src/common/defaults.h b/src/common/defaults.h index 36c7bc0..ab51690 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -66,4 +66,7 @@ /* Control if torsocks allows inbound connection or not. */ #define DEFAULT_ALLOW_INBOUND_ENV "TORSOCKS_ALLOW_INBOUND"
+/* Control if torsocks isolates based on PID or not. */ +#define DEFAULT_ISOLATE_PID_ENV "TORSOCKS_ISOLATE_PID" + #endif /* TORSOCKS_DEFAULTS_H */ diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c index 8f079fe..be00581 100644 --- a/src/lib/torsocks.c +++ b/src/lib/torsocks.c @@ -75,7 +75,7 @@ static void clean_exit(int status) static void read_env(void) { int ret; - const char *username, *password, *allow_in; + const char *username, *password, *allow_in, *isolate_pid;
if (is_suid) { goto end; @@ -89,6 +89,14 @@ static void read_env(void) } }
+ isolate_pid = getenv(DEFAULT_ISOLATE_PID_ENV); + if (isolate_pid) { + ret = conf_file_set_isolate_pid(isolate_pid, &tsocks_config); + if (ret < 0) { + goto error; + } + } + username = getenv(DEFAULT_SOCKS5_USER_ENV); password = getenv(DEFAULT_SOCKS5_PASS_ENV); if (!username && !password) { @@ -181,6 +189,12 @@ static void init_config(void)
/* Handle possible env. variables. */ read_env(); + + /* Finalize the SOCKS auth (Isolation) settings. */ + ret = conf_apply_socks_auth(&tsocks_config); + if (ret < 0) { + clean_exit(EXIT_FAILURE); + } }
/*
tor-commits@lists.torproject.org