Blame SOURCES/0049-curl-7.29.0-8fa54098.patch

c260e0
From bf2eb071494dd48bf1730ce2bc7d21a8fd13b5c8 Mon Sep 17 00:00:00 2001
c260e0
From: Daniel Stenberg <daniel@haxx.se>
c260e0
Date: Sat, 26 Oct 2013 20:19:27 +0200
c260e0
Subject: [PATCH 1/7] FTP: make the data connection work when going through
c260e0
 proxy
c260e0
c260e0
This is a regression since the switch to always-multi internally
c260e0
c43127414d89c.
c260e0
c260e0
Upstream-commit: d44b0142714041b784ffd10792318674ecb1ed56
c260e0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
c260e0
---
c260e0
 lib/connect.c |   2 +-
c260e0
 lib/ftp.c     | 183 +++++++++++++++++++++++++++++++---------------------------
c260e0
 lib/ftp.h     |   6 ++
c260e0
 lib/socks.c   |   4 ++
c260e0
 lib/url.c     |   9 ++-
c260e0
 lib/url.h     |   2 +-
c260e0
 6 files changed, 117 insertions(+), 89 deletions(-)
c260e0
c260e0
diff --git a/lib/connect.c b/lib/connect.c
c260e0
index 5aa53fe..78627e6 100644
c260e0
--- a/lib/connect.c
c260e0
+++ b/lib/connect.c
c260e0
@@ -715,7 +715,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
c260e0
       /* we are connected with TCP, awesome! */
c260e0
 
c260e0
       /* see if we need to do any proxy magic first once we connected */
c260e0
-      code = Curl_connected_proxy(conn);
c260e0
+      code = Curl_connected_proxy(conn, sockindex);
c260e0
       if(code)
c260e0
         return code;
c260e0
 
c260e0
diff --git a/lib/ftp.c b/lib/ftp.c
c260e0
index 63d1e64..b9fa12e 100644
c260e0
--- a/lib/ftp.c
c260e0
+++ b/lib/ftp.c
c260e0
@@ -1800,6 +1800,79 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
c260e0
   return result;
c260e0
 }
c260e0
 
c260e0
+/*
c260e0
+ * Perform the necessary magic that needs to be done once the TCP connection
c260e0
+ * to the proxy has completed.
c260e0
+ */
c260e0
+static CURLcode proxy_magic(struct connectdata *conn,
c260e0
+                            char *newhost, unsigned short newport,
c260e0
+                            bool *magicdone)
c260e0
+{
c260e0
+  struct SessionHandle *data=conn->data;
c260e0
+  CURLcode result;
c260e0
+
c260e0
+  *magicdone = FALSE;
c260e0
+  switch(conn->proxytype) {
c260e0
+  case CURLPROXY_SOCKS5:
c260e0
+  case CURLPROXY_SOCKS5_HOSTNAME:
c260e0
+    result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
c260e0
+                         newport, SECONDARYSOCKET, conn);
c260e0
+    *magicdone = TRUE;
c260e0
+    break;
c260e0
+  case CURLPROXY_SOCKS4:
c260e0
+    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
c260e0
+                         SECONDARYSOCKET, conn, FALSE);
c260e0
+    *magicdone = TRUE;
c260e0
+    break;
c260e0
+  case CURLPROXY_SOCKS4A:
c260e0
+    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
c260e0
+                         SECONDARYSOCKET, conn, TRUE);
c260e0
+    *magicdone = TRUE;
c260e0
+    break;
c260e0
+  case CURLPROXY_HTTP:
c260e0
+  case CURLPROXY_HTTP_1_0:
c260e0
+    /* do nothing here. handled later. */
c260e0
+    break;
c260e0
+  default:
c260e0
+    failf(data, "unknown proxytype option given");
c260e0
+    result = CURLE_COULDNT_CONNECT;
c260e0
+    break;
c260e0
+  }
c260e0
+
c260e0
+  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
c260e0
+    /* BLOCKING */
c260e0
+    /* We want "seamless" FTP operations through HTTP proxy tunnel */
c260e0
+
c260e0
+    /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
c260e0
+     * member conn->proto.http; we want FTP through HTTP and we have to
c260e0
+     * change the member temporarily for connecting to the HTTP proxy. After
c260e0
+     * Curl_proxyCONNECT we have to set back the member to the original
c260e0
+     * struct FTP pointer
c260e0
+     */
c260e0
+    struct HTTP http_proxy;
c260e0
+    struct FTP *ftp_save = data->state.proto.ftp;
c260e0
+    memset(&http_proxy, 0, sizeof(http_proxy));
c260e0
+    data->state.proto.http = &http_proxy;
c260e0
+
c260e0
+    result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
c260e0
+
c260e0
+    data->state.proto.ftp = ftp_save;
c260e0
+
c260e0
+    if(result)
c260e0
+      return result;
c260e0
+
c260e0
+    if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
c260e0
+      /* the CONNECT procedure is not complete, the tunnel is not yet up */
c260e0
+      state(conn, FTP_STOP); /* this phase is completed */
c260e0
+      conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
c260e0
+      return result;
c260e0
+    }
c260e0
+    else
c260e0
+      *magicdone = TRUE;
c260e0
+  }
c260e0
+  return result;
c260e0
+}
c260e0
+
c260e0
 static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
                                     int ftpcode)
