mirror of
https://github.com/moparisthebest/curl
synced 2024-11-11 12:05:06 -05:00
initial code added to support EPSV (IPv6-style PASV)
This commit is contained in:
parent
4382a80b9a
commit
6003f24f78
148
lib/ftp.c
148
lib/ftp.c
@ -1258,6 +1258,23 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
|||||||
char *buf = data->state.buffer; /* this is our buffer */
|
char *buf = data->state.buffer; /* this is our buffer */
|
||||||
int ftpcode; /* receive FTP response codes in this */
|
int ftpcode; /* receive FTP response codes in this */
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
Curl_addrinfo *addr=NULL;
|
||||||
|
Curl_ipconnect *conninfo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here's the excecutive summary on what to do:
|
||||||
|
|
||||||
|
PASV is RFC959, expect:
|
||||||
|
227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
|
||||||
|
|
||||||
|
LPSV is RFC1639, expect:
|
||||||
|
228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
|
||||||
|
(Is this actually supported *anywhere*?)
|
||||||
|
|
||||||
|
EPSV is RFC2428, expect:
|
||||||
|
229 Entering Extended Passive Mode (|||port|)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* no support for IPv6 passive mode yet */
|
/* no support for IPv6 passive mode yet */
|
||||||
@ -1268,6 +1285,13 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
|||||||
int results[] = { 227, 0 };
|
int results[] = { 227, 0 };
|
||||||
#endif
|
#endif
|
||||||
int modeoff;
|
int modeoff;
|
||||||
|
unsigned short connectport; /* the local port connect() should use! */
|
||||||
|
unsigned short newport; /* remote port, not necessary the local one */
|
||||||
|
char *hostdataptr=NULL;
|
||||||
|
|
||||||
|
/* newhost must be able to hold a full IP-style address in ASCII, which
|
||||||
|
in the IPv6 case means 5*8-1 = 39 letters */
|
||||||
|
char newhost[48];
|
||||||
|
|
||||||
for (modeoff = 0; mode[modeoff]; modeoff++) {
|
for (modeoff = 0; mode[modeoff]; modeoff++) {
|
||||||
FTPSENDF(conn, mode[modeoff], "");
|
FTPSENDF(conn, mode[modeoff], "");
|
||||||
@ -1283,16 +1307,9 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
|||||||
failf(data, "Odd return code after PASV");
|
failf(data, "Odd return code after PASV");
|
||||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||||
}
|
}
|
||||||
else if (strcmp(mode[modeoff], "PASV") == 0) {
|
else if (227 == results[modeoff]) {
|
||||||
int ip[4];
|
int ip[4];
|
||||||
int port[2];
|
int port[2];
|
||||||
unsigned short newport; /* remote port, not necessary the local one */
|
|
||||||
unsigned short connectport; /* the local port connect() should use! */
|
|
||||||
char newhost[32];
|
|
||||||
|
|
||||||
Curl_addrinfo *addr;
|
|
||||||
char *hostdataptr=NULL;
|
|
||||||
Curl_ipconnect *conninfo;
|
|
||||||
char *str=buf;
|
char *str=buf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1321,54 +1338,87 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
|||||||
|
|
||||||
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||||
newport = (port[0]<<8) + port[1];
|
newport = (port[0]<<8) + port[1];
|
||||||
if(data->change.proxy) {
|
|
||||||
/*
|
|
||||||
* This is a tunnel through a http proxy and we need to connect to the
|
|
||||||
* proxy again here. We already have the name info for it since the
|
|
||||||
* previous lookup.
|
|
||||||
*/
|
|
||||||
addr = conn->hostaddr;
|
|
||||||
connectport =
|
|
||||||
(unsigned short)conn->port; /* we connect to the proxy's port */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* normal, direct, ftp connection */
|
|
||||||
addr = Curl_getaddrinfo(data, newhost, newport, &hostdataptr);
|
|
||||||
if(!addr) {
|
|
||||||
failf(data, "Can't resolve new host %s", newhost);
|
|
||||||
return CURLE_FTP_CANT_GET_HOST;
|
|
||||||
}
|
|
||||||
connectport = newport; /* we connect to the remote port */
|
|
||||||
}
|
|
||||||
|
|
||||||
result = Curl_connecthost(conn,
|
|
||||||
addr,
|
|
||||||
connectport,
|
|
||||||
&conn->secondarysocket,
|
|
||||||
&conninfo);
|
|
||||||
|
|
||||||
if((CURLE_OK == result) &&
|
|
||||||
data->set.verbose)
|
|
||||||
/* this just dumps information about this second connection */
|
|
||||||
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
|
||||||
|
|
||||||
if(hostdataptr)
|
|
||||||
Curl_freeaddrinfo(hostdataptr);
|
|
||||||
|
|
||||||
if(CURLE_OK != result)
|
/* we should compare to see if this is the same IP like the one
|
||||||
return result;
|
we're already connected to, as then we can skip the name function
|
||||||
|
call below, in similar style that we do for the EPSV reply */
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
else if (strcmp(mode[modeoff], "EPSV") == 0) {
|
||||||
|
char *ptr = strchr(buf, '(');
|
||||||
|
if(ptr) {
|
||||||
|
unsigned int num;
|
||||||
|
char separator[4];
|
||||||
|
ptr++;
|
||||||
|
if(5 == sscanf(ptr, "%c%c%c%u%c",
|
||||||
|
&separator[0],
|
||||||
|
&separator[1],
|
||||||
|
&separator[2],
|
||||||
|
&num,
|
||||||
|
&separator[3])) {
|
||||||
|
/* the four separators should be identical */
|
||||||
|
newport = num;
|
||||||
|
|
||||||
if (data->set.tunnel_thru_httpproxy) {
|
/* we should use the same host we already are connected to */
|
||||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
addr = conn->hostaddr;
|
||||||
result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
|
}
|
||||||
newhost, newport);
|
else
|
||||||
if(CURLE_OK != result)
|
ptr=NULL;
|
||||||
return result;
|
}
|
||||||
|
if(!ptr) {
|
||||||
|
failf(data, "Weirdly formatted EPSV reply");
|
||||||
|
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
return CURLE_FTP_CANT_RECONNECT;
|
return CURLE_FTP_CANT_RECONNECT;
|
||||||
|
|
||||||
|
if(data->change.proxy) {
|
||||||
|
/*
|
||||||
|
* This is a tunnel through a http proxy and we need to connect to the
|
||||||
|
* proxy again here. We already have the name info for it since the
|
||||||
|
* previous lookup.
|
||||||
|
*/
|
||||||
|
addr = conn->hostaddr;
|
||||||
|
connectport =
|
||||||
|
(unsigned short)conn->port; /* we connect to the proxy's port */
|
||||||
|
}
|
||||||
|
else if(!addr) {
|
||||||
|
/* normal, direct, ftp connection */
|
||||||
|
addr = Curl_getaddrinfo(data, newhost, newport, &hostdataptr);
|
||||||
|
if(!addr) {
|
||||||
|
failf(data, "Can't resolve new host %s", newhost);
|
||||||
|
return CURLE_FTP_CANT_GET_HOST;
|
||||||
|
}
|
||||||
|
connectport = newport; /* we connect to the remote port */
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Curl_connecthost(conn,
|
||||||
|
addr,
|
||||||
|
connectport,
|
||||||
|
&conn->secondarysocket,
|
||||||
|
&conninfo);
|
||||||
|
|
||||||
|
if((CURLE_OK == result) &&
|
||||||
|
data->set.verbose)
|
||||||
|
/* this just dumps information about this second connection */
|
||||||
|
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
||||||
|
|
||||||
|
if(hostdataptr)
|
||||||
|
Curl_freeaddrinfo(hostdataptr);
|
||||||
|
|
||||||
|
if(CURLE_OK != result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (data->set.tunnel_thru_httpproxy) {
|
||||||
|
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||||
|
result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
|
||||||
|
newhost, newport);
|
||||||
|
if(CURLE_OK != result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user