diff options
Diffstat (limited to 'lib/ftp.c')
-rw-r--r-- | lib/ftp.c | 163 |
1 files changed, 82 insertions, 81 deletions
@@ -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); |