]> granicus.if.org Git - curl/commitdiff
socks: Fix destination host shown on SOCKS5 error
authorJay Satiro <raysatiro@yahoo.com>
Sat, 21 Sep 2019 07:39:21 +0000 (03:39 -0400)
committerJay Satiro <raysatiro@yahoo.com>
Sun, 22 Sep 2019 03:45:02 +0000 (23:45 -0400)
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

index d8fcc3bbba03a529b408f4432c264a5c743e465b..6ae98184d16ac640f8fa9309bd290d2b8f66c560 100644 (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");