[tor-commits] [torsocks/master] Add option to allow inbound connections

dgoulet at torproject.org dgoulet at torproject.org
Fri Apr 4 22:40:27 UTC 2014


commit e9f0be95b105aa15894549f047b9cd6eb78785f1
Author: David Goulet <dgoulet at ev0ke.net>
Date:   Tue Mar 4 17:17:12 2014 -0500

    Add option to allow inbound connections
    
    This adds the possibility of telling torsocks to allow inbound
    connections meaning allowing listen() and accept()/accept4() for non
    localhost address.
    
    Add a AllowInbound 0|1 option to the configuration file along with a
    TORSOCKS_ALLOW_INBOUND environment variable to control that behavior.
    
    By default, Unix socket are allowed.
    
    Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
 doc/torsocks.8           |    5 +++
 doc/torsocks.conf        |    4 ++
 doc/torsocks.conf.5      |    6 +++
 src/common/config-file.c |   36 ++++++++++++++++++
 src/common/config-file.h |    7 ++++
 src/common/defaults.h    |    3 ++
 src/lib/accept.c         |   92 +++++++++++++++++++++++++++++++++++++++++-----
 src/lib/listen.c         |   52 +++++++++++++++++++++++---
 src/lib/torsocks.c       |   16 ++++++--
 9 files changed, 202 insertions(+), 19 deletions(-)

diff --git a/doc/torsocks.8 b/doc/torsocks.8
index eb4c7dd..4a14703 100644
--- a/doc/torsocks.8
+++ b/doc/torsocks.8
@@ -94,6 +94,11 @@ also with the variable below.
 Set the password for the SOCKS5 authentication method. Username MUST be set
 also with the variable above.
 
+.PP
+.IP TORSOCKS_ALLOW_INBOUND
+Allow inbound connections so the application can accept and listen for
+connections.
+
 .SH KNOWN ISSUES
 
 .SS DNS
diff --git a/doc/torsocks.conf b/doc/torsocks.conf
index 7653818..c1596c0 100644
--- a/doc/torsocks.conf
+++ b/doc/torsocks.conf
@@ -24,3 +24,7 @@ OnionAddrRange 127.42.42.0/24
 # variable overrides these options.
 #SOCKS5Username <username>
 #SOCKS5Password <password>
+
+# Set Torsocks to accept inbound connections. If set to 1, listen() and
+# accept() will be allowed to be used with non localhost address. (Default: 0)
+#AllowInbound 1
diff --git a/doc/torsocks.conf.5 b/doc/torsocks.conf.5
index 6cd600f..7ccfa4a 100644
--- a/doc/torsocks.conf.5
+++ b/doc/torsocks.conf.5
@@ -71,6 +71,12 @@ Password to use for SOCKS5 authentication method that makes the connections to
 Tor to use a different circuit from other existing streams. If set, the
 SOCKS5Username must be specified also. (Default: none).
 
+.TP
+.I AllowInbound 0|1
+Allow inbound connections meaning that listen() and accept()/accept4() will be
+allowed for non localhost address so the applicaton can handle incoming
+connection. Note that Unix socket are allowed. (Default: 0)
+
 .SH EXAMPLE
   $ export TORSOCKS_CONF_FILE=$PWD/torsocks.conf
   $ torsocks ssh account at sshserver.com
diff --git a/src/common/config-file.c b/src/common/config-file.c
index 2882678..79fe5ca 100644
--- a/src/common/config-file.c
+++ b/src/common/config-file.c
@@ -37,6 +37,7 @@ static const char *conf_torport_str = "TorPort";
 static const char *conf_onion_str = "OnionAddrRange";
 static const char *conf_socks5_user_str = "SOCKS5Username";
 static const char *conf_socks5_pass_str = "SOCKS5Password";
