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