]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
introduced 'tunnel through http proxy' for ftp
authorDaniel Stenberg <daniel@haxx.se>
Thu, 14 Sep 2000 14:05:01 +0000 (14:05 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 14 Sep 2000 14:05:01 +0000 (14:05 +0000)
lib/ftp.c
lib/http.c
lib/http.h
lib/url.c
lib/urldata.h

index 71262012b19556785354e90803080e89b360aa2a..3d98efa587f1fa127e11f940ef8981817a68ba87 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -372,6 +372,7 @@ CURLcode ftp_connect(struct connectdata *conn)
   struct UrlData *data=conn->data;
   char *buf = data->buffer; /* this is our buffer */
   struct FTP *ftp;
+  CURLcode result;
 
   myalarm(0); /* switch off the alarm stuff */
 
@@ -387,6 +388,13 @@ CURLcode ftp_connect(struct connectdata *conn)
   ftp->user = data->user;
   ftp->passwd = data->passwd;
 
+  if (data->bits.tunnel_thru_httpproxy) {
+    /* We want "seamless" FTP operations through HTTP proxy tunnel */
+    result = GetHTTPProxyTunnel(data, data->firstsocket);
+    if(CURLE_OK != result)
+      return result;
+  }
+
   /* The first thing we do is wait for the "220*" line: */
   nread = GetLastResponse(data->firstsocket, buf, conn);
   if(nread < 0)
@@ -860,11 +868,17 @@ CURLcode _ftp(struct connectdata *conn)
         }
         return CURLE_FTP_CANT_RECONNECT;
       }
-    }
 
+      if (data->bits.tunnel_thru_httpproxy) {
+        /* We want "seamless" FTP operations through HTTP proxy tunnel */
+        result = GetHTTPProxyTunnel(data, data->secondarysocket);
+        if(CURLE_OK != result)
+          return result;
+      }
+    }
   }
   /* we have the (new) data connection ready */
-  infof(data, "Connected!\n");
+  infof(data, "Connected the data stream!\n");
 
   if(data->bits.upload) {
 
index 1ee8b45196359e550aaa8ee608a40cfb75130f0f..7d3507ce4d20ee20afb970486366f069aead8488 100644 (file)
@@ -134,9 +134,57 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
   return FALSE;
 }
 
