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]
This commit is contained in:
Andreas Kempe 2019-02-07 02:36:41 +01:00 committed by Duncaen
parent 66524481b2
commit 0c657582f2

View File

@ -277,11 +277,19 @@ fetch_bind(int sd, int af, const char *addr)
int int
fetch_socks5(conn_t *conn, struct url *url, struct url *socks, int verbose) fetch_socks5(conn_t *conn, struct url *url, struct url *socks, int verbose)
{ {
char buf[16]; char buf[262];
uint8_t auth; uint8_t auth;
size_t alen; size_t alen;
ssize_t dlen;
alen = strlen(url->host); 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') auth = (*socks->user != '\0' && *socks->pwd != '\0')
? SOCKS5_USER_PASS : SOCKS5_NO_AUTH; ? 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); fetch_info("connecting socks5 to %s:%d", url->host, url->port);
/* write request */ /* write request */
buf[0] = SOCKS5_VERSION; dlen = 0;
buf[1] = SOCKS5_TCP_STREAM; buf[dlen++] = SOCKS5_VERSION;
buf[2] = 0x00; buf[dlen++] = SOCKS5_TCP_STREAM;
buf[3] = SOCKS5_ATYPE_DOMAIN; buf[dlen++] = 0x00;
buf[4] = alen; buf[dlen++] = SOCKS5_ATYPE_DOMAIN;
if (fetch_write(conn, buf, 5) != 5) buf[dlen++] = alen;
return -1;
if (fetch_write(conn, url->host, alen) == -1) memcpy(&buf[dlen], url->host, alen);
return -1; dlen += alen;
buf[0] = (url->port >> 0x08); buf[dlen++] = (url->port >> 0x08);
buf[1] = (url->port & 0xFF); buf[dlen++] = (url->port & 0xFF);
if (fetch_write(conn, buf, 2) != 2)
if (fetch_write(conn, buf, dlen) != dlen)
return -1; return -1;
/* read answer */ /* read answer */