+static const char *conf_allow_inbound_str = "AllowInbound";
 
 /*
  * Once this value reaches 2, it means both user and password for a SOCKS5
@@ -221,6 +222,11 @@ static int parse_config_line(const char *line, struct configuration *config)
 		if (ret < 0) {
 			goto error;
 		}
+	} else if (!strcmp(tokens[0], conf_allow_inbound_str)) {
+		ret = conf_file_set_allow_inbound(tokens[1], config);
+		if (ret < 0) {
+			goto error;
+		}
 	} else {
 		WARN("Config file contains unknown value: %s", line);
 	}
@@ -332,6 +338,34 @@ error:
 }
 
 /*
+ * Set the allow inbound option for the given config.
+ *
+ * Return 0 if option is off, 1 if on and negative value on error.
+ */
+ATTR_HIDDEN
+int conf_file_set_allow_inbound(const char *val, struct configuration *config)
+{
+	int ret;
+
+	assert(val);
+	assert(config);
+
+	ret = atoi(val);
+	if (ret == 0) {
+		config->allow_inbound = 0;
+		DBG("[config] Inbound connections disallowed.");
+	} else if (ret == 1) {
+		config->allow_inbound = 1;
+		DBG("[config] Inbound connections allowed.");
+	} else {
+		ERR("[config] Invalid %s value for %s", val, conf_allow_inbound_str);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
  * Read and populate the given config parsed data structure.
  *
  * Return 0 on success or else a negative value.
@@ -370,6 +404,8 @@ int config_file_read(const char *filename, struct configuration *config)
 			/* ENOMEM is probably the only case here. */
 			goto error;
 		}
+
+		config->allow_inbound = 0;
 		goto end;
 	}
 
diff --git a/src/common/config-file.h b/src/common/config-file.h
index 04dbf42..c35507d 100644
--- a/src/common/config-file.h
+++ b/src/common/config-file.h
@@ -72,6 +72,12 @@ struct configuration {
 	 * initialized to something of len > 0.
 	 */
 	unsigned int socks5_use_auth:1;
+
+	/*
+	 * Allow inbound connections meaning listen() and accept() are permitted
+	 * for non localhost addresses.
+	 */
+	unsigned int allow_inbound:1;
 };
 
 int config_file_read(const char *filename, struct configuration *config);
@@ -80,5 +86,6 @@ int conf_file_set_socks5_pass(const char *password,
 		struct configuration *config);
 int conf_file_set_socks5_user(const char *username,
 		struct configuration *config);
+int conf_file_set_allow_inbound(const char *val, struct configuration *config);
 
 #endif /* CONFIG_FILE_H */
diff --git a/src/common/defaults.h b/src/common/defaults.h
index fe35a6d..36c7bc0 100644
--- a/src/common/defaults.h
+++ b/src/common/defaults.h
@@ -63,4 +63,7 @@
 #define DEFAULT_SOCKS5_USER_ENV     "TORSOCKS_USERNAME"
 #define DEFAULT_SOCKS5_PASS_ENV     "TORSOCKS_PASSWORD"
 
+/* Control if torsocks allows inbound connection or not. */
+#define DEFAULT_ALLOW_INBOUND_ENV   "TORSOCKS_ALLOW_INBOUND"
+
 #endif /* TORSOCKS_DEFAULTS_H */
diff --git a/src/lib/accept.c b/src/lib/accept.c
index 3dd7617..07715b3 100644
--- a/src/lib/accept.c
+++ b/src/lib/accept.c
@@ -17,6 +17,8 @@
 
 #include <assert.h>
 
+#include <common/utils.h>
+
 #include "torsocks.h"
 
 TSOCKS_LIBC_DECL(accept, LIBC_ACCEPT_RET_TYPE, LIBC_ACCEPT_SIG)
