1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

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
This commit is contained in:
Jay Satiro 2019-09-21 03:39:21 -04:00
parent e09749dd43
commit 5ee88eee68

View File

@ -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");