1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #ifndef CURL_DISABLE_FTP 26 27 #ifdef HAVE_NETINET_IN_H 28 #include <netinet/in.h> 29 #endif 30 #ifdef HAVE_ARPA_INET_H 31 #include <arpa/inet.h> 32 #endif 33 #ifdef HAVE_UTSNAME_H 34 #include <sys/utsname.h> 35 #endif 36 #ifdef HAVE_NETDB_H 37 #include <netdb.h> 38 #endif 39 #ifdef __VMS 40 #include <in.h> 41 #include <inet.h> 42 #endif 43 44 #if (defined(NETWARE) && defined(__NOVELL_LIBC__)) 45 #undef in_addr_t 46 #define in_addr_t unsigned long 47 #endif 48 49 #include <curl/curl.h> 50 #include "urldata.h" 51 #include "sendf.h" 52 #include "if2ip.h" 53 #include "hostip.h" 54 #include "progress.h" 55 #include "transfer.h" 56 #include "escape.h" 57 #include "http.h" /* for HTTP proxy tunnel stuff */ 58 #include "socks.h" 59 #include "ftp.h" 60 #include "fileinfo.h" 61 #include "ftplistparser.h" 62 #include "curl_range.h" 63 #include "curl_sec.h" 64 #include "strtoofft.h" 65 #include "strcase.h" 66 #include "vtls/vtls.h" 67 #include "connect.h" 68 #include "strerror.h" 69 #include "inet_ntop.h" 70 #include "inet_pton.h" 71 #include "select.h" 72 #include "parsedate.h" /* for the week day and month names */ 73 #include "sockaddr.h" /* required for Curl_sockaddr_storage */ 74 #include "multiif.h" 75 #include "url.h" 76 #include "strcase.h" 77 #include "speedcheck.h" 78 #include "warnless.h" 79 #include "http_proxy.h" 80 #include "non-ascii.h" 81 /* The last 3 #include files should be in this order */ 82 #include "curl_printf.h" 83 #include "curl_memory.h" 84 #include "memdebug.h" 85 86 #ifndef NI_MAXHOST 87 #define NI_MAXHOST 1025 88 #endif 89 #ifndef INET_ADDRSTRLEN 90 #define INET_ADDRSTRLEN 16 91 #endif 92 93 #ifdef CURL_DISABLE_VERBOSE_STRINGS 94 #define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt 95 #endif 96 97 /* Local API functions */ 98 #ifndef DEBUGBUILD 99 static void _state(struct connectdata *conn, 100 ftpstate newstate); 101 #define state(x,y) _state(x,y) 102 #else 103 static void _state(struct connectdata *conn, 104 ftpstate newstate, 105 int lineno); 106 #define state(x,y) _state(x,y,__LINE__) 107 #endif 108 109 static CURLcode ftp_sendquote(struct connectdata *conn, 110 struct curl_slist *quote); 111 static CURLcode ftp_quit(struct connectdata *conn); 112 static CURLcode ftp_parse_url_path(struct connectdata *conn); 113 static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done); 114 #ifndef CURL_DISABLE_VERBOSE_STRINGS 115 static void ftp_pasv_verbose(struct connectdata *conn, 116 Curl_addrinfo *ai, 117 char *newhost, /* ascii version */ 118 int port); 119 #endif 120 static CURLcode ftp_state_prepare_transfer(struct connectdata *conn); 121 static CURLcode ftp_state_mdtm(struct connectdata *conn); 122 static CURLcode ftp_state_quote(struct connectdata *conn, 123 bool init, ftpstate instate); 124 static CURLcode ftp_nb_type(struct connectdata *conn, 125 bool ascii, ftpstate newstate); 126 static int ftp_need_type(struct connectdata *conn, 127 bool ascii); 128 static CURLcode ftp_do(struct connectdata *conn, bool *done); 129 static CURLcode ftp_done(struct connectdata *conn, 130 CURLcode, bool premature); 131 static CURLcode ftp_connect(struct connectdata *conn, bool *done); 132 static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); 133 static CURLcode ftp_do_more(struct connectdata *conn, int *completed); 134 static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); 135 static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks, 136 int numsocks); 137 static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, 138 int numsocks); 139 static CURLcode ftp_doing(struct connectdata *conn, 140 bool *dophase_done); 141 static CURLcode ftp_setup_connection(struct connectdata * conn); 142 143 static CURLcode init_wc_data(struct connectdata *conn); 144 static CURLcode wc_statemach(struct connectdata *conn); 145 146 static void wc_data_dtor(void *ptr); 147 148 static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize); 149 150 static CURLcode ftp_readresp(curl_socket_t sockfd, 151 struct pingpong *pp, 152 int *ftpcode, 153 size_t *size); 154 static CURLcode ftp_dophase_done(struct connectdata *conn, 155 bool connected); 156 157 /* easy-to-use macro: */ 158 #define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \ 159 if(result) \ 160 return result 161 162 163 /* 164 * FTP protocol handler. 165 */ 166 167 const struct Curl_handler Curl_handler_ftp = { 168 "FTP", /* scheme */ 169 ftp_setup_connection, /* setup_connection */ 170 ftp_do, /* do_it */ 171 ftp_done, /* done */ 172 ftp_do_more, /* do_more */ 173 ftp_connect, /* connect_it */ 174 ftp_multi_statemach, /* connecting */ 175 ftp_doing, /* doing */ 176 ftp_getsock, /* proto_getsock */ 177 ftp_getsock, /* doing_getsock */ 178 ftp_domore_getsock, /* domore_getsock */ 179 ZERO_NULL, /* perform_getsock */ 180 ftp_disconnect, /* disconnect */ 181 ZERO_NULL, /* readwrite */ 182 ZERO_NULL, /* connection_check */ 183 PORT_FTP, /* defport */ 184 CURLPROTO_FTP, /* protocol */ 185 PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | 186 PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP | 187 PROTOPT_WILDCARD /* flags */ 188 }; 189 190 191 #ifdef USE_SSL 192 /* 193 * FTPS protocol handler. 194 */ 195 196 const struct Curl_handler Curl_handler_ftps = { 197 "FTPS", /* scheme */ 198 ftp_setup_connection, /* setup_connection */ 199 ftp_do, /* do_it */ 200 ftp_done, /* done */ 201 ftp_do_more, /* do_more */ 202 ftp_connect, /* connect_it */ 203 ftp_multi_statemach, /* connecting */ 204 ftp_doing, /* doing */ 205 ftp_getsock, /* proto_getsock */ 206 ftp_getsock, /* doing_getsock */ 207 ftp_domore_getsock, /* domore_getsock */ 208 ZERO_NULL, /* perform_getsock */ 209 ftp_disconnect, /* disconnect */ 210 ZERO_NULL, /* readwrite */ 211 ZERO_NULL, /* connection_check */ 212 PORT_FTPS, /* defport */ 213 CURLPROTO_FTPS, /* protocol */ 214 PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | 215 PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */ 216 }; 217 #endif 218 219 static void close_secondarysocket(struct connectdata *conn) 220 { 221 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { 222 Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); 223 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; 224 } 225 conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; 226 } 227 228 /* 229 * NOTE: back in the old days, we added code in the FTP code that made NOBODY 230 * requests on files respond with headers passed to the client/stdout that 231 * looked like HTTP ones. 232 * 233 * This approach is not very elegant, it causes confusion and is error-prone. 234 * It is subject for removal at the next (or at least a future) soname bump. 235 * Until then you can test the effects of the removal by undefining the 236 * following define named CURL_FTP_HTTPSTYLE_HEAD. 237 */ 238 #define CURL_FTP_HTTPSTYLE_HEAD 1 239 240 static void freedirs(struct ftp_conn *ftpc) 241 { 242 if(ftpc->dirs) { 243 int i; 244 for(i = 0; i < ftpc->dirdepth; i++) { 245 free(ftpc->dirs[i]); 246 ftpc->dirs[i] = NULL; 247 } 248 free(ftpc->dirs); 249 ftpc->dirs = NULL; 250 ftpc->dirdepth = 0; 251 } 252 Curl_safefree(ftpc->file); 253 254 /* no longer of any use */ 255 Curl_safefree(ftpc->newhost); 256 } 257 258 /* Returns non-zero if the given string contains CR (\r) or LF (\n), 259 which are not allowed within RFC 959 <string>. 260 Note: The input string is in the client's encoding which might 261 not be ASCII, so escape sequences \r & \n must be used instead 262 of hex values 0x0d & 0x0a. 263 */ 264 static bool isBadFtpString(const char *string) 265 { 266 return ((NULL != strchr(string, '\r')) || 267 (NULL != strchr(string, '\n'))) ? TRUE : FALSE; 268 } 269 270 /*********************************************************************** 271 * 272 * AcceptServerConnect() 273 * 274 * After connection request is received from the server this function is 275 * called to accept the connection and close the listening socket 276 * 277 */ 278 static CURLcode AcceptServerConnect(struct connectdata *conn) 279 { 280 struct Curl_easy *data = conn->data; 281 curl_socket_t sock = conn->sock[SECONDARYSOCKET]; 282 curl_socket_t s = CURL_SOCKET_BAD; 283 #ifdef ENABLE_IPV6 284 struct Curl_sockaddr_storage add; 285 #else 286 struct sockaddr_in add; 287 #endif 288 curl_socklen_t size = (curl_socklen_t) sizeof(add); 289 290 if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) { 291 size = sizeof(add); 292 293 s = accept(sock, (struct sockaddr *) &add, &size); 294 } 295 Curl_closesocket(conn, sock); /* close the first socket */ 296 297 if(CURL_SOCKET_BAD == s) { 298 failf(data, "Error accept()ing server connect"); 299 return CURLE_FTP_PORT_FAILED; 300 } 301 infof(data, "Connection accepted from server\n"); 302 /* when this happens within the DO state it is important that we mark us as 303 not needing DO_MORE anymore */ 304 conn->bits.do_more = FALSE; 305 306 conn->sock[SECONDARYSOCKET] = s; 307 (void)curlx_nonblock(s, TRUE); /* enable non-blocking */ 308 conn->sock_accepted[SECONDARYSOCKET] = TRUE; 309 310 if(data->set.fsockopt) { 311 int error = 0; 312 313 /* activate callback for setting socket options */ 314 Curl_set_in_callback(data, true); 315 error = data->set.fsockopt(data->set.sockopt_client, 316 s, 317 CURLSOCKTYPE_ACCEPT); 318 Curl_set_in_callback(data, false); 319 320 if(error) { 321 close_secondarysocket(conn); 322 return CURLE_ABORTED_BY_CALLBACK; 323 } 324 } 325 326 return CURLE_OK; 327 328 } 329 330 /* 331 * ftp_timeleft_accept() returns the amount of milliseconds left allowed for 332 * waiting server to connect. If the value is negative, the timeout time has 333 * already elapsed. 334 * 335 * The start time is stored in progress.t_acceptdata - as set with 336 * Curl_pgrsTime(..., TIMER_STARTACCEPT); 337 * 338 */ 339 static timediff_t ftp_timeleft_accept(struct Curl_easy *data) 340 { 341 timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; 342 timediff_t other; 343 struct curltime now; 344 345 if(data->set.accepttimeout > 0) 346 timeout_ms = data->set.accepttimeout; 347 348 now = Curl_now(); 349 350 /* check if the generic timeout possibly is set shorter */ 351 other = Curl_timeleft(data, &now, FALSE); 352 if(other && (other < timeout_ms)) 353 /* note that this also works fine for when other happens to be negative 354 due to it already having elapsed */ 355 timeout_ms = other; 356 else { 357 /* subtract elapsed time */ 358 timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata); 359 if(!timeout_ms) 360 /* avoid returning 0 as that means no timeout! */ 361 return -1; 362 } 363 364 return timeout_ms; 365 } 366 367 368 /*********************************************************************** 369 * 370 * ReceivedServerConnect() 371 * 372 * After allowing server to connect to us from data port, this function 373 * checks both data connection for connection establishment and ctrl 374 * connection for a negative response regarding a failure in connecting 375 * 376 */ 377 static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) 378 { 379 struct Curl_easy *data = conn->data; 380 curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; 381 curl_socket_t data_sock = conn->sock[SECONDARYSOCKET]; 382 struct ftp_conn *ftpc = &conn->proto.ftpc; 383 struct pingpong *pp = &ftpc->pp; 384 int result; 385 time_t timeout_ms; 386 ssize_t nread; 387 int ftpcode; 388 389 *received = FALSE; 390 391 timeout_ms = ftp_timeleft_accept(data); 392 infof(data, "Checking for server connect\n"); 393 if(timeout_ms < 0) { 394 /* if a timeout was already reached, bail out */ 395 failf(data, "Accept timeout occurred while waiting server connect"); 396 return CURLE_FTP_ACCEPT_TIMEOUT; 397 } 398 399 /* First check whether there is a cached response from server */ 400 if(pp->cache_size && pp->cache && pp->cache[0] > '3') { 401 /* Data connection could not be established, let's return */ 402 infof(data, "There is negative response in cache while serv connect\n"); 403 Curl_GetFTPResponse(&nread, conn, &ftpcode); 404 return CURLE_FTP_ACCEPT_FAILED; 405 } 406 407 result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); 408 409 /* see if the connection request is already here */ 410 switch(result) { 411 case -1: /* error */ 412 /* let's die here */ 413 failf(data, "Error while waiting for server connect"); 414 return CURLE_FTP_ACCEPT_FAILED; 415 case 0: /* Server connect is not received yet */ 416 break; /* loop */ 417 default: 418 419 if(result & CURL_CSELECT_IN2) { 420 infof(data, "Ready to accept data connection from server\n"); 421 *received = TRUE; 422 } 423 else if(result & CURL_CSELECT_IN) { 424 infof(data, "Ctrl conn has data while waiting for data conn\n"); 425 Curl_GetFTPResponse(&nread, conn, &ftpcode); 426 427 if(ftpcode/100 > 3) 428 return CURLE_FTP_ACCEPT_FAILED; 429 430 return CURLE_WEIRD_SERVER_REPLY; 431 } 432 433 break; 434 } /* switch() */ 435 436 return CURLE_OK; 437 } 438 439 440 /*********************************************************************** 441 * 442 * InitiateTransfer() 443 * 444 * After connection from server is accepted this function is called to 445 * setup transfer parameters and initiate the data transfer. 446 * 447 */ 448 static CURLcode InitiateTransfer(struct connectdata *conn) 449 { 450 struct Curl_easy *data = conn->data; 451 CURLcode result = CURLE_OK; 452 453 if(conn->bits.ftp_use_data_ssl) { 454 /* since we only have a plaintext TCP connection here, we must now 455 * do the TLS stuff */ 456 infof(data, "Doing the SSL/TLS handshake on the data stream\n"); 457 result = Curl_ssl_connect(conn, SECONDARYSOCKET); 458 if(result) 459 return result; 460 } 461 462 if(conn->proto.ftpc.state_saved == FTP_STOR) { 463 /* When we know we're uploading a specified file, we can get the file 464 size prior to the actual upload. */ 465 Curl_pgrsSetUploadSize(data, data->state.infilesize); 466 467 /* set the SO_SNDBUF for the secondary socket for those who need it */ 468 Curl_sndbufset(conn->sock[SECONDARYSOCKET]); 469 470 Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET); 471 } 472 else { 473 /* FTP download: */ 474 Curl_setup_transfer(data, SECONDARYSOCKET, 475 conn->proto.ftpc.retr_size_saved, FALSE, -1); 476 } 477 478 conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ 479 state(conn, FTP_STOP); 480 481 return CURLE_OK; 482 } 483 484 /*********************************************************************** 485 * 486 * AllowServerConnect() 487 * 488 * When we've issue the PORT command, we have told the server to connect to 489 * us. This function checks whether data connection is established if so it is 490 * accepted. 491 * 492 */ 493 static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) 494 { 495 struct Curl_easy *data = conn->data; 496 time_t timeout_ms; 497 CURLcode result = CURLE_OK; 498 499 *connected = FALSE; 500 infof(data, "Preparing for accepting server on data port\n"); 501 502 /* Save the time we start accepting server connect */ 503 Curl_pgrsTime(data, TIMER_STARTACCEPT); 504 505 timeout_ms = ftp_timeleft_accept(data); 506 if(timeout_ms < 0) { 507 /* if a timeout was already reached, bail out */ 508 failf(data, "Accept timeout occurred while waiting server connect"); 509 return CURLE_FTP_ACCEPT_TIMEOUT; 510 } 511 512 /* see if the connection request is already here */ 513 result = ReceivedServerConnect(conn, connected); 514 if(result) 515 return result; 516 517 if(*connected) { 518 result = AcceptServerConnect(conn); 519 if(result) 520 return result; 521 522 result = InitiateTransfer(conn); 523 if(result) 524 return result; 525 } 526 else { 527 /* Add timeout to multi handle and break out of the loop */ 528 if(!result && *connected == FALSE) { 529 Curl_expire(data, data->set.accepttimeout > 0 ? 530 data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0); 531 } 532 } 533 534 return result; 535 } 536 537 /* macro to check for a three-digit ftp status code at the start of the 538 given string */ 539 #define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \ 540 ISDIGIT(line[2])) 541 542 /* macro to check for the last line in an FTP server response */ 543 #define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) 544 545 static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, 546 int *code) 547 { 548 (void)conn; 549 550 if((len > 3) && LASTLINE(line)) { 551 *code = curlx_sltosi(strtol(line, NULL, 10)); 552 return TRUE; 553 } 554 555 return FALSE; 556 } 557 558 static CURLcode ftp_readresp(curl_socket_t sockfd, 559 struct pingpong *pp, 560 int *ftpcode, /* return the ftp-code if done */ 561 size_t *size) /* size of the response */ 562 { 563 struct connectdata *conn = pp->conn; 564 struct Curl_easy *data = conn->data; 565 #ifdef HAVE_GSSAPI 566 char * const buf = data->state.buffer; 567 #endif 568 CURLcode result = CURLE_OK; 569 int code; 570 571 result = Curl_pp_readresp(sockfd, pp, &code, size); 572 573 #if defined(HAVE_GSSAPI) 574 /* handle the security-oriented responses 6xx ***/ 575 /* FIXME: some errorchecking perhaps... ***/ 576 switch(code) { 577 case 631: 578 code = Curl_sec_read_msg(conn, buf, PROT_SAFE); 579 break; 580 case 632: 581 code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE); 582 break; 583 case 633: 584 code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL); 585 break; 586 default: 587 /* normal ftp stuff we pass through! */ 588 break; 589 } 590 #endif 591 592 /* store the latest code for later retrieval */ 593 data->info.httpcode = code; 594 595 if(ftpcode) 596 *ftpcode = code; 597 598 if(421 == code) { 599 /* 421 means "Service not available, closing control connection." and FTP 600 * servers use it to signal that idle session timeout has been exceeded. 601 * If we ignored the response, it could end up hanging in some cases. 602 * 603 * This response code can come at any point so having it treated 604 * generically is a good idea. 605 */ 606 infof(data, "We got a 421 - timeout!\n"); 607 state(conn, FTP_STOP); 608 return CURLE_OPERATION_TIMEDOUT; 609 } 610 611 return result; 612 } 613 614 /* --- parse FTP server responses --- */ 615 616 /* 617 * Curl_GetFTPResponse() is a BLOCKING function to read the full response 618 * from a server after a command. 619 * 620 */ 621 622 CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ 623 struct connectdata *conn, 624 int *ftpcode) /* return the ftp-code */ 625 { 626 /* 627 * We cannot read just one byte per read() and then go back to select() as 628 * the OpenSSL read() doesn't grok that properly. 629 * 630 * Alas, read as much as possible, split up into lines, use the ending 631 * line in a response or continue reading. */ 632 633 curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; 634 struct Curl_easy *data = conn->data; 635 CURLcode result = CURLE_OK; 636 struct ftp_conn *ftpc = &conn->proto.ftpc; 637 struct pingpong *pp = &ftpc->pp; 638 size_t nread; 639 int cache_skip = 0; 640 int value_to_be_ignored = 0; 641 642 if(ftpcode) 643 *ftpcode = 0; /* 0 for errors */ 644 else 645 /* make the pointer point to something for the rest of this function */ 646 ftpcode = &value_to_be_ignored; 647 648 *nreadp = 0; 649 650 while(!*ftpcode && !result) { 651 /* check and reset timeout value every lap */ 652 time_t timeout = Curl_pp_state_timeout(pp, FALSE); 653 time_t interval_ms; 654 655 if(timeout <= 0) { 656 failf(data, "FTP response timeout"); 657 return CURLE_OPERATION_TIMEDOUT; /* already too little time */ 658 } 659 660 interval_ms = 1000; /* use 1 second timeout intervals */ 661 if(timeout < interval_ms) 662 interval_ms = timeout; 663 664 /* 665 * Since this function is blocking, we need to wait here for input on the 666 * connection and only then we call the response reading function. We do 667 * timeout at least every second to make the timeout check run. 668 * 669 * A caution here is that the ftp_readresp() function has a cache that may 670 * contain pieces of a response from the previous invoke and we need to 671 * make sure we don't just wait for input while there is unhandled data in 672 * that cache. But also, if the cache is there, we call ftp_readresp() and 673 * the cache wasn't good enough to continue we must not just busy-loop 674 * around this function. 675 * 676 */ 677 678 if(pp->cache && (cache_skip < 2)) { 679 /* 680 * There's a cache left since before. We then skipping the wait for 681 * socket action, unless this is the same cache like the previous round 682 * as then the cache was deemed not enough to act on and we then need to 683 * wait for more data anyway. 684 */ 685 } 686 else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { 687 switch(SOCKET_READABLE(sockfd, interval_ms)) { 688 case -1: /* select() error, stop reading */ 689 failf(data, "FTP response aborted due to select/poll error: %d", 690 SOCKERRNO); 691 return CURLE_RECV_ERROR; 692 693 case 0: /* timeout */ 694 if(Curl_pgrsUpdate(conn)) 695 return CURLE_ABORTED_BY_CALLBACK; 696 continue; /* just continue in our loop for the timeout duration */ 697 698 default: /* for clarity */ 699 break; 700 } 701 } 702 result = ftp_readresp(sockfd, pp, ftpcode, &nread); 703 if(result) 704 break; 705 706 if(!nread && pp->cache) 707 /* bump cache skip counter as on repeated skips we must wait for more 708 data */ 709 cache_skip++; 710 else 711 /* when we got data or there is no cache left, we reset the cache skip 712 counter */ 713 cache_skip = 0; 714 715 *nreadp += nread; 716 717 } /* while there's buffer left and loop is requested */ 718 719 pp->pending_resp = FALSE; 720 721 return result; 722 } 723 724 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 725 /* for debug purposes */ 726 static const char * const ftp_state_names[]={ 727 "STOP", 728 "WAIT220", 729 "AUTH", 730 "USER", 731 "PASS", 732 "ACCT", 733 "PBSZ", 734 "PROT", 735 "CCC", 736 "PWD", 737 "SYST", 738 "NAMEFMT", 739 "QUOTE", 740 "RETR_PREQUOTE", 741 "STOR_PREQUOTE", 742 "POSTQUOTE", 743 "CWD", 744 "MKD", 745 "MDTM", 746 "TYPE", 747 "LIST_TYPE", 748 "RETR_TYPE", 749 "STOR_TYPE", 750 "SIZE", 751 "RETR_SIZE", 752 "STOR_SIZE", 753 "REST", 754 "RETR_REST", 755 "PORT", 756 "PRET", 757 "PASV", 758 "LIST", 759 "RETR", 760 "STOR", 761 "QUIT" 762 }; 763 #endif 764 765 /* This is the ONLY way to change FTP state! */ 766 static void _state(struct connectdata *conn, 767 ftpstate newstate 768 #ifdef DEBUGBUILD 769 , int lineno 770 #endif 771 ) 772 { 773 struct ftp_conn *ftpc = &conn->proto.ftpc; 774 775 #if defined(DEBUGBUILD) 776 777 #if defined(CURL_DISABLE_VERBOSE_STRINGS) 778 (void) lineno; 779 #else 780 if(ftpc->state != newstate) 781 infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", 782 (void *)ftpc, lineno, ftp_state_names[ftpc->state], 783 ftp_state_names[newstate]); 784 #endif 785 #endif 786 787 ftpc->state = newstate; 788 } 789 790 static CURLcode ftp_state_user(struct connectdata *conn) 791 { 792 CURLcode result; 793 struct FTP *ftp = conn->data->req.protop; 794 /* send USER */ 795 PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); 796 797 state(conn, FTP_USER); 798 conn->data->state.ftp_trying_alternative = FALSE; 799 800 return CURLE_OK; 801 } 802 803 static CURLcode ftp_state_pwd(struct connectdata *conn) 804 { 805 CURLcode result; 806 807 /* send PWD to discover our entry point */ 808 PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD"); 809 state(conn, FTP_PWD); 810 811 return CURLE_OK; 812 } 813 814 /* For the FTP "protocol connect" and "doing" phases only */ 815 static int ftp_getsock(struct connectdata *conn, 816 curl_socket_t *socks, 817 int numsocks) 818 { 819 return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); 820 } 821 822 /* For the FTP "DO_MORE" phase only */ 823 static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, 824 int numsocks) 825 { 826 struct ftp_conn *ftpc = &conn->proto.ftpc; 827 828 if(!numsocks) 829 return GETSOCK_BLANK; 830 831 /* When in DO_MORE state, we could be either waiting for us to connect to a 832 * remote site, or we could wait for that site to connect to us. Or just 833 * handle ordinary commands. 834 */ 835 836 if(FTP_STOP == ftpc->state) { 837 int bits = GETSOCK_READSOCK(0); 838 839 /* if stopped and still in this state, then we're also waiting for a 840 connect on the secondary connection */ 841 socks[0] = conn->sock[FIRSTSOCKET]; 842 843 if(!conn->data->set.ftp_use_port) { 844 int s; 845 int i; 846 /* PORT is used to tell the server to connect to us, and during that we 847 don't do happy eyeballs, but we do if we connect to the server */ 848 for(s = 1, i = 0; i<2; i++) { 849 if(conn->tempsock[i] != CURL_SOCKET_BAD) { 850 socks[s] = conn->tempsock[i]; 851 bits |= GETSOCK_WRITESOCK(s++); 852 } 853 } 854 } 855 else { 856 socks[1] = conn->sock[SECONDARYSOCKET]; 857 bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1); 858 } 859 860 return bits; 861 } 862 return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); 863 } 864 865 /* This is called after the FTP_QUOTE state is passed. 866 867 ftp_state_cwd() sends the range of CWD commands to the server to change to 868 the correct directory. It may also need to send MKD commands to create 869 missing ones, if that option is enabled. 870 */ 871 static CURLcode ftp_state_cwd(struct connectdata *conn) 872 { 873 CURLcode result = CURLE_OK; 874 struct ftp_conn *ftpc = &conn->proto.ftpc; 875 876 if(ftpc->cwddone) 877 /* already done and fine */ 878 result = ftp_state_mdtm(conn); 879 else { 880 ftpc->count2 = 0; /* count2 counts failed CWDs */ 881 882 /* count3 is set to allow a MKD to fail once. In the case when first CWD 883 fails and then MKD fails (due to another session raced it to create the 884 dir) this then allows for a second try to CWD to it */ 885 ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0; 886 887 if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount) 888 /* No CWD necessary */ 889 result = ftp_state_mdtm(conn); 890 else if(conn->bits.reuse && ftpc->entrypath) { 891 /* This is a re-used connection. Since we change directory to where the 892 transfer is taking place, we must first get back to the original dir 893 where we ended up after login: */ 894 ftpc->cwdcount = 0; /* we count this as the first path, then we add one 895 for all upcoming ones in the ftp->dirs[] array */ 896 PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath); 897 state(conn, FTP_CWD); 898 } 899 else { 900 if(ftpc->dirdepth) { 901 ftpc->cwdcount = 1; 902 /* issue the first CWD, the rest is sent when the CWD responses are 903 received... */ 904 PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]); 905 state(conn, FTP_CWD); 906 } 907 else { 908 /* No CWD necessary */ 909 result = ftp_state_mdtm(conn); 910 } 911 } 912 } 913 return result; 914 } 915 916 typedef enum { 917 EPRT, 918 PORT, 919 DONE 920 } ftpport; 921 922 static CURLcode ftp_state_use_port(struct connectdata *conn, 923 ftpport fcmd) /* start with this */ 924 925 { 926 CURLcode result = CURLE_OK; 927 struct ftp_conn *ftpc = &conn->proto.ftpc; 928 struct Curl_easy *data = conn->data; 929 curl_socket_t portsock = CURL_SOCKET_BAD; 930 char myhost[256] = ""; 931 932 struct Curl_sockaddr_storage ss; 933 Curl_addrinfo *res, *ai; 934 curl_socklen_t sslen; 935 char hbuf[NI_MAXHOST]; 936 struct sockaddr *sa = (struct sockaddr *)&ss; 937 struct sockaddr_in * const sa4 = (void *)sa; 938 #ifdef ENABLE_IPV6 939 struct sockaddr_in6 * const sa6 = (void *)sa; 940 #endif 941 char tmp[1024]; 942 static const char mode[][5] = { "EPRT", "PORT" }; 943 int rc; 944 int error; 945 char *host = NULL; 946 char *string_ftpport = data->set.str[STRING_FTPPORT]; 947 struct Curl_dns_entry *h = NULL; 948 unsigned short port_min = 0; 949 unsigned short port_max = 0; 950 unsigned short port; 951 bool possibly_non_local = TRUE; 952 char buffer[STRERROR_LEN]; 953 char *addr = NULL; 954 955 /* Step 1, figure out what is requested, 956 * accepted format : 957 * (ipv4|ipv6|domain|interface)?(:port(-range)?)? 958 */ 959 960 if(data->set.str[STRING_FTPPORT] && 961 (strlen(data->set.str[STRING_FTPPORT]) > 1)) { 962 963 #ifdef ENABLE_IPV6 964 size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ? 965 INET6_ADDRSTRLEN : strlen(string_ftpport); 966 #else 967 size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ? 968 INET_ADDRSTRLEN : strlen(string_ftpport); 969 #endif 970 char *ip_start = string_ftpport; 971 char *ip_end = NULL; 972 char *port_start = NULL; 973 char *port_sep = NULL; 974 975 addr = calloc(addrlen + 1, 1); 976 if(!addr) 977 return CURLE_OUT_OF_MEMORY; 978 979 #ifdef ENABLE_IPV6 980 if(*string_ftpport == '[') { 981 /* [ipv6]:port(-range) */ 982 ip_start = string_ftpport + 1; 983 ip_end = strchr(string_ftpport, ']'); 984 if(ip_end) 985 strncpy(addr, ip_start, ip_end - ip_start); 986 } 987 else 988 #endif 989 if(*string_ftpport == ':') { 990 /* :port */ 991 ip_end = string_ftpport; 992 } 993 else { 994 ip_end = strchr(string_ftpport, ':'); 995 if(ip_end) { 996 /* either ipv6 or (ipv4|domain|interface):port(-range) */ 997 #ifdef ENABLE_IPV6 998 if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { 999 /* ipv6 */ 1000 port_min = port_max = 0; 1001 strcpy(addr, string_ftpport); 1002 ip_end = NULL; /* this got no port ! */ 1003 } 1004 else 1005 #endif 1006 /* (ipv4|domain|interface):port(-range) */ 1007 strncpy(addr, string_ftpport, ip_end - ip_start); 1008 } 1009 else 1010 /* ipv4|interface */ 1011 strcpy(addr, string_ftpport); 1012 } 1013 1014 /* parse the port */ 1015 if(ip_end != NULL) { 1016 port_start = strchr(ip_end, ':'); 1017 if(port_start) { 1018 port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10)); 1019 port_sep = strchr(port_start, '-'); 1020 if(port_sep) { 1021 port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); 1022 } 1023 else 1024 port_max = port_min; 1025 } 1026 } 1027 1028 /* correct errors like: 1029 * :1234-1230 1030 * :-4711, in this case port_min is (unsigned)-1, 1031 * therefore port_min > port_max for all cases 1032 * but port_max = (unsigned)-1 1033 */ 1034 if(port_min > port_max) 1035 port_min = port_max = 0; 1036 1037 1038 if(*addr != '\0') { 1039 /* attempt to get the address of the given interface name */ 1040 switch(Curl_if2ip(conn->ip_addr->ai_family, 1041 Curl_ipv6_scope(conn->ip_addr->ai_addr), 1042 conn->scope_id, addr, hbuf, sizeof(hbuf))) { 1043 case IF2IP_NOT_FOUND: 1044 /* not an interface, use the given string as host name instead */ 1045 host = addr; 1046 break; 1047 case IF2IP_AF_NOT_SUPPORTED: 1048 return CURLE_FTP_PORT_FAILED; 1049 case IF2IP_FOUND: 1050 host = hbuf; /* use the hbuf for host name */ 1051 } 1052 } 1053 else 1054 /* there was only a port(-range) given, default the host */ 1055 host = NULL; 1056 } /* data->set.ftpport */ 1057 1058 if(!host) { 1059 /* not an interface and not a host name, get default by extracting 1060 the IP from the control connection */ 1061 sslen = sizeof(ss); 1062 if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { 1063 failf(data, "getsockname() failed: %s", 1064 Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 1065 free(addr); 1066 return CURLE_FTP_PORT_FAILED; 1067 } 1068 switch(sa->sa_family) { 1069 #ifdef ENABLE_IPV6 1070 case AF_INET6: 1071 Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf)); 1072 break; 1073 #endif 1074 default: 1075 Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf)); 1076 break; 1077 } 1078 host = hbuf; /* use this host name */ 1079 possibly_non_local = FALSE; /* we know it is local now */ 1080 } 1081 1082 /* resolv ip/host to ip */ 1083 rc = Curl_resolv(conn, host, 0, &h); 1084 if(rc == CURLRESOLV_PENDING) 1085 (void)Curl_resolver_wait_resolv(conn, &h); 1086 if(h) { 1087 res = h->addr; 1088 /* when we return from this function, we can forget about this entry 1089 to we can unlock it now already */ 1090 Curl_resolv_unlock(data, h); 1091 } /* (h) */ 1092 else 1093 res = NULL; /* failure! */ 1094 1095 if(res == NULL) { 1096 failf(data, "failed to resolve the address provided to PORT: %s", host); 1097 free(addr); 1098 return CURLE_FTP_PORT_FAILED; 1099 } 1100 1101 free(addr); 1102 host = NULL; 1103 1104 /* step 2, create a socket for the requested address */ 1105 1106 portsock = CURL_SOCKET_BAD; 1107 error = 0; 1108 for(ai = res; ai; ai = ai->ai_next) { 1109 result = Curl_socket(conn, ai, NULL, &portsock); 1110 if(result) { 1111 error = SOCKERRNO; 1112 continue; 1113 } 1114 break; 1115 } 1116 if(!ai) { 1117 failf(data, "socket failure: %s", 1118 Curl_strerror(error, buffer, sizeof(buffer))); 1119 return CURLE_FTP_PORT_FAILED; 1120 } 1121 1122 /* step 3, bind to a suitable local address */ 1123 1124 memcpy(sa, ai->ai_addr, ai->ai_addrlen); 1125 sslen = ai->ai_addrlen; 1126 1127 for(port = port_min; port <= port_max;) { 1128 if(sa->sa_family == AF_INET) 1129 sa4->sin_port = htons(port); 1130 #ifdef ENABLE_IPV6 1131 else 1132 sa6->sin6_port = htons(port); 1133 #endif 1134 /* Try binding the given address. */ 1135 if(bind(portsock, sa, sslen) ) { 1136 /* It failed. */ 1137 error = SOCKERRNO; 1138 if(possibly_non_local && (error == EADDRNOTAVAIL)) { 1139 /* The requested bind address is not local. Use the address used for 1140 * the control connection instead and restart the port loop 1141 */ 1142 infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, 1143 Curl_strerror(error, buffer, sizeof(buffer))); 1144 1145 sslen = sizeof(ss); 1146 if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { 1147 failf(data, "getsockname() failed: %s", 1148 Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 1149 Curl_closesocket(conn, portsock); 1150 return CURLE_FTP_PORT_FAILED; 1151 } 1152 port = port_min; 1153 possibly_non_local = FALSE; /* don't try this again */ 1154 continue; 1155 } 1156 if(error != EADDRINUSE && error != EACCES) { 1157 failf(data, "bind(port=%hu) failed: %s", port, 1158 Curl_strerror(error, buffer, sizeof(buffer))); 1159 Curl_closesocket(conn, portsock); 1160 return CURLE_FTP_PORT_FAILED; 1161 } 1162 } 1163 else 1164 break; 1165 1166 port++; 1167 } 1168 1169 /* maybe all ports were in use already*/ 1170 if(port > port_max) { 1171 failf(data, "bind() failed, we ran out of ports!"); 1172 Curl_closesocket(conn, portsock); 1173 return CURLE_FTP_PORT_FAILED; 1174 } 1175 1176 /* get the name again after the bind() so that we can extract the 1177 port number it uses now */ 1178 sslen = sizeof(ss); 1179 if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { 1180 failf(data, "getsockname() failed: %s", 1181 Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 1182 Curl_closesocket(conn, portsock); 1183 return CURLE_FTP_PORT_FAILED; 1184 } 1185 1186 /* step 4, listen on the socket */ 1187 1188 if(listen(portsock, 1)) { 1189 failf(data, "socket failure: %s", 1190 Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 1191 Curl_closesocket(conn, portsock); 1192 return CURLE_FTP_PORT_FAILED; 1193 } 1194 1195 /* step 5, send the proper FTP command */ 1196 1197 /* get a plain printable version of the numerical address to work with 1198 below */ 1199 Curl_printable_address(ai, myhost, sizeof(myhost)); 1200 1201 #ifdef ENABLE_IPV6 1202 if(!conn->bits.ftp_use_eprt && conn->bits.ipv6) 1203 /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the 1204 request and enable EPRT again! */ 1205 conn->bits.ftp_use_eprt = TRUE; 1206 #endif 1207 1208 for(; fcmd != DONE; fcmd++) { 1209 1210 if(!conn->bits.ftp_use_eprt && (EPRT == fcmd)) 1211 /* if disabled, goto next */ 1212 continue; 1213 1214 if((PORT == fcmd) && sa->sa_family != AF_INET) 1215 /* PORT is IPv4 only */ 1216 continue; 1217 1218 switch(sa->sa_family) { 1219 case AF_INET: 1220 port = ntohs(sa4->sin_port); 1221 break; 1222 #ifdef ENABLE_IPV6 1223 case AF_INET6: 1224 port = ntohs(sa6->sin6_port); 1225 break; 1226 #endif 1227 default: 1228 continue; /* might as well skip this */ 1229 } 1230 1231 if(EPRT == fcmd) { 1232 /* 1233 * Two fine examples from RFC2428; 1234 * 1235 * EPRT |1|132.235.1.2|6275| 1236 * 1237 * EPRT |2|1080::8:800:200C:417A|5282| 1238 */ 1239 1240 result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], 1241 sa->sa_family == AF_INET?1:2, 1242 myhost, port); 1243 if(result) { 1244 failf(data, "Failure sending EPRT command: %s", 1245 curl_easy_strerror(result)); 1246 Curl_closesocket(conn, portsock); 1247 /* don't retry using PORT */ 1248 ftpc->count1 = PORT; 1249 /* bail out */ 1250 state(conn, FTP_STOP); 1251 return result; 1252 } 1253 break; 1254 } 1255 if(PORT == fcmd) { 1256 char *source = myhost; 1257 char *dest = tmp; 1258 1259 /* translate x.x.x.x to x,x,x,x */ 1260 while(source && *source) { 1261 if(*source == '.') 1262 *dest = ','; 1263 else 1264 *dest = *source; 1265 dest++; 1266 source++; 1267 } 1268 *dest = 0; 1269 msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); 1270 1271 result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); 1272 if(result) { 1273 failf(data, "Failure sending PORT command: %s", 1274 curl_easy_strerror(result)); 1275 Curl_closesocket(conn, portsock); 1276 /* bail out */ 1277 state(conn, FTP_STOP); 1278 return result; 1279 } 1280 break; 1281 } 1282 } 1283 1284 /* store which command was sent */ 1285 ftpc->count1 = fcmd; 1286 1287 close_secondarysocket(conn); 1288 1289 /* we set the secondary socket variable to this for now, it is only so that 1290 the cleanup function will close it in case we fail before the true 1291 secondary stuff is made */ 1292 conn->sock[SECONDARYSOCKET] = portsock; 1293 1294 /* this tcpconnect assignment below is a hackish work-around to make the 1295 multi interface with active FTP work - as it will not wait for a 1296 (passive) connect in Curl_is_connected(). 1297 1298 The *proper* fix is to make sure that the active connection from the 1299 server is done in a non-blocking way. Currently, it is still BLOCKING. 1300 */ 1301 conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; 1302 1303 state(conn, FTP_PORT); 1304 return result; 1305 } 1306 1307 static CURLcode ftp_state_use_pasv(struct connectdata *conn) 1308 { 1309 struct ftp_conn *ftpc = &conn->proto.ftpc; 1310 CURLcode result = CURLE_OK; 1311 /* 1312 Here's the excecutive summary on what to do: 1313 1314 PASV is RFC959, expect: 1315 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) 1316 1317 LPSV is RFC1639, expect: 1318 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) 1319 1320 EPSV is RFC2428, expect: 1321 229 Entering Extended Passive Mode (|||port|) 1322 1323 */ 1324 1325 static const char mode[][5] = { "EPSV", "PASV" }; 1326 int modeoff; 1327 1328 #ifdef PF_INET6 1329 if(!conn->bits.ftp_use_epsv && conn->bits.ipv6) 1330 /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the 1331 request and enable EPSV again! */ 1332 conn->bits.ftp_use_epsv = TRUE; 1333 #endif 1334 1335 modeoff = conn->bits.ftp_use_epsv?0:1; 1336 1337 PPSENDF(&ftpc->pp, "%s", mode[modeoff]); 1338 1339 ftpc->count1 = modeoff; 1340 state(conn, FTP_PASV); 1341 infof(conn->data, "Connect data stream passively\n"); 1342 1343 return result; 1344 } 1345 1346 /* 1347 * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc. 1348 * 1349 * REST is the last command in the chain of commands when a "head"-like 1350 * request is made. Thus, if an actual transfer is to be made this is where we 1351 * take off for real. 1352 */ 1353 static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) 1354 { 1355 CURLcode result = CURLE_OK; 1356 struct FTP *ftp = conn->data->req.protop; 1357 struct Curl_easy *data = conn->data; 1358 1359 if(ftp->transfer != FTPTRANSFER_BODY) { 1360 /* doesn't transfer any data */ 1361 1362 /* still possibly do PRE QUOTE jobs */ 1363 state(conn, FTP_RETR_PREQUOTE); 1364 result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); 1365 } 1366 else if(data->set.ftp_use_port) { 1367 /* We have chosen to use the PORT (or similar) command */ 1368 result = ftp_state_use_port(conn, EPRT); 1369 } 1370 else { 1371 /* We have chosen (this is default) to use the PASV (or similar) command */ 1372 if(data->set.ftp_use_pret) { 1373 /* The user has requested that we send a PRET command 1374 to prepare the server for the upcoming PASV */ 1375 if(!conn->proto.ftpc.file) { 1376 PPSENDF(&conn->proto.ftpc.pp, "PRET %s", 1377 data->set.str[STRING_CUSTOMREQUEST]? 1378 data->set.str[STRING_CUSTOMREQUEST]: 1379 (data->set.ftp_list_only?"NLST":"LIST")); 1380 } 1381 else if(data->set.upload) { 1382 PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file); 1383 } 1384 else { 1385 PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file); 1386 } 1387 state(conn, FTP_PRET); 1388 } 1389 else { 1390 result = ftp_state_use_pasv(conn); 1391 } 1392 } 1393 return result; 1394 } 1395 1396 static CURLcode ftp_state_rest(struct connectdata *conn) 1397 { 1398 CURLcode result = CURLE_OK; 1399 struct FTP *ftp = conn->data->req.protop; 1400 struct ftp_conn *ftpc = &conn->proto.ftpc; 1401 1402 if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { 1403 /* if a "head"-like request is being made (on a file) */ 1404 1405 /* Determine if server can respond to REST command and therefore 1406 whether it supports range */ 1407 PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0); 1408 1409 state(conn, FTP_REST); 1410 } 1411 else 1412 result = ftp_state_prepare_transfer(conn); 1413 1414 return result; 1415 } 1416 1417 static CURLcode ftp_state_size(struct connectdata *conn) 1418 { 1419 CURLcode result = CURLE_OK; 1420 struct FTP *ftp = conn->data->req.protop; 1421 struct ftp_conn *ftpc = &conn->proto.ftpc; 1422 1423 if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { 1424 /* if a "head"-like request is being made (on a file) */ 1425 1426 /* we know ftpc->file is a valid pointer to a file name */ 1427 PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); 1428 1429 state(conn, FTP_SIZE); 1430 } 1431 else 1432 result = ftp_state_rest(conn); 1433 1434 return result; 1435 } 1436 1437 static CURLcode ftp_state_list(struct connectdata *conn) 1438 { 1439 CURLcode result = CURLE_OK; 1440 struct Curl_easy *data = conn->data; 1441 struct FTP *ftp = data->req.protop; 1442 1443 /* If this output is to be machine-parsed, the NLST command might be better 1444 to use, since the LIST command output is not specified or standard in any 1445 way. It has turned out that the NLST list output is not the same on all 1446 servers either... */ 1447 1448 /* 1449 if FTPFILE_NOCWD was specified, we are currently in 1450 the user's home directory, so we should add the path 1451 as argument for the LIST / NLST / or custom command. 1452 Whether the server will support this, is uncertain. 1453 1454 The other ftp_filemethods will CWD into dir/dir/ first and 1455 then just do LIST (in that case: nothing to do here) 1456 */ 1457 char *cmd, *lstArg, *slashPos; 1458 const char *inpath = ftp->path; 1459 1460 lstArg = NULL; 1461 if((data->set.ftp_filemethod == FTPFILE_NOCWD) && 1462 inpath && inpath[0] && strchr(inpath, '/')) { 1463 size_t n = strlen(inpath); 1464 1465 /* Check if path does not end with /, as then we cut off the file part */ 1466 if(inpath[n - 1] != '/') { 1467 /* chop off the file part if format is dir/dir/file */ 1468 slashPos = strrchr(inpath, '/'); 1469 n = slashPos - inpath; 1470 } 1471 result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE); 1472 if(result) 1473 return result; 1474 } 1475 1476 cmd = aprintf("%s%s%s", 1477 data->set.str[STRING_CUSTOMREQUEST]? 1478 data->set.str[STRING_CUSTOMREQUEST]: 1479 (data->set.ftp_list_only?"NLST":"LIST"), 1480 lstArg? " ": "", 1481 lstArg? lstArg: ""); 1482 1483 if(!cmd) { 1484 free(lstArg); 1485 return CURLE_OUT_OF_MEMORY; 1486 } 1487 1488 result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); 1489 1490 free(lstArg); 1491 free(cmd); 1492 1493 if(result) 1494 return result; 1495 1496 state(conn, FTP_LIST); 1497 1498 return result; 1499 } 1500 1501 static CURLcode ftp_state_retr_prequote(struct connectdata *conn) 1502 { 1503 CURLcode result = CURLE_OK; 1504 1505 /* We've sent the TYPE, now we must send the list of prequote strings */ 1506 1507 result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); 1508 1509 return result; 1510 } 1511 1512 static CURLcode ftp_state_stor_prequote(struct connectdata *conn) 1513 { 1514 CURLcode result = CURLE_OK; 1515 1516 /* We've sent the TYPE, now we must send the list of prequote strings */ 1517 1518 result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE); 1519 1520 return result; 1521 } 1522 1523 static CURLcode ftp_state_type(struct connectdata *conn) 1524 { 1525 CURLcode result = CURLE_OK; 1526 struct FTP *ftp = conn->data->req.protop; 1527 struct Curl_easy *data = conn->data; 1528 struct ftp_conn *ftpc = &conn->proto.ftpc; 1529 1530 /* If we have selected NOBODY and HEADER, it means that we only want file 1531 information. Which in FTP can't be much more than the file size and 1532 date. */ 1533 if(data->set.opt_no_body && ftpc->file && 1534 ftp_need_type(conn, data->set.prefer_ascii)) { 1535 /* The SIZE command is _not_ RFC 959 specified, and therefore many servers 1536 may not support it! It is however the only way we have to get a file's 1537 size! */ 1538 1539 ftp->transfer = FTPTRANSFER_INFO; 1540 /* this means no actual transfer will be made */ 1541 1542 /* Some servers return different sizes for different modes, and thus we 1543 must set the proper type before we check the size */ 1544 result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); 1545 if(result) 1546 return result; 1547 } 1548 else 1549 result = ftp_state_size(conn); 1550 1551 return result; 1552 } 1553 1554 /* This is called after the CWD commands have been done in the beginning of 1555 the DO phase */ 1556 static CURLcode ftp_state_mdtm(struct connectdata *conn) 1557 { 1558 CURLcode result = CURLE_OK; 1559 struct Curl_easy *data = conn->data; 1560 struct ftp_conn *ftpc = &conn->proto.ftpc; 1561 1562 /* Requested time of file or time-depended transfer? */ 1563 if((data->set.get_filetime || data->set.timecondition) && ftpc->file) { 1564 1565 /* we have requested to get the modified-time of the file, this is a white 1566 spot as the MDTM is not mentioned in RFC959 */ 1567 PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file); 1568 1569 state(conn, FTP_MDTM); 1570 } 1571 else 1572 result = ftp_state_type(conn); 1573 1574 return result; 1575 } 1576 1577 1578 /* This is called after the TYPE and possible quote commands have been sent */ 1579 static CURLcode ftp_state_ul_setup(struct connectdata *conn, 1580 bool sizechecked) 1581 { 1582 CURLcode result = CURLE_OK; 1583 struct FTP *ftp = conn->data->req.protop; 1584 struct Curl_easy *data = conn->data; 1585 struct ftp_conn *ftpc = &conn->proto.ftpc; 1586 1587 if((data->state.resume_from && !sizechecked) || 1588 ((data->state.resume_from > 0) && sizechecked)) { 1589 /* we're about to continue the uploading of a file */ 1590 /* 1. get already existing file's size. We use the SIZE command for this 1591 which may not exist in the server! The SIZE command is not in 1592 RFC959. */ 1593 1594 /* 2. This used to set REST. But since we can do append, we 1595 don't another ftp command. We just skip the source file 1596 offset and then we APPEND the rest on the file instead */ 1597 1598 /* 3. pass file-size number of bytes in the source file */ 1599 /* 4. lower the infilesize counter */ 1600 /* => transfer as usual */ 1601 int seekerr = CURL_SEEKFUNC_OK; 1602 1603 if(data->state.resume_from < 0) { 1604 /* Got no given size to start from, figure it out */ 1605 PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); 1606 state(conn, FTP_STOR_SIZE); 1607 return result; 1608 } 1609 1610 /* enable append */ 1611 data->set.ftp_append = TRUE; 1612 1613 /* Let's read off the proper amount of bytes from the input. */ 1614 if(conn->seek_func) { 1615 Curl_set_in_callback(data, true); 1616 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, 1617 SEEK_SET); 1618 Curl_set_in_callback(data, false); 1619 } 1620 1621 if(seekerr != CURL_SEEKFUNC_OK) { 1622 curl_off_t passed = 0; 1623 if(seekerr != CURL_SEEKFUNC_CANTSEEK) { 1624 failf(data, "Could not seek stream"); 1625 return CURLE_FTP_COULDNT_USE_REST; 1626 } 1627 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ 1628 do { 1629 size_t readthisamountnow = 1630 (data->state.resume_from - passed > data->set.buffer_size) ? 1631 (size_t)data->set.buffer_size : 1632 curlx_sotouz(data->state.resume_from - passed); 1633 1634 size_t actuallyread = 1635 data->state.fread_func(data->state.buffer, 1, readthisamountnow, 1636 data->state.in); 1637 1638 passed += actuallyread; 1639 if((actuallyread == 0) || (actuallyread > readthisamountnow)) { 1640 /* this checks for greater-than only to make sure that the 1641 CURL_READFUNC_ABORT return code still aborts */ 1642 failf(data, "Failed to read data"); 1643 return CURLE_FTP_COULDNT_USE_REST; 1644 } 1645 } while(passed < data->state.resume_from); 1646 } 1647 /* now, decrease the size of the read */ 1648 if(data->state.infilesize>0) { 1649 data->state.infilesize -= data->state.resume_from; 1650 1651 if(data->state.infilesize <= 0) { 1652 infof(data, "File already completely uploaded\n"); 1653 1654 /* no data to transfer */ 1655 Curl_setup_transfer(data, -1, -1, FALSE, -1); 1656 1657 /* Set ->transfer so that we won't get any error in 1658 * ftp_done() because we didn't transfer anything! */ 1659 ftp->transfer = FTPTRANSFER_NONE; 1660 1661 state(conn, FTP_STOP); 1662 return CURLE_OK; 1663 } 1664 } 1665 /* we've passed, proceed as normal */ 1666 } /* resume_from */ 1667 1668 PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", 1669 ftpc->file); 1670 1671 state(conn, FTP_STOR); 1672 1673 return result; 1674 } 1675 1676 static CURLcode ftp_state_quote(struct connectdata *conn, 1677 bool init, 1678 ftpstate instate) 1679 { 1680 CURLcode result = CURLE_OK; 1681 struct Curl_easy *data = conn->data; 1682 struct FTP *ftp = data->req.protop; 1683 struct ftp_conn *ftpc = &conn->proto.ftpc; 1684 bool quote = FALSE; 1685 struct curl_slist *item; 1686 1687 switch(instate) { 1688 case FTP_QUOTE: 1689 default: 1690 item = data->set.quote; 1691 break; 1692 case FTP_RETR_PREQUOTE: 1693 case FTP_STOR_PREQUOTE: 1694 item = data->set.prequote; 1695 break; 1696 case FTP_POSTQUOTE: 1697 item = data->set.postquote; 1698 break; 1699 } 1700 1701 /* 1702 * This state uses: 1703 * 'count1' to iterate over the commands to send 1704 * 'count2' to store whether to allow commands to fail 1705 */ 1706 1707 if(init) 1708 ftpc->count1 = 0; 1709 else 1710 ftpc->count1++; 1711 1712 if(item) { 1713 int i = 0; 1714 1715 /* Skip count1 items in the linked list */ 1716 while((i< ftpc->count1) && item) { 1717 item = item->next; 1718 i++; 1719 } 1720 if(item) { 1721 char *cmd = item->data; 1722 if(cmd[0] == '*') { 1723 cmd++; 1724 ftpc->count2 = 1; /* the sent command is allowed to fail */ 1725 } 1726 else 1727 ftpc->count2 = 0; /* failure means cancel operation */ 1728 1729 PPSENDF(&ftpc->pp, "%s", cmd); 1730 state(conn, instate); 1731 quote = TRUE; 1732 } 1733 } 1734 1735 if(!quote) { 1736 /* No more quote to send, continue to ... */ 1737 switch(instate) { 1738 case FTP_QUOTE: 1739 default: 1740 result = ftp_state_cwd(conn); 1741 break; 1742 case FTP_RETR_PREQUOTE: 1743 if(ftp->transfer != FTPTRANSFER_BODY) 1744 state(conn, FTP_STOP); 1745 else { 1746 if(ftpc->known_filesize != -1) { 1747 Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); 1748 result = ftp_state_retr(conn, ftpc->known_filesize); 1749 } 1750 else { 1751 if(data->set.ignorecl) { 1752 /* This code is to support download of growing files. It prevents 1753 the state machine from requesting the file size from the 1754 server. With an unknown file size the download continues until 1755 the server terminates it, otherwise the client stops if the 1756 received byte count exceeds the reported file size. Set option 1757 CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/ 1758 PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); 1759 state(conn, FTP_RETR); 1760 } 1761 else { 1762 PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); 1763 state(conn, FTP_RETR_SIZE); 1764 } 1765 } 1766 } 1767 break; 1768 case FTP_STOR_PREQUOTE: 1769 result = ftp_state_ul_setup(conn, FALSE); 1770 break; 1771 case FTP_POSTQUOTE: 1772 break; 1773 } 1774 } 1775 1776 return result; 1777 } 1778 1779 /* called from ftp_state_pasv_resp to switch to PASV in case of EPSV 1780 problems */ 1781 static CURLcode ftp_epsv_disable(struct connectdata *conn) 1782 { 1783 CURLcode result = CURLE_OK; 1784 1785 if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) { 1786 /* We can't disable EPSV when doing IPv6, so this is instead a fail */ 1787 failf(conn->data, "Failed EPSV attempt, exiting\n"); 1788 return CURLE_WEIRD_SERVER_REPLY; 1789 } 1790 1791 infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); 1792 /* disable it for next transfer */ 1793 conn->bits.ftp_use_epsv = FALSE; 1794 conn->data->state.errorbuf = FALSE; /* allow error message to get 1795 rewritten */ 1796 PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV"); 1797 conn->proto.ftpc.count1++; 1798 /* remain in/go to the FTP_PASV state */ 1799 state(conn, FTP_PASV); 1800 return result; 1801 } 1802 1803 1804 static char *control_address(struct connectdata *conn) 1805 { 1806 /* Returns the control connection IP address. 1807 If a proxy tunnel is used, returns the original host name instead, because 1808 the effective control connection address is the proxy address, 1809 not the ftp host. */ 1810 if(conn->bits.tunnel_proxy || conn->bits.socksproxy) 1811 return conn->host.name; 1812 1813 return conn->ip_addr_str; 1814 } 1815 1816 static CURLcode ftp_state_pasv_resp(struct connectdata *conn, 1817 int ftpcode) 1818 { 1819 struct ftp_conn *ftpc = &conn->proto.ftpc; 1820 CURLcode result; 1821 struct Curl_easy *data = conn->data; 1822 struct Curl_dns_entry *addr = NULL; 1823 int rc; 1824 unsigned short connectport; /* the local port connect() should use! */ 1825 char *str = &data->state.buffer[4]; /* start on the first letter */ 1826 1827 /* if we come here again, make sure the former name is cleared */ 1828 Curl_safefree(ftpc->newhost); 1829 1830 if((ftpc->count1 == 0) && 1831 (ftpcode == 229)) { 1832 /* positive EPSV response */ 1833 char *ptr = strchr(str, '('); 1834 if(ptr) { 1835 unsigned int num; 1836 char separator[4]; 1837 ptr++; 1838 if(5 == sscanf(ptr, "%c%c%c%u%c", 1839 &separator[0], 1840 &separator[1], 1841 &separator[2], 1842 &num, 1843 &separator[3])) { 1844 const char sep1 = separator[0]; 1845 int i; 1846 1847 /* The four separators should be identical, or else this is an oddly 1848 formatted reply and we bail out immediately. */ 1849 for(i = 1; i<4; i++) { 1850 if(separator[i] != sep1) { 1851 ptr = NULL; /* set to NULL to signal error */ 1852 break; 1853 } 1854 } 1855 if(num > 0xffff) { 1856 failf(data, "Illegal port number in EPSV reply"); 1857 return CURLE_FTP_WEIRD_PASV_REPLY; 1858 } 1859 if(ptr) { 1860 ftpc->newport = (unsigned short)(num & 0xffff); 1861 ftpc->newhost = strdup(control_address(conn)); 1862 if(!ftpc->newhost) 1863 return CURLE_OUT_OF_MEMORY; 1864 } 1865 } 1866 else 1867 ptr = NULL; 1868 } 1869 if(!ptr) { 1870 failf(data, "Weirdly formatted EPSV reply"); 1871 return CURLE_FTP_WEIRD_PASV_REPLY; 1872 } 1873 } 1874 else if((ftpc->count1 == 1) && 1875 (ftpcode == 227)) { 1876 /* positive PASV response */ 1877 unsigned int ip[4]; 1878 unsigned int port[2]; 1879 1880 /* 1881 * Scan for a sequence of six comma-separated numbers and use them as 1882 * IP+port indicators. 1883 * 1884 * Found reply-strings include: 1885 * "227 Entering Passive Mode (127,0,0,1,4,51)" 1886 * "227 Data transfer will passively listen to 127,0,0,1,4,51" 1887 * "227 Entering passive mode. 127,0,0,1,4,51" 1888 */ 1889 while(*str) { 1890 if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u", 1891 &ip[0], &ip[1], &ip[2], &ip[3], 1892 &port[0], &port[1])) 1893 break; 1894 str++; 1895 } 1896 1897 if(!*str || (ip[0] > 255) || (ip[1] > 255) || (ip[2] > 255) || 1898 (ip[3] > 255) || (port[0] > 255) || (port[1] > 255) ) { 1899 failf(data, "Couldn't interpret the 227-response"); 1900 return CURLE_FTP_WEIRD_227_FORMAT; 1901 } 1902 1903 /* we got OK from server */ 1904 if(data->set.ftp_skip_ip) { 1905 /* told to ignore the remotely given IP but instead use the host we used 1906 for the control connection */ 1907 infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n", 1908 ip[0], ip[1], ip[2], ip[3], 1909 conn->host.name); 1910 ftpc->newhost = strdup(control_address(conn)); 1911 } 1912 else 1913 ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); 1914 1915 if(!ftpc->newhost) 1916 return CURLE_OUT_OF_MEMORY; 1917 1918 ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); 1919 } 1920 else if(ftpc->count1 == 0) { 1921 /* EPSV failed, move on to PASV */ 1922 return ftp_epsv_disable(conn); 1923 } 1924 else { 1925 failf(data, "Bad PASV/EPSV response: %03d", ftpcode); 1926 return CURLE_FTP_WEIRD_PASV_REPLY; 1927 } 1928 1929 if(conn->bits.proxy) { 1930 /* 1931 * This connection uses a proxy and we need to connect to the proxy again 1932 * here. We don't want to rely on a former host lookup that might've 1933 * expired now, instead we remake the lookup here and now! 1934 */ 1935 const char * const host_name = conn->bits.socksproxy ? 1936 conn->socks_proxy.host.name : conn->http_proxy.host.name; 1937 rc = Curl_resolv(conn, host_name, (int)conn->port, &addr); 1938 if(rc == CURLRESOLV_PENDING) 1939 /* BLOCKING, ignores the return code but 'addr' will be NULL in 1940 case of failure */ 1941 (void)Curl_resolver_wait_resolv(conn, &addr); 1942 1943 connectport = 1944 (unsigned short)conn->port; /* we connect to the proxy's port */ 1945 1946 if(!addr) { 1947 failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); 1948 return CURLE_COULDNT_RESOLVE_PROXY; 1949 } 1950 } 1951 else { 1952 /* normal, direct, ftp connection */ 1953 rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr); 1954 if(rc == CURLRESOLV_PENDING) 1955 /* BLOCKING */ 1956 (void)Curl_resolver_wait_resolv(conn, &addr); 1957 1958 connectport = ftpc->newport; /* we connect to the remote port */ 1959 1960 if(!addr) { 1961 failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport); 1962 return CURLE_FTP_CANT_GET_HOST; 1963 } 1964 } 1965 1966 conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; 1967 result = Curl_connecthost(conn, addr); 1968 1969 if(result) { 1970 Curl_resolv_unlock(data, addr); /* we're done using this address */ 1971 if(ftpc->count1 == 0 && ftpcode == 229) 1972 return ftp_epsv_disable(conn); 1973 1974 return result; 1975 } 1976 1977 1978 /* 1979 * When this is used from the multi interface, this might've returned with 1980 * the 'connected' set to FALSE and thus we are now awaiting a non-blocking 1981 * connect to connect. 1982 */ 1983 1984 if(data->set.verbose) 1985 /* this just dumps information about this second connection */ 1986 ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); 1987 1988 Curl_resolv_unlock(data, addr); /* we're done using this address */ 1989 1990 Curl_safefree(conn->secondaryhostname); 1991 conn->secondary_port = ftpc->newport; 1992 conn->secondaryhostname = strdup(ftpc->newhost); 1993 if(!conn->secondaryhostname) 1994 return CURLE_OUT_OF_MEMORY; 1995 1996 conn->bits.do_more = TRUE; 1997 state(conn, FTP_STOP); /* this phase is completed */ 1998 1999 return result; 2000 } 2001 2002 static CURLcode ftp_state_port_resp(struct connectdata *conn, 2003 int ftpcode) 2004 { 2005 struct Curl_easy *data = conn->data; 2006 struct ftp_conn *ftpc = &conn->proto.ftpc; 2007 ftpport fcmd = (ftpport)ftpc->count1; 2008 CURLcode result = CURLE_OK; 2009 2010 /* The FTP spec tells a positive response should have code 200. 2011 Be more permissive here to tolerate deviant servers. */ 2012 if(ftpcode / 100 != 2) { 2013 /* the command failed */ 2014 2015 if(EPRT == fcmd) { 2016 infof(data, "disabling EPRT usage\n"); 2017 conn->bits.ftp_use_eprt = FALSE; 2018 } 2019 fcmd++; 2020 2021 if(fcmd == DONE) { 2022 failf(data, "Failed to do PORT"); 2023 result = CURLE_FTP_PORT_FAILED; 2024 } 2025 else 2026 /* try next */ 2027 result = ftp_state_use_port(conn, fcmd); 2028 } 2029 else { 2030 infof(data, "Connect data stream actively\n"); 2031 state(conn, FTP_STOP); /* end of DO phase */ 2032 result = ftp_dophase_done(conn, FALSE); 2033 } 2034 2035 return result; 2036 } 2037 2038 static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, 2039 int ftpcode) 2040 { 2041 CURLcode result = CURLE_OK; 2042 struct Curl_easy *data = conn->data; 2043 struct FTP *ftp = data->req.protop; 2044 struct ftp_conn *ftpc = &conn->proto.ftpc; 2045 2046 switch(ftpcode) { 2047 case 213: 2048 { 2049 /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the 2050 last .sss part is optional and means fractions of a second */ 2051 int year, month, day, hour, minute, second; 2052 if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d", 2053 &year, &month, &day, &hour, &minute, &second)) { 2054 /* we have a time, reformat it */ 2055 char timebuf[24]; 2056 time_t secs = time(NULL); 2057 2058 msnprintf(timebuf, sizeof(timebuf), 2059 "%04d%02d%02d %02d:%02d:%02d GMT", 2060 year, month, day, hour, minute, second); 2061 /* now, convert this into a time() value: */ 2062 data->info.filetime = curl_getdate(timebuf, &secs); 2063 } 2064 2065 #ifdef CURL_FTP_HTTPSTYLE_HEAD 2066 /* If we asked for a time of the file and we actually got one as well, 2067 we "emulate" a HTTP-style header in our output. */ 2068 2069 if(data->set.opt_no_body && 2070 ftpc->file && 2071 data->set.get_filetime && 2072 (data->info.filetime >= 0) ) { 2073 char headerbuf[128]; 2074 time_t filetime = data->info.filetime; 2075 struct tm buffer; 2076 const struct tm *tm = &buffer; 2077 2078 result = Curl_gmtime(filetime, &buffer); 2079 if(result) 2080 return result; 2081 2082 /* format: "Tue, 15 Nov 1994 12:45:26" */ 2083 msnprintf(headerbuf, sizeof(headerbuf), 2084 "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", 2085 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], 2086 tm->tm_mday, 2087 Curl_month[tm->tm_mon], 2088 tm->tm_year + 1900, 2089 tm->tm_hour, 2090 tm->tm_min, 2091 tm->tm_sec); 2092 result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0); 2093 if(result) 2094 return result; 2095 } /* end of a ridiculous amount of conditionals */ 2096 #endif 2097 } 2098 break; 2099 default: 2100 infof(data, "unsupported MDTM reply format\n"); 2101 break; 2102 case 550: /* "No such file or directory" */ 2103 failf(data, "Given file does not exist"); 2104 result = CURLE_FTP_COULDNT_RETR_FILE; 2105 break; 2106 } 2107 2108 if(data->set.timecondition) { 2109 if((data->info.filetime > 0) && (data->set.timevalue > 0)) { 2110 switch(data->set.timecondition) { 2111 case CURL_TIMECOND_IFMODSINCE: 2112 default: 2113 if(data->info.filetime <= data->set.timevalue) { 2114 infof(data, "The requested document is not new enough\n"); 2115 ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ 2116 data->info.timecond = TRUE; 2117 state(conn, FTP_STOP); 2118 return CURLE_OK; 2119 } 2120 break; 2121 case CURL_TIMECOND_IFUNMODSINCE: 2122 if(data->info.filetime > data->set.timevalue) { 2123 infof(data, "The requested document is not old enough\n"); 2124 ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ 2125 data->info.timecond = TRUE; 2126 state(conn, FTP_STOP); 2127 return CURLE_OK; 2128 } 2129 break; 2130 } /* switch */ 2131 } 2132 else { 2133 infof(data, "Skipping time comparison\n"); 2134 } 2135 } 2136 2137 if(!result) 2138 result = ftp_state_type(conn); 2139 2140 return result; 2141 } 2142 2143 static CURLcode ftp_state_type_resp(struct connectdata *conn, 2144 int ftpcode, 2145 ftpstate instate) 2146 { 2147 CURLcode result = CURLE_OK; 2148 struct Curl_easy *data = conn->data; 2149 2150 if(ftpcode/100 != 2) { 2151 /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a 2152 successful 'TYPE I'. While that is not as RFC959 says, it is still a 2153 positive response code and we allow that. */ 2154 failf(data, "Couldn't set desired mode"); 2155 return CURLE_FTP_COULDNT_SET_TYPE; 2156 } 2157 if(ftpcode != 200) 2158 infof(data, "Got a %03d response code instead of the assumed 200\n", 2159 ftpcode); 2160 2161 if(instate == FTP_TYPE) 2162 result = ftp_state_size(conn); 2163 else if(instate == FTP_LIST_TYPE) 2164 result = ftp_state_list(conn); 2165 else if(instate == FTP_RETR_TYPE) 2166 result = ftp_state_retr_prequote(conn); 2167 else if(instate == FTP_STOR_TYPE) 2168 result = ftp_state_stor_prequote(conn); 2169 2170 return result; 2171 } 2172 2173 static CURLcode ftp_state_retr(struct connectdata *conn, 2174 curl_off_t filesize) 2175 { 2176 CURLcode result = CURLE_OK; 2177 struct Curl_easy *data = conn->data; 2178 struct FTP *ftp = data->req.protop; 2179 struct ftp_conn *ftpc = &conn->proto.ftpc; 2180 2181 if(data->set.max_filesize && (filesize > data->set.max_filesize)) { 2182 failf(data, "Maximum file size exceeded"); 2183 return CURLE_FILESIZE_EXCEEDED; 2184 } 2185 ftp->downloadsize = filesize; 2186 2187 if(data->state.resume_from) { 2188 /* We always (attempt to) get the size of downloads, so it is done before 2189 this even when not doing resumes. */ 2190 if(filesize == -1) { 2191 infof(data, "ftp server doesn't support SIZE\n"); 2192 /* We couldn't get the size and therefore we can't know if there really 2193 is a part of the file left to get, although the server will just 2194 close the connection when we start the connection so it won't cause 2195 us any harm, just not make us exit as nicely. */ 2196 } 2197 else { 2198 /* We got a file size report, so we check that there actually is a 2199 part of the file left to get, or else we go home. */ 2200 if(data->state.resume_from< 0) { 2201 /* We're supposed to download the last abs(from) bytes */ 2202 if(filesize < -data->state.resume_from) { 2203 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T 2204 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", 2205 data->state.resume_from, filesize); 2206 return CURLE_BAD_DOWNLOAD_RESUME; 2207 } 2208 /* convert to size to download */ 2209 ftp->downloadsize = -data->state.resume_from; 2210 /* download from where? */ 2211 data->state.resume_from = filesize - ftp->downloadsize; 2212 } 2213 else { 2214 if(filesize < data->state.resume_from) { 2215 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T 2216 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", 2217 data->state.resume_from, filesize); 2218 return CURLE_BAD_DOWNLOAD_RESUME; 2219 } 2220 /* Now store the number of bytes we are expected to download */ 2221 ftp->downloadsize = filesize-data->state.resume_from; 2222 } 2223 } 2224 2225 if(ftp->downloadsize == 0) { 2226 /* no data to transfer */ 2227 Curl_setup_transfer(data, -1, -1, FALSE, -1); 2228 infof(data, "File already completely downloaded\n"); 2229 2230 /* Set ->transfer so that we won't get any error in ftp_done() 2231 * because we didn't transfer the any file */ 2232 ftp->transfer = FTPTRANSFER_NONE; 2233 state(conn, FTP_STOP); 2234 return CURLE_OK; 2235 } 2236 2237 /* Set resume file transfer offset */ 2238 infof(data, "Instructs server to resume from offset %" 2239 CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); 2240 2241 PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, 2242 data->state.resume_from); 2243 2244 state(conn, FTP_RETR_REST); 2245 } 2246 else { 2247 /* no resume */ 2248 PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); 2249 state(conn, FTP_RETR); 2250 } 2251 2252 return result; 2253 } 2254 2255 static CURLcode ftp_state_size_resp(struct connectdata *conn, 2256 int ftpcode, 2257 ftpstate instate) 2258 { 2259 CURLcode result = CURLE_OK; 2260 struct Curl_easy *data = conn->data; 2261 curl_off_t filesize = -1; 2262 char *buf = data->state.buffer; 2263 2264 /* get the size from the ascii string: */ 2265 if(ftpcode == 213) 2266 /* ignores parsing errors, which will make the size remain unknown */ 2267 (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize); 2268 2269 if(instate == FTP_SIZE) { 2270 #ifdef CURL_FTP_HTTPSTYLE_HEAD 2271 if(-1 != filesize) { 2272 char clbuf[128]; 2273 msnprintf(clbuf, sizeof(clbuf), 2274 "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); 2275 result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0); 2276 if(result) 2277 return result; 2278 } 2279 #endif 2280 Curl_pgrsSetDownloadSize(data, filesize); 2281 result = ftp_state_rest(conn); 2282 } 2283 else if(instate == FTP_RETR_SIZE) { 2284 Curl_pgrsSetDownloadSize(data, filesize); 2285 result = ftp_state_retr(conn, filesize); 2286 } 2287 else if(instate == FTP_STOR_SIZE) { 2288 data->state.resume_from = filesize; 2289 result = ftp_state_ul_setup(conn, TRUE); 2290 } 2291 2292 return result; 2293 } 2294 2295 static CURLcode ftp_state_rest_resp(struct connectdata *conn, 2296 int ftpcode, 2297 ftpstate instate) 2298 { 2299 CURLcode result = CURLE_OK; 2300 struct ftp_conn *ftpc = &conn->proto.ftpc; 2301 2302 switch(instate) { 2303 case FTP_REST: 2304 default: 2305 #ifdef CURL_FTP_HTTPSTYLE_HEAD 2306 if(ftpcode == 350) { 2307 char buffer[24]= { "Accept-ranges: bytes\r\n" }; 2308 result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0); 2309 if(result) 2310 return result; 2311 } 2312 #endif 2313 result = ftp_state_prepare_transfer(conn); 2314 break; 2315 2316 case FTP_RETR_REST: 2317 if(ftpcode != 350) { 2318 failf(conn->data, "Couldn't use REST"); 2319 result = CURLE_FTP_COULDNT_USE_REST; 2320 } 2321 else { 2322 PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); 2323 state(conn, FTP_RETR); 2324 } 2325 break; 2326 } 2327 2328 return result; 2329 } 2330 2331 static CURLcode ftp_state_stor_resp(struct connectdata *conn, 2332 int ftpcode, ftpstate instate) 2333 { 2334 CURLcode result = CURLE_OK; 2335 struct Curl_easy *data = conn->data; 2336 2337 if(ftpcode >= 400) { 2338 failf(data, "Failed FTP upload: %0d", ftpcode); 2339 state(conn, FTP_STOP); 2340 /* oops, we never close the sockets! */ 2341 return CURLE_UPLOAD_FAILED; 2342 } 2343 2344 conn->proto.ftpc.state_saved = instate; 2345 2346 /* PORT means we are now awaiting the server to connect to us. */ 2347 if(data->set.ftp_use_port) { 2348 bool connected; 2349 2350 state(conn, FTP_STOP); /* no longer in STOR state */ 2351 2352 result = AllowServerConnect(conn, &connected); 2353 if(result) 2354 return result; 2355 2356 if(!connected) { 2357 struct ftp_conn *ftpc = &conn->proto.ftpc; 2358 infof(data, "Data conn was not available immediately\n"); 2359 ftpc->wait_data_conn = TRUE; 2360 } 2361 2362 return CURLE_OK; 2363 } 2364 return InitiateTransfer(conn); 2365 } 2366 2367 /* for LIST and RETR responses */ 2368 static CURLcode ftp_state_get_resp(struct connectdata *conn, 2369 int ftpcode, 2370 ftpstate instate) 2371 { 2372 CURLcode result = CURLE_OK; 2373 struct Curl_easy *data = conn->data; 2374 struct FTP *ftp = data->req.protop; 2375 2376 if((ftpcode == 150) || (ftpcode == 125)) { 2377 2378 /* 2379 A; 2380 150 Opening BINARY mode data connection for /etc/passwd (2241 2381 bytes). (ok, the file is being transferred) 2382 2383 B: 2384 150 Opening ASCII mode data connection for /bin/ls 2385 2386 C: 2387 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). 2388 2389 D: 2390 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes) 2391 2392 E: 2393 125 Data connection already open; Transfer starting. */ 2394 2395 curl_off_t size = -1; /* default unknown size */ 2396 2397 2398 /* 2399 * It appears that there are FTP-servers that return size 0 for files when 2400 * SIZE is used on the file while being in BINARY mode. To work around 2401 * that (stupid) behavior, we attempt to parse the RETR response even if 2402 * the SIZE returned size zero. 2403 * 2404 * Debugging help from Salvatore Sorrentino on February 26, 2003. 2405 */ 2406 2407 if((instate != FTP_LIST) && 2408 !data->set.prefer_ascii && 2409 (ftp->downloadsize < 1)) { 2410 /* 2411 * It seems directory listings either don't show the size or very 2412 * often uses size 0 anyway. ASCII transfers may very well turn out 2413 * that the transferred amount of data is not the same as this line 2414 * tells, why using this number in those cases only confuses us. 2415 * 2416 * Example D above makes this parsing a little tricky */ 2417 char *bytes; 2418 char *buf = data->state.buffer; 2419 bytes = strstr(buf, " bytes"); 2420 if(bytes) { 2421 long in = (long)(--bytes-buf); 2422 /* this is a hint there is size information in there! ;-) */ 2423 while(--in) { 2424 /* scan for the left parenthesis and break there */ 2425 if('(' == *bytes) 2426 break; 2427 /* skip only digits */ 2428 if(!ISDIGIT(*bytes)) { 2429 bytes = NULL; 2430 break; 2431 } 2432 /* one more estep backwards */ 2433 bytes--; 2434 } 2435 /* if we have nothing but digits: */ 2436 if(bytes++) { 2437 /* get the number! */ 2438 (void)curlx_strtoofft(bytes, NULL, 0, &size); 2439 } 2440 } 2441 } 2442 else if(ftp->downloadsize > -1) 2443 size = ftp->downloadsize; 2444 2445 if(size > data->req.maxdownload && data->req.maxdownload > 0) 2446 size = data->req.size = data->req.maxdownload; 2447 else if((instate != FTP_LIST) && (data->set.prefer_ascii)) 2448 size = -1; /* kludge for servers that understate ASCII mode file size */ 2449 2450 infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", 2451 data->req.maxdownload); 2452 2453 if(instate != FTP_LIST) 2454 infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n", 2455 size); 2456 2457 /* FTP download: */ 2458 conn->proto.ftpc.state_saved = instate; 2459 conn->proto.ftpc.retr_size_saved = size; 2460 2461 if(data->set.ftp_use_port) { 2462 bool connected; 2463 2464 result = AllowServerConnect(conn, &connected); 2465 if(result) 2466 return result; 2467 2468 if(!connected) { 2469 struct ftp_conn *ftpc = &conn->proto.ftpc; 2470 infof(data, "Data conn was not available immediately\n"); 2471 state(conn, FTP_STOP); 2472 ftpc->wait_data_conn = TRUE; 2473 } 2474 } 2475 else 2476 return InitiateTransfer(conn); 2477 } 2478 else { 2479 if((instate == FTP_LIST) && (ftpcode == 450)) { 2480 /* simply no matching files in the dir listing */ 2481 ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ 2482 state(conn, FTP_STOP); /* this phase is over */ 2483 } 2484 else { 2485 failf(data, "RETR response: %03d", ftpcode); 2486 return instate == FTP_RETR && ftpcode == 550? 2487 CURLE_REMOTE_FILE_NOT_FOUND: 2488 CURLE_FTP_COULDNT_RETR_FILE; 2489 } 2490 } 2491 2492 return result; 2493 } 2494 2495 /* after USER, PASS and ACCT */ 2496 static CURLcode ftp_state_loggedin(struct connectdata *conn) 2497 { 2498 CURLcode result = CURLE_OK; 2499 2500 if(conn->ssl[FIRSTSOCKET].use) { 2501 /* PBSZ = PROTECTION BUFFER SIZE. 2502 2503 The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says: 2504 2505 Specifically, the PROT command MUST be preceded by a PBSZ 2506 command and a PBSZ command MUST be preceded by a successful 2507 security data exchange (the TLS negotiation in this case) 2508 2509 ... (and on page 8): 2510 2511 Thus the PBSZ command must still be issued, but must have a 2512 parameter of '0' to indicate that no buffering is taking place 2513 and the data connection should not be encapsulated. 2514 */ 2515 PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0); 2516 state(conn, FTP_PBSZ); 2517 } 2518 else { 2519 result = ftp_state_pwd(conn); 2520 } 2521 return result; 2522 } 2523 2524 /* for USER and PASS responses */ 2525 static CURLcode ftp_state_user_resp(struct connectdata *conn, 2526 int ftpcode, 2527 ftpstate instate) 2528 { 2529 CURLcode result = CURLE_OK; 2530 struct Curl_easy *data = conn->data; 2531 struct FTP *ftp = data->req.protop; 2532 struct ftp_conn *ftpc = &conn->proto.ftpc; 2533 (void)instate; /* no use for this yet */ 2534 2535 /* some need password anyway, and others just return 2xx ignored */ 2536 if((ftpcode == 331) && (ftpc->state == FTP_USER)) { 2537 /* 331 Password required for ... 2538 (the server requires to send the user's password too) */ 2539 PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); 2540 state(conn, FTP_PASS); 2541 } 2542 else if(ftpcode/100 == 2) { 2543 /* 230 User ... logged in. 2544 (the user logged in with or without password) */ 2545 result = ftp_state_loggedin(conn); 2546 } 2547 else if(ftpcode == 332) { 2548 if(data->set.str[STRING_FTP_ACCOUNT]) { 2549 PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); 2550 state(conn, FTP_ACCT); 2551 } 2552 else { 2553 failf(data, "ACCT requested but none available"); 2554 result = CURLE_LOGIN_DENIED; 2555 } 2556 } 2557 else { 2558 /* All other response codes, like: 2559 2560 530 User ... access denied 2561 (the server denies to log the specified user) */ 2562 2563 if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && 2564 !conn->data->state.ftp_trying_alternative) { 2565 /* Ok, USER failed. Let's try the supplied command. */ 2566 PPSENDF(&conn->proto.ftpc.pp, "%s", 2567 conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); 2568 conn->data->state.ftp_trying_alternative = TRUE; 2569 state(conn, FTP_USER); 2570 result = CURLE_OK; 2571 } 2572 else { 2573 failf(data, "Access denied: %03d", ftpcode); 2574 result = CURLE_LOGIN_DENIED; 2575 } 2576 } 2577 return result; 2578 } 2579 2580 /* for ACCT response */ 2581 static CURLcode ftp_state_acct_resp(struct connectdata *conn, 2582 int ftpcode) 2583 { 2584 CURLcode result = CURLE_OK; 2585 struct Curl_easy *data = conn->data; 2586 if(ftpcode != 230) { 2587 failf(data, "ACCT rejected by server: %03d", ftpcode); 2588 result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ 2589 } 2590 else 2591 result = ftp_state_loggedin(conn); 2592 2593 return result; 2594 } 2595 2596 2597 static CURLcode ftp_statemach_act(struct connectdata *conn) 2598 { 2599 CURLcode result; 2600 curl_socket_t sock = conn->sock[FIRSTSOCKET]; 2601 struct Curl_easy *data = conn->data; 2602 int ftpcode; 2603 struct ftp_conn *ftpc = &conn->proto.ftpc; 2604 struct pingpong *pp = &ftpc->pp; 2605 static const char ftpauth[][4] = { "SSL", "TLS" }; 2606 size_t nread = 0; 2607 2608 if(pp->sendleft) 2609 return Curl_pp_flushsend(pp); 2610 2611 result = ftp_readresp(sock, pp, &ftpcode, &nread); 2612 if(result) 2613 return result; 2614 2615 if(ftpcode) { 2616 /* we have now received a full FTP server response */ 2617 switch(ftpc->state) { 2618 case FTP_WAIT220: 2619 if(ftpcode == 230) 2620 /* 230 User logged in - already! */ 2621 return ftp_state_user_resp(conn, ftpcode, ftpc->state); 2622 else if(ftpcode != 220) { 2623 failf(data, "Got a %03d ftp-server response when 220 was expected", 2624 ftpcode); 2625 return CURLE_WEIRD_SERVER_REPLY; 2626 } 2627 2628 /* We have received a 220 response fine, now we proceed. */ 2629 #ifdef HAVE_GSSAPI 2630 if(data->set.krb) { 2631 /* If not anonymous login, try a secure login. Note that this 2632 procedure is still BLOCKING. */ 2633 2634 Curl_sec_request_prot(conn, "private"); 2635 /* We set private first as default, in case the line below fails to 2636 set a valid level */ 2637 Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); 2638 2639 if(Curl_sec_login(conn)) 2640 infof(data, "Logging in with password in cleartext!\n"); 2641 else 2642 infof(data, "Authentication successful\n"); 2643 } 2644 #endif 2645 2646 if(data->set.use_ssl && 2647 (!conn->ssl[FIRSTSOCKET].use || 2648 (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && 2649 !conn->proxy_ssl[FIRSTSOCKET].use))) { 2650 /* We don't have a SSL/TLS connection yet, but FTPS is 2651 requested. Try a FTPS connection now */ 2652 2653 ftpc->count3 = 0; 2654 switch(data->set.ftpsslauth) { 2655 case CURLFTPAUTH_DEFAULT: 2656 case CURLFTPAUTH_SSL: 2657 ftpc->count2 = 1; /* add one to get next */ 2658 ftpc->count1 = 0; 2659 break; 2660 case CURLFTPAUTH_TLS: 2661 ftpc->count2 = -1; /* subtract one to get next */ 2662 ftpc->count1 = 1; 2663 break; 2664 default: 2665 failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", 2666 (int)data->set.ftpsslauth); 2667 return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ 2668 } 2669 PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); 2670 state(conn, FTP_AUTH); 2671 } 2672 else { 2673 result = ftp_state_user(conn); 2674 if(result) 2675 return result; 2676 } 2677 2678 break; 2679 2680 case FTP_AUTH: 2681 /* we have gotten the response to a previous AUTH command */ 2682 2683 /* RFC2228 (page 5) says: 2684 * 2685 * If the server is willing to accept the named security mechanism, 2686 * and does not require any security data, it must respond with 2687 * reply code 234/334. 2688 */ 2689 2690 if((ftpcode == 234) || (ftpcode == 334)) { 2691 /* Curl_ssl_connect is BLOCKING */ 2692 result = Curl_ssl_connect(conn, FIRSTSOCKET); 2693 if(!result) { 2694 conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ 2695 result = ftp_state_user(conn); 2696 } 2697 } 2698 else if(ftpc->count3 < 1) { 2699 ftpc->count3++; 2700 ftpc->count1 += ftpc->count2; /* get next attempt */ 2701 result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); 2702 /* remain in this same state */ 2703 } 2704 else { 2705 if(data->set.use_ssl > CURLUSESSL_TRY) 2706 /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */ 2707 result = CURLE_USE_SSL_FAILED; 2708 else 2709 /* ignore the failure and continue */ 2710 result = ftp_state_user(conn); 2711 } 2712 2713 if(result) 2714 return result; 2715 break; 2716 2717 case FTP_USER: 2718 case FTP_PASS: 2719 result = ftp_state_user_resp(conn, ftpcode, ftpc->state); 2720 break; 2721 2722 case FTP_ACCT: 2723 result = ftp_state_acct_resp(conn, ftpcode); 2724 break; 2725 2726 case FTP_PBSZ: 2727 PPSENDF(&ftpc->pp, "PROT %c", 2728 data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); 2729 state(conn, FTP_PROT); 2730 2731 break; 2732 2733 case FTP_PROT: 2734 if(ftpcode/100 == 2) 2735 /* We have enabled SSL for the data connection! */ 2736 conn->bits.ftp_use_data_ssl = 2737 (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; 2738 /* FTP servers typically responds with 500 if they decide to reject 2739 our 'P' request */ 2740 else if(data->set.use_ssl > CURLUSESSL_CONTROL) 2741 /* we failed and bails out */ 2742 return CURLE_USE_SSL_FAILED; 2743 2744 if(data->set.ftp_ccc) { 2745 /* CCC - Clear Command Channel 2746 */ 2747 PPSENDF(&ftpc->pp, "%s", "CCC"); 2748 state(conn, FTP_CCC); 2749 } 2750 else { 2751 result = ftp_state_pwd(conn); 2752 if(result) 2753 return result; 2754 } 2755 break; 2756 2757 case FTP_CCC: 2758 if(ftpcode < 500) { 2759 /* First shut down the SSL layer (note: this call will block) */ 2760 result = Curl_ssl_shutdown(conn, FIRSTSOCKET); 2761 2762 if(result) { 2763 failf(conn->data, "Failed to clear the command channel (CCC)"); 2764 return result; 2765 } 2766 } 2767 2768 /* Then continue as normal */ 2769 result = ftp_state_pwd(conn); 2770 if(result) 2771 return result; 2772 break; 2773 2774 case FTP_PWD: 2775 if(ftpcode == 257) { 2776 char *ptr = &data->state.buffer[4]; /* start on the first letter */ 2777 const size_t buf_size = data->set.buffer_size; 2778 char *dir; 2779 bool entry_extracted = FALSE; 2780 2781 dir = malloc(nread + 1); 2782 if(!dir) 2783 return CURLE_OUT_OF_MEMORY; 2784 2785 /* Reply format is like 2786 257<space>[rubbish]"<directory-name>"<space><commentary> and the 2787 RFC959 says 2788 2789 The directory name can contain any character; embedded 2790 double-quotes should be escaped by double-quotes (the 2791 "quote-doubling" convention). 2792 */ 2793 2794 /* scan for the first double-quote for non-standard responses */ 2795 while(ptr < &data->state.buffer[buf_size] 2796 && *ptr != '\n' && *ptr != '\0' && *ptr != '"') 2797 ptr++; 2798 2799 if('\"' == *ptr) { 2800 /* it started good */ 2801 char *store; 2802 ptr++; 2803 for(store = dir; *ptr;) { 2804 if('\"' == *ptr) { 2805 if('\"' == ptr[1]) { 2806 /* "quote-doubling" */ 2807 *store = ptr[1]; 2808 ptr++; 2809 } 2810 else { 2811 /* end of path */ 2812 entry_extracted = TRUE; 2813 break; /* get out of this loop */ 2814 } 2815 } 2816 else 2817 *store = *ptr; 2818 store++; 2819 ptr++; 2820 } 2821 *store = '\0'; /* zero terminate */ 2822 } 2823 if(entry_extracted) { 2824 /* If the path name does not look like an absolute path (i.e.: it 2825 does not start with a '/'), we probably need some server-dependent 2826 adjustments. For example, this is the case when connecting to 2827 an OS400 FTP server: this server supports two name syntaxes, 2828 the default one being incompatible with standard paths. In 2829 addition, this server switches automatically to the regular path 2830 syntax when one is encountered in a command: this results in 2831 having an entrypath in the wrong syntax when later used in CWD. 2832 The method used here is to check the server OS: we do it only 2833 if the path name looks strange to minimize overhead on other 2834 systems. */ 2835 2836 if(!ftpc->server_os && dir[0] != '/') { 2837 2838 result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST"); 2839 if(result) { 2840 free(dir); 2841 return result; 2842 } 2843 Curl_safefree(ftpc->entrypath); 2844 ftpc->entrypath = dir; /* remember this */ 2845 infof(data, "Entry path is '%s'\n", ftpc->entrypath); 2846 /* also save it where getinfo can access it: */ 2847 data->state.most_recent_ftp_entrypath = ftpc->entrypath; 2848 state(conn, FTP_SYST); 2849 break; 2850 } 2851 2852 Curl_safefree(ftpc->entrypath); 2853 ftpc->entrypath = dir; /* remember this */ 2854 infof(data, "Entry path is '%s'\n", ftpc->entrypath); 2855 /* also save it where getinfo can access it: */ 2856 data->state.most_recent_ftp_entrypath = ftpc->entrypath; 2857 } 2858 else { 2859 /* couldn't get the path */ 2860 free(dir); 2861 infof(data, "Failed to figure out path\n"); 2862 } 2863 } 2864 state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ 2865 DEBUGF(infof(data, "protocol connect phase DONE\n")); 2866 break; 2867 2868 case FTP_SYST: 2869 if(ftpcode == 215) { 2870 char *ptr = &data->state.buffer[4]; /* start on the first letter */ 2871 char *os; 2872 char *store; 2873 2874 os = malloc(nread + 1); 2875 if(!os) 2876 return CURLE_OUT_OF_MEMORY; 2877 2878 /* Reply format is like 2879 215<space><OS-name><space><commentary> 2880 */ 2881 while(*ptr == ' ') 2882 ptr++; 2883 for(store = os; *ptr && *ptr != ' ';) 2884 *store++ = *ptr++; 2885 *store = '\0'; /* zero terminate */ 2886 2887 /* Check for special servers here. */ 2888 2889 if(strcasecompare(os, "OS/400")) { 2890 /* Force OS400 name format 1. */ 2891 result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1"); 2892 if(result) { 2893 free(os); 2894 return result; 2895 } 2896 /* remember target server OS */ 2897 Curl_safefree(ftpc->server_os); 2898 ftpc->server_os = os; 2899 state(conn, FTP_NAMEFMT); 2900 break; 2901 } 2902 /* Nothing special for the target server. */ 2903 /* remember target server OS */ 2904 Curl_safefree(ftpc->server_os); 2905 ftpc->server_os = os; 2906 } 2907 else { 2908 /* Cannot identify server OS. Continue anyway and cross fingers. */ 2909 } 2910 2911 state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ 2912 DEBUGF(infof(data, "protocol connect phase DONE\n")); 2913 break; 2914 2915 case FTP_NAMEFMT: 2916 if(ftpcode == 250) { 2917 /* Name format change successful: reload initial path. */ 2918 ftp_state_pwd(conn); 2919 break; 2920 } 2921 2922 state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ 2923 DEBUGF(infof(data, "protocol connect phase DONE\n")); 2924 break; 2925 2926 case FTP_QUOTE: 2927 case FTP_POSTQUOTE: 2928 case FTP_RETR_PREQUOTE: 2929 case FTP_STOR_PREQUOTE: 2930 if((ftpcode >= 400) && !ftpc->count2) { 2931 /* failure response code, and not allowed to fail */ 2932 failf(conn->data, "QUOT command failed with %03d", ftpcode); 2933 return CURLE_QUOTE_ERROR; 2934 } 2935 result = ftp_state_quote(conn, FALSE, ftpc->state); 2936 if(result) 2937 return result; 2938 2939 break; 2940 2941 case FTP_CWD: 2942 if(ftpcode/100 != 2) { 2943 /* failure to CWD there */ 2944 if(conn->data->set.ftp_create_missing_dirs && 2945 ftpc->cwdcount && !ftpc->count2) { 2946 /* try making it */ 2947 ftpc->count2++; /* counter to prevent CWD-MKD loops */ 2948 PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]); 2949 state(conn, FTP_MKD); 2950 } 2951 else { 2952 /* return failure */ 2953 failf(data, "Server denied you to change to the given directory"); 2954 ftpc->cwdfail = TRUE; /* don't remember this path as we failed 2955 to enter it */ 2956 return CURLE_REMOTE_ACCESS_DENIED; 2957 } 2958 } 2959 else { 2960 /* success */ 2961 ftpc->count2 = 0; 2962 if(++ftpc->cwdcount <= ftpc->dirdepth) { 2963 /* send next CWD */ 2964 PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); 2965 } 2966 else { 2967 result = ftp_state_mdtm(conn); 2968 if(result) 2969 return result; 2970 } 2971 } 2972 break; 2973 2974 case FTP_MKD: 2975 if((ftpcode/100 != 2) && !ftpc->count3--) { 2976 /* failure to MKD the dir */ 2977 failf(data, "Failed to MKD dir: %03d", ftpcode); 2978 return CURLE_REMOTE_ACCESS_DENIED; 2979 } 2980 state(conn, FTP_CWD); 2981 /* send CWD */ 2982 PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); 2983 break; 2984 2985 case FTP_MDTM: 2986 result = ftp_state_mdtm_resp(conn, ftpcode); 2987 break; 2988 2989 case FTP_TYPE: 2990 case FTP_LIST_TYPE: 2991 case FTP_RETR_TYPE: 2992 case FTP_STOR_TYPE: 2993 result = ftp_state_type_resp(conn, ftpcode, ftpc->state); 2994 break; 2995 2996 case FTP_SIZE: 2997 case FTP_RETR_SIZE: 2998 case FTP_STOR_SIZE: 2999 result = ftp_state_size_resp(conn, ftpcode, ftpc->state); 3000 break; 3001 3002 case FTP_REST: 3003 case FTP_RETR_REST: 3004 result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); 3005 break; 3006 3007 case FTP_PRET: 3008 if(ftpcode != 200) { 3009 /* there only is this one standard OK return code. */ 3010 failf(data, "PRET command not accepted: %03d", ftpcode); 3011 return CURLE_FTP_PRET_FAILED; 3012 } 3013 result = ftp_state_use_pasv(conn); 3014 break; 3015 3016 case FTP_PASV: 3017 result = ftp_state_pasv_resp(conn, ftpcode); 3018 break; 3019 3020 case FTP_PORT: 3021 result = ftp_state_port_resp(conn, ftpcode); 3022 break; 3023 3024 case FTP_LIST: 3025 case FTP_RETR: 3026 result = ftp_state_get_resp(conn, ftpcode, ftpc->state); 3027 break; 3028 3029 case FTP_STOR: 3030 result = ftp_state_stor_resp(conn, ftpcode, ftpc->state); 3031 break; 3032 3033 case FTP_QUIT: 3034 /* fallthrough, just stop! */ 3035 default: 3036 /* internal error */ 3037 state(conn, FTP_STOP); 3038 break; 3039 } 3040 } /* if(ftpcode) */ 3041 3042 return result; 3043 } 3044 3045 3046 /* called repeatedly until done from multi.c */ 3047 static CURLcode ftp_multi_statemach(struct connectdata *conn, 3048 bool *done) 3049 { 3050 struct ftp_conn *ftpc = &conn->proto.ftpc; 3051 CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE); 3052 3053 /* Check for the state outside of the Curl_socket_check() return code checks 3054 since at times we are in fact already in this state when this function 3055 gets called. */ 3056 *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE; 3057 3058 return result; 3059 } 3060 3061 static CURLcode ftp_block_statemach(struct connectdata *conn) 3062 { 3063 struct ftp_conn *ftpc = &conn->proto.ftpc; 3064 struct pingpong *pp = &ftpc->pp; 3065 CURLcode result = CURLE_OK; 3066 3067 while(ftpc->state != FTP_STOP) { 3068 result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */); 3069 if(result) 3070 break; 3071 } 3072 3073 return result; 3074 } 3075 3076 /* 3077 * ftp_connect() should do everything that is to be considered a part of 3078 * the connection phase. 3079 * 3080 * The variable 'done' points to will be TRUE if the protocol-layer connect 3081 * phase is done when this function returns, or FALSE if not. 3082 * 3083 */ 3084 static CURLcode ftp_connect(struct connectdata *conn, 3085 bool *done) /* see description above */ 3086 { 3087 CURLcode result; 3088 struct ftp_conn *ftpc = &conn->proto.ftpc; 3089 struct pingpong *pp = &ftpc->pp; 3090 3091 *done = FALSE; /* default to not done yet */ 3092 3093 /* We always support persistent connections on ftp */ 3094 connkeep(conn, "FTP default"); 3095 3096 pp->response_time = RESP_TIMEOUT; /* set default response time-out */ 3097 pp->statemach_act = ftp_statemach_act; 3098 pp->endofresp = ftp_endofresp; 3099 pp->conn = conn; 3100 3101 if(conn->handler->flags & PROTOPT_SSL) { 3102 /* BLOCKING */ 3103 result = Curl_ssl_connect(conn, FIRSTSOCKET); 3104 if(result) 3105 return result; 3106 } 3107 3108 Curl_pp_init(pp); /* init the generic pingpong data */ 3109 3110 /* When we connect, we start in the state where we await the 220 3111 response */ 3112 state(conn, FTP_WAIT220); 3113 3114 result = ftp_multi_statemach(conn, done); 3115 3116 return result; 3117 } 3118 3119 /*********************************************************************** 3120 * 3121 * ftp_done() 3122 * 3123 * The DONE function. This does what needs to be done after a single DO has 3124 * performed. 3125 * 3126 * Input argument is already checked for validity. 3127 */ 3128 static CURLcode ftp_done(struct connectdata *conn, CURLcode status, 3129 bool premature) 3130 { 3131 struct Curl_easy *data = conn->data; 3132 struct FTP *ftp = data->req.protop; 3133 struct ftp_conn *ftpc = &conn->proto.ftpc; 3134 struct pingpong *pp = &ftpc->pp; 3135 ssize_t nread; 3136 int ftpcode; 3137 CURLcode result = CURLE_OK; 3138 char *path = NULL; 3139 3140 if(!ftp) 3141 return CURLE_OK; 3142 3143 switch(status) { 3144 case CURLE_BAD_DOWNLOAD_RESUME: 3145 case CURLE_FTP_WEIRD_PASV_REPLY: 3146 case CURLE_FTP_PORT_FAILED: 3147 case CURLE_FTP_ACCEPT_FAILED: 3148 case CURLE_FTP_ACCEPT_TIMEOUT: 3149 case CURLE_FTP_COULDNT_SET_TYPE: 3150 case CURLE_FTP_COULDNT_RETR_FILE: 3151 case CURLE_PARTIAL_FILE: 3152 case CURLE_UPLOAD_FAILED: 3153 case CURLE_REMOTE_ACCESS_DENIED: 3154 case CURLE_FILESIZE_EXCEEDED: 3155 case CURLE_REMOTE_FILE_NOT_FOUND: 3156 case CURLE_WRITE_ERROR: 3157 /* the connection stays alive fine even though this happened */ 3158 /* fall-through */ 3159 case CURLE_OK: /* doesn't affect the control connection's status */ 3160 if(!premature) 3161 break; 3162 3163 /* until we cope better with prematurely ended requests, let them 3164 * fallback as if in complete failure */ 3165 /* FALLTHROUGH */ 3166 default: /* by default, an error means the control connection is 3167 wedged and should not be used anymore */ 3168 ftpc->ctl_valid = FALSE; 3169 ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the 3170 current path, as this connection is going */ 3171 connclose(conn, "FTP ended with bad error code"); 3172 result = status; /* use the already set error code */ 3173 break; 3174 } 3175 3176 /* now store a copy of the directory we are in */ 3177 free(ftpc->prevpath); 3178 3179 if(data->state.wildcardmatch) { 3180 if(data->set.chunk_end && ftpc->file) { 3181 Curl_set_in_callback(data, true); 3182 data->set.chunk_end(data->wildcard.customptr); 3183 Curl_set_in_callback(data, false); 3184 } 3185 ftpc->known_filesize = -1; 3186 } 3187 3188 if(!result) 3189 /* get the "raw" path */ 3190 result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE); 3191 if(result) { 3192 /* We can limp along anyway (and should try to since we may already be in 3193 * the error path) */ 3194 ftpc->ctl_valid = FALSE; /* mark control connection as bad */ 3195 connclose(conn, "FTP: out of memory!"); /* mark for connection closure */ 3196 ftpc->prevpath = NULL; /* no path remembering */ 3197 } 3198 else { 3199 size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */ 3200 size_t dlen = strlen(path)-flen; 3201 if(!ftpc->cwdfail) { 3202 ftpc->prevmethod = data->set.ftp_filemethod; 3203 if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) { 3204 ftpc->prevpath = path; 3205 if(flen) 3206 /* if 'path' is not the whole string */ 3207 ftpc->prevpath[dlen] = 0; /* terminate */ 3208 } 3209 else { 3210 free(path); 3211 /* we never changed dir */ 3212 ftpc->prevpath = strdup(""); 3213 if(!ftpc->prevpath) 3214 return CURLE_OUT_OF_MEMORY; 3215 } 3216 if(ftpc->prevpath) 3217 infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); 3218 } 3219 else { 3220 ftpc->prevpath = NULL; /* no path */ 3221 free(path); 3222 } 3223 } 3224 /* free the dir tree and file parts */ 3225 freedirs(ftpc); 3226 3227 /* shut down the socket to inform the server we're done */ 3228 3229 #ifdef _WIN32_WCE 3230 shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ 3231 #endif 3232 3233 if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { 3234 if(!result && ftpc->dont_check && data->req.maxdownload > 0) { 3235 /* partial download completed */ 3236 result = Curl_pp_sendf(pp, "%s", "ABOR"); 3237 if(result) { 3238 failf(data, "Failure sending ABOR command: %s", 3239 curl_easy_strerror(result)); 3240 ftpc->ctl_valid = FALSE; /* mark control connection as bad */ 3241 connclose(conn, "ABOR command failed"); /* connection closure */ 3242 } 3243 } 3244 3245 if(conn->ssl[SECONDARYSOCKET].use) { 3246 /* The secondary socket is using SSL so we must close down that part 3247 first before we close the socket for real */ 3248 Curl_ssl_close(conn, SECONDARYSOCKET); 3249 3250 /* Note that we keep "use" set to TRUE since that (next) connection is 3251 still requested to use SSL */ 3252 } 3253 close_secondarysocket(conn); 3254 } 3255 3256 if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && 3257 pp->pending_resp && !premature) { 3258 /* 3259 * Let's see what the server says about the transfer we just performed, 3260 * but lower the timeout as sometimes this connection has died while the 3261 * data has been transferred. This happens when doing through NATs etc that 3262 * abandon old silent connections. 3263 */ 3264 long old_time = pp->response_time; 3265 3266 pp->response_time = 60*1000; /* give it only a minute for now */ 3267 pp->response = Curl_now(); /* timeout relative now */ 3268 3269 result = Curl_GetFTPResponse(&nread, conn, &ftpcode); 3270 3271 pp->response_time = old_time; /* set this back to previous value */ 3272 3273 if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { 3274 failf(data, "control connection looks dead"); 3275 ftpc->ctl_valid = FALSE; /* mark control connection as bad */ 3276 connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */ 3277 } 3278 3279 if(result) 3280 return result; 3281 3282 if(ftpc->dont_check && data->req.maxdownload > 0) { 3283 /* we have just sent ABOR and there is no reliable way to check if it was 3284 * successful or not; we have to close the connection now */ 3285 infof(data, "partial download completed, closing connection\n"); 3286 connclose(conn, "Partial download with no ability to check"); 3287 return result; 3288 } 3289 3290 if(!ftpc->dont_check) { 3291 /* 226 Transfer complete, 250 Requested file action okay, completed. */ 3292 if((ftpcode != 226) && (ftpcode != 250)) { 3293 failf(data, "server did not report OK, got %d", ftpcode); 3294 result = CURLE_PARTIAL_FILE; 3295 } 3296 } 3297 } 3298 3299 if(result || premature) 3300 /* the response code from the transfer showed an error already so no 3301 use checking further */ 3302 ; 3303 else if(data->set.upload) { 3304 if((-1 != data->state.infilesize) && 3305 (data->state.infilesize != data->req.writebytecount) && 3306 !data->set.crlf && 3307 (ftp->transfer == FTPTRANSFER_BODY)) { 3308 failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T 3309 " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", 3310 data->req.bytecount, data->state.infilesize); 3311 result = CURLE_PARTIAL_FILE; 3312 } 3313 } 3314 else { 3315 if((-1 != data->req.size) && 3316 (data->req.size != data->req.bytecount) && 3317 #ifdef CURL_DO_LINEEND_CONV 3318 /* Most FTP servers don't adjust their file SIZE response for CRLFs, so 3319 * we'll check to see if the discrepancy can be explained by the number 3320 * of CRLFs we've changed to LFs. 3321 */ 3322 ((data->req.size + data->state.crlf_conversions) != 3323 data->req.bytecount) && 3324 #endif /* CURL_DO_LINEEND_CONV */ 3325 (data->req.maxdownload != data->req.bytecount)) { 3326 failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T 3327 " bytes", data->req.bytecount); 3328 result = CURLE_PARTIAL_FILE; 3329 } 3330 else if(!ftpc->dont_check && 3331 !data->req.bytecount && 3332 (data->req.size>0)) { 3333 failf(data, "No data was received!"); 3334 result = CURLE_FTP_COULDNT_RETR_FILE; 3335 } 3336 } 3337 3338 /* clear these for next connection */ 3339 ftp->transfer = FTPTRANSFER_BODY; 3340 ftpc->dont_check = FALSE; 3341 3342 /* Send any post-transfer QUOTE strings? */ 3343 if(!status && !result && !premature && data->set.postquote) 3344 result = ftp_sendquote(conn, data->set.postquote); 3345 Curl_safefree(ftp->pathalloc); 3346 return result; 3347 } 3348 3349 /*********************************************************************** 3350 * 3351 * ftp_sendquote() 3352 * 3353 * Where a 'quote' means a list of custom commands to send to the server. 3354 * The quote list is passed as an argument. 3355 * 3356 * BLOCKING 3357 */ 3358 3359 static 3360 CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) 3361 { 3362 struct curl_slist *item; 3363 ssize_t nread; 3364 int ftpcode; 3365 CURLcode result; 3366 struct ftp_conn *ftpc = &conn->proto.ftpc; 3367 struct pingpong *pp = &ftpc->pp; 3368 3369 item = quote; 3370 while(item) { 3371 if(item->data) { 3372 char *cmd = item->data; 3373 bool acceptfail = FALSE; 3374 3375 /* if a command starts with an asterisk, which a legal FTP command never 3376 can, the command will be allowed to fail without it causing any 3377 aborts or cancels etc. It will cause libcurl to act as if the command 3378 is successful, whatever the server reponds. */ 3379 3380 if(cmd[0] == '*') { 3381 cmd++; 3382 acceptfail = TRUE; 3383 } 3384 3385 PPSENDF(&conn->proto.ftpc.pp, "%s", cmd); 3386 3387 pp->response = Curl_now(); /* timeout relative now */ 3388 3389 result = Curl_GetFTPResponse(&nread, conn, &ftpcode); 3390 if(result) 3391 return result; 3392 3393 if(!acceptfail && (ftpcode >= 400)) { 3394 failf(conn->data, "QUOT string not accepted: %s", cmd); 3395 return CURLE_QUOTE_ERROR; 3396 } 3397 } 3398 3399 item = item->next; 3400 } 3401 3402 return CURLE_OK; 3403 } 3404 3405 /*********************************************************************** 3406 * 3407 * ftp_need_type() 3408 * 3409 * Returns TRUE if we in the current situation should send TYPE 3410 */ 3411 static int ftp_need_type(struct connectdata *conn, 3412 bool ascii_wanted) 3413 { 3414 return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I'); 3415 } 3416 3417 /*********************************************************************** 3418 * 3419 * ftp_nb_type() 3420 * 3421 * Set TYPE. We only deal with ASCII or BINARY so this function 3422 * sets one of them. 3423 * If the transfer type is not sent, simulate on OK response in newstate 3424 */ 3425 static CURLcode ftp_nb_type(struct connectdata *conn, 3426 bool ascii, ftpstate newstate) 3427 { 3428 struct ftp_conn *ftpc = &conn->proto.ftpc; 3429 CURLcode result; 3430 char want = (char)(ascii?'A':'I'); 3431 3432 if(ftpc->transfertype == want) { 3433 state(conn, newstate); 3434 return ftp_state_type_resp(conn, 200, newstate); 3435 } 3436 3437 PPSENDF(&ftpc->pp, "TYPE %c", want); 3438 state(conn, newstate); 3439 3440 /* keep track of our current transfer type */ 3441 ftpc->transfertype = want; 3442 return CURLE_OK; 3443 } 3444 3445 /*************************************************************************** 3446 * 3447 * ftp_pasv_verbose() 3448 * 3449 * This function only outputs some informationals about this second connection 3450 * when we've issued a PASV command before and thus we have connected to a 3451 * possibly new IP address. 3452 * 3453 */ 3454 #ifndef CURL_DISABLE_VERBOSE_STRINGS 3455 static void 3456 ftp_pasv_verbose(struct connectdata *conn, 3457 Curl_addrinfo *ai, 3458 char *newhost, /* ascii version */ 3459 int port) 3460 { 3461 char buf[256]; 3462 Curl_printable_address(ai, buf, sizeof(buf)); 3463 infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); 3464 } 3465 #endif 3466 3467 /* 3468 * ftp_do_more() 3469 * 3470 * This function shall be called when the second FTP (data) connection is 3471 * connected. 3472 * 3473 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back 3474 * (which basically is only for when PASV is being sent to retry a failed 3475 * EPSV). 3476 */ 3477 3478 static CURLcode ftp_do_more(struct connectdata *conn, int *completep) 3479 { 3480 struct Curl_easy *data = conn->data; 3481 struct ftp_conn *ftpc = &conn->proto.ftpc; 3482 CURLcode result = CURLE_OK; 3483 bool connected = FALSE; 3484 bool complete = FALSE; 3485 3486 /* the ftp struct is inited in ftp_connect() */ 3487 struct FTP *ftp = data->req.protop; 3488 3489 /* if the second connection isn't done yet, wait for it */ 3490 if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { 3491 if(Curl_connect_ongoing(conn)) { 3492 /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port 3493 aren't used so we blank their arguments. TODO: make this nicer */ 3494 result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); 3495 3496 return result; 3497 } 3498 3499 result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); 3500 3501 /* Ready to do more? */ 3502 if(connected) { 3503 DEBUGF(infof(data, "DO-MORE connected phase starts\n")); 3504 } 3505 else { 3506 if(result && (ftpc->count1 == 0)) { 3507 *completep = -1; /* go back to DOING please */ 3508 /* this is a EPSV connect failing, try PASV instead */ 3509 return ftp_epsv_disable(conn); 3510 } 3511 return result; 3512 } 3513 } 3514 3515 result = Curl_proxy_connect(conn, SECONDARYSOCKET); 3516 if(result) 3517 return result; 3518 3519 if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) 3520 return result; 3521 3522 if(conn->bits.tunnel_proxy && conn->bits.httpproxy && 3523 Curl_connect_ongoing(conn)) 3524 return result; 3525 3526 3527 if(ftpc->state) { 3528 /* already in a state so skip the initial commands. 3529 They are only done to kickstart the do_more state */ 3530 result = ftp_multi_statemach(conn, &complete); 3531 3532 *completep = (int)complete; 3533 3534 /* if we got an error or if we don't wait for a data connection return 3535 immediately */ 3536 if(result || (ftpc->wait_data_conn != TRUE)) 3537 return result; 3538 3539 if(ftpc->wait_data_conn) 3540 /* if we reach the end of the FTP state machine here, *complete will be 3541 TRUE but so is ftpc->wait_data_conn, which says we need to wait for 3542 the data connection and therefore we're not actually complete */ 3543 *completep = 0; 3544 } 3545 3546 if(ftp->transfer <= FTPTRANSFER_INFO) { 3547 /* a transfer is about to take place, or if not a file name was given 3548 so we'll do a SIZE on it later and then we need the right TYPE first */ 3549 3550 if(ftpc->wait_data_conn == TRUE) { 3551 bool serv_conned; 3552 3553 result = ReceivedServerConnect(conn, &serv_conned); 3554 if(result) 3555 return result; /* Failed to accept data connection */ 3556 3557 if(serv_conned) { 3558 /* It looks data connection is established */ 3559 result = AcceptServerConnect(conn); 3560 ftpc->wait_data_conn = FALSE; 3561 if(!result) 3562 result = InitiateTransfer(conn); 3563 3564 if(result) 3565 return result; 3566 3567 *completep = 1; /* this state is now complete when the server has 3568 connected back to us */ 3569 } 3570 } 3571 else if(data->set.upload) { 3572 result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); 3573 if(result) 3574 return result; 3575 3576 result = ftp_multi_statemach(conn, &complete); 3577 if(ftpc->wait_data_conn) 3578 /* if we reach the end of the FTP state machine here, *complete will be 3579 TRUE but so is ftpc->wait_data_conn, which says we need to wait for 3580 the data connection and therefore we're not actually complete */ 3581 *completep = 0; 3582 else 3583 *completep = (int)complete; 3584 } 3585 else { 3586 /* download */ 3587 ftp->downloadsize = -1; /* unknown as of yet */ 3588 3589 result = Curl_range(conn); 3590 3591 if(result == CURLE_OK && data->req.maxdownload >= 0) { 3592 /* Don't check for successful transfer */ 3593 ftpc->dont_check = TRUE; 3594 } 3595 3596 if(result) 3597 ; 3598 else if(data->set.ftp_list_only || !ftpc->file) { 3599 /* The specified path ends with a slash, and therefore we think this 3600 is a directory that is requested, use LIST. But before that we 3601 need to set ASCII transfer mode. */ 3602 3603 /* But only if a body transfer was requested. */ 3604 if(ftp->transfer == FTPTRANSFER_BODY) { 3605 result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE); 3606 if(result) 3607 return result; 3608 } 3609 /* otherwise just fall through */ 3610 } 3611 else { 3612 result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE); 3613 if(result) 3614 return result; 3615 } 3616 3617 result = ftp_multi_statemach(conn, &complete); 3618 *completep = (int)complete; 3619 } 3620 return result; 3621 } 3622 3623 if(!result && (ftp->transfer != FTPTRANSFER_BODY)) 3624 /* no data to transfer. FIX: it feels like a kludge to have this here 3625 too! */ 3626 Curl_setup_transfer(data, -1, -1, FALSE, -1); 3627 3628 if(!ftpc->wait_data_conn) { 3629 /* no waiting for the data connection so this is now complete */ 3630 *completep = 1; 3631 DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); 3632 } 3633 3634 return result; 3635 } 3636 3637 3638 3639 /*********************************************************************** 3640 * 3641 * ftp_perform() 3642 * 3643 * This is the actual DO function for FTP. Get a file/directory according to 3644 * the options previously setup. 3645 */ 3646 3647 static 3648 CURLcode ftp_perform(struct connectdata *conn, 3649 bool *connected, /* connect status after PASV / PORT */ 3650 bool *dophase_done) 3651 { 3652 /* this is FTP and no proxy */ 3653 CURLcode result = CURLE_OK; 3654 3655 DEBUGF(infof(conn->data, "DO phase starts\n")); 3656 3657 if(conn->data->set.opt_no_body) { 3658 /* requested no body means no transfer... */ 3659 struct FTP *ftp = conn->data->req.protop; 3660 ftp->transfer = FTPTRANSFER_INFO; 3661 } 3662 3663 *dophase_done = FALSE; /* not done yet */ 3664 3665 /* start the first command in the DO phase */ 3666 result = ftp_state_quote(conn, TRUE, FTP_QUOTE); 3667 if(result) 3668 return result; 3669 3670 /* run the state-machine */ 3671 result = ftp_multi_statemach(conn, dophase_done); 3672 3673 *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; 3674 3675 infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); 3676 3677 if(*dophase_done) 3678 DEBUGF(infof(conn->data, "DO phase is complete1\n")); 3679 3680 return result; 3681 } 3682 3683 static void wc_data_dtor(void *ptr) 3684 { 3685 struct ftp_wc *ftpwc = ptr; 3686 if(ftpwc && ftpwc->parser) 3687 Curl_ftp_parselist_data_free(&ftpwc->parser); 3688 free(ftpwc); 3689 } 3690 3691 static CURLcode init_wc_data(struct connectdata *conn) 3692 { 3693 char *last_slash; 3694 struct FTP *ftp = conn->data->req.protop; 3695 char *path = ftp->path; 3696 struct WildcardData *wildcard = &(conn->data->wildcard); 3697 CURLcode result = CURLE_OK; 3698 struct ftp_wc *ftpwc = NULL; 3699 3700 last_slash = strrchr(ftp->path, '/'); 3701 if(last_slash) { 3702 last_slash++; 3703 if(last_slash[0] == '\0') { 3704 wildcard->state = CURLWC_CLEAN; 3705 result = ftp_parse_url_path(conn); 3706 return result; 3707 } 3708 wildcard->pattern = strdup(last_slash); 3709 if(!wildcard->pattern) 3710 return CURLE_OUT_OF_MEMORY; 3711 last_slash[0] = '\0'; /* cut file from path */ 3712 } 3713 else { /* there is only 'wildcard pattern' or nothing */ 3714 if(path[0]) { 3715 wildcard->pattern = strdup(path); 3716 if(!wildcard->pattern) 3717 return CURLE_OUT_OF_MEMORY; 3718 path[0] = '\0'; 3719 } 3720 else { /* only list */ 3721 wildcard->state = CURLWC_CLEAN; 3722 result = ftp_parse_url_path(conn); 3723 return result; 3724 } 3725 } 3726 3727 /* program continues only if URL is not ending with slash, allocate needed 3728 resources for wildcard transfer */ 3729 3730 /* allocate ftp protocol specific wildcard data */ 3731 ftpwc = calloc(1, sizeof(struct ftp_wc)); 3732 if(!ftpwc) { 3733 result = CURLE_OUT_OF_MEMORY; 3734 goto fail; 3735 } 3736 3737 /* INITIALIZE parselist structure */ 3738 ftpwc->parser = Curl_ftp_parselist_data_alloc(); 3739 if(!ftpwc->parser) { 3740 result = CURLE_OUT_OF_MEMORY; 3741 goto fail; 3742 } 3743 3744 wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */ 3745 wildcard->dtor = wc_data_dtor; 3746 3747 /* wildcard does not support NOCWD option (assert it?) */ 3748 if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD) 3749 conn->data->set.ftp_filemethod = FTPFILE_MULTICWD; 3750 3751 /* try to parse ftp url */ 3752 result = ftp_parse_url_path(conn); 3753 if(result) { 3754 goto fail; 3755 } 3756 3757 wildcard->path = strdup(ftp->path); 3758 if(!wildcard->path) { 3759 result = CURLE_OUT_OF_MEMORY; 3760 goto fail; 3761 } 3762 3763 /* backup old write_function */ 3764 ftpwc->backup.write_function = conn->data->set.fwrite_func; 3765 /* parsing write function */ 3766 conn->data->set.fwrite_func = Curl_ftp_parselist; 3767 /* backup old file descriptor */ 3768 ftpwc->backup.file_descriptor = conn->data->set.out; 3769 /* let the writefunc callback know what curl pointer is working with */ 3770 conn->data->set.out = conn; 3771 3772 infof(conn->data, "Wildcard - Parsing started\n"); 3773 return CURLE_OK; 3774 3775 fail: 3776 if(ftpwc) { 3777 Curl_ftp_parselist_data_free(&ftpwc->parser); 3778 free(ftpwc); 3779 } 3780 Curl_safefree(wildcard->pattern); 3781 wildcard->dtor = ZERO_NULL; 3782 wildcard->protdata = NULL; 3783 return result; 3784 } 3785 3786 /* This is called recursively */ 3787 static CURLcode wc_statemach(struct connectdata *conn) 3788 { 3789 struct WildcardData * const wildcard = &(conn->data->wildcard); 3790 CURLcode result = CURLE_OK; 3791 3792 switch(wildcard->state) { 3793 case CURLWC_INIT: 3794 result = init_wc_data(conn); 3795 if(wildcard->state == CURLWC_CLEAN) 3796 /* only listing! */ 3797 break; 3798 wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; 3799 break; 3800 3801 case CURLWC_MATCHING: { 3802 /* In this state is LIST response successfully parsed, so lets restore 3803 previous WRITEFUNCTION callback and WRITEDATA pointer */ 3804 struct ftp_wc *ftpwc = wildcard->protdata; 3805 conn->data->set.fwrite_func = ftpwc->backup.write_function; 3806 conn->data->set.out = ftpwc->backup.file_descriptor; 3807 ftpwc->backup.write_function = ZERO_NULL; 3808 ftpwc->backup.file_descriptor = NULL; 3809 wildcard->state = CURLWC_DOWNLOADING; 3810 3811 if(Curl_ftp_parselist_geterror(ftpwc->parser)) { 3812 /* error found in LIST parsing */ 3813 wildcard->state = CURLWC_CLEAN; 3814 return wc_statemach(conn); 3815 } 3816 if(wildcard->filelist.size == 0) { 3817 /* no corresponding file */ 3818 wildcard->state = CURLWC_CLEAN; 3819 return CURLE_REMOTE_FILE_NOT_FOUND; 3820 } 3821 return wc_statemach(conn); 3822 } 3823 3824 case CURLWC_DOWNLOADING: { 3825 /* filelist has at least one file, lets get first one */ 3826 struct ftp_conn *ftpc = &conn->proto.ftpc; 3827 struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; 3828 struct FTP *ftp = conn->data->req.protop; 3829 3830 char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); 3831 if(!tmp_path) 3832 return CURLE_OUT_OF_MEMORY; 3833 3834 /* switch default ftp->path and tmp_path */ 3835 free(ftp->pathalloc); 3836 ftp->pathalloc = ftp->path = tmp_path; 3837 3838 infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); 3839 if(conn->data->set.chunk_bgn) { 3840 long userresponse; 3841 Curl_set_in_callback(conn->data, true); 3842 userresponse = conn->data->set.chunk_bgn( 3843 finfo, wildcard->customptr, (int)wildcard->filelist.size); 3844 Curl_set_in_callback(conn->data, false); 3845 switch(userresponse) { 3846 case CURL_CHUNK_BGN_FUNC_SKIP: 3847 infof(conn->data, "Wildcard - \"%s\" skipped by user\n", 3848 finfo->filename); 3849 wildcard->state = CURLWC_SKIP; 3850 return wc_statemach(conn); 3851 case CURL_CHUNK_BGN_FUNC_FAIL: 3852 return CURLE_CHUNK_FAILED; 3853 } 3854 } 3855 3856 if(finfo->filetype != CURLFILETYPE_FILE) { 3857 wildcard->state = CURLWC_SKIP; 3858 return wc_statemach(conn); 3859 } 3860 3861 if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) 3862 ftpc->known_filesize = finfo->size; 3863 3864 result = ftp_parse_url_path(conn); 3865 if(result) 3866 return result; 3867 3868 /* we don't need the Curl_fileinfo of first file anymore */ 3869 Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); 3870 3871 if(wildcard->filelist.size == 0) { /* remains only one file to down. */ 3872 wildcard->state = CURLWC_CLEAN; 3873 /* after that will be ftp_do called once again and no transfer 3874 will be done because of CURLWC_CLEAN state */ 3875 return CURLE_OK; 3876 } 3877 } break; 3878 3879 case CURLWC_SKIP: { 3880 if(conn->data->set.chunk_end) { 3881 Curl_set_in_callback(conn->data, true); 3882 conn->data->set.chunk_end(conn->data->wildcard.customptr); 3883 Curl_set_in_callback(conn->data, false); 3884 } 3885 Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); 3886 wildcard->state = (wildcard->filelist.size == 0) ? 3887 CURLWC_CLEAN : CURLWC_DOWNLOADING; 3888 return wc_statemach(conn); 3889 } 3890 3891 case CURLWC_CLEAN: { 3892 struct ftp_wc *ftpwc = wildcard->protdata; 3893 result = CURLE_OK; 3894 if(ftpwc) 3895 result = Curl_ftp_parselist_geterror(ftpwc->parser); 3896 3897 wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; 3898 } break; 3899 3900 case CURLWC_DONE: 3901 case CURLWC_ERROR: 3902 case CURLWC_CLEAR: 3903 if(wildcard->dtor) 3904 wildcard->dtor(wildcard->protdata); 3905 break; 3906 } 3907 3908 return result; 3909 } 3910 3911 /*********************************************************************** 3912 * 3913 * ftp_do() 3914 * 3915 * This function is registered as 'curl_do' function. It decodes the path 3916 * parts etc as a wrapper to the actual DO function (ftp_perform). 3917 * 3918 * The input argument is already checked for validity. 3919 */ 3920 static CURLcode ftp_do(struct connectdata *conn, bool *done) 3921 { 3922 CURLcode result = CURLE_OK; 3923 struct ftp_conn *ftpc = &conn->proto.ftpc; 3924 3925 *done = FALSE; /* default to false */ 3926 ftpc->wait_data_conn = FALSE; /* default to no such wait */ 3927 3928 if(conn->data->state.wildcardmatch) { 3929 result = wc_statemach(conn); 3930 if(conn->data->wildcard.state == CURLWC_SKIP || 3931 conn->data->wildcard.state == CURLWC_DONE) { 3932 /* do not call ftp_regular_transfer */ 3933 return CURLE_OK; 3934 } 3935 if(result) /* error, loop or skipping the file */ 3936 return result; 3937 } 3938 else { /* no wildcard FSM needed */ 3939 result = ftp_parse_url_path(conn); 3940 if(result) 3941 return result; 3942 } 3943 3944 result = ftp_regular_transfer(conn, done); 3945 3946 return result; 3947 } 3948 3949 3950 CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd) 3951 { 3952 ssize_t bytes_written; 3953 #define SBUF_SIZE 1024 3954 char s[SBUF_SIZE]; 3955 size_t write_len; 3956 char *sptr = s; 3957 CURLcode result = CURLE_OK; 3958 #ifdef HAVE_GSSAPI 3959 enum protection_level data_sec = conn->data_prot; 3960 #endif 3961 3962 if(!cmd) 3963 return CURLE_BAD_FUNCTION_ARGUMENT; 3964 3965 write_len = strlen(cmd); 3966 if(!write_len || write_len > (sizeof(s) -3)) 3967 return CURLE_BAD_FUNCTION_ARGUMENT; 3968 3969 memcpy(&s, cmd, write_len); 3970 strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */ 3971 write_len += 2; 3972 bytes_written = 0; 3973 3974 result = Curl_convert_to_network(conn->data, s, write_len); 3975 /* Curl_convert_to_network calls failf if unsuccessful */ 3976 if(result) 3977 return result; 3978 3979 for(;;) { 3980 #ifdef HAVE_GSSAPI 3981 conn->data_prot = PROT_CMD; 3982 #endif 3983 result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, 3984 &bytes_written); 3985 #ifdef HAVE_GSSAPI 3986 DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); 3987 conn->data_prot = data_sec; 3988 #endif 3989 3990 if(result) 3991 break; 3992 3993 if(conn->data->set.verbose) 3994 Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written); 3995 3996 if(bytes_written != (ssize_t)write_len) { 3997 write_len -= bytes_written; 3998 sptr += bytes_written; 3999 } 4000 else 4001 break; 4002 } 4003 4004 return result; 4005 } 4006 4007 /*********************************************************************** 4008 * 4009 * ftp_quit() 4010 * 4011 * This should be called before calling sclose() on an ftp control connection 4012 * (not data connections). We should then wait for the response from the 4013 * server before returning. The calling code should then try to close the 4014 * connection. 4015 * 4016 */ 4017 static CURLcode ftp_quit(struct connectdata *conn) 4018 { 4019 CURLcode result = CURLE_OK; 4020 4021 if(conn->proto.ftpc.ctl_valid) { 4022 result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT"); 4023 if(result) { 4024 failf(conn->data, "Failure sending QUIT command: %s", 4025 curl_easy_strerror(result)); 4026 conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */ 4027 connclose(conn, "QUIT command failed"); /* mark for connection closure */ 4028 state(conn, FTP_STOP); 4029 return result; 4030 } 4031 4032 state(conn, FTP_QUIT); 4033 4034 result = ftp_block_statemach(conn); 4035 } 4036 4037 return result; 4038 } 4039 4040 /*********************************************************************** 4041 * 4042 * ftp_disconnect() 4043 * 4044 * Disconnect from an FTP server. Cleanup protocol-specific per-connection 4045 * resources. BLOCKING. 4046 */ 4047 static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) 4048 { 4049 struct ftp_conn *ftpc = &conn->proto.ftpc; 4050 struct pingpong *pp = &ftpc->pp; 4051 4052 /* We cannot send quit unconditionally. If this connection is stale or 4053 bad in any way, sending quit and waiting around here will make the 4054 disconnect wait in vain and cause more problems than we need to. 4055 4056 ftp_quit() will check the state of ftp->ctl_valid. If it's ok it 4057 will try to send the QUIT command, otherwise it will just return. 4058 */ 4059 if(dead_connection) 4060 ftpc->ctl_valid = FALSE; 4061 4062 /* The FTP session may or may not have been allocated/setup at this point! */ 4063 (void)ftp_quit(conn); /* ignore errors on the QUIT */ 4064 4065 if(ftpc->entrypath) { 4066 struct Curl_easy *data = conn->data; 4067 if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { 4068 data->state.most_recent_ftp_entrypath = NULL; 4069 } 4070 free(ftpc->entrypath); 4071 ftpc->entrypath = NULL; 4072 } 4073 4074 freedirs(ftpc); 4075 free(ftpc->prevpath); 4076 ftpc->prevpath = NULL; 4077 free(ftpc->server_os); 4078 ftpc->server_os = NULL; 4079 4080 Curl_pp_disconnect(pp); 4081 4082 #ifdef HAVE_GSSAPI 4083 Curl_sec_end(conn); 4084 #endif 4085 4086 return CURLE_OK; 4087 } 4088 4089 /*********************************************************************** 4090 * 4091 * ftp_parse_url_path() 4092 * 4093 * Parse the URL path into separate path components. 4094 * 4095 */ 4096 static 4097 CURLcode ftp_parse_url_path(struct connectdata *conn) 4098 { 4099 struct Curl_easy *data = conn->data; 4100 /* the ftp struct is already inited in ftp_connect() */ 4101 struct FTP *ftp = data->req.protop; 4102 struct ftp_conn *ftpc = &conn->proto.ftpc; 4103 const char *slash_pos; /* position of the first '/' char in curpos */ 4104 const char *path_to_use = ftp->path; 4105 const char *cur_pos; 4106 const char *filename = NULL; 4107 4108 cur_pos = path_to_use; /* current position in path. point at the begin of 4109 next path component */ 4110 4111 ftpc->ctl_valid = FALSE; 4112 ftpc->cwdfail = FALSE; 4113 4114 switch(data->set.ftp_filemethod) { 4115 case FTPFILE_NOCWD: 4116 /* fastest, but less standard-compliant */ 4117 4118 /* 4119 The best time to check whether the path is a file or directory is right 4120 here. so: 4121 4122 the first condition in the if() right here, is there just in case 4123 someone decides to set path to NULL one day 4124 */ 4125 if(path_to_use[0] && 4126 (path_to_use[strlen(path_to_use) - 1] != '/') ) 4127 filename = path_to_use; /* this is a full file path */ 4128 /* 4129 else { 4130 ftpc->file is not used anywhere other than for operations on a file. 4131 In other words, never for directory operations. 4132 So we can safely leave filename as NULL here and use it as a 4133 argument in dir/file decisions. 4134 } 4135 */ 4136 break; 4137 4138 case FTPFILE_SINGLECWD: 4139 /* get the last slash */ 4140 if(!path_to_use[0]) { 4141 /* no dir, no file */ 4142 ftpc->dirdepth = 0; 4143 break; 4144 } 4145 slash_pos = strrchr(cur_pos, '/'); 4146 if(slash_pos || !*cur_pos) { 4147 size_t dirlen = slash_pos-cur_pos; 4148 CURLcode result; 4149 4150 ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); 4151 if(!ftpc->dirs) 4152 return CURLE_OUT_OF_MEMORY; 4153 4154 if(!dirlen) 4155 dirlen++; 4156 4157 result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/", 4158 slash_pos ? dirlen : 1, 4159 &ftpc->dirs[0], NULL, 4160 TRUE); 4161 if(result) { 4162 freedirs(ftpc); 4163 return result; 4164 } 4165 ftpc->dirdepth = 1; /* we consider it to be a single dir */ 4166 filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */ 4167 } 4168 else 4169 filename = cur_pos; /* this is a file name only */ 4170 break; 4171 4172 default: /* allow pretty much anything */ 4173 case FTPFILE_MULTICWD: 4174 ftpc->dirdepth = 0; 4175 ftpc->diralloc = 5; /* default dir depth to allocate */ 4176 ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0])); 4177 if(!ftpc->dirs) 4178 return CURLE_OUT_OF_MEMORY; 4179 4180 /* we have a special case for listing the root dir only */ 4181 if(!strcmp(path_to_use, "/")) { 4182 cur_pos++; /* make it point to the zero byte */ 4183 ftpc->dirs[0] = strdup("/"); 4184 ftpc->dirdepth++; 4185 } 4186 else { 4187 /* parse the URL path into separate path components */ 4188 while((slash_pos = strchr(cur_pos, '/')) != NULL) { 4189 /* 1 or 0 pointer offset to indicate absolute directory */ 4190 ssize_t absolute_dir = ((cur_pos - ftp->path > 0) && 4191 (ftpc->dirdepth == 0))?1:0; 4192 4193 /* seek out the next path component */ 4194 if(slash_pos-cur_pos) { 4195 /* we skip empty path components, like "x//y" since the FTP command 4196 CWD requires a parameter and a non-existent parameter a) doesn't 4197 work on many servers and b) has no effect on the others. */ 4198 size_t len = slash_pos - cur_pos + absolute_dir; 4199 CURLcode result = 4200 Curl_urldecode(conn->data, cur_pos - absolute_dir, len, 4201 &ftpc->dirs[ftpc->dirdepth], NULL, 4202 TRUE); 4203 if(result) { 4204 freedirs(ftpc); 4205 return result; 4206 } 4207 } 4208 else { 4209 cur_pos = slash_pos + 1; /* jump to the rest of the string */ 4210 if(!ftpc->dirdepth) { 4211 /* path starts with a slash, add that as a directory */ 4212 ftpc->dirs[ftpc->dirdepth] = strdup("/"); 4213 if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */ 4214 failf(data, "no memory"); 4215 freedirs(ftpc); 4216 return CURLE_OUT_OF_MEMORY; 4217 } 4218 } 4219 continue; 4220 } 4221 4222 cur_pos = slash_pos + 1; /* jump to the rest of the string */ 4223 if(++ftpc->dirdepth >= ftpc->diralloc) { 4224 /* enlarge array */ 4225 char **bigger; 4226 ftpc->diralloc *= 2; /* double the size each time */ 4227 bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0])); 4228 if(!bigger) { 4229 freedirs(ftpc); 4230 return CURLE_OUT_OF_MEMORY; 4231 } 4232 ftpc->dirs = bigger; 4233 } 4234 } 4235 } 4236 filename = cur_pos; /* the rest is the file name */ 4237 break; 4238 } /* switch */ 4239 4240 if(filename && *filename) { 4241 CURLcode result = 4242 Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE); 4243 4244 if(result) { 4245 freedirs(ftpc); 4246 return result; 4247 } 4248 } 4249 else 4250 ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL 4251 pointer */ 4252 4253 if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { 4254 /* We need a file name when uploading. Return error! */ 4255 failf(data, "Uploading to a URL without a file name!"); 4256 return CURLE_URL_MALFORMAT; 4257 } 4258 4259 ftpc->cwddone = FALSE; /* default to not done */ 4260 4261 if(ftpc->prevpath) { 4262 /* prevpath is "raw" so we convert the input path before we compare the 4263 strings */ 4264 size_t dlen; 4265 char *path; 4266 CURLcode result = 4267 Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE); 4268 if(result) { 4269 freedirs(ftpc); 4270 return result; 4271 } 4272 4273 dlen -= ftpc->file?strlen(ftpc->file):0; 4274 if((dlen == strlen(ftpc->prevpath)) && 4275 !strncmp(path, ftpc->prevpath, dlen) && 4276 (ftpc->prevmethod == data->set.ftp_filemethod)) { 4277 infof(data, "Request has same path as previous transfer\n"); 4278 ftpc->cwddone = TRUE; 4279 } 4280 free(path); 4281 } 4282 4283 return CURLE_OK; 4284 } 4285 4286 /* call this when the DO phase has completed */ 4287 static CURLcode ftp_dophase_done(struct connectdata *conn, 4288 bool connected) 4289 { 4290 struct FTP *ftp = conn->data->req.protop; 4291 struct ftp_conn *ftpc = &conn->proto.ftpc; 4292 4293 if(connected) { 4294 int completed; 4295 CURLcode result = ftp_do_more(conn, &completed); 4296 4297 if(result) { 4298 close_secondarysocket(conn); 4299 return result; 4300 } 4301 } 4302 4303 if(ftp->transfer != FTPTRANSFER_BODY) 4304 /* no data to transfer */ 4305 Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); 4306 else if(!connected) 4307 /* since we didn't connect now, we want do_more to get called */ 4308 conn->bits.do_more = TRUE; 4309 4310 ftpc->ctl_valid = TRUE; /* seems good */ 4311 4312 return CURLE_OK; 4313 } 4314 4315 /* called from multi.c while DOing */ 4316 static CURLcode ftp_doing(struct connectdata *conn, 4317 bool *dophase_done) 4318 { 4319 CURLcode result = ftp_multi_statemach(conn, dophase_done); 4320 4321 if(result) 4322 DEBUGF(infof(conn->data, "DO phase failed\n")); 4323 else if(*dophase_done) { 4324 result = ftp_dophase_done(conn, FALSE /* not connected */); 4325 4326 DEBUGF(infof(conn->data, "DO phase is complete2\n")); 4327 } 4328 return result; 4329 } 4330 4331 /*********************************************************************** 4332 * 4333 * ftp_regular_transfer() 4334 * 4335 * The input argument is already checked for validity. 4336 * 4337 * Performs all commands done before a regular transfer between a local and a 4338 * remote host. 4339 * 4340 * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the 4341 * ftp_done() function without finding any major problem. 4342 */ 4343 static 4344 CURLcode ftp_regular_transfer(struct connectdata *conn, 4345 bool *dophase_done) 4346 { 4347 CURLcode result = CURLE_OK; 4348 bool connected = FALSE; 4349 struct Curl_easy *data = conn->data; 4350 struct ftp_conn *ftpc = &conn->proto.ftpc; 4351 data->req.size = -1; /* make sure this is unknown at this point */ 4352 4353 Curl_pgrsSetUploadCounter(data, 0); 4354 Curl_pgrsSetDownloadCounter(data, 0); 4355 Curl_pgrsSetUploadSize(data, -1); 4356 Curl_pgrsSetDownloadSize(data, -1); 4357 4358 ftpc->ctl_valid = TRUE; /* starts good */ 4359 4360 result = ftp_perform(conn, 4361 &connected, /* have we connected after PASV/PORT */ 4362 dophase_done); /* all commands in the DO-phase done? */ 4363 4364 if(!result) { 4365 4366 if(!*dophase_done) 4367 /* the DO phase has not completed yet */ 4368 return CURLE_OK; 4369 4370 result = ftp_dophase_done(conn, connected); 4371 4372 if(result) 4373 return result; 4374 } 4375 else 4376 freedirs(ftpc); 4377 4378 return result; 4379 } 4380 4381 static CURLcode ftp_setup_connection(struct connectdata *conn) 4382 { 4383 struct Curl_easy *data = conn->data; 4384 char *type; 4385 struct FTP *ftp; 4386 4387 conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1); 4388 if(NULL == ftp) 4389 return CURLE_OUT_OF_MEMORY; 4390 4391 ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ 4392 4393 /* FTP URLs support an extension like ";type=<typecode>" that 4394 * we'll try to get now! */ 4395 type = strstr(ftp->path, ";type="); 4396 4397 if(!type) 4398 type = strstr(conn->host.rawalloc, ";type="); 4399 4400 if(type) { 4401 char command; 4402 *type = 0; /* it was in the middle of the hostname */ 4403 command = Curl_raw_toupper(type[6]); 4404 conn->bits.type_set = TRUE; 4405 4406 switch(command) { 4407 case 'A': /* ASCII mode */ 4408 data->set.prefer_ascii = TRUE; 4409 break; 4410 4411 case 'D': /* directory mode */ 4412 data->set.ftp_list_only = TRUE; 4413 break; 4414 4415 case 'I': /* binary mode */ 4416 default: 4417 /* switch off ASCII */ 4418 data->set.prefer_ascii = FALSE; 4419 break; 4420 } 4421 } 4422 4423 /* get some initial data into the ftp struct */ 4424 ftp->transfer = FTPTRANSFER_BODY; 4425 ftp->downloadsize = 0; 4426 4427 /* No need to duplicate user+password, the connectdata struct won't change 4428 during a session, but we re-init them here since on subsequent inits 4429 since the conn struct may have changed or been replaced. 4430 */ 4431 ftp->user = conn->user; 4432 ftp->passwd = conn->passwd; 4433 if(isBadFtpString(ftp->user)) 4434 return CURLE_URL_MALFORMAT; 4435 if(isBadFtpString(ftp->passwd)) 4436 return CURLE_URL_MALFORMAT; 4437 4438 conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ 4439 4440 return CURLE_OK; 4441 } 4442 4443 #endif /* CURL_DISABLE_FTP */ 4444