introduced 'tunnel through http proxy' for ftp
This commit is contained in:
Родитель
be8b2a1e30
Коммит
86ff2c46b7
18
lib/ftp.c
18
lib/ftp.c
|
@ -372,6 +372,7 @@ CURLcode ftp_connect(struct connectdata *conn)
|
||||||
struct UrlData *data=conn->data;
|
struct UrlData *data=conn->data;
|
||||||
char *buf = data->buffer; /* this is our buffer */
|
char *buf = data->buffer; /* this is our buffer */
|
||||||
struct FTP *ftp;
|
struct FTP *ftp;
|
||||||
|
CURLcode result;
|
||||||
|
|
||||||
myalarm(0); /* switch off the alarm stuff */
|
myalarm(0); /* switch off the alarm stuff */
|
||||||
|
|
||||||
|
@ -387,6 +388,13 @@ CURLcode ftp_connect(struct connectdata *conn)
|
||||||
ftp->user = data->user;
|
ftp->user = data->user;
|
||||||
ftp->passwd = data->passwd;
|
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: */
|
/* The first thing we do is wait for the "220*" line: */
|
||||||
nread = GetLastResponse(data->firstsocket, buf, conn);
|
nread = GetLastResponse(data->firstsocket, buf, conn);
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
|
@ -860,11 +868,17 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
}
|
}
|
||||||
return CURLE_FTP_CANT_RECONNECT;
|
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 */
|
/* we have the (new) data connection ready */
|
||||||
infof(data, "Connected!\n");
|
infof(data, "Connected the data stream!\n");
|
||||||
|
|
||||||
if(data->bits.upload) {
|
if(data->bits.upload) {
|
||||||
|
|
||||||
|
|
114
lib/http.c
114
lib/http.c
|
@ -134,9 +134,57 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
|
||||||
return FALSE;
|
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)
|
CURLcode http_connect(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
struct UrlData *data;
|
struct UrlData *data;
|
||||||
|
CURLcode result;
|
||||||
|
|
||||||
data=conn->data;
|
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
|
* us to the host we want to talk to. Only after the connect
|
||||||
* has occured, can we start talking SSL
|
* has occured, can we start talking SSL
|
||||||
*/
|
*/
|
||||||
if (conn->protocol & PROT_HTTPS) {
|
if (conn->protocol & PROT_HTTPS) {
|
||||||
if (data->bits.httpproxy) {
|
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 */
|
/* now, perform the SSL initialization for this socket */
|
||||||
sendf(data->firstsocket, data,
|
if(UrgSSLConnect (data)) {
|
||||||
"CONNECT %s:%d HTTP/1.0\015\012"
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
"%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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
|
if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
|
||||||
/* Authorization: is requested, this is not a followed location, get the
|
/* Authorization: is requested, this is not a followed location, get the
|
||||||
original host name */
|
original host name */
|
||||||
data->auth_host = strdup(data->hostname);
|
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
|
/* called from curl_close() when this struct is about to get wasted, free
|
||||||
|
|
|
@ -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(struct connectdata *conn);
|
||||||
CURLcode http_done(struct connectdata *conn);
|
CURLcode http_done(struct connectdata *conn);
|
||||||
CURLcode http_connect(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->proxy = va_arg(param, char *);
|
||||||
data->bits.httpproxy = data->proxy?1:0;
|
data->bits.httpproxy = data->proxy?1:0;
|
||||||
break;
|
break;
|
||||||
|
case CURLOPT_HTTPPROXYTUNNEL:
|
||||||
|
data->bits.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
|
||||||
|
break;
|
||||||
case CURLOPT_PROXYPORT:
|
case CURLOPT_PROXYPORT:
|
||||||
data->proxyport = va_arg(param, long);
|
data->proxyport = va_arg(param, long);
|
||||||
break;
|
break;
|
||||||
|
@ -619,6 +622,7 @@ CURLcode curl_disconnect(CURLconnect *c_connect)
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME curl_connect()
|
* NAME curl_connect()
|
||||||
*
|
*
|
||||||
|
@ -948,7 +952,10 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
|
||||||
data->remote_port = PORT_FTP;
|
data->remote_port = PORT_FTP;
|
||||||
conn->protocol |= PROT_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_do = http;
|
||||||
conn->curl_done = http_done;
|
conn->curl_done = http_done;
|
||||||
conn->curl_close = http_close;
|
conn->curl_close = http_close;
|
||||||
|
|
|
@ -245,6 +245,7 @@ struct FTP {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Configbits {
|
struct Configbits {
|
||||||
|
bool tunnel_thru_httpproxy;
|
||||||
bool ftp_append;
|
bool ftp_append;
|
||||||
bool ftp_ascii;
|
bool ftp_ascii;
|
||||||
bool ftp_list_only;
|
bool ftp_list_only;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче