commit ebbcae0c5f6ad4772e459a80e6d99cacb731fb1f Author: David Goulet dgoulet@ev0ke.net Date: Thu Feb 20 10:59:10 2014 +0000
Fix: deny connection to ANY address
It's possible to connect to 0.0.0.0/:: which are addresses that Tor can't of course handle thus deny the call and send back EINVAL.
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/common/compat.h | 2 ++ src/common/utils.c | 30 ++++++++++++++++++++++++++++++ src/common/utils.h | 1 + src/lib/connect.c | 9 +++++++++ tests/unit/test_utils.c | 38 +++++++++++++++++++++++++++++++++++++- 5 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/src/common/compat.h b/src/common/compat.h index ee8263f..e977b41 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -104,5 +104,7 @@ void tsocks_mutex_unlock(tsocks_mutex_t *m); /* Loopback address in network byte order. */ #define TSOCKS_LOOPBACK 0x0100007f #define TSOCKS_LOOPBACK6 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } +#define TSOCKS_ANY ((unsigned long int) 0x00000000) +#define TSOCKS_ANY6 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
#endif /* TORSOCKS_COMPAT_H */ diff --git a/src/common/utils.c b/src/common/utils.c index e526ce7..578d290 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -306,3 +306,33 @@ match: error: return -EINVAL; } + +/* + * For a given sockaddr, check if the IP address is ANY which is 0.0.0.0 for + * IPv4 and :: for IPv6. + * + * Return 1 if it is else 0. + */ +ATTR_HIDDEN +int utils_is_addr_any(const struct sockaddr *sa) +{ + int ret; + + assert(sa); + + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const struct sockaddr_in *) sa; + ret = (sin->sin_addr.s_addr == TSOCKS_ANY); + } else if (sa->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *) sa; + const uint8_t addr[] = TSOCKS_ANY6; + ret = !memcmp(sin6->sin6_addr.s6_addr, addr, + sizeof(sin6->sin6_addr.s6_addr)); + } else { + ret = 0; + goto end; + } + +end: + return ret; +} diff --git a/src/common/utils.h b/src/common/utils.h index b0281eb..2f950aa 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -32,5 +32,6 @@ int utils_is_address_ipv4(const char *ip); int utils_is_address_ipv6(const char *ip); int utils_sockaddr_is_localhost(const struct sockaddr *sa); int utils_localhost_resolve(const char *name, int af, void *buf, size_t len); +int utils_is_addr_any(const struct sockaddr *sa);
#endif /* TORSOCKS_UTILS_H */ diff --git a/src/lib/connect.c b/src/lib/connect.c index bb15882..e47ab38 100644 --- a/src/lib/connect.c +++ b/src/lib/connect.c @@ -65,6 +65,15 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) goto error; }
+ /* + * Trying to connect to ANY address will evidently not work for Tor thus we + * deny the call. + */ + if (utils_is_addr_any(addr)) { + errno = EINVAL; + goto error; + } + DBG("[connect] Socket family %s and type %d", addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type);
diff --git a/tests/unit/test_utils.c b/tests/unit/test_utils.c index 2db255b..8efa19a 100644 --- a/tests/unit/test_utils.c +++ b/tests/unit/test_utils.c @@ -24,7 +24,7 @@
#include <tap/tap.h>
-#define NUM_TESTS 26 +#define NUM_TESTS 30
static void test_is_address_ipv4(void) { @@ -178,6 +178,41 @@ static void test_utils_tokenize_ignore_comments(void) ok(nb_token == 0, "Returns 0 tokens for comment"); }
+static void test_is_addr_any(void) +{ + int ret; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + + sin.sin_family = AF_INET; + sin.sin_port = htons(42); + inet_pton(sin.sin_family, "0.0.0.0", &sin.sin_addr); + + ret = utils_is_addr_any((const struct sockaddr *) &sin); + ok(ret == 1, "This address is 0.0.0.0"); + + sin.sin_family = AF_INET; + sin.sin_port = htons(42); + inet_pton(sin.sin_family, "1.0.0.0", &sin.sin_addr); + + ret = utils_is_addr_any((const struct sockaddr *) &sin); + ok(ret == 0, "This address is NOT 0.0.0.0"); + + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(42); + inet_pton(sin6.sin6_family, "::", &sin6.sin6_addr); + + ret = utils_is_addr_any((const struct sockaddr *) &sin6); + ok(ret == 1, "This address is ::"); + + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(42); + inet_pton(sin6.sin6_family, "fe80::1", &sin6.sin6_addr); + + ret = utils_is_addr_any((const struct sockaddr *) &sin6); + ok(ret == 0, "This address is NOT ::"); +} + int main(int argc, char **argv) { /* Libtap call for the number of tests planned. */ @@ -188,6 +223,7 @@ int main(int argc, char **argv) test_localhost_resolve(); test_sockaddr_is_localhost(); test_utils_tokenize_ignore_comments(); + test_is_addr_any();
return exit_status(); }