[tor-commits] [torsocks/master] Fix: socks5 resolve wasn't sending data correctly

dgoulet at torproject.org dgoulet at torproject.org
Wed May 27 17:22:49 UTC 2015


commit 72039624bb190dfec3e758b7389410a987adc8a3
Author: David Goulet <dgoulet at ev0ke.net>
Date:   Wed May 27 13:20:03 2015 -0400

    Fix: socks5 resolve wasn't sending data correctly
    
    The resolve function was sending uninitialized data to tor and sometimes
    too much data than needed. Furthermore, a valid SOCKS5 request for that
    needs a port so add one in both resolve and resolve_ptr.
    
    Reported-by: Yawning Angel <yawning at schwanenlied.me>
    Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
 src/common/socks5.c |   43 +++++++++++++++++++++++++++++++------------
 src/common/socks5.h |    2 ++
 2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/src/common/socks5.c b/src/common/socks5.c
index 3c9544a..3f284ca 100644
--- a/src/common/socks5.c
+++ b/src/common/socks5.c
@@ -564,20 +564,19 @@ ATTR_HIDDEN
 int socks5_send_resolve_request(const char *hostname, struct connection *conn)
 {
 	int ret, ret_send;
-	/*
-	 * Can't go bigger than that. 4 bytes for the header, 1 for the name len
-	 * and 255 for the name.
-	 */
-	unsigned char buffer[260];
 	size_t name_len, msg_len, data_len;
 	struct socks5_request msg;
 	struct socks5_request_resolve req;
+	/* Can't go bigger than that. 4 bytes for the header, 1 for the name len,
+	 * 255 for the name and 2 bytes for the port. */
+	unsigned char buffer[sizeof(msg) + sizeof(req)];
 
 	assert(hostname);
 	assert(conn);
 	assert(conn->fd >= 0);
 
 	memset(buffer, 0, sizeof(buffer));
+	memset(&req, 0, sizeof(req));
 	msg_len = sizeof(msg);
 
 	msg.ver = SOCKS5_VERSION;
@@ -596,11 +595,21 @@ int socks5_send_resolve_request(const char *hostname, struct connection *conn)
 	/* Setup resolve request. */
 	req.len = name_len;
 	memcpy(req.name, hostname, name_len);
+	/* Dummy port, tor doesn't need it. */
+	req.port = htons(42);
 
 	/* Copy final buffer. */
 	memcpy(buffer, &msg, msg_len);
-	memcpy(buffer + msg_len, &req, sizeof(req));
-	data_len = msg_len + sizeof(req);
+	data_len = msg_len;
+	/* Add the length of hostname. */
+	memcpy(buffer + data_len, &req.len, sizeof(req.len));
+	data_len += sizeof(req.len);
+	/* Add hostname without NULL terminated byte. */
+	memcpy(buffer + data_len, req.name, req.len);
+	data_len += req.len;
+	/* Add the dummy port at the end. */
+	memcpy(buffer + data_len, &req.port, sizeof(req.port));
+	data_len += sizeof(req.port);
 
 	ret_send = send_data(conn->fd, &buffer, data_len);
 	if (ret_send < 0) {
@@ -703,10 +712,11 @@ ATTR_HIDDEN
 int socks5_send_resolve_ptr_request(struct connection *conn, const void *ip, int af)
 {
 	int ret, ret_send;
-	unsigned char buffer[20];	/* Can't go higher than that (with IPv6). */
 	size_t msg_len, data_len;
 	struct socks5_request msg;
 	struct socks5_request_resolve_ptr req;
+	/* Can't go higher than that (with IPv6). */
+	unsigned char buffer[sizeof(msg) + sizeof(req)];
 
 	assert(conn);
 	assert(conn->fd >= 0);
@@ -724,11 +734,17 @@ int socks5_send_resolve_ptr_request(struct connection *conn, const void *ip, int
 	switch (af) {
 	case AF_INET:
 		msg.atyp = SOCKS5_ATYP_IPV4;
-		memcpy(req.addr.ipv4, ip, 4);
+		memcpy(req.addr.ipv4, ip, sizeof(req.addr.ipv4));
+		/* Copy right away the IP since we know the family type. */
+		memcpy(buffer + msg_len, &req.addr, sizeof(req.addr.ipv4));
+		data_len = msg_len + sizeof(req.addr.ipv4);
 		break;
 	case AF_INET6:
 		msg.atyp = SOCKS5_ATYP_IPV6;
-		memcpy(req.addr.ipv6, ip, 16);
+		memcpy(req.addr.ipv6, ip, sizeof(req.addr.ipv6));
+		/* Copy right away the IP since we know the family type. */
+		memcpy(buffer + msg_len, &req.addr, sizeof(req.addr.ipv6));
+		data_len = msg_len + sizeof(req.addr.ipv6);
 		break;
 	default:
 		ERR("Unknown address domain of %d", ip);
@@ -736,10 +752,13 @@ int socks5_send_resolve_ptr_request(struct connection *conn, const void *ip, int
 		goto error;
 	}
 
+	/* Dummy port, tor doesn't need it. */
+	req.port = htons(42);
+
 	/* Copy final buffer. */
 	memcpy(buffer, &msg, msg_len);
-	memcpy(buffer + msg_len, &req, sizeof(req));
-	data_len = msg_len + sizeof(req);
+	memcpy(buffer + data_len, &req.port, sizeof(req.port));
+	data_len += sizeof(req.port);
 
 	ret_send = send_data(conn->fd, &buffer, data_len);
 	if (ret_send < 0) {
diff --git a/src/common/socks5.h b/src/common/socks5.h
index 35c7d2b..41da679 100644
--- a/src/common/socks5.h
+++ b/src/common/socks5.h
@@ -108,6 +108,7 @@ struct socks5_request_domain {
 struct socks5_request_resolve {
 	uint8_t len;
 	unsigned char name[UINT8_MAX];
+	uint16_t port;
 };
 
 /* Use for the Tor resolve ptr command. */
@@ -116,6 +117,7 @@ struct socks5_request_resolve_ptr {
 		uint8_t ipv4[4];
 		uint8_t ipv6[16];
 	} addr;
+	uint16_t port;
 };
 
 /* Non variable part of a reply. */



More information about the tor-commits mailing list