diff options
Diffstat (limited to 'Utilities/cmcurl/lib/ftp.c')
-rw-r--r-- | Utilities/cmcurl/lib/ftp.c | 196 |
1 files changed, 68 insertions, 128 deletions
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c index 9d0a03c..89c7e40 100644 --- a/Utilities/cmcurl/lib/ftp.c +++ b/Utilities/cmcurl/lib/ftp.c @@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn) * Curl_pgrsTime(..., TIMER_STARTACCEPT); * */ -static long ftp_timeleft_accept(struct Curl_easy *data) +static time_t ftp_timeleft_accept(struct Curl_easy *data) { - long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; - long other; + time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + time_t other; struct timeval now; if(data->set.accepttimeout > 0) @@ -430,7 +430,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; int result; - long timeout_ms; + time_t timeout_ms; ssize_t nread; int ftpcode; @@ -455,7 +455,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); /* see if the connection request is already here */ - switch (result) { + switch(result) { case -1: /* error */ /* let's die here */ failf(data, "Error while waiting for server connect"); @@ -499,7 +499,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) struct FTP *ftp = data->req.protop; CURLcode result = CURLE_OK; - if(conn->ssl[SECONDARYSOCKET].use) { + if(conn->bits.ftp_use_data_ssl) { /* since we only have a plaintext TCP connection here, we must now * do the TLS stuff */ infof(data, "Doing the SSL/TLS handshake on the data stream\n"); @@ -547,7 +547,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) { struct Curl_easy *data = conn->data; - long timeout_ms; + time_t timeout_ms; CURLcode result = CURLE_OK; *connected = FALSE; @@ -687,8 +687,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * line in a response or continue reading. */ curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - long timeout; /* timeout in milliseconds */ - long interval_ms; + time_t timeout; /* timeout in milliseconds */ + time_t interval_ms; struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -740,8 +740,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * wait for more data anyway. */ } - else { - switch (SOCKET_READABLE(sockfd, interval_ms)) { + else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { + switch(SOCKET_READABLE(sockfd, interval_ms)) { case -1: /* select() error, stop reading */ failf(data, "FTP response aborted due to select/poll error: %d", SOCKERRNO); @@ -1035,7 +1035,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(*string_ftpport == '[') { /* [ipv6]:port(-range) */ ip_start = string_ftpport + 1; - if((ip_end = strchr(string_ftpport, ']')) != NULL) + ip_end = strchr(string_ftpport, ']'); + if(ip_end) strncpy(addr, ip_start, ip_end - ip_start); } else @@ -1043,30 +1044,35 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(*string_ftpport == ':') { /* :port */ ip_end = string_ftpport; - } - else if((ip_end = strchr(string_ftpport, ':')) != NULL) { - /* either ipv6 or (ipv4|domain|interface):port(-range) */ -#ifdef ENABLE_IPV6 - if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { - /* ipv6 */ - port_min = port_max = 0; - strcpy(addr, string_ftpport); - ip_end = NULL; /* this got no port ! */ } - else + else { + ip_end = strchr(string_ftpport, ':'); + if(ip_end) { + /* either ipv6 or (ipv4|domain|interface):port(-range) */ +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { + /* ipv6 */ + port_min = port_max = 0; + strcpy(addr, string_ftpport); + ip_end = NULL; /* this got no port ! */ + } + else #endif - /* (ipv4|domain|interface):port(-range) */ - strncpy(addr, string_ftpport, ip_end - ip_start); - } - else - /* ipv4|interface */ - strcpy(addr, string_ftpport); + /* (ipv4|domain|interface):port(-range) */ + strncpy(addr, string_ftpport, ip_end - ip_start); + } + else + /* ipv4|interface */ + strcpy(addr, string_ftpport); + } /* parse the port */ if(ip_end != NULL) { - if((port_start = strchr(ip_end, ':')) != NULL) { + port_start = strchr(ip_end, ':'); + if(port_start) { port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); - if((port_sep = strchr(port_start, '-')) != NULL) { + port_sep = strchr(port_start, '-'); + if(port_sep) { port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); } else @@ -1850,84 +1856,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn) return result; } -/* - * Perform the necessary magic that needs to be done once the TCP connection - * to the proxy has completed. - */ -static CURLcode proxy_magic(struct connectdata *conn, - char *newhost, unsigned short newport, - bool *magicdone) -{ - CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - -#if defined(CURL_DISABLE_PROXY) - (void) newhost; - (void) newport; -#endif - - *magicdone = FALSE; - - switch(conn->proxytype) { - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, - newport, SECONDARYSOCKET, conn); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, FALSE); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, TRUE); - *magicdone = TRUE; - break; - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - failf(data, "unknown proxytype option given"); - result = CURLE_COULDNT_CONNECT; - break; - } - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* BLOCKING */ - /* We want "seamless" FTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want FTP through HTTP and we have to - * change the member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original - * struct FTP pointer - */ - struct HTTP http_proxy; - struct FTP *ftp_save = data->req.protop; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->req.protop = &http_proxy; - - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); - - data->req.protop = ftp_save; - - if(result) - return result; - - if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { - /* the CONNECT procedure is not complete, the tunnel is not yet up */ - state(conn, FTP_STOP); /* this phase is completed */ - return result; - } - else - *magicdone = TRUE; - } - - return result; -} static char *control_address(struct connectdata *conn) { @@ -1935,11 +1863,7 @@ static char *control_address(struct connectdata *conn) 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) + if(conn->bits.tunnel_proxy || conn->bits.socksproxy) return conn->host.name; return conn->ip_addr_str; @@ -2063,7 +1987,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, * here. We don't want to rely on a former host lookup that might've * expired now, instead we remake the lookup here and now! */ - rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr); + const char * const host_name = conn->bits.socksproxy ? + conn->socks_proxy.host.name : conn->http_proxy.host.name; + rc = Curl_resolv(conn, host_name, (int)conn->port, &addr); if(rc == CURLRESOLV_PENDING) /* BLOCKING, ignores the return code but 'addr' will be NULL in case of failure */ @@ -2073,8 +1999,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, (unsigned short)conn->port; /* we connect to the proxy's port */ if(!addr) { - failf(data, "Can't resolve proxy host %s:%hu", - conn->proxy.name, connectport); + failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); return CURLE_FTP_CANT_GET_HOST; } } @@ -2115,6 +2040,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, /* this just dumps information about this second connection */ ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + Curl_safefree(conn->secondaryhostname); + conn->secondaryhostname = strdup(ftpc->newhost); + conn->secondary_port = ftpc->newport; + Curl_resolv_unlock(data, addr); /* we're done using this address */ conn->bits.do_more = TRUE; state(conn, FTP_STOP); /* this phase is completed */ @@ -2763,7 +2692,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) } #endif - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + if(data->set.use_ssl && + (!conn->ssl[FIRSTSOCKET].use || + (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && + !conn->proxy_ssl[FIRSTSOCKET].use))) { /* We don't have a SSL/TLS connection yet, but FTPS is requested. Try a FTPS connection now */ @@ -2808,7 +2740,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(!result) { - conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */ + conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ result = ftp_state_user(conn); } } @@ -2850,7 +2782,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) case FTP_PROT: if(ftpcode/100 == 2) /* We have enabled SSL for the data connection! */ - conn->ssl[SECONDARYSOCKET].use = + conn->bits.ftp_use_data_ssl = (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; /* FTP servers typically responds with 500 if they decide to reject our 'P' request */ @@ -3250,7 +3182,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, ssize_t nread; int ftpcode; CURLcode result = CURLE_OK; - char *path; + char *path = NULL; const char *path_to_use = data->state.path; if(!ftp) @@ -3666,10 +3598,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) /* Ready to do more? */ if(connected) { DEBUGF(infof(data, "DO-MORE connected phase starts\n")); - if(conn->bits.proxy) { - infof(data, "Connection to proxy confirmed\n"); - result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); - } } else { if(result && (ftpc->count1 == 0)) { @@ -3681,6 +3609,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) } } + result = Curl_proxy_connect(conn, SECONDARYSOCKET); + if(result) + return result; + + if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) + return result; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) + return result; + + if(ftpc->state) { /* already in a state so skip the initial commands. They are only done to kickstart the do_more state */ @@ -3940,7 +3880,7 @@ static CURLcode wc_statemach(struct connectdata *conn) struct WildcardData * const wildcard = &(conn->data->wildcard); CURLcode result = CURLE_OK; - switch (wildcard->state) { + switch(wildcard->state) { case CURLWC_INIT: result = init_wc_data(conn); if(wildcard->state == CURLWC_CLEAN) @@ -4247,8 +4187,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) const char *cur_pos; const char *filename = NULL; - cur_pos = path_to_use; /* current position in path. point at the begin - of next path component */ + cur_pos = path_to_use; /* current position in path. point at the begin of + next path component */ ftpc->ctl_valid = FALSE; ftpc->cwdfail = FALSE; @@ -4568,7 +4508,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) command = Curl_raw_toupper(type[6]); conn->bits.type_set = TRUE; - switch (command) { + switch(command) { case 'A': /* ASCII mode */ data->set.prefer_ascii = TRUE; break; |