From 5ee88eee6861ab1c98c03bc0b1c8f63c447c7fdc Mon Sep 17 00:00:00 2001 From: Jay Satiro Date: Sat, 21 Sep 2019 03:39:21 -0400 Subject: [PATCH] socks: Fix destination host shown on SOCKS5 error Prior to this change when a server returned a socks5 connect error then curl would parse the destination address:port from that data and show it to the user as the destination: curld -v --socks5 10.0.3.1:1080 http://google.com:99 * SOCKS5 communication to google.com:99 * SOCKS5 connect to IPv4 172.217.12.206 (locally resolved) * Can't complete SOCKS5 connection to 253.127.0.0:26673. (1) curl: (7) Can't complete SOCKS5 connection to 253.127.0.0:26673. (1) That's incorrect because the address:port included in the connect error is actually a bind address:port (typically unused) and not the destination address:port. This fix changes curl to show the destination information that curl sent to the server instead: curld -v --socks5 10.0.3.1:1080 http://google.com:99 * SOCKS5 communication to google.com:99 * SOCKS5 connect to IPv4 172.217.7.14:99 (locally resolved) * Can't complete SOCKS5 connection to 172.217.7.14:99. (1) curl: (7) Can't complete SOCKS5 connection to 172.217.7.14:99. (1) curld -v --socks5-hostname 10.0.3.1:1080 http://google.com:99 * SOCKS5 communication to google.com:99 * SOCKS5 connect to google.com:99 (remotely resolved) * Can't complete SOCKS5 connection to google.com:99. (1) curl: (7) Can't complete SOCKS5 connection to google.com:99. (1) Ref: https://tools.ietf.org/html/rfc1928#section-6 Closes https://github.com/curl/curl/pull/4394 --- lib/socks.c | 64 +++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/lib/socks.c b/lib/socks.c index d8fcc3bbb..6ae98184d 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -38,7 +38,9 @@ #include "timeval.h" #include "socks.h" -/* The last #include file should be: */ +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" #include "memdebug.h" /* @@ -372,8 +374,9 @@ CURLcode Curl_SOCKS5(const char *proxy_user, o REP Reply field: o X'00' succeeded */ - - unsigned char socksreq[600]; /* room for large user/pw (255 max each) */ +#define REQUEST_BUFSIZE 600 /* room for large user/pw (255 max each) */ + unsigned char socksreq[REQUEST_BUFSIZE]; + char dest[REQUEST_BUFSIZE] = "unknown"; /* printable hostname:port */ int idx; ssize_t actualread; ssize_t written; @@ -605,6 +608,8 @@ CURLcode Curl_SOCKS5(const char *proxy_user, socksreq[len++] = (char) hostname_len; /* address length */ memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */ len += hostname_len; + msnprintf(dest, sizeof(dest), "%s:%d", hostname, remote_port); + infof(data, "SOCKS5 connect to %s (remotely resolved)\n", dest); } else { struct Curl_dns_entry *dns; @@ -628,8 +633,13 @@ CURLcode Curl_SOCKS5(const char *proxy_user, if(dns) hp = dns->addr; if(hp) { - char buf[64]; - Curl_printable_address(hp, buf, sizeof(buf)); + if(Curl_printable_address(hp, dest, sizeof(dest))) { + size_t destlen = strlen(dest); + msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port); + } + else { + strcpy(dest, "unknown"); + } if(hp->ai_family == AF_INET) { int i; @@ -641,7 +651,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user, socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; } - infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf); + infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest); } #ifdef ENABLE_IPV6 else if(hp->ai_family == AF_INET6) { @@ -655,13 +665,13 @@ CURLcode Curl_SOCKS5(const char *proxy_user, ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; } - infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf); + infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest); } #endif else { hp = NULL; /* fail! */ - failf(data, "SOCKS5 connection to %s not supported\n", buf); + failf(data, "SOCKS5 connection to %s not supported\n", dest); } Curl_resolv_unlock(data, dns); /* not used anymore from now on */ @@ -756,42 +766,8 @@ CURLcode Curl_SOCKS5(const char *proxy_user, #endif if(socksreq[1] != 0) { /* Anything besides 0 is an error */ - if(socksreq[3] == 1) { - failf(data, - "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (((unsigned char)socksreq[8] << 8) | - (unsigned char)socksreq[9]), - (unsigned char)socksreq[1]); - } - else if(socksreq[3] == 3) { - unsigned char port_upper = (unsigned char)socksreq[len - 2]; - socksreq[len - 2] = 0; - failf(data, - "Can't complete SOCKS5 connection to %s:%d. (%d)", - (char *)&socksreq[5], - ((port_upper << 8) | - (unsigned char)socksreq[len - 1]), - (unsigned char)socksreq[1]); - socksreq[len - 2] = port_upper; - } - else if(socksreq[3] == 4) { - failf(data, - "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:" - "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (unsigned char)socksreq[8], (unsigned char)socksreq[9], - (unsigned char)socksreq[10], (unsigned char)socksreq[11], - (unsigned char)socksreq[12], (unsigned char)socksreq[13], - (unsigned char)socksreq[14], (unsigned char)socksreq[15], - (unsigned char)socksreq[16], (unsigned char)socksreq[17], - (unsigned char)socksreq[18], (unsigned char)socksreq[19], - (((unsigned char)socksreq[20] << 8) | - (unsigned char)socksreq[21]), - (unsigned char)socksreq[1]); - } + failf(data, "Can't complete SOCKS5 connection to %s. (%d)", + dest, (unsigned char)socksreq[1]); return CURLE_COULDNT_CONNECT; } infof(data, "SOCKS5 request granted.\n");