+/*
+ * GetHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This
+ * function will issue the necessary commands to get a seamless tunnel through
+ * this proxy. After that, the socket can be used just as a normal socket.
+ */
+
+CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket)
+{
+  int httperror=0;
+  int subversion=0;
+
+  infof(data, "Establish HTTP proxy tunnel\n");
+
+  /* OK, now send the connect statment */
+  sendf(tunnelsocket, data,
+        "CONNECT %s:%d HTTP/1.0\015\012"
+        "%s"
+        "%s"
+        "\r\n",
+        data->hostname, data->remote_port,
+        (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
+        (data->useragent?data->ptr_uagent:"")
+        );
+
+  /* wait for the proxy to send us a HTTP/1.0 200 OK header */
+  while(GetLine(tunnelsocket, data->buffer, data)) {
+    if('\r' == data->buffer[0])
+      break; /* end of headers */
+    if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
+                   &subversion,
+                   &httperror)) {
+      ;
+    }
+  }
+  if(200 != httperror) {
+    if(407 == httperror)
+      /* Added Nov 6 1998 */
+      failf(data, "Proxy requires authorization!");
+    else 
+      failf(data, "Received error code %d from proxy", httperror);
+    return CURLE_READ_ERROR;
+  }
+
+  infof (data, "Proxy replied to CONNECT request\n");
+  return CURLE_OK;
+}
+
 CURLcode http_connect(struct connectdata *conn)
 {
   struct UrlData *data;
+  CURLcode result;
 
   data=conn->data;
 
@@ -146,59 +194,27 @@ CURLcode http_connect(struct connectdata *conn)
    * us to the host we want to talk to.  Only after the connect
    * has occured, can we start talking SSL
    */
-   if (conn->protocol & PROT_HTTPS) {
-     if (data->bits.httpproxy) {
+  if (conn->protocol & PROT_HTTPS) {
+    if (data->bits.httpproxy) {
+      /* HTTPS through a proxy can only be done with a tunnel */
+      result = GetHTTPProxyTunnel(data, data->firstsocket);
+      if(CURLE_OK != result)
+        return result;
+    }
 
-        /* OK, now send the connect statment */
-        sendf(data->firstsocket, data,
-              "CONNECT %s:%d HTTP/1.0\015\012"
-              "%s"
-             "%s"
-              "\r\n",
-              data->hostname, data->remote_port,
-              (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
-             (data->useragent?data->ptr_uagent:"")
-              );
-
-        /* wait for the proxy to send us a HTTP/1.0 200 OK header */
-       /* Daniel rewrote this part Nov 5 1998 to make it more obvious */
-       {
-         int httperror=0;
-         int subversion=0;
-         while(GetLine(data->firstsocket, data->buffer, data)) {
-           if('\r' == data->buffer[0])
-             break; /* end of headers */
-           if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
-                          &subversion,
-                          &httperror)) {
-             ;
-           }
-         }
-         if(200 != httperror) {
-           if(407 == httperror)
-             /* Added Nov 6 1998 */
-             failf(data, "Proxy requires authorization!");
-           else 
-             failf(data, "Received error code %d from proxy", httperror);
-           return CURLE_READ_ERROR;
-         }
-       }
-        infof (data, "Proxy has replied to CONNECT request\n");
-     }
-
-      /* now, perform the SSL initialization for this socket */
-     if(UrgSSLConnect (data)) {
-       return CURLE_SSL_CONNECT_ERROR;
-     }
+    /* now, perform the SSL initialization for this socket */
+    if(UrgSSLConnect (data)) {
+      return CURLE_SSL_CONNECT_ERROR;
+    }
   }
 
-   if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
-     /* Authorization: is requested, this is not a followed location, get the
-        original host name */
-     data->auth_host = strdup(data->hostname);
-   }
+  if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
+    /* Authorization: is requested, this is not a followed location, get the
+       original host name */
+    data->auth_host = strdup(data->hostname);
+  }
 
-   return CURLE_OK;
+  return CURLE_OK;
 }
 
 /* called from curl_close() when this struct is about to get wasted, free
index 0fb98e1081b33a74d6d99ad6aa0e70ab620c4342..4653f6e14d65bfd06395c25ea57123b3c4090315 100644 (file)
  * ------------------------------------------------------------
  ****************************************************************************/
 
-/* protocol-specific functions set up to be called by the main engine */
+/* ftp can use this as well */
+CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket);
 
+/* protocol-specific functions set up to be called by the main engine */
 CURLcode http(struct connectdata *conn);
 CURLcode http_done(struct connectdata *conn);
 CURLcode http_connect(struct connectdata *conn);
index 4b67717a95a721558c448fb58482adce2254744a..0f2dbfb0a59d0bf27a6f5c95fa84f9430273540a 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -437,6 +437,9 @@ CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
     data->proxy = va_arg(param, char *);
     data->bits.httpproxy = data->proxy?1:0;
     break;
+  case CURLOPT_HTTPPROXYTUNNEL:
+    data->bits.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
+    break;
   case CURLOPT_PROXYPORT:
     data->proxyport = va_arg(param, long);
     break;
@@ -619,6 +622,7 @@ CURLcode curl_disconnect(CURLconnect *c_connect)
   return CURLE_OK;
 }
 
+
 /*
  * NAME curl_connect()
  *
@@ -948,7 +952,10 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
     data->remote_port = PORT_FTP;
     conn->protocol |= PROT_FTP;
 
-    if(data->bits.httpproxy) {
+    if(data->bits.httpproxy &&
+       !data->bits.tunnel_thru_httpproxy) {
+      /* Unless we have asked to tunnel ftp operations through the proxy, we
+         switch and use HTTP operations only */
       conn->curl_do = http;
       conn->curl_done = http_done;
       conn->curl_close = http_close;
index 226237db228eca1297fce058b47249a0dd531ef3..8b28632f91f8bc34fb4fb73c348c854536a4a586 100644 (file)
@@ -245,6 +245,7 @@ struct FTP {
 };
 
 struct Configbits {
+  bool tunnel_thru_httpproxy;
   bool ftp_append;
   bool ftp_ascii;
   bool ftp_list_only;