commit 1e4e20b1bbed7d2e3b8b4d60420a746a0615f1af Author: Robert Hogan robert@roberthogan.net Date: Mon Sep 20 22:38:58 2010 +0100
Partially revert commit c8c6c60b.
The SO_DOMAIN socket() option is Linux only. So revert to inspecting the sock_addr_t in sendmsg() and sendto() but ensure it is non-null before doing so.
Move the address inspection to the end of sendmsg() and sendto() so that we can exit early if the socket is not SOCK_STREAM (i.e. tcp). --- src/tsocks.c | 55 +++++++++++++++++++++++-------------------------------- 1 files changed, 23 insertions(+), 32 deletions(-)
diff --git a/src/tsocks.c b/src/tsocks.c index 40b7e11..02e21fc 100644 --- a/src/tsocks.c +++ b/src/tsocks.c @@ -1667,14 +1667,13 @@ ssize_t tsocks_sendto_guts(SENDTO_SIGNATURE, ssize_t (*original_sendto)(SENDTO_S { int sock_type = -1; unsigned int sock_type_len = sizeof(sock_type); - int sock_domain = -1; - unsigned int sock_domain_len = sizeof(sock_domain); + struct sockaddr_in *connaddr;
/* See comment in close() */ if (!tsocks_init_complete) tsocks_init();
- /* If the real connect doesn't exist, we're stuffed */ + /* If the real sendto doesn't exist, we're stuffed */ if (original_sendto == NULL) { show_msg(MSGERR, "Unresolved symbol: sendto\n"); return(-1); @@ -1682,17 +1681,6 @@ ssize_t tsocks_sendto_guts(SENDTO_SIGNATURE, ssize_t (*original_sendto)(SENDTO_S
show_msg(MSGDEBUG, "Got sendto request\n");
- /* Get the domain of the socket */ - getsockopt(s, SOL_SOCKET, SO_DOMAIN, - (void *) &sock_domain, &sock_domain_len); - - /* If this isn't an INET socket we can't handle it, just call the real - connect now */ - if ((sock_domain != PF_INET)) { - show_msg(MSGDEBUG, "Connection isn't an Internet socket ignoring\n"); - return (ssize_t) original_sendto(s, buf, len, flags, to, tolen); - } - /* Get the type of the socket */ getsockopt(s, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len); @@ -1707,22 +1695,29 @@ ssize_t tsocks_sendto_guts(SENDTO_SIGNATURE, ssize_t (*original_sendto)(SENDTO_S return -1; }
- return (ssize_t) original_sendto(s, buf, len, flags, to, tolen); + connaddr = (struct sockaddr_in *) to; + + /* If there is no address in 'to', sendto will only work if we + already allowed the socket to connect(), so we let it through. + Likewise if the socket is not an Internet connection. */ + if (connaddr && (connaddr->sin_family != AF_INET)) { + show_msg(MSGDEBUG, "Connection isn't an Internet socket ignoring\n"); + }
+ return (ssize_t) original_sendto(s, buf, len, flags, to, tolen); }
ssize_t tsocks_sendmsg_guts(SENDMSG_SIGNATURE, ssize_t (*original_sendmsg)(SENDMSG_SIGNATURE)) { int sock_type = -1; unsigned int sock_type_len = sizeof(sock_type); - int sock_domain = -1; - unsigned int sock_domain_len = sizeof(sock_domain); + struct sockaddr_in *connaddr;
/* See comment in close() */ if (!tsocks_init_complete) tsocks_init();
- /* If the real connect doesn't exist, we're stuffed */ + /* If the real sendmsg doesn't exist, we're stuffed */ if (original_sendmsg == NULL) { show_msg(MSGERR, "Unresolved symbol: sendmsg\n"); return(-1); @@ -1730,31 +1725,27 @@ ssize_t tsocks_sendmsg_guts(SENDMSG_SIGNATURE, ssize_t (*original_sendmsg)(SENDM
show_msg(MSGDEBUG, "Got sendmsg request\n");
- /* Get the domain of the socket */ - getsockopt(s, SOL_SOCKET, SO_DOMAIN, - (void *) &sock_domain, &sock_domain_len); - - /* If this isn't an INET socket we can't handle it, just call the real - connect now */ - if ((sock_domain != PF_INET)) { - show_msg(MSGDEBUG, "Connection isn't an Internet socket ignoring\n"); - return (ssize_t) original_sendmsg(s, msg, flags); - } - /* Get the type of the socket */ getsockopt(s, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len);
show_msg(MSGDEBUG, "sockopt: %i\n", sock_type);
- /* If this a UDP socket then we refuse it, since it is probably a DNS - request */ if ((sock_type != SOCK_STREAM)) { show_msg(MSGERR, "sendmsg: Connection is a UDP or ICMP stream, may be a " - "DNS request or other form of leak: rejecting.\n"); + "DNS request or other form of leak: rejecting.\n"); return -1; }
+ connaddr = (struct sockaddr_in *) msg->msg_name; + + /* If there is no address in msg_name, sendmsg will only work if we + already allowed the socket to connect(), so we let it through. + Likewise if the socket is not an Internet connection. */ + if (connaddr && (connaddr->sin_family != AF_INET)) { + show_msg(MSGDEBUG, "Connection isn't an Internet socket\n"); + } + return (ssize_t) original_sendmsg(s, msg, flags); }
tor-commits@lists.torproject.org