commit cb980d0533539790127ac59509fcce96f8a3e996 Author: David Goulet dgoulet@ev0ke.net Date: Sun Jun 23 13:20:11 2013 -0400
Separate libc call in specific files
No code has been changed, only function renaming in torsocks.c and a non static function move at the end of torsocks.c
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/lib/Makefile.am | 3 +- src/lib/connect.c | 117 +++++++++++++++++++++ src/lib/getaddrinfo.c | 101 ++++++++++++++++++ src/lib/gethostbyname.c | 86 ++++++++++++++++ src/lib/torsocks.c | 263 +++-------------------------------------------- src/lib/torsocks.h | 5 + 6 files changed, 327 insertions(+), 248 deletions(-)
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 3c7b3df..bf9237e 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -10,7 +10,8 @@ EXTRA_DIST = torsocks.in usewithtor.in
lib_LTLIBRARIES = libtorsocks.la
-libtorsocks_la_SOURCES = torsocks.c torsocks.h +libtorsocks_la_SOURCES = torsocks.c torsocks.h \ + connect.c gethostbyname.c getaddrinfo.c
libtorsocks_la_LIBADD = \ $(top_builddir)/src/common/libcommon.la \ diff --git a/src/lib/connect.c b/src/lib/connect.c new file mode 100644 index 0000000..cee4d76 --- /dev/null +++ b/src/lib/connect.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2000-2008 - Shaun Clowes delius@progsoc.org + * 2008-2011 - Robert Hogan robert@roberthogan.net + * 2013 - David Goulet dgoulet@ev0ke.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <assert.h> + +#include <common/connection.h> +#include <common/log.h> + +#include "torsocks.h" + +/* + * Torsocks call for connect(2). + */ +LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) +{ + int ret, sock_type; + socklen_t optlen; + struct connection *new_conn; + + DBG("Connect catched on fd %d", __sockfd); + + ret = getsockopt(__sockfd, SOL_SOCKET, SO_TYPE, &sock_type, &optlen); + if (ret < 0) { + /* Use the getsockopt() errno value. */ + goto error; + } + + /* We can't handle a non inet socket. */ + if (__addr->sa_family != AF_INET && + __addr->sa_family != AF_INET6) { + DBG("[conect] Connection is not IPv4/v6. Ignoring."); + goto libc_connect; + } + + /* + * Refuse non stream socket. There is a chance that this might be a DNS + * request that we can't pass through Tor using raw UDP packet. + */ + if (sock_type != SOCK_STREAM) { + ERR("[connect] UDP or ICMP stream can't be handled. Rejecting."); + errno = EBADF; + goto error; + } + + DBG("[connect] Socket family %s and type %d", + __addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type); + + /* + * 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 + * connect() on the same file descriptor is an error so the registry is + * quickly unlocked and no reference is needed. + */ + connection_registry_lock(); + new_conn = connection_find(__sockfd); + connection_registry_unlock(); + if (new_conn) { + /* Double connect() for the same fd. */ + errno = EISCONN; + goto error; + } + + new_conn = connection_create(__sockfd, __addr); + if (!new_conn) { + errno = ENOMEM; + goto error; + } + + /* Connect the socket to the Tor network. */ + ret = tsocks_connect_to_tor(new_conn); + if (ret < 0) { + errno = -ret; + goto error; + } + + connection_registry_lock(); + /* This can't fail since a lookup was done previously. */ + connection_insert(new_conn); + connection_registry_unlock(); + + /* Flag errno for success */ + ret = errno = 0; + return ret; + +libc_connect: + return tsocks_libc_connect(LIBC_CONNECT_ARGS); +error: + /* At this point, errno MUST be set to a valid connect() error value. */ + return -1; +} + +/* + * Libc hijacked symbol connect(2). + */ +LIBC_CONNECT_DECL +{ + /* Find symbol if not already set. Exit if not found. */ + tsocks_libc_connect = tsocks_find_libc_symbol(LIBC_CONNECT_NAME_STR, + TSOCKS_SYM_EXIT_NOT_FOUND); + return tsocks_connect(LIBC_CONNECT_ARGS); +} diff --git a/src/lib/getaddrinfo.c b/src/lib/getaddrinfo.c new file mode 100644 index 0000000..683bfc7 --- /dev/null +++ b/src/lib/getaddrinfo.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2000-2008 - Shaun Clowes delius@progsoc.org + * 2008-2011 - Robert Hogan robert@roberthogan.net + * 2013 - David Goulet dgoulet@ev0ke.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <arpa/inet.h> +#include <assert.h> + +#include <common/log.h> + +#include "torsocks.h" + +/* + * Torsocks call for getaddrinfo(3). + */ +LIBC_GETADDRINFO_RET_TYPE tsocks_getaddrinfo(LIBC_GETADDRINFO_SIG) +{ + int ret, af; + struct in_addr addr4; + struct in6_addr addr6; + void *addr; + char *ip_str, ipv4[INET_ADDRSTRLEN], ipv6[INET6_ADDRSTRLEN]; + socklen_t ip_str_size; + const char *node; + + DBG("[getaddrinfo] Requesting %s hostname", __node); + + if (!__node) { + ret = EAI_NONAME; + goto error; + } + + /* Use right domain for the next step. */ + switch (__hints->ai_family) { + default: + /* Default value is to use IPv4. */ + case AF_INET: + addr = &addr4; + ip_str = ipv4; + ip_str_size = sizeof(ipv4); + af = AF_INET; + break; + case AF_INET6: + addr = &addr6; + ip_str = ipv6; + ip_str_size = sizeof(ipv6); + af = AF_INET6; + break; + } + + ret = inet_pton(af, __node, &addr); + if (ret == 0) { + /* The node most probably is a DNS name. */ + ret = tsocks_tor_resolve(__node, (uint32_t *) addr); + if (ret < 0) { + ret = EAI_FAIL; + goto error; + } + + (void) inet_ntop(af, addr, ip_str, ip_str_size); + node = ip_str; + DBG("[getaddrinfo] Node %s resolved to %s", __node, node); + } else { + node = __node; + DBG("[getaddrinfo] Node %s will be passed to the libc call", node); + } + + ret = tsocks_libc_getaddrinfo(node, __service, __hints, __res); + if (ret) { + goto error; + } + + return 0; + +error: + return ret; +} + +/* + * Libc hijacked symbol getaddrinfo(3). + */ +LIBC_GETADDRINFO_DECL +{ + tsocks_libc_getaddrinfo = tsocks_find_libc_symbol(LIBC_GETADDRINFO_NAME_STR, + TSOCKS_SYM_EXIT_NOT_FOUND); + return tsocks_getaddrinfo(LIBC_GETADDRINFO_ARGS); +} diff --git a/src/lib/gethostbyname.c b/src/lib/gethostbyname.c new file mode 100644 index 0000000..58a7290 --- /dev/null +++ b/src/lib/gethostbyname.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2000-2008 - Shaun Clowes delius@progsoc.org + * 2008-2011 - Robert Hogan robert@roberthogan.net + * 2013 - David Goulet dgoulet@ev0ke.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <arpa/inet.h> +#include <assert.h> + +#include <common/log.h> + +#include "torsocks.h" +/* + * Torsocks call for gethostbyname(3). + * + * NOTE: This call is OBSOLETE in the glibc. + */ +LIBC_GETHOSTBYNAME_RET_TYPE tsocks_gethostbyname(LIBC_GETHOSTBYNAME_SIG) +{ + int ret; + uint32_t ip; + const char *ret_str; + + DBG("[gethostbyname] Requesting %s hostname", __name); + + if (!__name) { + h_errno = HOST_NOT_FOUND; + goto error; + } + + /* Resolve the given hostname through Tor. */ + ret = tsocks_tor_resolve(__name, &ip); + if (ret < 0) { + goto error; + } + + /* Reset static host entry of tsocks. */ + memset(&tsocks_he, 0, sizeof(tsocks_he)); + memset(tsocks_he_addr_list, 0, sizeof(tsocks_he_addr_list)); + memset(tsocks_he_addr, 0, sizeof(tsocks_he_addr)); + + ret_str = inet_ntop(AF_INET, &ip, tsocks_he_addr, sizeof(tsocks_he_addr)); + if (!ret_str) { + PERROR("inet_ntop"); + h_errno = NO_ADDRESS; + goto error; + } + + tsocks_he_addr_list[0] = tsocks_he_addr; + tsocks_he_addr_list[1] = NULL; + + tsocks_he.h_name = (char *) __name; + tsocks_he.h_aliases = NULL; + tsocks_he.h_length = sizeof(in_addr_t); + tsocks_he.h_addrtype = AF_INET; + tsocks_he.h_addr_list = tsocks_he_addr_list; + + DBG("Hostname %s resolved to %s", __name, tsocks_he_addr); + + errno = 0; + return &tsocks_he; + +error: + return NULL; +} + +/* + * Libc hijacked symbol gethostbyname(3). + */ +LIBC_GETHOSTBYNAME_DECL +{ + return tsocks_gethostbyname(LIBC_GETHOSTBYNAME_ARGS); +} diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c index 7793e38..28cd183 100644 --- a/src/lib/torsocks.c +++ b/src/lib/torsocks.c @@ -17,7 +17,6 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-#include <arpa/inet.h> #include <assert.h> #include <dlfcn.h> #include <stdlib.h> @@ -54,30 +53,6 @@ static void clean_exit(int status) }
/* - * Lookup symbol in the loaded libraries of the binary. - * - * Return the function pointer or NULL on error. - */ -static void *find_libc_symbol(const char *symbol, - enum tsocks_sym_action action) -{ - void *fct_ptr = NULL; - - assert(symbol); - - fct_ptr = dlsym(RTLD_NEXT, symbol); - if (!fct_ptr) { - ERR("Unable to find %s", symbol); - if (action == TSOCKS_SYM_EXIT_NOT_FOUND) { - ERR("This is critical for torsocks. Exiting"); - clean_exit(EXIT_FAILURE); - } - } - - return fct_ptr; -} - -/* * Initialize torsocks configuration from a given conf file or the default one. */ static void init_config(void) @@ -130,7 +105,7 @@ static void init_config(void) */ static void init_libc_symbols(void) { - tsocks_libc_connect = find_libc_symbol(LIBC_CONNECT_NAME_STR, + tsocks_libc_connect = tsocks_find_libc_symbol(LIBC_CONNECT_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND); }
@@ -255,7 +230,7 @@ error: * Return 0 on success or else a negative value being the errno value that * needs to be sent back. */ -static int connect_to_tor_network(struct connection *conn) +int tsocks_connect_to_tor(struct connection *conn) { int ret;
@@ -287,7 +262,7 @@ error: * * Return 0 on success else a negative value and the result addr is untouched. */ -static int tor_resolve(const char *hostname, uint32_t *ip_addr) +int tsocks_tor_resolve(const char *hostname, uint32_t *ip_addr) { int ret; struct connection conn; @@ -329,231 +304,25 @@ error: }
/* - * Torsocks call for connect(2). - */ -LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) -{ - int ret, sock_type; - socklen_t optlen; - struct connection *new_conn; - - DBG("Connect catched on fd %d", __sockfd); - - ret = getsockopt(__sockfd, SOL_SOCKET, SO_TYPE, &sock_type, &optlen); - if (ret < 0) { - /* Use the getsockopt() errno value. */ - goto error; - } - - /* We can't handle a non inet socket. */ - if (__addr->sa_family != AF_INET && - __addr->sa_family != AF_INET6) { - DBG("[conect] Connection is not IPv4/v6. Ignoring."); - goto libc_connect; - } - - /* - * Refuse non stream socket. There is a chance that this might be a DNS - * request that we can't pass through Tor using raw UDP packet. - */ - if (sock_type != SOCK_STREAM) { - ERR("[connect] UDP or ICMP stream can't be handled. Rejecting."); - errno = EBADF; - goto error; - } - - DBG("[connect] Socket family %s and type %d", - __addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type); - - /* - * 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 - * connect() on the same file descriptor is an error so the registry is - * quickly unlocked and no reference is needed. - */ - connection_registry_lock(); - new_conn = connection_find(__sockfd); - connection_registry_unlock(); - if (new_conn) { - /* Double connect() for the same fd. */ - errno = EISCONN; - goto error; - } - - new_conn = connection_create(__sockfd, __addr); - if (!new_conn) { - errno = ENOMEM; - goto error; - } - - /* Connect the socket to the Tor network. */ - ret = connect_to_tor_network(new_conn); - if (ret < 0) { - errno = -ret; - goto error; - } - - connection_registry_lock(); - /* This can't fail since a lookup was done previously. */ - connection_insert(new_conn); - connection_registry_unlock(); - - /* Flag errno for success */ - ret = errno = 0; - return ret; - -libc_connect: - return tsocks_libc_connect(LIBC_CONNECT_ARGS); -error: - /* At this point, errno MUST be set to a valid connect() error value. */ - return -1; -} - -/* - * Libc hijacked symbol connect(2). - */ -LIBC_CONNECT_DECL -{ - /* Find symbol if not already set. Exit if not found. */ - tsocks_libc_connect = find_libc_symbol(LIBC_CONNECT_NAME_STR, - TSOCKS_SYM_EXIT_NOT_FOUND); - return tsocks_connect(LIBC_CONNECT_ARGS); -} - -/* - * Torsocks call for gethostbyname(3). + * Lookup symbol in the loaded libraries of the binary. * - * NOTE: This call is OBSOLETE in the glibc. - */ -LIBC_GETHOSTBYNAME_RET_TYPE tsocks_gethostbyname(LIBC_GETHOSTBYNAME_SIG) -{ - int ret; - uint32_t ip; - const char *ret_str; - - DBG("[gethostbyname] Requesting %s hostname", __name); - - if (!__name) { - h_errno = HOST_NOT_FOUND; - goto error; - } - - /* Resolve the given hostname through Tor. */ - ret = tor_resolve(__name, &ip); - if (ret < 0) { - goto error; - } - - /* Reset static host entry of tsocks. */ - memset(&tsocks_he, 0, sizeof(tsocks_he)); - memset(tsocks_he_addr_list, 0, sizeof(tsocks_he_addr_list)); - memset(tsocks_he_addr, 0, sizeof(tsocks_he_addr)); - - ret_str = inet_ntop(AF_INET, &ip, tsocks_he_addr, sizeof(tsocks_he_addr)); - if (!ret_str) { - PERROR("inet_ntop"); - h_errno = NO_ADDRESS; - goto error; - } - - tsocks_he_addr_list[0] = tsocks_he_addr; - tsocks_he_addr_list[1] = NULL; - - tsocks_he.h_name = (char *) __name; - tsocks_he.h_aliases = NULL; - tsocks_he.h_length = sizeof(in_addr_t); - tsocks_he.h_addrtype = AF_INET; - tsocks_he.h_addr_list = tsocks_he_addr_list; - - DBG("Hostname %s resolved to %s", __name, tsocks_he_addr); - - errno = 0; - return &tsocks_he; - -error: - return NULL; -} - -/* - * Libc hijacked symbol gethostbyname(3). - */ -LIBC_GETHOSTBYNAME_DECL -{ - return tsocks_gethostbyname(LIBC_GETHOSTBYNAME_ARGS); -} - -/* - * Torsocks call for getaddrinfo(3). + * Return the function pointer or NULL on error. */ -LIBC_GETADDRINFO_RET_TYPE tsocks_getaddrinfo(LIBC_GETADDRINFO_SIG) +void *tsocks_find_libc_symbol(const char *symbol, + enum tsocks_sym_action action) { - int ret, af; - struct in_addr addr4; - struct in6_addr addr6; - void *addr; - char *ip_str, ipv4[INET_ADDRSTRLEN], ipv6[INET6_ADDRSTRLEN]; - socklen_t ip_str_size; - const char *node; - - DBG("[getaddrinfo] Requesting %s hostname", __node); - - if (!__node) { - ret = EAI_NONAME; - goto error; - } + void *fct_ptr = NULL;
- /* Use right domain for the next step. */ - switch (__hints->ai_family) { - default: - /* Default value is to use IPv4. */ - case AF_INET: - addr = &addr4; - ip_str = ipv4; - ip_str_size = sizeof(ipv4); - af = AF_INET; - break; - case AF_INET6: - addr = &addr6; - ip_str = ipv6; - ip_str_size = sizeof(ipv6); - af = AF_INET6; - break; - } + assert(symbol);
- ret = inet_pton(af, __node, &addr); - if (ret == 0) { - /* The node most probably is a DNS name. */ - ret = tor_resolve(__node, (uint32_t *) addr); - if (ret < 0) { - ret = EAI_FAIL; - goto error; + fct_ptr = dlsym(RTLD_NEXT, symbol); + if (!fct_ptr) { + ERR("Unable to find %s", symbol); + if (action == TSOCKS_SYM_EXIT_NOT_FOUND) { + ERR("This is critical for torsocks. Exiting"); + clean_exit(EXIT_FAILURE); } - - (void) inet_ntop(af, addr, ip_str, ip_str_size); - node = ip_str; - DBG("[getaddrinfo] Node %s resolved to %s", __node, node); - } else { - node = __node; - DBG("[getaddrinfo] Node %s will be passed to the libc call", node); - } - - ret = tsocks_libc_getaddrinfo(node, __service, __hints, __res); - if (ret) { - goto error; }
- return 0; - -error: - return ret; -} - -/* - * Libc hijacked symbol getaddrinfo(3). - */ -LIBC_GETADDRINFO_DECL -{ - tsocks_libc_getaddrinfo = find_libc_symbol(LIBC_GETADDRINFO_NAME_STR, - TSOCKS_SYM_EXIT_NOT_FOUND); - return tsocks_getaddrinfo(LIBC_GETADDRINFO_ARGS); + return fct_ptr; } diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h index adbe67f..de62c33 100644 --- a/src/lib/torsocks.h +++ b/src/lib/torsocks.h @@ -114,4 +114,9 @@ enum tsocks_sym_action { /* Global configuration. Initialized once in the library constructor. */ extern struct configuration tsocks_config;
+int tsocks_connect_to_tor(struct connection *conn); +void *tsocks_find_libc_symbol(const char *symbol, + enum tsocks_sym_action action); +int tsocks_tor_resolve(const char *hostname, uint32_t *ip_addr); + #endif /* TORSOCKS_H */
tor-commits@lists.torproject.org