commit 467f3a847b7f9c529bf1ffc1f65eb275dfaa8062 Author: David Goulet dgoulet@ev0ke.net Date: Thu Nov 7 20:03:31 2013 -0500
Fix: fix localhost resolution address
Every DNS resolving call now will query the local host table (usually /etc/hosts) before trying through Tor. Thus this fixes the issue of localhost resolution.
If the application tries to connect to localhost, it is refused since it might be a TCP DNS query to a local DNS server.
Adds a test for localhost resolution with getaddrinfo().
Fixes #14
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/common/compat.h | 8 ++++++++ src/common/utils.c | 15 +++++++++++++++ src/common/utils.h | 2 ++ src/lib/connect.c | 11 +++++++++++ src/lib/torsocks.c | 39 +++++++++++++++++++++++++++++++++++++++ tests/test_dns.c | 9 ++++++++- 6 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/src/common/compat.h b/src/common/compat.h index 9173caf..faadfdb 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -101,4 +101,12 @@ void tsocks_mutex_unlock(tsocks_mutex_t *m);
#endif /* __FreeBSD__, __FreeBSD_kernel__, __darwin__, __NetBSD__ */
+/* + * Shamelessly taken from linux/in.h of the libc. This is consider trivial code + * by the GPL license thus copying it as is should be OK. + */ +#ifndef IN_LOOPBACK +#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) +#endif + #endif /* TORSOCKS_COMPAT_H */ diff --git a/src/common/utils.c b/src/common/utils.c index 0c5c2c8..33fc109 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h>
+#include "compat.h" #include "macros.h" #include "utils.h"
@@ -176,3 +177,17 @@ int utils_strcasecmpend(const char *s1, const char *s2) return strncasecmp(s1 + (n1 - n2), s2, n2); } } + + +/* + * Check if the given IPv4 is in the loopback net (127.x.x.x). + * + * Return 1 if so else 0 if not. + */ +ATTR_HIDDEN +int utils_is_ipv4_local(in_addr_t addr) +{ + assert(addr); + + return IN_LOOPBACK(addr); +} diff --git a/src/common/utils.h b/src/common/utils.h index aeda872..062441e 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -29,4 +29,6 @@ int utils_tokenize_ignore_comments(const char *_line, size_t size, char **tokens int utils_is_address_ipv4(const char *ip); int utils_is_address_ipv6(const char *ip);
+int utils_is_ipv4_local(in_addr_t addr); + #endif /* TORSOCKS_UTILS_H */ diff --git a/src/lib/connect.c b/src/lib/connect.c index bc3ac9d..09d3be6 100644 --- a/src/lib/connect.c +++ b/src/lib/connect.c @@ -22,6 +22,7 @@ #include <common/connection.h> #include <common/log.h> #include <common/onion.h> +#include <common/utils.h>
#include "torsocks.h"
@@ -70,6 +71,16 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG)
inet_addr = (struct sockaddr_in *) __addr;
+ /* Check if address is local IPv4. */ + if (__addr->sa_family == AF_INET && + utils_is_ipv4_local(be32toh(inet_addr->sin_addr.s_addr))) { + WARN("[connect] Connection to a local address are denied since it " + "might be a TCP DNS query to a local DNS server. " + "Rejecting it for safety reasons."); + errno = EPERM; + goto error; + } + /* * Lock registry to get the connection reference if one. In this code path, * if a connection object is found, it will not be used since a double diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c index 55ae98b..93c2c35 100644 --- a/src/lib/torsocks.c +++ b/src/lib/torsocks.c @@ -322,6 +322,40 @@ error: }
/* + * Lookup the local host table (usually /etc/hosts) for a given hostname. + * + * If found, ip_addr is populated and 0 is returned. + * If NOT found, -1 is return and ip_addr is untouched. + */ +static int hosts_file_resolve(const char *hostname, uint32_t *ip_addr) +{ + int ret; + struct hostent *host; + + assert(hostname); + assert(ip_addr); + + DBG("Looking in local host table for %s", hostname); + + /* Query the local host table if the hostname is present. */ + while ((host = gethostent()) != NULL) { + if (strncasecmp(hostname, host->h_name, strlen(hostname)) == 0) { + /* IP is found, copying and returning success. */ + memcpy(ip_addr, host->h_addr_list[0], sizeof(uint32_t)); + ret = 0; + goto end; + } + } + + /* Not found. */ + ret = -1; + +end: + endhostent(); + return ret; +} + +/* * Initiate a SOCK5 connection to the Tor network using the given connection. * The socks5 API will use the torsocks configuration object to find the tor * daemon. @@ -369,6 +403,11 @@ int tsocks_tor_resolve(const char *hostname, uint32_t *ip_addr) assert(hostname); assert(ip_addr);
+ ret = hosts_file_resolve(hostname, ip_addr); + if (!ret) { + goto end; + } + DBG("Resolving %s on the Tor network", hostname);
/* diff --git a/tests/test_dns.c b/tests/test_dns.c index 01bb5d9..58c7675 100644 --- a/tests/test_dns.c +++ b/tests/test_dns.c @@ -24,7 +24,7 @@
#include <tap/tap.h>
-#define NUM_TESTS 3 +#define NUM_TESTS 4
struct test_host { const char *name; @@ -49,6 +49,12 @@ static const struct test_host tor_dir_auth2 = { .ip = "171.25.193.9", };
+/* localhost resolution. */ +static const struct test_host tor_localhost = { + .name = "localhost", + .ip = "127.0.0.1", +}; + static void test_gethostbyname(const struct test_host *host) { struct hostent *he; @@ -133,6 +139,7 @@ int main(int argc, char **argv) test_getaddrinfo(&tor_check); test_gethostbyname(&tor_dir_auth1); test_gethostbyaddr(&tor_dir_auth2); + test_getaddrinfo(&tor_localhost);
return 0; }
tor-commits@lists.torproject.org