summaryrefslogtreecommitdiff
path: root/lib/ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ftp.c')
-rw-r--r--lib/ftp.c163
1 files changed, 82 insertions, 81 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index fade092e4..2f4351e0c 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,7 +77,9 @@
#include "warnless.h"
#include "http_proxy.h"
#include "non-ascii.h"
-#include "curl_printf.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
@@ -283,17 +285,19 @@ static void freedirs(struct ftp_conn *ftpc)
int i;
if(ftpc->dirs) {
for(i=0; i < ftpc->dirdepth; i++) {
- free(ftpc->dirs[i]);
- ftpc->dirs[i]=NULL;
+ if(ftpc->dirs[i]) {
+ free(ftpc->dirs[i]);
+ ftpc->dirs[i]=NULL;
+ }
}
free(ftpc->dirs);
ftpc->dirs = NULL;
ftpc->dirdepth = 0;
}
- Curl_safefree(ftpc->file);
-
- /* no longer of any use */
- Curl_safefree(ftpc->newhost);
+ if(ftpc->file) {
+ free(ftpc->file);
+ ftpc->file = NULL;
+ }
}
/* Returns non-zero if the given string contains CR (\r) or LF (\n),
@@ -1101,7 +1105,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(conn, SOCKERRNO) );
- free(addr);
+ Curl_safefree(addr);
return CURLE_FTP_PORT_FAILED;
}
switch(sa->sa_family) {
@@ -1133,11 +1137,11 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(res == NULL) {
failf(data, "failed to resolve the address provided to PORT: %s", host);
- free(addr);
+ Curl_safefree(addr);
return CURLE_FTP_PORT_FAILED;
}
- free(addr);
+ Curl_safefree(addr);
host = NULL;
/* step 2, create a socket for the requested address */
@@ -1491,13 +1495,13 @@ static CURLcode ftp_state_list(struct connectdata *conn)
The other ftp_filemethods will CWD into dir/dir/ first and
then just do LIST (in that case: nothing to do here)
*/
- char *cmd, *lstArg, *slashPos;
+ char *cmd,*lstArg,*slashPos;
lstArg = NULL;
if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
data->state.path &&
data->state.path[0] &&
- strchr(data->state.path, '/')) {
+ strchr(data->state.path,'/')) {
lstArg = strdup(data->state.path);
if(!lstArg)
@@ -1507,7 +1511,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
if(lstArg[strlen(lstArg) - 1] != '/') {
/* chop off the file part if format is dir/dir/file */
- slashPos = strrchr(lstArg, '/');
+ slashPos = strrchr(lstArg,'/');
if(slashPos)
*(slashPos+1) = '\0';
}
@@ -1521,13 +1525,16 @@ static CURLcode ftp_state_list(struct connectdata *conn)
lstArg? lstArg: "" );
if(!cmd) {
- free(lstArg);
+ if(lstArg)
+ free(lstArg);
return CURLE_OUT_OF_MEMORY;
}
result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
- free(lstArg);
+ if(lstArg)
+ free(lstArg);
+
free(cmd);
if(result)
@@ -1670,8 +1677,8 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
- data->set.fread_func(data->state.buffer, 1, readthisamountnow,
- data->set.in);
+ conn->fread_func(data->state.buffer, 1, readthisamountnow,
+ conn->fread_in);
passed += actuallyread;
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
@@ -1808,13 +1815,6 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
static CURLcode ftp_epsv_disable(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
-
- if(conn->bits.ipv6) {
- /* We can't disable EPSV when doing IPv6, so this is instead a fail */
- failf(conn->data, "Failed EPSV attempt, exiting\n");
- return CURLE_FTP_WEIRD_SERVER_REPLY;
- }
-
infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
@@ -1887,7 +1887,7 @@ static CURLcode proxy_magic(struct connectdata *conn,
memset(&http_proxy, 0, sizeof(http_proxy));
data->req.protop = &http_proxy;
- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
data->req.protop = ftp_save;
@@ -1906,22 +1906,6 @@ static CURLcode proxy_magic(struct connectdata *conn,
return result;
}
-static char *control_address(struct connectdata *conn)
-{
- /* Returns the control connection IP address.
- If a proxy tunnel is used, returns the original host name instead, because
- the effective control connection address is the proxy address,
- not the ftp host. */
- if(conn->bits.tunnel_proxy ||
- conn->proxytype == CURLPROXY_SOCKS5 ||
- conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
- conn->proxytype == CURLPROXY_SOCKS4 ||
- conn->proxytype == CURLPROXY_SOCKS4A)
- return conn->host.name;
-
- return conn->ip_addr_str;
-}
-
static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
int ftpcode)
{
@@ -1933,9 +1917,6 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
unsigned short connectport; /* the local port connect() should use! */
char *str=&data->state.buffer[4]; /* start on the first letter */
- /* if we come here again, make sure the former name is cleared */
- Curl_safefree(ftpc->newhost);
-
if((ftpc->count1 == 0) &&
(ftpcode == 229)) {
/* positive EPSV response */
@@ -1944,12 +1925,12 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
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])) {
+ if(5 == sscanf(ptr, "%c%c%c%u%c",
+ &separator[0],
+ &separator[1],
+ &separator[2],
+ &num,
+ &separator[3])) {
const char sep1 = separator[0];
int i;
@@ -1967,9 +1948,19 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
}
if(ptr) {
ftpc->newport = (unsigned short)(num & 0xffff);
- ftpc->newhost = strdup(control_address(conn));
- if(!ftpc->newhost)
- return CURLE_OUT_OF_MEMORY;
+
+ if(conn->bits.tunnel_proxy ||
+ conn->proxytype == CURLPROXY_SOCKS5 ||
+ conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+ conn->proxytype == CURLPROXY_SOCKS4 ||
+ conn->proxytype == CURLPROXY_SOCKS4A)
+ /* proxy tunnel -> use other host info because ip_addr_str is the
+ proxy address not the ftp host */
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
+ conn->host.name);
+ else
+ /* use the same IP we are already connected to */
+ snprintf(ftpc->newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str);
}
}
else
@@ -1997,8 +1988,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
*/
while(*str) {
if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d",
- &ip[0], &ip[1], &ip[2], &ip[3],
- &port[0], &port[1]))
+ &ip[0], &ip[1], &ip[2], &ip[3],
+ &port[0], &port[1]))
break;
str++;
}
@@ -2010,19 +2001,26 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
/* we got OK from server */
if(data->set.ftp_skip_ip) {
- /* told to ignore the remotely given IP but instead use the host we used
+ /* told to ignore the remotely given IP but instead use the one we used
for the control connection */
- infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n",
+ infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n",
ip[0], ip[1], ip[2], ip[3],
- conn->host.name);
- ftpc->newhost = strdup(control_address(conn));
+ conn->ip_addr_str);
+ if(conn->bits.tunnel_proxy ||
+ conn->proxytype == CURLPROXY_SOCKS5 ||
+ conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+ conn->proxytype == CURLPROXY_SOCKS4 ||
+ conn->proxytype == CURLPROXY_SOCKS4A)
+ /* proxy tunnel -> use other host info because ip_addr_str is the
+ proxy address not the ftp host */
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", conn->host.name);
+ else
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
+ conn->ip_addr_str);
}
else
- ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
-
- if(!ftpc->newhost)
- return CURLE_OUT_OF_MEMORY;
-
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost),
+ "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
}
else if(ftpc->count1 == 0) {
@@ -2073,8 +2071,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
result = Curl_connecthost(conn, addr);
+ Curl_resolv_unlock(data, addr); /* we're done using this address */
+
if(result) {
- Curl_resolv_unlock(data, addr); /* we're done using this address */
if(ftpc->count1 == 0 && ftpcode == 229)
return ftp_epsv_disable(conn);
@@ -2090,9 +2089,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
if(data->set.verbose)
/* this just dumps information about this second connection */
- ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
+ ftp_pasv_verbose(conn, conn->ip_addr, ftpc->newhost, connectport);
- Curl_resolv_unlock(data, addr); /* we're done using this address */
conn->bits.do_more = TRUE;
state(conn, FTP_STOP); /* this phase is completed */
@@ -2107,9 +2105,7 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn,
ftpport fcmd = (ftpport)ftpc->count1;
CURLcode result = CURLE_OK;
- /* The FTP spec tells a positive response should have code 200.
- Be more permissive here to tolerate deviant servers. */
- if(ftpcode / 100 != 2) {
+ if(ftpcode != 200) {
/* the command failed */
if(EPRT == fcmd) {
@@ -3273,7 +3269,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
}
/* now store a copy of the directory we are in */
- free(ftpc->prevpath);
+ if(ftpc->prevpath)
+ free(ftpc->prevpath);
if(data->set.wildcardmatch) {
if(data->set.chunk_end && ftpc->file) {
@@ -3322,7 +3319,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
/* shut down the socket to inform the server we're done */
#ifdef _WIN32_WCE
- shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */
+ shutdown(conn->sock[SECONDARYSOCKET],2); /* SD_BOTH */
#endif
if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
@@ -3645,7 +3642,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
aren't used so we blank their arguments. TODO: make this nicer */
- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
return result;
}
@@ -3819,7 +3816,7 @@ static void wc_data_dtor(void *ptr)
struct ftp_wc_tmpdata *tmp = ptr;
if(tmp)
Curl_ftp_parselist_data_free(&tmp->parser);
- free(tmp);
+ Curl_safefree(tmp);
}
static CURLcode init_wc_data(struct connectdata *conn)
@@ -3873,7 +3870,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
if(!ftp_tmp->parser) {
Curl_safefree(wildcard->pattern);
- free(ftp_tmp);
+ Curl_safefree(ftp_tmp);
return CURLE_OUT_OF_MEMORY;
}
@@ -4099,7 +4096,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
result = Curl_convert_to_network(conn->data, s, write_len);
/* Curl_convert_to_network calls failf if unsuccessful */
if(result)
- return result;
+ return(result);
for(;;) {
#ifdef HAVE_GSSAPI
@@ -4198,10 +4195,14 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
}
freedirs(ftpc);
- free(ftpc->prevpath);
- ftpc->prevpath = NULL;
- free(ftpc->server_os);
- ftpc->server_os = NULL;
+ if(ftpc->prevpath) {
+ free(ftpc->prevpath);
+ ftpc->prevpath = NULL;
+ }
+ if(ftpc->server_os) {
+ free(ftpc->server_os);
+ ftpc->server_os = NULL;
+ }
Curl_pp_disconnect(pp);