aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ftp.c18
-rw-r--r--lib/http.c114
-rw-r--r--lib/http.h4
-rw-r--r--lib/url.c9
-rw-r--r--lib/urldata.h1
5 files changed, 93 insertions, 53 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 71262012b..3d98efa58 100644
--- 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) {
diff --git a/lib/http.c b/lib/http.c
index 1ee8b4519..7d3507ce4 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -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
diff --git a/lib/http.h b/lib/http.h
index 0fb98e108..4653f6e14 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -41,8 +41,10 @@
* ------------------------------------------------------------
****************************************************************************/
-/* 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);
diff --git a/lib/url.c b/lib/url.c
index 4b67717a9..0f2dbfb0a 100644
--- 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;
diff --git a/lib/urldata.h b/lib/urldata.h
index 226237db2..8b28632f9 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -245,6 +245,7 @@ struct FTP {
};
struct Configbits {
+ bool tunnel_thru_httpproxy;
bool ftp_append;
bool ftp_ascii;
bool ftp_list_only;