From 0c657582f2308c6d5031440408b55cf677d5c3a8 Mon Sep 17 00:00:00 2001 From: Andreas Kempe Date: Thu, 7 Feb 2019 02:36:41 +0100 Subject: [PATCH] lib/fetch/common.c: send socks5 request as a single transaction Splitting the socks5 request is causing issues when running against Tor. It causes Tor to fail with an address unknown error. Assembling the request and sending it in its entirety solves the issue. An strace of torsocks, that functions correctly when used with xbps, shows that the request is being sent all at once: recvfrom(3, "\5\0", 2, 0, NULL, NULL) sendto(3, "\5\1\0\3>lysator7eknrfl47rlyxvgeamrv7ucefgrrlhk7rouv3sna25asetwid.onion\0P", 69, 0, NULL, 0) recvfrom(3, "\5\0\0\1\0\0\0\0\0\0", 10, 0, NULL, NULL) Closes: #54 [via git-merge-pr] --- lib/fetch/common.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/fetch/common.c b/lib/fetch/common.c index 399c4628..6f9be7fd 100644 --- a/lib/fetch/common.c +++ b/lib/fetch/common.c @@ -277,11 +277,19 @@ fetch_bind(int sd, int af, const char *addr) int fetch_socks5(conn_t *conn, struct url *url, struct url *socks, int verbose) { - char buf[16]; + char buf[262]; uint8_t auth; size_t alen; + ssize_t dlen; alen = strlen(url->host); + if (alen > 255) { + if (verbose) + fetch_info("socks5 only supports addresses <= 255 bytes"); + errno = EINVAL; + return -1; + } + auth = (*socks->user != '\0' && *socks->pwd != '\0') ? SOCKS5_USER_PASS : SOCKS5_NO_AUTH; @@ -352,20 +360,20 @@ fetch_socks5(conn_t *conn, struct url *url, struct url *socks, int verbose) fetch_info("connecting socks5 to %s:%d", url->host, url->port); /* write request */ - buf[0] = SOCKS5_VERSION; - buf[1] = SOCKS5_TCP_STREAM; - buf[2] = 0x00; - buf[3] = SOCKS5_ATYPE_DOMAIN; - buf[4] = alen; - if (fetch_write(conn, buf, 5) != 5) - return -1; + dlen = 0; + buf[dlen++] = SOCKS5_VERSION; + buf[dlen++] = SOCKS5_TCP_STREAM; + buf[dlen++] = 0x00; + buf[dlen++] = SOCKS5_ATYPE_DOMAIN; + buf[dlen++] = alen; - if (fetch_write(conn, url->host, alen) == -1) - return -1; + memcpy(&buf[dlen], url->host, alen); + dlen += alen; - buf[0] = (url->port >> 0x08); - buf[1] = (url->port & 0xFF); - if (fetch_write(conn, buf, 2) != 2) + buf[dlen++] = (url->port >> 0x08); + buf[dlen++] = (url->port & 0xFF); + + if (fetch_write(conn, buf, dlen) != dlen) return -1; /* read answer */