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