c260e0
 {
c260e0
@@ -1810,13 +1883,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
   struct Curl_dns_entry *addr=NULL;
c260e0
   int rc;
c260e0
   unsigned short connectport; /* the local port connect() should use! */
c260e0
-  unsigned short newport=0; /* remote port */
c260e0
   bool connected;
c260e0
-
c260e0
-  /* newhost must be able to hold a full IP-style address in ASCII, which
c260e0
-     in the IPv6 case means 5*8-1 = 39 letters */
c260e0
-#define NEWHOST_BUFSIZE 48
c260e0
-  char newhost[NEWHOST_BUFSIZE];
c260e0
   char *str=&data->state.buffer[4];  /* start on the first letter */
c260e0
 
c260e0
   if((ftpc->count1 == 0) &&
c260e0
@@ -1849,7 +1916,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
           return CURLE_FTP_WEIRD_PASV_REPLY;
c260e0
         }
c260e0
         if(ptr) {
c260e0
-          newport = (unsigned short)(num & 0xffff);
c260e0
+          ftpc->newport = (unsigned short)(num & 0xffff);
c260e0
 
c260e0
           if(conn->bits.tunnel_proxy ||
c260e0
              conn->proxytype == CURLPROXY_SOCKS5 ||
c260e0
@@ -1858,10 +1925,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
              conn->proxytype == CURLPROXY_SOCKS4A)
c260e0
             /* proxy tunnel -> use other host info because ip_addr_str is the
c260e0
                proxy address not the ftp host */
c260e0
-            snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
c260e0
+            snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
c260e0
+                     conn->host.name);
c260e0
           else
c260e0
             /* use the same IP we are already connected to */
c260e0
-            snprintf(newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str);
c260e0
+            snprintf(ftpc->newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str);
c260e0
         }
c260e0
       }
c260e0
       else
c260e0
@@ -1914,14 +1982,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
          conn->proxytype == CURLPROXY_SOCKS4A)
c260e0
         /* proxy tunnel -> use other host info because ip_addr_str is the
c260e0
            proxy address not the ftp host */
c260e0
-        snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
c260e0
+        snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", conn->host.name);
c260e0
       else
c260e0
-        snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str);
c260e0
+        snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
c260e0
+                 conn->ip_addr_str);
c260e0
     }
c260e0
     else
c260e0
-      snprintf(newhost, sizeof(newhost),
c260e0
+      snprintf(ftpc->newhost, sizeof(ftpc->newhost),
c260e0
                "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
c260e0
-    newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
c260e0
+    ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
c260e0
   }
c260e0
   else if(ftpc->count1 == 0) {
c260e0
     /* EPSV failed, move on to PASV */
c260e0
@@ -1957,15 +2026,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
   }
c260e0
   else {
c260e0
     /* normal, direct, ftp connection */
c260e0
-    rc = Curl_resolv(conn, newhost, newport, &addr);
c260e0
+    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
c260e0
     if(rc == CURLRESOLV_PENDING)
c260e0
       /* BLOCKING */
c260e0
       (void)Curl_resolver_wait_resolv(conn, &addr);
c260e0
 
c260e0
-    connectport = newport; /* we connect to the remote port */
c260e0
+    connectport = ftpc->newport; /* we connect to the remote port */
c260e0
 
c260e0
     if(!addr) {
c260e0
-      failf(data, "Can't resolve new host %s:%hu", newhost, connectport);
c260e0
+      failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
c260e0
       return CURLE_FTP_CANT_GET_HOST;
c260e0
     }
c260e0
   }
c260e0
@@ -1990,80 +2059,20 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
c260e0
   /*
c260e0
    * When this is used from the multi interface, this might've returned with
c260e0
    * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
c260e0
-   * connect to connect and we should not be "hanging" here waiting.
c260e0
+   * connect to connect.
c260e0
    */
c260e0
 
c260e0
   if(data->set.verbose)
c260e0
     /* this just dumps information about this second connection */
c260e0
-    ftp_pasv_verbose(conn, conninfo, newhost, connectport);
c260e0
-
c260e0
-  switch(conn->proxytype) {
c260e0
-    /* FIX: this MUST wait for a proper connect first if 'connected' is
c260e0
-     * FALSE */
c260e0
-  case CURLPROXY_SOCKS5:
c260e0
-  case CURLPROXY_SOCKS5_HOSTNAME:
c260e0
-    result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport,
c260e0
-                         SECONDARYSOCKET, conn);
c260e0
-    connected = TRUE;
c260e0
-    break;
c260e0
-  case CURLPROXY_SOCKS4:
c260e0
-    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
c260e0
-                         SECONDARYSOCKET, conn, FALSE);
c260e0
-    connected = TRUE;
c260e0
-    break;
c260e0
-  case CURLPROXY_SOCKS4A:
c260e0
-    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
c260e0
-                         SECONDARYSOCKET, conn, TRUE);
c260e0
-    connected = TRUE;
c260e0
-    break;
c260e0
-  case CURLPROXY_HTTP:
c260e0
-  case CURLPROXY_HTTP_1_0:
c260e0
-    /* do nothing here. handled later. */
c260e0
-    break;
c260e0
-  default:
c260e0
-    failf(data, "unknown proxytype option given");
c260e0
-    result = CURLE_COULDNT_CONNECT;
c260e0
-    break;
c260e0
-  }
c260e0
-
c260e0
-  if(result) {
c260e0
-    if(ftpc->count1 == 0 && ftpcode == 229)
c260e0
-      return ftp_epsv_disable(conn);
c260e0
-    return result;
c260e0
-  }
c260e0
-
c260e0
-  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
c260e0
-    /* FIX: this MUST wait for a proper connect first if 'connected' is
c260e0
-     * FALSE */
c260e0
-
c260e0
-    /* BLOCKING */
c260e0
-    /* We want "seamless" FTP operations through HTTP proxy tunnel */
c260e0
-
c260e0
-    /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member
c260e0
-     * conn->proto.http; we want FTP through HTTP and we have to change the
c260e0
-     * member temporarily for connecting to the HTTP proxy. After
c260e0
-     * Curl_proxyCONNECT we have to set back the member to the original struct
c260e0
-     * FTP pointer
c260e0
-     */
c260e0
-    struct HTTP http_proxy;
c260e0
-    struct FTP *ftp_save = data->state.proto.ftp;
c260e0
-    memset(&http_proxy, 0, sizeof(http_proxy));
c260e0
-    data->state.proto.http = &http_proxy;
c260e0
-
c260e0
-    result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
c260e0
+    ftp_pasv_verbose(conn, conninfo, ftpc->newhost, connectport);
c260e0
 