@@ -26,14 +28,44 @@ TSOCKS_LIBC_DECL(accept, LIBC_ACCEPT_RET_TYPE, LIBC_ACCEPT_SIG)
  */
 LIBC_ACCEPT_RET_TYPE tsocks_accept(LIBC_ACCEPT_SIG)
 {
-	DBG("[accept] Syscall denied since inbound connection are not allowed.");
+	int ret;
+
+	if (tsocks_config.allow_inbound) {
+		/* Allowed by the user so directly go to the libc. */
+		goto libc_call;
+	}
+
+	if (!addr) {
+		errno = EFAULT;
+		goto error;
+	}
 
 	/*
-	 * Accept is completely denied here since this means that the application
-	 * can accept inbound connections that are obviously NOT handled by the Tor
-	 * network thus reject this call.
+	 * accept() on a Unix socket is allowed else we are going to try to match
+	 * it on INET localhost socket.
 	 */
-	errno = EPERM;
+	if (addr->sa_family == AF_UNIX) {
+		goto libc_call;
+	}
+
+	/* Inbound localhost connections are allowed. */
+	ret = utils_sockaddr_is_localhost(addr);
+	if (!ret) {
+
+		/*
+		 * Accept is completely denied here since this means that the
+		 * application can accept inbound connections on non localhost that are
+		 * obviously NOT handled by the Tor network thus reject this call.
+		 */
+		DBG("[accept] Non localhost inbound connection are not allowed.");
+		errno = EPERM;
+		goto error;
+	}
+
+libc_call:
+	return tsocks_libc_accept(LIBC_ACCEPT_ARGS);
+
+error:
 	return -1;
 }
 
