Richard Atterer brought a patch that added support for SOCKS4a proxies, which
authorDaniel Stenberg <daniel@haxx.se>
Wed, 2 Jan 2008 21:40:11 +0000 (21:40 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 2 Jan 2008 21:40:11 +0000 (21:40 +0000)
is an inofficial PROXY4 variant that sends the hostname to the proxy instead
of the resolved address (which is already supported by SOCKS5).  --socks4a is
the curl command line option for it and CURLOPT_PROXYTYPE can now be set to
CURLPROXY_SOCKS4A as well.

CHANGES
RELEASE-NOTES
docs/curl.1
docs/libcurl/curl_easy_setopt.3
include/curl/curl.h
lib/ftp.c
lib/socks.c
lib/socks.h
lib/url.c
src/main.c

diff --git a/CHANGES b/CHANGES
index be257d4..bd9a29a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,13 @@
 
                                   Changelog
 
+Daniel S (2 Jan 2008)
+- Richard Atterer brought a patch that added support for SOCKS4a proxies,
+  which is an inofficial PROXY4 variant that sends the hostname to the proxy
+  instead of the resolved address (which is already supported by SOCKS5).
+  --socks4a is the curl command line option for it and CURLOPT_PROXYTYPE can
+  now be set to CURLPROXY_SOCKS4A as well.
+
 Daniel S (1 Jan 2008)
 - Mohun Biswas pointed out that --libcurl generated a source code with an int
   function but without a return statement. While fixing that, I also took care
index 9e72192..68ad0fb 100644 (file)
@@ -1,7 +1,7 @@
 Curl and libcurl 7.17.2
 
  Public curl releases:         103
- Command line options:         123
+ Command line options:         124
  curl_easy_setopt() options:   148
  Public functions in libcurl:  55
  Public web site mirrors:      42
@@ -13,6 +13,7 @@ This release includes the following changes:
  o --data-urlencode was added
  o CURLOPT_PROXY_TRANSFER_MODE was added
  o --no-keep-alive was added
+ o --socks4a added (proxy type CURLPROXY_SOCKS4A for libcurl)
 
 This release includes the following bugfixes:
 
@@ -62,6 +63,6 @@ advice from friends like these:
  Robin Johnson, Michal Marek, Ates Goral, Andres Garcia, Rob Crittenden,
  Emil Romanus, Alessandro Vesely, Ray Pekowski, Spacen Jasset, Andrew Moise,
  Gilles Blanc, David Wright, Vikram Saxena, Mateusz Loskot, Gary Maxwell,
- Dmitry Kurochkin, Mohun Biswas
+ Dmitry Kurochkin, Mohun Biswas, Richard Atterer
  
         Thanks! (and sorry if I forgot to mention someone)
index 0d85cc9..b94a1dc 100644 (file)
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -1075,6 +1075,14 @@ This option overrides any previous use of \fI-x/--proxy\fP, as they are
 mutually exclusive.
 
 If this option is used several times, the last one will be used.
+.IP "--socks4a <host[:port]>"
+Use the specified SOCKS4a proxy. If the port number is not specified, it is
+assumed at port 1080. (Added in 7.17.2)
+
+This option overrides any previous use of \fI-x/--proxy\fP, as they are
+mutually exclusive.
+
+If this option is used several times, the last one will be used.
 .IP "--socks5 <host[:port]>"
 Use the specified SOCKS5 proxy. If the port number is not specified, it is
 assumed at port 1080. (Added in 7.11.1)
index 2016ffc..cc2af68 100644 (file)
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -430,8 +430,9 @@ Pass a long with this option to set the proxy port to connect to unless it is
 specified in the proxy string \fICURLOPT_PROXY\fP.
 .IP CURLOPT_PROXYTYPE
 Pass a long with this option to set type of the proxy. Available options for
-this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2)
-\fICURLPROXY_SOCKS5\fP. The HTTP type is default. (Added in 7.10)
+this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2),
+\fICURLPROXY_SOCKS5\fP and \fICURLPROXY_SOCKS4A\fP (added in 7.17.2). The HTTP
+type is default. (Added in 7.10)
 .IP CURLOPT_HTTPPROXYTUNNEL
 Set the parameter to non-zero to get the library to tunnel all operations
 through a given HTTP proxy. There is a big difference between using a proxy