c260e0
-    data->state.proto.ftp = ftp_save;
c260e0
-
c260e0
-    if(result)
c260e0
-      return result;
c260e0
-
c260e0
-    if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
c260e0
-      /* the CONNECT procedure is not complete, the tunnel is not yet up */
c260e0
-      state(conn, FTP_STOP); /* this phase is completed */
c260e0
-      conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
c260e0
-
c260e0
-      return result;
c260e0
-    }
c260e0
+  if(connected) {
c260e0
+    /* Only do the proxy connection magic if we're actually connected.  We do
c260e0
+       this little trick and send in the same 'connected' variable here again
c260e0
+       and it will be set FALSE by proxy_magic() for when for example the
c260e0
+       CONNECT procedure doesn't complete */
c260e0
+    infof(data, "Connection to proxy confirmed almost instantly\n");
c260e0
+    result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
c260e0
   }
c260e0
 
c260e0
   conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
c260e0
@@ -3686,6 +3695,10 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
c260e0
     /* Ready to do more? */
c260e0
     if(connected) {
c260e0
       DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
c260e0
+      if(conn->bits.proxy) {
c260e0
+        infof(data, "Connection to proxy confirmed\n");
c260e0
+        result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
c260e0
+      }
c260e0
     }
c260e0
     else {
c260e0
       if(result && (ftpc->count1 == 0)) {
c260e0
diff --git a/lib/ftp.h b/lib/ftp.h
c260e0
index d359f28..4b4a488 100644
c260e0
--- a/lib/ftp.h
c260e0
+++ b/lib/ftp.h
c260e0
@@ -154,6 +154,12 @@ struct ftp_conn {
c260e0
   curl_off_t known_filesize; /* file size is different from -1, if wildcard
c260e0
                                 LIST parsing was done and wc_statemach set
c260e0
                                 it */
c260e0
+  /* newhost must be able to hold a full IP-style address in ASCII, which
c260e0
+     in the IPv6 case means 5*8-1 = 39 letters */
c260e0
+#define NEWHOST_BUFSIZE 48
c260e0
+  char newhost[NEWHOST_BUFSIZE]; /* this is the pair to connect the DATA... */
c260e0
+  unsigned short newport;        /* connection to */
c260e0
+
c260e0
 };
c260e0
 
c260e0
 #define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */
c260e0
diff --git a/lib/socks.c b/lib/socks.c
c260e0
index 51bb946..0cf397c 100644
c260e0
--- a/lib/socks.c
c260e0
+++ b/lib/socks.c
c260e0
@@ -129,6 +129,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
c260e0
 
c260e0
   curlx_nonblock(sock, FALSE);
c260e0
 
c260e0
+  infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
c260e0
+
c260e0
   /*
c260e0
    * Compose socks4 request
c260e0
    *
c260e0
@@ -182,6 +184,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
c260e0
       else
c260e0
         hp = NULL; /* fail! */
c260e0
 
c260e0
+      infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
c260e0
+
c260e0
       Curl_resolv_unlock(data, dns); /* not used anymore from now on */
c260e0
 
c260e0
     }
c260e0
diff --git a/lib/url.c b/lib/url.c
c260e0
index cfc2744..11e0ff5 100644
c260e0
--- a/lib/url.c
c260e0
+++ b/lib/url.c
c260e0
@@ -3103,8 +3103,13 @@ static CURLcode ConnectionStore(struct SessionHandle *data,
c260e0
    Note: this function's sub-functions call failf()
c260e0
 
c260e0
 */
c260e0
-CURLcode Curl_connected_proxy(struct connectdata *conn)
c260e0
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
c260e0
 {
c260e0
+  if(!conn->bits.proxy || sockindex)
c260e0
+    /* this magic only works for the primary socket as the secondary is used
c260e0
+       for FTP only and it has FTP specific magic in ftp.c */
c260e0
+    return CURLE_OK;
c260e0
+
c260e0
   switch(conn->proxytype) {
c260e0
 #ifndef CURL_DISABLE_PROXY
c260e0
   case CURLPROXY_SOCKS5:
c260e0
@@ -3162,7 +3167,7 @@ static CURLcode ConnectPlease(struct SessionHandle *data,
c260e0
     conn->ip_addr = addr;
c260e0
 
c260e0
     if(*connected) {
c260e0
-      result = Curl_connected_proxy(conn);
c260e0
+      result = Curl_connected_proxy(conn, FIRSTSOCKET);
c260e0
       if(!result) {
c260e0
         conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
c260e0
         Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
c260e0
diff --git a/lib/url.h b/lib/url.h
c260e0
index c0d9c38..1da9be3 100644
c260e0
--- a/lib/url.h
c260e0
+++ b/lib/url.h
c260e0
@@ -74,7 +74,7 @@ void Curl_reset_reqproto(struct connectdata *conn);
c260e0
 #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
c260e0
                                                      service */
c260e0
 
c260e0
-CURLcode Curl_connected_proxy(struct connectdata *conn);
c260e0
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
c260e0
 
c260e0
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
c260e0
 #define Curl_verboseconnect(x)  Curl_nop_stmt
c260e0
-- 
c260e0
2.9.3
c260e0
c260e0
c260e0
From 4157798db51c859a1130203cebf377e77f56398a Mon Sep 17 00:00:00 2001
c260e0
From: Steve Holme <steve_holme@hotmail.com>
c260e0
Date: Sun, 27 Oct 2013 00:00:01 +0100
c260e0
Subject: [PATCH 2/7] ftp: Fixed compiler warning
c260e0
c260e0
warning: 'result' may be used uninitialized in this function
c260e0
c260e0
Upstream-commit: 9f503a254b0c720706124cb75922a0123f0079f0
c260e0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
c260e0
---
c260e0
 lib/ftp.c | 2 +-
c260e0
 1 file changed, 1 insertion(+), 1 deletion(-)
c260e0
c260e0
diff --git a/lib/ftp.c b/lib/ftp.c
c260e0
index b9fa12e..9c863b9 100644
c260e0
--- a/lib/ftp.c
c260e0
+++ b/lib/ftp.c
c260e0
@@ -1808,8 +1808,8 @@ static CURLcode proxy_magic(struct connectdata *conn,
c260e0
                             char *newhost, unsigned short newport,
c260e0
                             bool *magicdone)
c260e0
 {
c260e0
+  CURLcode result = CURLE_OK;
c260e0
   struct SessionHandle *data=conn->data;
c260e0
-  CURLcode result;
c260e0
 
c260e0
   *magicdone = FALSE;
c260e0
   switch(conn->proxytype) {
c260e0
-- 
c260e0
2.9.3
c260e0
c260e0
c260e0
From 30566b76d17d9c5e13e3af621ecae0f4cafc3ac8 Mon Sep 17 00:00:00 2001
c260e0
From: Daniel Stenberg <daniel@haxx.se>
c260e0
Date: Sat, 19 Jul 2014 23:58:58 +0200
c260e0
Subject: [PATCH 3/7] CONNECT: Revert Curl_proxyCONNECT back to 7.29.0 design
c260e0
c260e0
This reverts commit cb3e6dfa3511 and instead fixes the problem
c260e0
differently.
c260e0
c260e0
The reverted commit addressed a test failure in test 1021 by simplifying
c260e0
and generalizing the code flow in a way that damaged the
c260e0
performance. Now we modify the flow so that Curl_proxyCONNECT() again
c260e0
does as much as possible in one go, yet still do test 1021 with and
c260e0
without valgrind. It failed due to mistakes in the multi state machine.
c260e0
c260e0
Bug: http://curl.haxx.se/bug/view.cgi?id=1397
c260e0
Reported-by: Paul Saab
c260e0
c260e0
Upstream-commit: a4cece3d47cf092da00cf9910e87bb60b9eff533
c260e0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
c260e0
---
c260e0
 lib/http_proxy.c | 47 ++++++++++++++++++++++++++++++-----------------
c260e0
 lib/multi.c      | 16 ++++++++++------
c260e0
 2 files changed, 40 insertions(+), 23 deletions(-)
c260e0
c260e0
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
c260e0
index c2eb667..d311b89 100644
c260e0
--- a/lib/http_proxy.c
c260e0
+++ b/lib/http_proxy.c
c260e0
@@ -98,8 +98,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
   struct SessionHandle *data=conn->data;
c260e0
   struct SingleRequest *k = &data->req;
c260e0
   CURLcode result;
c260e0
-  long timeout =
c260e0
-    data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
c260e0
   curl_socket_t tunnelsocket = conn->sock[sockindex];
c260e0
   curl_off_t cl=0;
c260e0
   bool closeConnection = FALSE;
c260e0
@@ -223,14 +221,25 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
         return result;
c260e0
 
c260e0
       conn->tunnel_state[sockindex] = TUNNEL_CONNECT;
c260e0
+    } /* END CONNECT PHASE */
c260e0
+
c260e0
+    check = Curl_timeleft(data, NULL, TRUE);
c260e0
+    if(check <= 0) {
c260e0
+      failf(data, "Proxy CONNECT aborted due to timeout");
c260e0
+      return CURLE_RECV_ERROR;
c260e0
+    }
c260e0
 
c260e0
-      /* now we've issued the CONNECT and we're waiting to hear back, return
c260e0
-         and get called again polling-style */
c260e0
+    if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
c260e0
+      /* return so we'll be called again polling-style */
c260e0
       return CURLE_OK;
c260e0
+    else {
c260e0
+      DEBUGF(infof(data,
c260e0
+                   "Read response immediately from proxy CONNECT\n"));
c260e0
+    }
c260e0
 
c260e0
-    } /* END CONNECT PHASE */
c260e0
+    /* at this point, the tunnel_connecting phase is over. */
c260e0
 
c260e0
-    { /* BEGIN NEGOTIATION PHASE */
c260e0
+    { /* READING RESPONSE PHASE */
c260e0
       size_t nread;   /* total size read */
c260e0
       int perline; /* count bytes per line */
c260e0
       int keepon=TRUE;
c260e0
@@ -247,9 +256,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
 
c260e0
       while((nread
c260e0
 
c260e0
-        /* if timeout is requested, find out how much remaining time we have */
c260e0
-        check = timeout - /* timeout time */
c260e0
-          Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
c260e0
+        check = Curl_timeleft(data, NULL, TRUE);
c260e0
         if(check <= 0) {
c260e0
           failf(data, "Proxy CONNECT aborted due to timeout");
c260e0
           error = SELECT_TIMEOUT; /* already too little time */
c260e0
@@ -279,6 +286,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
               /* proxy auth was requested and there was proxy auth available,
c260e0
                  then deem this as "mere" proxy disconnect */
c260e0
               conn->bits.proxy_connect_closed = TRUE;
c260e0
+              infof(data, "Proxy CONNECT connection closed");
c260e0
             }
c260e0
             else {
c260e0
               error = SELECT_ERROR;
c260e0
@@ -519,7 +527,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
         conn->sock[sockindex] = CURL_SOCKET_BAD;
c260e0
         break;
c260e0
       }
c260e0
-    } /* END NEGOTIATION PHASE */
c260e0
+    } /* END READING RESPONSE PHASE */
c260e0
 
c260e0
     /* If we are supposed to continue and request a new URL, which basically
c260e0
      * means the HTTP authentication is still going on so if the tunnel
c260e0
@@ -534,13 +542,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
   } while(data->req.newurl);
c260e0
 
c260e0
   if(200 != data->req.httpcode) {
c260e0
-    failf(data, "Received HTTP code %d from proxy after CONNECT",
c260e0
-          data->req.httpcode);
c260e0
-
c260e0
-    if(closeConnection && data->req.newurl)
c260e0
+    if(closeConnection && data->req.newurl) {
c260e0
       conn->bits.proxy_connect_closed = TRUE;
c260e0
-
c260e0
-    if(data->req.newurl) {
c260e0
+      infof(data, "Connect me again please\n");
c260e0
+    }
c260e0
+    else if(data->req.newurl) {
c260e0
       /* this won't be used anymore for the CONNECT so free it now */
c260e0
       free(data->req.newurl);
c260e0
       data->req.newurl = NULL;
c260e0
@@ -549,7 +555,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
     /* to back to init state */
c260e0
     conn->tunnel_state[sockindex] = TUNNEL_INIT;
c260e0
 
c260e0
-    return CURLE_RECV_ERROR;
c260e0
+    if(conn->bits.proxy_connect_closed)
c260e0
+      /* this is not an error, just part of the connection negotiation */
c260e0
+      return CURLE_OK;
c260e0
+    else {
c260e0
+      failf(data, "Received HTTP code %d from proxy after CONNECT",
c260e0
+            data->req.httpcode);
c260e0
+      return CURLE_RECV_ERROR;
c260e0
+    }
c260e0
   }
c260e0
 
c260e0
   conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
c260e0
diff --git a/lib/multi.c b/lib/multi.c
c260e0
index 0e0bb19..3029fa6 100644
c260e0
--- a/lib/multi.c
c260e0
+++ b/lib/multi.c
c260e0
@@ -1134,11 +1134,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
c260e0
       easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
c260e0
 
c260e0
       if(easy->easy_conn->bits.proxy_connect_closed) {
c260e0
-        /* reset the error buffer */
c260e0
-        if(data->set.errorbuffer)
c260e0
-          data->set.errorbuffer[0] = '\0';
c260e0
-        data->state.errorbuf = FALSE;
c260e0
-
c260e0
+        /* connect back to proxy again */
c260e0
         easy->result = CURLE_OK;
c260e0
         result = CURLM_CALL_MULTI_PERFORM;
c260e0
         multistate(easy, CURLM_STATE_CONNECT);
c260e0
@@ -1164,7 +1160,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
c260e0
                                                &protocol_connect);
c260e0
       }
c260e0
 
c260e0
-      if(CURLE_OK != easy->result) {
c260e0
+      if(easy->easy_conn->bits.proxy_connect_closed) {
c260e0
+        /* connect back to proxy again since it was closed in a proxy CONNECT
c260e0
+           setup */
c260e0
+        easy->result = CURLE_OK;
c260e0
+        result = CURLM_CALL_MULTI_PERFORM;
c260e0
+        multistate(easy, CURLM_STATE_CONNECT);
c260e0
+        break;
c260e0
+      }
c260e0
+      else if(CURLE_OK != easy->result) {
c260e0
         /* failure detected */
c260e0
         /* Just break, the cleaning up is handled all in one place */
c260e0
         disconnect_conn = TRUE;
c260e0
-- 
c260e0
2.9.3
c260e0
c260e0
c260e0
From 6ab9346d63e88ddfb8fd3f509ad350cab24c37f4 Mon Sep 17 00:00:00 2001
c260e0
From: Daniel Stenberg <daniel@haxx.se>
c260e0
Date: Wed, 17 Jun 2015 00:30:06 +0200
c260e0
Subject: [PATCH 4/7] FTP: do the HTTP CONNECT for data connection blocking
c260e0
c260e0
** WORK-AROUND **
c260e0
c260e0
The introduced non-blocking general behaviour for Curl_proxyCONNECT()
c260e0
didn't work for the data connection establishment unless it was very
c260e0
fast. The newly introduced function argument makes it operate in a more
c260e0
blocking manner, more like it used to work in the past. This blocking
c260e0
approach is only used when the FTP data connecting through HTTP proxy.
c260e0
c260e0
Blocking like this is bad. A better fix would make it work more
c260e0
asynchronously.
c260e0
c260e0
Bug: https://github.com/bagder/curl/issues/278
c260e0
c260e0
Upstream-commit: b88f980a7437abc1159a1185c04d381347c8f5b1
c260e0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
c260e0
---
c260e0
 lib/ftp.c        |  4 ++--
c260e0
 lib/http_proxy.c | 22 ++++++++++++++--------
c260e0
 lib/http_proxy.h |  3 ++-
c260e0
 3 files changed, 18 insertions(+), 11 deletions(-)
c260e0
c260e0
diff --git a/lib/ftp.c b/lib/ftp.c
c260e0
index 63d1e64..db1e29e 100644
c260e0
--- a/lib/ftp.c
c260e0
+++ b/lib/ftp.c
c260e0
@@ -1854,7 +1854,7 @@ static CURLcode proxy_magic(struct connectdata *conn,
c260e0
     memset(&http_proxy, 0, sizeof(http_proxy));
c260e0
     data->state.proto.http = &http_proxy;
c260e0
 
c260e0
-    result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
c260e0
+    result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
c260e0
 
c260e0
     data->state.proto.ftp = ftp_save;
c260e0
 
c260e0
@@ -3685,7 +3685,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
c260e0
     if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
c260e0
       /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
c260e0
          aren't used so we blank their arguments. TODO: make this nicer */
c260e0
-      result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
c260e0
+      result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
c260e0
 
c260e0
       return result;
c260e0
     }
c260e0
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
c260e0
index d311b89..4ab280f 100644
c260e0
--- a/lib/http_proxy.c
c260e0
+++ b/lib/http_proxy.c
c260e0
@@ -71,7 +71,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
c260e0
     conn->data->state.proto.http = &http_proxy;
c260e0
     conn->bits.close = FALSE;
c260e0
     result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
c260e0
-                               conn->host.name, conn->remote_port);
c260e0
+                               conn->host.name, conn->remote_port, FALSE);
c260e0
     conn->data->state.proto.generic = prot_save;
c260e0
     if(CURLE_OK != result)
c260e0
       return result;
c260e0
@@ -87,12 +87,16 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
c260e0
  * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
c260e0
  * function will issue the necessary commands to get a seamless tunnel through
c260e0
  * this proxy. After that, the socket can be used just as a normal socket.
c260e0
+ *
c260e0
+ * 'blocking' set to TRUE means that this function will do the entire CONNECT
c260e0
+ * + response in a blocking fashion. Should be avoided!
c260e0
  */
c260e0
 
c260e0
 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
                            int sockindex,
c260e0
                            const char *hostname,
c260e0
-                           unsigned short remote_port)
c260e0
+                           unsigned short remote_port,
c260e0
+                           bool blocking)
c260e0
 {
c260e0
   int subversion=0;
c260e0
   struct SessionHandle *data=conn->data;
c260e0
@@ -229,12 +233,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
       return CURLE_RECV_ERROR;
c260e0
     }
c260e0
 
c260e0
-    if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
c260e0
-      /* return so we'll be called again polling-style */
c260e0
-      return CURLE_OK;
c260e0
-    else {
c260e0
-      DEBUGF(infof(data,
c260e0
-                   "Read response immediately from proxy CONNECT\n"));
c260e0
+    if(!blocking) {
c260e0
+      if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
c260e0
+        /* return so we'll be called again polling-style */
c260e0
+        return CURLE_OK;
c260e0
+      else {
c260e0
+        DEBUGF(infof(data,
c260e0
+               "Read response immediately from proxy CONNECT\n"));
c260e0
+      }
c260e0
     }
c260e0
 
c260e0
     /* at this point, the tunnel_connecting phase is over. */
c260e0
diff --git a/lib/http_proxy.h b/lib/http_proxy.h
c260e0
index 518c093..4dddc3b 100644
c260e0
--- a/lib/http_proxy.h
c260e0
+++ b/lib/http_proxy.h
c260e0
@@ -26,7 +26,8 @@
c260e0
 /* ftp can use this as well */
c260e0
 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
c260e0
                            int tunnelsocket,
c260e0
-                           const char *hostname, unsigned short remote_port);
c260e0
+                           const char *hostname, unsigned short remote_port,
c260e0
+                           bool blocking);
c260e0
 
c260e0
 /* Default proxy timeout in milliseconds */
c260e0
 #define PROXY_TIMEOUT (3600*1000)
c260e0
-- 
c260e0
2.9.3
c260e0
c260e0
c260e0
From 7be64d4d3e1b966d491c6cde4fe3b6d69f03185b Mon Sep 17 00:00:00 2001
c260e0
From: Kamil Dudka <kdudka@redhat.com>
c260e0
Date: Thu, 9 Feb 2017 16:21:52 +0100
c260e0
Subject: [PATCH 5/7] nss: make FTPS work with --proxytunnel
c260e0
c260e0
If the NSS code was in the middle of a non-blocking handshake and it
c260e0
was asked to finish the handshake in blocking mode, it unexpectedly
c260e0
continued in the non-blocking mode, which caused a FTPS connection
c260e0
over CONNECT to fail with "(81) Socket not ready for send/recv".
c260e0
c260e0
Bug: https://bugzilla.redhat.com/1420327
c260e0
c260e0
Upstream-commit: 8fa5409800668ad5305e7517597286014c7708fb
c260e0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
c260e0
---
c260e0
 lib/nss.c | 23 +++++++++++------------
c260e0
 1 file changed, 11 insertions(+), 12 deletions(-)
c260e0
c260e0
diff --git a/lib/nss.c b/lib/nss.c
c260e0
index 848ce86..cf45f3a 100644
c260e0
--- a/lib/nss.c
c260e0
+++ b/lib/nss.c
c260e0
@@ -1305,13 +1305,14 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
c260e0
   return curlerr;
c260e0
 }
c260e0
 
c260e0
-/* Switch the SSL socket into non-blocking mode. */
c260e0
-static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
c260e0
-                                 struct SessionHandle *data)
c260e0
+/* Switch the SSL socket into blocking or non-blocking mode. */
c260e0
+static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
c260e0
+                                 struct SessionHandle *data,
c260e0
+                                 bool blocking)
c260e0
 {
c260e0
   static PRSocketOptionData sock_opt;
c260e0
   sock_opt.option = PR_SockOpt_Nonblocking;
c260e0
-  sock_opt.value.non_blocking = PR_TRUE;
c260e0
+  sock_opt.value.non_blocking = !blocking;
c260e0
 
c260e0
   if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
c260e0
     return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
c260e0
@@ -1615,16 +1616,14 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
c260e0
       /* we do not expect CURLE_AGAIN from nss_setup_connect() */
c260e0
       return rv;
c260e0
 
c260e0
-    if(!blocking) {
c260e0
-      /* in non-blocking mode, set NSS non-blocking mode before handshake */
c260e0
-      rv = nss_set_nonblock(connssl, data);
c260e0
-      if(rv)
c260e0
-        return rv;
c260e0
-    }
c260e0
-
c260e0
     connssl->connecting_state = ssl_connect_2;
c260e0
   }
c260e0
 
c260e0
+  /* enable/disable blocking mode before handshake */
c260e0
+  rv = nss_set_blocking(connssl, data, blocking);
c260e0
+  if(rv)
c260e0
+    return rv;
c260e0
+
c260e0
   rv = nss_do_connect(conn, sockindex);
c260e0
   switch(rv) {
c260e0
   case CURLE_OK:
c260e0
@@ -1640,7 +1639,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
c260e0
 
c260e0
   if(blocking) {
c260e0
     /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
c260e0
-    rv = nss_set_nonblock(connssl, data);
c260e0
+    rv = nss_set_blocking(connssl, data, /* blocking */ FALSE);
c260e0
     if(rv)
c260e0
       return rv;
c260e0
   }
c260e0
-- 
c260e0
2.7.4
c260e0
c260e0
c260e0
From 9dbd6550acdc143da0b044ae3b06368a87c8449a Mon Sep 17 00:00:00 2001
c260e0
From: Kamil Dudka <kdudka@redhat.com>
c260e0
Date: Mon, 27 Mar 2017 18:00:44 +0200
c260e0
Subject: [PATCH 6/7] url: plug memory leaks triggered by
c260e0
 curl-7_37_1-19-ga4cece3
c260e0
c260e0
---
c260e0
 lib/url.c | 9 +++++++++
c260e0
 1 file changed, 9 insertions(+)
c260e0
c260e0
diff --git a/lib/url.c b/lib/url.c
c260e0
index cfc2744..ed72be1 100644
c260e0
--- a/lib/url.c
c260e0
+++ b/lib/url.c
c260e0
@@ -421,6 +421,7 @@ CURLcode Curl_close(struct SessionHandle *data)
c260e0
   data->state.path = NULL;
c260e0
 
c260e0
   Curl_safefree(data->state.proto.generic);
c260e0
+  Curl_safefree(data->req.newurl);
c260e0
 
c260e0
   /* Close down all open SSL info and sessions */
c260e0
   Curl_ssl_close_all(data);
c260e0
@@ -3923,6 +3924,14 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
c260e0
   const struct Curl_handler * p;
c260e0
   CURLcode result;
c260e0
 
c260e0
+  /* XXX: picked from curl-7_32_0-2-g4ad8e14 */
c260e0
+  /* in some case in the multi state-machine, we go back to the CONNECT state
c260e0
+     and then a second (or third or...) call to this function will be made
c260e0
+     without doing a DISCONNECT or DONE in between (since the connection is
c260e0
+     yet in place) and therefore this function needs to first make sure
c260e0
+     there's no lingering previous data allocated. */
c260e0
+  Curl_safefree(conn->data->req.newurl);
c260e0
+
c260e0
   conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
c260e0
 
c260e0
   /* Scan protocol handler table. */
c260e0
-- 
c260e0
2.9.3
c260e0
c260e0
c260e0
From cfb58b02f5bb78a2f4b17f3bb6ce6acd196b3ec6 Mon Sep 17 00:00:00 2001
c260e0
From: Kamil Dudka <kdudka@redhat.com>
c260e0
Date: Tue, 28 Mar 2017 15:50:59 +0200
c260e0
Subject: [PATCH 7/7] http: do not treat FTPS over CONNECT as HTTPS
c260e0
c260e0
If we use FTPS over CONNECT, the TLS handshake for the FTPS control
c260e0
connection needs to be initiated in the SENDPROTOCONNECT state, not
c260e0
the WAITPROXYCONNECT state.  Otherwise, if the TLS handshake completed
c260e0
without blocking, the information about the completed TLS handshake
c260e0
would be saved to a wrong flag.  Consequently, the TLS handshake would
c260e0
be initiated in the SENDPROTOCONNECT state once again on the same
c260e0
connection, resulting in a failure of the TLS handshake.  I was able to
c260e0
observe the failure with the NSS backend if curl ran through valgrind.
c260e0
c260e0
Note that this commit partially reverts curl-7_21_6-52-ge34131d.
c260e0
c260e0
Upstream-commit: 2549831daaa3aef394f7b42e750cba1afae35642
c260e0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
c260e0
---
c260e0
 lib/http.c | 2 +-
c260e0
 1 file changed, 1 insertion(+), 1 deletion(-)
c260e0
c260e0
diff --git a/lib/http.c b/lib/http.c
c260e0
index 04beeb1..db37cf9 100644
c260e0
--- a/lib/http.c
c260e0
+++ b/lib/http.c
c260e0
@@ -1310,7 +1310,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
c260e0
     /* nothing else to do except wait right now - we're not done here. */
c260e0
     return CURLE_OK;
c260e0
 
c260e0
-  if(conn->given->flags & PROTOPT_SSL) {
c260e0
+  if(conn->given->protocol & CURLPROTO_HTTPS) {
c260e0
     /* perform SSL initialization */
c260e0
     result = https_connecting(conn, done);
c260e0
     if(result)
c260e0
-- 
c260e0
2.9.3
c260e0