[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