[tor-commits] [torsocks/master] Add automatic per process isolation (IsolatePID)

dgoulet at torproject.org dgoulet at torproject.org
Tue May 12 16:10:00 UTC 2015


commit 1875ef7416f9f6108e1bb2a2eea7d6e4a972a988
Author: Yawning Angel <yawning at 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 at schwanenlied.me>
    Signed-off-by: David Goulet <dgoulet at 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 at 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);
+	}
 }
 
 /*



More information about the tor-commits mailing list