]> granicus.if.org Git - curl/commitdiff
proxy: fix hostname resolution and IDN conversion
authorMichael Kaufmann <mail@michael-kaufmann.ch>
Sat, 18 Feb 2017 12:56:56 +0000 (13:56 +0100)
committerMichael Kaufmann <mail@michael-kaufmann.ch>
Sat, 18 Feb 2017 14:04:43 +0000 (15:04 +0100)
Properly resolve, convert and log the proxy host names.
Support the "--connect-to" feature for SOCKS proxies and for passive FTP
data transfers.

Follow-up to cb4e2be

Reported-by: Jay Satiro
Fixes https://github.com/curl/curl/issues/1248

lib/http_proxy.c
lib/multi.c
lib/url.c
lib/urldata.h
tests/data/Makefile.inc
tests/data/test2055 [new file with mode: 0755]
tests/data/test712
tests/data/test713 [new file with mode: 0755]
tests/data/test714 [new file with mode: 0755]
tests/data/test715 [new file with mode: 0755]

index d523ba519108670335b48768bbbce9cdf50f60d1..7fde11dbb8be725c983981bbe46573f882f5799d 100644 (file)
@@ -98,16 +98,21 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
      * original pointer
      *
      * This function might be called several times in the multi interface case
-     * if the proxy's CONNTECT response is not instant.
+     * if the proxy's CONNECT response is not instant.
      */
     prot_save = conn->data->req.protop;
     memset(&http_proxy, 0, sizeof(http_proxy));
     conn->data->req.protop = &http_proxy;
     connkeep(conn, "HTTP proxy CONNECT");
-    if(sockindex == SECONDARYSOCKET)
-      hostname = conn->secondaryhostname;
-    else if(conn->bits.conn_to_host)
+
+    /* for the secondary socket (FTP), use the "connect to host"
+     * but ignore the "connect to port" (use the secondary port)
+     */
+
+    if(conn->bits.conn_to_host)
       hostname = conn->conn_to_host.name;
+    else if(sockindex == SECONDARYSOCKET)
+      hostname = conn->secondaryhostname;
     else
       hostname = conn->host.name;
 
index 950b600cba351e0cc91caff7ba3b47c096527b43..04bf3f9371104d754560432fa001b07dfd222cd9 100644 (file)
@@ -638,7 +638,10 @@ static CURLcode multi_done(struct connectdata **connp,
 
       infof(data, "Connection #%ld to host %s left intact\n",
             conn->connection_id,
-            conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
+            conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+            conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+            conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+            conn->host.dispname);
     }
     else
       data->state.lastconnect = NULL;
@@ -1477,8 +1480,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       struct connectdata *conn = data->easy_conn;
       const char *hostname;
 
-      if(conn->bits.proxy)
-        hostname = conn->proxy.name;
+      if(conn->bits.httpproxy)
+        hostname = conn->http_proxy.host.name;
       else if(conn->bits.conn_to_host)
         hostname = conn->conn_to_host.name;
       else
index 8d1c0cc7f2d85623da152b943e8afc40ec18b152..2886abec85faa7d92376c9c41ed0d38dd87377f9 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -3054,7 +3054,6 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
 
   free_fixed_hostname(&conn->host);
   free_fixed_hostname(&conn->conn_to_host);
-  free_fixed_hostname(&conn->proxy);
   free_fixed_hostname(&conn->http_proxy.host);
   free_fixed_hostname(&conn->socks_proxy.host);
 
@@ -3819,17 +3818,19 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
 
   if(conn->bits.socksproxy) {
 #ifndef CURL_DISABLE_PROXY
-    const char * const host = conn->bits.conn_to_host ?
-                              conn->conn_to_host.name :
-                              conn->bits.httpproxy ?
+    /* for the secondary socket (FTP), use the "connect to host"
+     * but ignore the "connect to port" (use the secondary port)
+     */
+    const char * const host = conn->bits.httpproxy ?
                               conn->http_proxy.host.name :
+                              conn->bits.conn_to_host ?
+                              conn->conn_to_host.name :
                               sockindex == SECONDARYSOCKET ?
                               conn->secondaryhostname : conn->host.name;
-    const int port = conn->bits.conn_to_port ? conn->conn_to_port :
-                     conn->bits.httpproxy ?
-                     (int)conn->http_proxy.port :
-                     sockindex == SECONDARYSOCKET ?
-                      conn->secondary_port : conn->remote_port;
+    const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port :
+                     sockindex == SECONDARYSOCKET ? conn->secondary_port :
+                     conn->bits.conn_to_port ? conn->conn_to_port :
+                     conn->remote_port;
     conn->bits.socksproxy_connecting = TRUE;
     switch(conn->socks_proxy.proxytype) {
     case CURLPROXY_SOCKS5:
@@ -3867,7 +3868,8 @@ void Curl_verboseconnect(struct connectdata *conn)
     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
           conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
           conn->bits.httpproxy ? conn->http_proxy.host.dispname :
-                             conn->host.dispname,
+          conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+          conn->host.dispname,
           conn->ip_addr_str, conn->port, conn->connection_id);
 }
 #endif
