
commit bd6ae94ff0d1a1a1064e6cfd40320182e8ff5ccc Author: Tim RÃŒhsen <tim.ruehsen@gmx.de> Date: Wed Jan 14 14:48:37 2015 +0100 Allow TCP Fast Open clients go through tor This patch prevents TFO clients to silently leak when torified. TFO uses sendto() instead of connect()/send(). Signed-off-by: David Goulet <dgoulet@ev0ke.net> --- src/lib/Makefile.am | 2 +- src/lib/sendto.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/torsocks.h | 19 +++++++++++- 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index d64b3f6..6e137f3 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -9,6 +9,6 @@ lib_LTLIBRARIES = libtorsocks.la libtorsocks_la_SOURCES = torsocks.c torsocks.h \ connect.c gethostbyname.c getaddrinfo.c close.c \ getpeername.c socket.c syscall.c socketpair.c recv.c \ - exit.c accept.c listen.c fclose.c + exit.c accept.c listen.c fclose.c sendto.c libtorsocks_la_LIBADD = $(top_builddir)/src/common/libcommon.la diff --git a/src/lib/sendto.c b/src/lib/sendto.c new file mode 100644 index 0000000..3362026 --- /dev/null +++ b/src/lib/sendto.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2015 - Tim Rühsen <tim.ruehsen@gmx.de> + * + * 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/log.h> +#include <common/utils.h> + +#include "torsocks.h" + +/* + * Using TCP Fast Open (TFO) uses sendto() instead of connect() with 'flags' + * set to MSG_FASTOPEN. Without this code, using TFO simply bypasses Tor + * without letting the user know. + * + * This solution simply ignores TFO and falls back to connect(). At the time + * the tor server supports TFO, socks5.c (client code) could implement it in + * send_data() and connect_socks5(). + */ + +/* sendto(2) + * args: int sockfd, const void *buf, size_t len, int flags, + * const struct sockaddr *dest_addr, socklen_t addrlen + */ +TSOCKS_LIBC_DECL(sendto, LIBC_SENDTO_RET_TYPE, LIBC_SENDTO_SIG) + +/* + * Torsocks call for sendto(2). + */ +LIBC_SENDTO_RET_TYPE tsocks_sendto(LIBC_SENDTO_SIG) +{ +#ifdef MSG_FASTOPEN + int ret; + + if ((flags & MSG_FASTOPEN) == 0) { + /* No TFO, fallback to libc sendto() */ + goto libc_sendto; + } + + DBG("[sendto] TCP fast open catched on fd %d", sockfd); + + ret = connect(sockfd, dest_addr, addrlen); + if (ret == 0) { + /* Connection established, send payload */ + ret = send(sockfd, buf, len, flags & ~MSG_FASTOPEN); + } + + return ret; + +libc_sendto: +#endif /* MSG_FASTOPEN */ + + return tsocks_libc_sendto(LIBC_SENDTO_ARGS); +} + +/* + * Libc hijacked symbol sendto(2). + */ +LIBC_SENDTO_DECL +{ + if (!tsocks_libc_sendto) { + tsocks_libc_sendto = tsocks_find_libc_symbol( + LIBC_SENDTO_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND); + } + + return tsocks_sendto(LIBC_SENDTO_ARGS); +} diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h index 6ded557..3b9cda2 100644 --- a/src/lib/torsocks.h +++ b/src/lib/torsocks.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2008 - Shaun Clowes <delius@progsoc.org> + * Copyright (C) 2000-2008 - Shaun Clowes <delius@progsoc.org> * 2008-2011 - Robert Hogan <robert@roberthogan.net> * 2013 - David Goulet <dgoulet@ev0ke.net> * @@ -170,6 +170,7 @@ struct hostent **result, int *h_errnop int sockfd, struct sockaddr *addr, socklen_t *addrlen #define LIBC_GETPEERNAME_ARGS sockfd, addr, addrlen +/* recvmsg(2) */ #define LIBC_RECVMSG_NAME recvmsg #define LIBC_RECVMSG_NAME_STR XSTR(LIBC_RECVMSG_NAME) #define LIBC_RECVMSG_RET_TYPE ssize_t @@ -178,6 +179,16 @@ struct hostent **result, int *h_errnop #define LIBC_RECVMSG_ARGS \ sockfd, msg, flags +/* sendto(2) */ +#define LIBC_SENDTO_NAME sendto +#define LIBC_SENDTO_NAME_STR XSTR(LIBC_SENDTO_NAME) +#define LIBC_SENDTO_RET_TYPE ssize_t +#define LIBC_SENDTO_SIG \ + int sockfd, const void *buf, size_t len, int flags,\ + const struct sockaddr *dest_addr, socklen_t addrlen +#define LIBC_SENDTO_ARGS \ + sockfd, buf, len, flags, dest_addr, addrlen + /* accept(2) */ #define LIBC_ACCEPT_NAME accept #define LIBC_ACCEPT_NAME_STR XSTR(LIBC_ACCEPT_NAME) @@ -277,6 +288,12 @@ TSOCKS_DECL(recvmsg, LIBC_RECVMSG_RET_TYPE, LIBC_RECVMSG_SIG) #define LIBC_RECVMSG_DECL \ LIBC_RECVMSG_RET_TYPE LIBC_RECVMSG_NAME(LIBC_RECVMSG_SIG) +/* sendto(2) */ +extern TSOCKS_LIBC_DECL(sendto, LIBC_SENDTO_RET_TYPE, LIBC_SENDTO_SIG) +TSOCKS_DECL(sendto, LIBC_SENDTO_RET_TYPE, LIBC_SENDTO_SIG) +#define LIBC_SENDTO_DECL \ + LIBC_SENDTO_RET_TYPE LIBC_SENDTO_NAME(LIBC_SENDTO_SIG) + /* socket(2) */ extern TSOCKS_LIBC_DECL(socket, LIBC_SOCKET_RET_TYPE, LIBC_SOCKET_SIG) TSOCKS_DECL(socket, LIBC_SOCKET_RET_TYPE, LIBC_SOCKET_SIG)