@@ -42,6 +74,11 @@ LIBC_ACCEPT_RET_TYPE tsocks_accept(LIBC_ACCEPT_SIG)
  */
 LIBC_ACCEPT_DECL
 {
+	if (!tsocks_libc_accept) {
+		tsocks_libc_accept = tsocks_find_libc_symbol(
+				LIBC_ACCEPT_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
+	}
+
 	return tsocks_accept(LIBC_ACCEPT_ARGS);
 }
 
@@ -54,14 +91,44 @@ TSOCKS_LIBC_DECL(accept4, LIBC_ACCEPT4_RET_TYPE, LIBC_ACCEPT4_SIG)
  */
 LIBC_ACCEPT4_RET_TYPE tsocks_accept4(LIBC_ACCEPT4_SIG)
 {
-	DBG("[accept] Syscall denied since inbound connection are not allowed.");
+	int ret;
+
+	if (tsocks_config.allow_inbound) {
+		/* Allowed by the user so directly go to the libc. */
+		goto libc_call;
+	}
+
+	if (!addr) {
+		errno = EFAULT;
+		goto error;
+	}
 
 	/*
-	 * Accept is completely denied here since this means that the application
-	 * can accept inbound connections that are obviously NOT handled by the Tor
-	 * network thus reject this call.
+	 * accept4() on a Unix socket is allowed else we are going to try to match
+	 * it on INET localhost socket.
 	 */
-	errno = EPERM;
+	if (addr->sa_family == AF_UNIX) {
+		goto libc_call;
+	}
+
+	/* Inbound localhost connections are allowed. */
+	ret = utils_sockaddr_is_localhost(addr);
+	if (!ret) {
+
+		/*
+		 * Accept is completely denied here since this means that the
+		 * application can accept inbound connections on non localhost that are
+		 * obviously NOT handled by the Tor network thus reject this call.
+		 */
+		DBG("[accept4] Non localhost inbound connection are not allowed.");
+		errno = EPERM;
+		goto error;
+	}
+
+libc_call:
+	return tsocks_libc_accept4(LIBC_ACCEPT4_ARGS);
+
+error:
 	return -1;
 }
 
@@ -70,6 +137,11 @@ LIBC_ACCEPT4_RET_TYPE tsocks_accept4(LIBC_ACCEPT4_SIG)
  */
 LIBC_ACCEPT4_DECL
 {
+	if (!tsocks_libc_accept4) {
+		tsocks_libc_accept4 = tsocks_find_libc_symbol(
+				LIBC_ACCEPT4_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
+	}
+
 	return tsocks_accept4(LIBC_ACCEPT4_ARGS);
 }
 #endif
diff --git a/src/lib/listen.c b/src/lib/listen.c
index e72f1f6..38c37d8 100644
--- a/src/lib/listen.c
+++ b/src/lib/listen.c
@@ -17,6 +17,8 @@
 
 #include <assert.h>
 
+#include <common/utils.h>
+
 #include "torsocks.h"
 
 TSOCKS_LIBC_DECL(listen, LIBC_LISTEN_RET_TYPE, LIBC_LISTEN_SIG)
@@ -26,14 +28,49 @@ TSOCKS_LIBC_DECL(listen, LIBC_LISTEN_RET_TYPE, LIBC_LISTEN_SIG)
  */
 LIBC_LISTEN_RET_TYPE tsocks_listen(LIBC_LISTEN_SIG)
 {
-	DBG("[accept] Syscall denied since inbound connection are not allowed.");
+	int ret;
+	socklen_t addrlen;
+	struct sockaddr sa;
+
+	if (tsocks_config.allow_inbound) {
+		/* Allowed by the user so directly go to the libc. */
+		goto libc_call;
+	}
+
+	addrlen = sizeof(sa);
+
+	ret = getsockname(sockfd, &sa, &addrlen);
+	if (ret < 0) {
+		PERROR("[listen] getsockname");
+		goto error;
+	}
 
 	/*
-	 * Bind is completely denied here since this means that the application
-	 * can accept inbound connections that are obviously NOT handled by the Tor
-	 * network thus reject this call.
+	 * Listen () on a Unix socket is allowed else we are going to try to match
+	 * it on INET localhost socket.
 	 */
-	errno = EPERM;
+	if (sa.sa_family == AF_UNIX) {
+		goto libc_call;
+	}
+
+	/* Inbound localhost connections are allowed. */
+	ret = utils_sockaddr_is_localhost(&sa);
+	if (!ret) {
+		/*
+		 * Listen is completely denied here since this means that the
+		 * application can accept inbound connections on non localhost that are
+		 * obviously NOT handled by the Tor network thus reject this call.
+		 */
+		DBG("[listen] Non localhost inbound connection are not allowed.");
+		errno = EPERM;
+		goto error;
+	}
+
+libc_call:
+	DBG("[listen] Passing listen fd %d to libc", sockfd);
+	return tsocks_libc_listen(LIBC_LISTEN_ARGS);
+
+error:
 	return -1;
 }
 
@@ -42,5 +79,10 @@ LIBC_LISTEN_RET_TYPE tsocks_listen(LIBC_LISTEN_SIG)
  */
 LIBC_LISTEN_DECL
 {
+	if (!tsocks_libc_listen) {
+		tsocks_libc_listen = tsocks_find_libc_symbol(
+				LIBC_LISTEN_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
+	}
+
 	return tsocks_listen(LIBC_LISTEN_ARGS);
 }
diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c
index a20e94f..af4ab79 100644
--- a/src/lib/torsocks.c
+++ b/src/lib/torsocks.c
@@ -69,15 +69,23 @@ static void clean_exit(int status)
  * Read SOCKS5 username and password environment variable and if found set them
  * in the configuration. If we are setuid, return gracefully.
  */
-static void read_user_pass_env(void)
+static void read_env(void)
 {
 	int ret;
-	const char *username, *password;
+	const char *username, *password, *allow_in;
 
 	if (is_suid) {
 		goto end;
 	}
 
+	allow_in = getenv(DEFAULT_ALLOW_INBOUND_ENV);
+	if (allow_in) {
+		ret = conf_file_set_allow_inbound(allow_in, &tsocks_config);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
 	username = getenv(DEFAULT_SOCKS5_USER_ENV);
 	password = getenv(DEFAULT_SOCKS5_PASS_ENV);
 	if (!username && !password) {
@@ -168,8 +176,8 @@ static void init_config(void)
 		clean_exit(EXIT_FAILURE);
 	}
 
-	/* Handle SOCKS5 user/pass env. variables. */
-	read_user_pass_env();
+	/* Handle possible env. variables. */
+	read_env();
 }
 
 /*





More information about the tor-commits mailing list