[tor-commits] [torsocks/master] Support the RESOLVE PTR Tor command in the socks5 API

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


commit c48811e759850815048713f91e30140f6df63aac
Author: David Goulet <dgoulet at ev0ke.net>
Date:   Sun Jun 23 14:32:58 2013 -0400

    Support the RESOLVE PTR Tor command in the socks5 API
    
    Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
 src/common/socks5.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/socks5.h |   10 ++++
 2 files changed, 138 insertions(+)

diff --git a/src/common/socks5.c b/src/common/socks5.c
index 8a16b9a..d007599 100644
--- a/src/common/socks5.c
+++ b/src/common/socks5.c
@@ -15,9 +15,11 @@
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <arpa/inet.h>
 #include <assert.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <stdlib.h>
 
 #include <lib/torsocks.h>
 
@@ -493,3 +495,129 @@ int socks5_recv_resolve_reply(struct connection *conn, uint32_t *ip_addr)
 error:
 	return ret;
 }
+
+/*
+ * Send a SOCKS5 Tor resolve ptr request for a given ip address using an
+ * already connected connection.
+ *
+ * Return 0 on success or else a negative value.
+ */
+int socks5_send_resolve_ptr_request(const void *ip, struct connection *conn)
+{
+	int ret, ret_send;
+	char buffer[20];	/* Can't go higher than that (with IPv6). */
+	char ip_str[INET6_ADDRSTRLEN];
+	size_t msg_len, data_len;
+	struct socks5_request msg;
+	struct socks5_request_resolve_ptr req;
+
+	assert(conn);
+	assert(conn->fd >= 0);
+
+	DBG("[socks5] Resolve ptr request for ip %u", ip);
+
+	memset(buffer, 0, sizeof(buffer));
+	msg_len = sizeof(msg);
+
+	msg.ver = SOCKS5_VERSION;
+	msg.cmd = SOCKS5_CMD_RESOLVE_PTR;
+	/* Always zeroed. */
+	msg.rsv = 0;
+
+	if (inet_ntop(AF_INET, ip, ip_str, sizeof(ip_str))) {
+		msg.atyp = SOCKS5_ATYP_IPV4;
+		memcpy(req.addr.ipv4, ip, 4);
+	} else if (inet_ntop(AF_INET6, ip, ip_str, sizeof(ip_str))) {
+		msg.atyp = SOCKS5_ATYP_IPV6;
+		memcpy(req.addr.ipv4, ip, 16);
+	} else {
+		ERR("Unknown address domain of %d", ip);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Copy final buffer. */
+	memcpy(buffer, &msg, msg_len);
+	memcpy(buffer + msg_len, &req, sizeof(req));
+	data_len = msg_len + sizeof(req);
+
+	ret_send = send_data(conn->fd, &buffer, data_len);
+	if (ret_send < 0) {
+		ret = ret_send;
+		goto error;
+	}
+
+	/* Data was sent successfully. */
+	ret = 0;
+	DBG("[socks5] Resolve PTR for %u sent successfully", ip);
+
+error:
+	return ret;
+}
+
+/*
+ * Receive a Tor resolve ptr reply on the given connection. The hostname value
+ * is populated with the returned name from Tor. On error, it's untouched. The
+ * memory is allocated so the caller needs to free the memory on success.
+ *
+ * Return 0 on success else a negative value.
+ */
+int socks5_recv_resolve_ptr_reply(struct connection *conn, char **_hostname)
+{
+	int ret;
+	ssize_t ret_recv;
+	char *hostname = NULL;
+	struct {
+		struct socks5_reply msg;
+		uint8_t len;
+	} buffer;
+
+	assert(conn);
+	assert(conn >= 0);
+	assert(_hostname);
+
+	ret_recv = recv_data(conn->fd, &buffer, sizeof(buffer));
+	if (ret_recv < 0) {
+		ret = ret_recv;
+		goto error;
+	}
+
+	if (buffer.msg.ver != SOCKS5_VERSION) {
+		ERR("Bad SOCKS5 version reply");
+		ret = -ECONNABORTED;
+		goto error;
+	}
+
+	if (buffer.msg.rep != SOCKS5_REPLY_SUCCESS) {
+		ERR("Unable to resolve. Status reply: %d", buffer.msg.rep);
+		ret = -ECONNABORTED;
+		goto error;
+	}
+
+	if (buffer.msg.atyp == SOCKS5_ATYP_DOMAIN) {
+		/* Allocate hostname len plus an extra for the null byte. */
+		hostname = zmalloc(buffer.len + 1);
+		if (!hostname) {
+			ret = -ENOMEM;
+			goto error;
+		}
+		ret_recv = recv_data(conn->fd, hostname, buffer.len);
+		if (ret_recv < 0) {
+			ret = ret_recv;
+			goto error;
+		}
+		hostname[buffer.len] = '\0';
+	} else {
+		ERR("Bad SOCKS5 atyp reply %d", buffer.msg.atyp);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	*_hostname = hostname;
+	DBG("[socks5] Resolve reply received: %s", *_hostname);
+	return 0;
+
+error:
+	free(hostname);
+	return ret;
+}
diff --git a/src/common/socks5.h b/src/common/socks5.h
index c11c097..9b47aa1 100644
--- a/src/common/socks5.h
+++ b/src/common/socks5.h
@@ -102,6 +102,14 @@ struct socks5_request_resolve {
 	char name[UINT8_MAX];
 };
 
+/* Use for the Tor resolve ptr command. */
+struct socks5_request_resolve_ptr {
+	union {
+		uint8_t ipv4[4];
+		uint8_t ipv6[16];
+	} addr;
+};
+
 /* Non variable part of a reply. */
 struct socks5_reply {
 	uint8_t ver;
@@ -123,5 +131,7 @@ int socks5_recv_connect_reply(struct connection *conn);
 /* Tor DNS resolve. */
 int socks5_send_resolve_request(const char *hostname, struct connection *conn);
 int socks5_recv_resolve_reply(struct connection *conn, uint32_t *ip_addr);
+int socks5_recv_resolve_ptr_reply(struct connection *conn, char **_hostname);
+int socks5_send_resolve_ptr_request(const void *ip, struct connection *conn);
 
 #endif /* TORSOCKS_SOCKS_H */





More information about the tor-commits mailing list