commit e9f0be95b105aa15894549f047b9cd6eb78785f1 Author: David Goulet dgoulet@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@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@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(); }
/*
tor-commits@lists.torproject.org