index ad2bb70..a4140af 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -510,10 +510,12 @@ typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */
                                           void *userptr);
 
 typedef enum {
-  CURLPROXY_HTTP = 0,
-  CURLPROXY_SOCKS4 = 4,
-  CURLPROXY_SOCKS5 = 5
-} curl_proxytype;
+  CURLPROXY_HTTP = 0,   /* added in 7.10 */
+  CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+                           in 7.10 */
+  CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+  CURLPROXY_SOCKS4A = 6 /* added in 7.17.2 */
+} curl_proxytype;  /* this enum was added in 7.10 */
 
 #define CURLAUTH_NONE         0       /* nothing */
 #define CURLAUTH_BASIC        (1<<0)  /* Basic (default) */
@@ -958,7 +960,7 @@ typedef enum {
   CINIT(SHARE, OBJECTPOINT, 100),
 
   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
-     CURLPROXY_SOCKS4 and CURLPROXY_SOCKS5. */
+     CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
   CINIT(PROXYTYPE, LONG, 101),
 
   /* Set the Accept-Encoding string. Use this to tell a server you would like
index 3b1f3f7..588cd5b 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -1726,8 +1726,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
           newport = (unsigned short)(num & 0xffff);
 
           if(conn->bits.tunnel_proxy ||
-              data->set.proxytype == CURLPROXY_SOCKS5 ||
-              data->set.proxytype == CURLPROXY_SOCKS4)
+             data->set.proxytype == CURLPROXY_SOCKS5 ||
+             data->set.proxytype == CURLPROXY_SOCKS4 ||
+             data->set.proxytype == CURLPROXY_SOCKS4A)
             /* proxy tunnel -> use other host info because ip_addr_str is the
                proxy address not the ftp host */
             snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
@@ -1781,7 +1782,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
             conn->ip_addr_str);
       if(conn->bits.tunnel_proxy ||
           data->set.proxytype == CURLPROXY_SOCKS5 ||
-          data->set.proxytype == CURLPROXY_SOCKS4)
+          data->set.proxytype == CURLPROXY_SOCKS4 ||
+          data->set.proxytype == CURLPROXY_SOCKS4A)
         /* proxy tunnel -> use other host info because ip_addr_str is the
            proxy address not the ftp host */
         snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
@@ -1886,7 +1888,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
     break;
   case CURLPROXY_SOCKS4:
     result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                         SECONDARYSOCKET, conn);
+                         SECONDARYSOCKET, conn, false);
+    break;
+  case CURLPROXY_SOCKS4A:
+    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
+                         SECONDARYSOCKET, conn, true);
     break;
   default:
     failf(data, "unknown proxytype option given");
index 2b3113d..5146b0d 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -118,16 +118,19 @@ static int blockread_all(struct connectdata *conn, /* connection data */
 *   http://socks.permeo.com/protocol/socks4.protocol
 *
 * Note :
-*   Nonsupport "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
+*   Set protocol4a=true for  "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
 *   Nonsupport "Identification Protocol (RFC1413)"
 */
 CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn)
