diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ftp.c | 18 | ||||
-rw-r--r-- | lib/http.c | 114 | ||||
-rw-r--r-- | lib/http.h | 4 | ||||
-rw-r--r-- | lib/url.c | 9 | ||||
-rw-r--r-- | lib/urldata.h | 1 |
5 files changed, 93 insertions, 53 deletions
@@ -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); @@ -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; |