@@ -4114,7 +4116,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
   conn->connection_id = -1;    /* no ID */
   conn->port = -1; /* unknown at this point */
-  conn->remote_port = -1; /* unknown */
+  conn->remote_port = -1; /* unknown at this point */
 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
@@ -5925,7 +5927,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
       if(conn->bits.conn_to_port)
         conn->port = conn->conn_to_port;
       else
-        conn->port = conn->remote_port; /* it is the same port */
+        conn->port = conn->remote_port;
 
       /* Resolve target host right on */
       rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
@@ -5981,11 +5983,9 @@ static void reuse_conn(struct connectdata *old_conn,
 {
   free_fixed_hostname(&old_conn->http_proxy.host);
   free_fixed_hostname(&old_conn->socks_proxy.host);
-  free_fixed_hostname(&old_conn->proxy);
 
   free(old_conn->http_proxy.host.rawalloc);
   free(old_conn->socks_proxy.host.rawalloc);
-  free(old_conn->proxy.rawalloc);
 
   /* free the SSL config struct from this connection struct as this was
      allocated in vain and is targeted for destruction */
@@ -6432,12 +6432,14 @@ static CURLcode create_conn(struct Curl_easy *data,
   fix_hostname(conn, &conn->host);
   if(conn->bits.conn_to_host)
     fix_hostname(conn, &conn->conn_to_host);
-  if(conn->proxy.name && *conn->proxy.name)
-    fix_hostname(conn, &conn->proxy);
+  if(conn->bits.httpproxy)
+    fix_hostname(conn, &conn->http_proxy.host);
+  if(conn->bits.socksproxy)
+    fix_hostname(conn, &conn->socks_proxy.host);
 
   /*************************************************************
    * Check whether the host and the "connect to host" are equal.
-   * Do this after the hostnames have been IDN-fixed .
+   * Do this after the hostnames have been IDN-fixed.
    *************************************************************/
   if(conn->bits.conn_to_host &&
      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
index e37b566a5ae655ece3032e43a2c50a51c0de18fd..c17e42cc0c538efebd17d34f269e50387385c126 100644 (file)
@@ -936,7 +936,6 @@ struct connectdata {
   char *secondaryhostname; /* secondary socket host name (ftp) */
   struct hostname conn_to_host; /* the host to connect to. valid only if
                                    bits.conn_to_host is set */
-  struct hostname proxy;
 
   struct proxy_info socks_proxy;
   struct proxy_info http_proxy;
@@ -1644,7 +1643,6 @@ struct UserDefined {
   struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
   struct ssl_general_config general_ssl; /* general user defined SSL stuff */
   curl_proxytype proxytype; /* what kind of proxy that is in use */
-  curl_proxytype socks_proxytype; /* what kind of socks proxy that is in use */
   long dns_cache_timeout; /* DNS cache timeout */
   long buffer_size;      /* size of receive buffer to use */
   void *private_data; /* application-private data */
index 953916d9740f005b28579d0c852392e8ac66b44a..33dce05d84f2a420d2735c733751a690022ecb42 100644 (file)
@@ -80,7 +80,7 @@ test626 test627 test628 test629 test630 test631 test632 test633 test634 \
 test635 test636 test637 test638 test639 test640 test641 \
 \
 test700 test701 test702 test703 test704 test705 test706 test707 test708 \
-test709 test710 test711 test712 \
+test709 test710 test711 test712 test713 test714 test715 \
 \
 test800 test801 test802 test803 test804 test805 test806 test807 test808 \
 test809 test810 test811 test812 test813 test814 test815 test816 test817 \
@@ -176,4 +176,4 @@ test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
 test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
 test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
-test2048 test2049 test2050 test2051 test2052 test2053 test2054
+test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055
diff --git a/tests/data/test2055 b/tests/data/test2055
new file mode 100755 (executable)
index 0000000..cca4494
--- /dev/null
@@ -0,0 +1,80 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP CONNECT
+HTTP proxy
+proxytunnel
+CURLOPT_CONNECT_TO
+SOCKS5
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 200 Connection established
+
+</connect>
+
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 3
+Content-Type: text/plain
+
+OK
+</data>
+
+<datacheck>
+HTTP/1.1 200 Connection established
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 3
+Content-Type: text/plain
+
+OK
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+http-proxy
+socks5
+</server>
+ <name>
+Connect to specific host via SOCKS proxy and HTTP proxy (switch to tunnel mode automatically)
+ </name>
+
+ <command>
+http://www.example.com.2055/2055 --connect-to ::connect.example.com.2055:%HTTPPORT -x %HOSTIP:%PROXYPORT --preproxy socks5://%HOSTIP:%SOCKSPORT
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<proxy>
+CONNECT connect.example.com.2055:%HTTPPORT HTTP/1.1\r
+Host: connect.example.com.2055:%HTTPPORT\r
+Proxy-Connection: Keep-Alive\r
+\r
+</proxy>
+<protocol>
+GET /2055 HTTP/1.1\r
+Host: www.example.com.2055\r
+Accept: */*\r
+\r
+</protocol>
+
+</verify>
+</testcase>
index c62e9f2c5def06ed7ad7c8681329418419904c0b..252c9ef0e16cd90281f23489bfa034c30d812e2d 100644 (file)
@@ -6,7 +6,6 @@ FTP
 PASV
 RETR
 SOCKS5
-all_proxy
 </keywords>
 </info>
 #
diff --git a/tests/data/test713 b/tests/data/test713
new file mode 100755 (executable)
index 0000000..bb79994
--- /dev/null
@@ -0,0 +1,49 @@
+<testcase>
+#based off test 712
+<info>
+<keywords>
+FTP
+PASV
+RETR
+SOCKS5
+CURLOPT_CONNECT_TO
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+silly content
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+socks5
+</server>
+ <name>
+FTP fetch with --proxy set to socks5:// and with --connect-to
+ </name>
+ <command>
+ftp://ftp.example.com/713 --connect-to ::%HOSTIP:%FTPPORT --proxy socks5://%HOSTIP:%SOCKSPORT 
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous\r
+PASS ftp@example.com\r
+PWD\r
+EPSV\r
+TYPE I\r
+SIZE 713\r
+RETR 713\r
+QUIT\r
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test714 b/tests/data/test714
new file mode 100755 (executable)
index 0000000..9d1f0a9
--- /dev/null
@@ -0,0 +1,64 @@
+<testcase>
+#based off test 712
+<info>
+<keywords>
+FTP
+PASV
+RETR
+HTTP
+HTTP CONNECT
+proxytunnel
+CURLOPT_CONNECT_TO
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 200 Connection established
+
+</connect>
+
+<data nocheck="yes">
+silly content
+</data>
+
+<datacheck>
+HTTP/1.1 200 Connection established
+
+HTTP/1.1 200 Connection established
+
+silly content
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+http-proxy
+</server>
+ <name>
+FTP fetch with --proxy set to http:// and with --connect-to
+ </name>
+ <command>
+ftp://ftp.example.com.714/714 --connect-to ::connect.example.com.714:%FTPPORT --proxytunnel --proxy http://%HOSTIP:%PROXYPORT 
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous\r
+PASS ftp@example.com\r
+PWD\r
+EPSV\r
+TYPE I\r
+SIZE 714\r
+RETR 714\r
+QUIT\r
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test715 b/tests/data/test715
new file mode 100755 (executable)
index 0000000..ffcfc7e
--- /dev/null
@@ -0,0 +1,66 @@
+<testcase>
+#based off test 712
+<info>
+<keywords>
+FTP
+PASV
+RETR
+HTTP
+HTTP CONNECT
+proxytunnel
+SOCKS5
+CURLOPT_CONNECT_TO
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 200 Connection established
+
+</connect>
+
+<data nocheck="yes">
+silly content
+</data>
+
+<datacheck>
+HTTP/1.1 200 Connection established
+
+HTTP/1.1 200 Connection established
+
+silly content
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+http-proxy
+socks5
+</server>
+ <name>
+FTP fetch with --preproxy, --proxy and --connect-to
+ </name>
+ <command>
+ftp://ftp.example.com.715/715 --connect-to ::connect.example.com.715:%FTPPORT --proxytunnel --proxy %HOSTIP:%PROXYPORT --preproxy socks5://%HOSTIP:%SOCKSPORT 
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous\r
+PASS ftp@example.com\r
+PWD\r
+EPSV\r
+TYPE I\r
+SIZE 715\r
+RETR 715\r
+QUIT\r
+</protocol>
+</verify>
+</testcase>