X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fftp.c;h=fade092e4e2cfe46828a7d0f55964371c1903faa;hb=31368b6eac8092a307849518e912b4c475c0238a;hp=2f4351e0cd74fd5e03c477f5bab9cb26ffe25afe;hpb=ff9f0eb35d80c251e9a54162eae18f44349ae59d;p=platform%2Fupstream%2Fcurl.git diff --git a/lib/ftp.c b/lib/ftp.c index 2f4351e..fade092 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2015, Daniel Stenberg, , 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,9 +77,7 @@ #include "warnless.h" #include "http_proxy.h" #include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include +#include "curl_printf.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -285,19 +283,17 @@ static void freedirs(struct ftp_conn *ftpc) int i; if(ftpc->dirs) { for(i=0; i < ftpc->dirdepth; i++) { - if(ftpc->dirs[i]) { - free(ftpc->dirs[i]); - ftpc->dirs[i]=NULL; - } + free(ftpc->dirs[i]); + ftpc->dirs[i]=NULL; } free(ftpc->dirs); ftpc->dirs = NULL; ftpc->dirdepth = 0; } - if(ftpc->file) { - free(ftpc->file); - ftpc->file = NULL; - } + Curl_safefree(ftpc->file); + + /* no longer of any use */ + Curl_safefree(ftpc->newhost); } /* Returns non-zero if the given string contains CR (\r) or LF (\n), @@ -1105,7 +1101,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) ); - Curl_safefree(addr); + free(addr); return CURLE_FTP_PORT_FAILED; } switch(sa->sa_family) { @@ -1137,11 +1133,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); - Curl_safefree(addr); + free(addr); return CURLE_FTP_PORT_FAILED; } - Curl_safefree(addr); + free(addr); host = NULL; /* step 2, create a socket for the requested address */ @@ -1495,13 +1491,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) @@ -1511,7 +1507,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'; } @@ -1525,16 +1521,13 @@ static CURLcode ftp_state_list(struct connectdata *conn) lstArg? lstArg: "" ); if(!cmd) { - if(lstArg) - free(lstArg); + free(lstArg); return CURLE_OUT_OF_MEMORY; } result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); - if(lstArg) - free(lstArg); - + free(lstArg); free(cmd); if(result) @@ -1677,8 +1670,8 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, BUFSIZE : curlx_sotouz(data->state.resume_from - passed); size_t actuallyread = - conn->fread_func(data->state.buffer, 1, readthisamountnow, - conn->fread_in); + data->set.fread_func(data->state.buffer, 1, readthisamountnow, + data->set.in); passed += actuallyread; if((actuallyread == 0) || (actuallyread > readthisamountnow)) { @@ -1815,6 +1808,13 @@ 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); + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); data->req.protop = ftp_save; @@ -1906,6 +1906,22 @@ 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) { @@ -1917,6 +1933,9 @@ 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 */ @@ -1925,12 +1944,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; @@ -1948,19 +1967,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, } if(ptr) { ftpc->newport = (unsigned short)(num & 0xffff); - - 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); + ftpc->newhost = strdup(control_address(conn)); + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; } } else @@ -1988,8 +1997,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++; } @@ -2001,26 +2010,19 @@ 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 one we used + /* told to ignore the remotely given IP but instead use the host we used for the control connection */ - infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n", + infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n", ip[0], ip[1], ip[2], ip[3], - 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); + conn->host.name); + ftpc->newhost = strdup(control_address(conn)); } else - snprintf(ftpc->newhost, sizeof(ftpc->newhost), - "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); } else if(ftpc->count1 == 0) { @@ -2071,9 +2073,8 @@ 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); @@ -2089,8 +2090,9 @@ 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, conn->ip_addr, ftpc->newhost, connectport); + ftp_pasv_verbose(conn, addr->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 */ @@ -2105,7 +2107,9 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn, ftpport fcmd = (ftpport)ftpc->count1; CURLcode result = CURLE_OK; - if(ftpcode != 200) { + /* The FTP spec tells a positive response should have code 200. + Be more permissive here to tolerate deviant servers. */ + if(ftpcode / 100 != 2) { /* the command failed */ if(EPRT == fcmd) { @@ -3269,8 +3273,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, } /* now store a copy of the directory we are in */ - if(ftpc->prevpath) - free(ftpc->prevpath); + free(ftpc->prevpath); if(data->set.wildcardmatch) { if(data->set.chunk_end && ftpc->file) { @@ -3319,7 +3322,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) { @@ -3642,7 +3645,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); + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE); return result; } @@ -3816,7 +3819,7 @@ static void wc_data_dtor(void *ptr) struct ftp_wc_tmpdata *tmp = ptr; if(tmp) Curl_ftp_parselist_data_free(&tmp->parser); - Curl_safefree(tmp); + free(tmp); } static CURLcode init_wc_data(struct connectdata *conn) @@ -3870,7 +3873,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); - Curl_safefree(ftp_tmp); + free(ftp_tmp); return CURLE_OUT_OF_MEMORY; } @@ -4096,7 +4099,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 @@ -4195,14 +4198,10 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) } freedirs(ftpc); - if(ftpc->prevpath) { - free(ftpc->prevpath); - ftpc->prevpath = NULL; - } - if(ftpc->server_os) { - free(ftpc->server_os); - ftpc->server_os = NULL; - } + free(ftpc->prevpath); + ftpc->prevpath = NULL; + free(ftpc->server_os); + ftpc->server_os = NULL; Curl_pp_disconnect(pp);