+                     struct connectdata *conn,
+                     bool protocol4a)
 {
-  unsigned char socksreq[262]; /* room for SOCKS4 request incl. user id */
+#define SOCKS4REQLEN 262
+  unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
+                                           id */
   int result;
   CURLcode code;
   curl_socket_t sock = conn->sock[sockindex];
@@ -165,8 +168,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
   socksreq[1] = 1; /* connect */
   *((unsigned short*)&socksreq[2]) = htons((unsigned short)remote_port);
 
-  /* DNS resolve */
-  {
+  /* DNS resolve only for SOCKS4, not SOCKS4a */
+  if (!protocol4a) {
     struct Curl_dns_entry *dns;
     Curl_addrinfo *hp=NULL;
     int rc;
@@ -225,15 +228,40 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
   {
     ssize_t actualread;
     ssize_t written;
+    ssize_t hostnamelen = 0;
     int packetsize = 9 +
       (int)strlen((char*)socksreq + 8); /* size including NUL */
 
+    /* If SOCKS4a, set special invalid IP address 0.0.0.x */
+    if (protocol4a) {
+      socksreq[4] = 0;
+      socksreq[5] = 0;
+      socksreq[6] = 0;
+      socksreq[7] = 1;
+      /* If still enough room in buffer, also append hostname */
+      hostnamelen = strlen(hostname) + 1; /* length including NUL */
+      if (packetsize + hostnamelen <= SOCKS4REQLEN)
+        strcpy((char*)socksreq + packetsize, hostname);
+      else
+        hostnamelen = 0; /* Flag: hostname did not fit in buffer */
+    }
+
     /* Send request */
-    code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
-    if((code != CURLE_OK) || (written != packetsize)) {
+    code = Curl_write(conn, sock, (char *)socksreq, packetsize + hostnamelen,
+                      &written);
+    if((code != CURLE_OK) || (written != packetsize + hostnamelen)) {
       failf(data, "Failed to send SOCKS4 connect request.");
       return CURLE_COULDNT_CONNECT;
     }
+    if (protocol4a && hostnamelen == 0) {
+      /* SOCKS4a with very long hostname - send that name separately */
+      hostnamelen = strlen(hostname) + 1;
+      code = Curl_write(conn, sock, (char *)hostname, hostnamelen, &written);
+      if((code != CURLE_OK) || (written != hostnamelen)) {
+        failf(data, "Failed to send SOCKS4 connect request.");
+        return CURLE_COULDNT_CONNECT;
+      }
+    }
 
     packetsize = 8; /* receive data size */
 
@@ -275,7 +303,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
     switch(socksreq[1])
     {
     case 90:
-      infof(data, "SOCKS4 request granted.\n");
+      if (protocol4a)
+        infof(data, "SOCKS4a request granted.\n");
+      else
+        infof(data, "SOCKS4 request granted.\n");
       break;
     case 91:
       failf(data,
index 8da142f..756ecc3 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  ***************************************************************************/
 
 /*
- * This function logs in to a SOCKS4 proxy and sends the specifics to the
+ * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
  * final destination server.
  */
 CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn);
+                     struct connectdata *conn,
+                     bool protocol4a);
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the
index ee8b916..a205f9a 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -1868,7 +1868,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
 
   case CURLOPT_PROXYTYPE:
     /*
-     * Set proxy type. HTTP/SOCKS4/SOCKS5
+     * Set proxy type. HTTP/SOCKS4/SOCKS4a/SOCKS5
      */
     data->set.proxytype = (curl_proxytype)va_arg(param, long);
     break;
@@ -2643,8 +2643,12 @@ static CURLcode ConnectPlease(struct SessionHandle *data,
         /* do nothing here. handled later. */
         break;
       case CURLPROXY_SOCKS4:
-        result = Curl_SOCKS4(conn->proxyuser, conn->host.name, conn->remote_port,
-                             FIRSTSOCKET, conn);
+        result = Curl_SOCKS4(conn->proxyuser, conn->host.name,
+                             conn->remote_port, FIRSTSOCKET, conn, false);
+        break;
+      case CURLPROXY_SOCKS4A:
+        result = Curl_SOCKS4(conn->proxyuser, conn->host.name,
+                             conn->remote_port, FIRSTSOCKET, conn, true);
         break;
       default:
         failf(data, "unknown proxytype option given");
index 5d83b6b..7729891 100644 (file)
@@ -712,6 +712,7 @@ static void help(void)
     " -s/--silent        Silent mode. Don't output anything",
     " -S/--show-error    Show error. With -s, make curl show errors when they occur",
     "    --socks4 <host[:port]> Use SOCKS4 proxy on given host + port",
+    "    --socks4a <host[:port]> Use SOCKS4a proxy on given host + port",
     "    --socks5 <host[:port]> Use SOCKS5 proxy on given host + port",
     "    --stderr <file> Where to redirect stderr. - means stdout",
     " -t/--telnet-option <OPT=val> Set telnet option",
@@ -1532,6 +1533,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     {"$r", "ftp-method", TRUE},
     {"$s", "local-port", TRUE},
     {"$t", "socks4",     TRUE},
+    {"$T", "socks4a",    TRUE},
     {"$u", "ftp-alternative-to-user", TRUE},
     {"$v", "ftp-ssl-reqd", FALSE},
     {"$w", "no-sessionid", FALSE},
@@ -1906,6 +1908,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
         GetStr(&config->socksproxy, nextarg);
         config->socksver = CURLPROXY_SOCKS4;
         break;
+      case 'T': /* --socks4a specifies a socks4a proxy to use */
+        GetStr(&config->socksproxy, nextarg);
+        config->socksver = CURLPROXY_SOCKS4A;
+        break;
       case 'd': /* --tcp-nodelay option */
         config->tcp_nodelay ^= TRUE;
         break;