[tor-commits] [torsocks/master] Fix: fix localhost resolution address

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


commit 467f3a847b7f9c529bf1ffc1f65eb275dfaa8062
Author: David Goulet <dgoulet at 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 at 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;
 }





More information about the tor-commits mailing list