1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@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 http://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/* #define CURL_LIBSSH2_DEBUG */ 24 25#include "setup.h" 26 27#ifdef USE_LIBSSH2 28#include <stdio.h> 29#include <string.h> 30#include <stdlib.h> 31#include <stdarg.h> 32#include <ctype.h> 33#ifdef HAVE_LIMITS_H 34# include <limits.h> 35#endif 36 37#include <libssh2.h> 38#include <libssh2_sftp.h> 39 40#ifdef HAVE_UNISTD_H 41#include <unistd.h> 42#endif 43 44#ifdef HAVE_FCNTL_H 45#include <fcntl.h> 46#endif 47 48#ifdef HAVE_TIME_H 49#include <time.h> 50#endif 51 52#ifndef WIN32 53#ifdef HAVE_SYS_SOCKET_H 54#include <sys/socket.h> 55#endif 56#ifdef HAVE_NETINET_IN_H 57#include <netinet/in.h> 58#endif 59#ifdef HAVE_ARPA_INET_H 60#include <arpa/inet.h> 61#endif 62#ifdef HAVE_UTSNAME_H 63#include <sys/utsname.h> 64#endif 65#ifdef HAVE_NETDB_H 66#include <netdb.h> 67#endif 68#ifdef __VMS 69#include <in.h> 70#include <inet.h> 71#endif 72#endif /* !WIN32 */ 73 74#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) 75#undef in_addr_t 76#define in_addr_t unsigned long 77#endif 78 79#include <curl/curl.h> 80#include "urldata.h" 81#include "sendf.h" 82#include "hostip.h" 83#include "progress.h" 84#include "transfer.h" 85#include "escape.h" 86#include "http.h" /* for HTTP proxy tunnel stuff */ 87#include "ssh.h" 88#include "url.h" 89#include "speedcheck.h" 90#include "getinfo.h" 91 92#include "strequal.h" 93#include "sslgen.h" 94#include "connect.h" 95#include "strerror.h" 96#include "inet_ntop.h" 97#include "parsedate.h" /* for the week day and month names */ 98#include "sockaddr.h" /* required for Curl_sockaddr_storage */ 99#include "strtoofft.h" 100#include "multiif.h" 101#include "select.h" 102#include "warnless.h" 103 104#define _MPRINTF_REPLACE /* use our functions only */ 105#include <curl/mprintf.h> 106 107#include "curl_memory.h" 108/* The last #include file should be: */ 109#include "memdebug.h" 110 111#ifndef PATH_MAX 112#define PATH_MAX 1024 /* just an extra precaution since there are systems that 113 have their definition hidden well */ 114#endif 115 116/* Local functions: */ 117static const char *sftp_libssh2_strerror(unsigned long err); 118static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); 119static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); 120static LIBSSH2_FREE_FUNC(my_libssh2_free); 121 122static CURLcode get_pathname(const char **cpp, char **path); 123 124static CURLcode ssh_connect(struct connectdata *conn, bool *done); 125static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); 126static CURLcode ssh_do(struct connectdata *conn, bool *done); 127 128static CURLcode ssh_getworkingpath(struct connectdata *conn, 129 char *homedir, /* when SFTP is used */ 130 char **path); 131 132static CURLcode scp_done(struct connectdata *conn, 133 CURLcode, bool premature); 134static CURLcode scp_doing(struct connectdata *conn, 135 bool *dophase_done); 136static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); 137 138static CURLcode sftp_done(struct connectdata *conn, 139 CURLcode, bool premature); 140static CURLcode sftp_doing(struct connectdata *conn, 141 bool *dophase_done); 142static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); 143static 144CURLcode sftp_perform(struct connectdata *conn, 145 bool *connected, 146 bool *dophase_done); 147 148static int ssh_getsock(struct connectdata *conn, 149 curl_socket_t *sock, /* points to numsocks number 150 of sockets */ 151 int numsocks); 152 153static int ssh_perform_getsock(const struct connectdata *conn, 154 curl_socket_t *sock, /* points to numsocks 155 number of sockets */ 156 int numsocks); 157 158/* 159 * SCP protocol handler. 160 */ 161 162const struct Curl_handler Curl_handler_scp = { 163 "SCP", /* scheme */ 164 ZERO_NULL, /* setup_connection */ 165 ssh_do, /* do_it */ 166 scp_done, /* done */ 167 ZERO_NULL, /* do_more */ 168 ssh_connect, /* connect_it */ 169 ssh_multi_statemach, /* connecting */ 170 scp_doing, /* doing */ 171 ssh_getsock, /* proto_getsock */ 172 ssh_getsock, /* doing_getsock */ 173 ssh_perform_getsock, /* perform_getsock */ 174 scp_disconnect, /* disconnect */ 175 ZERO_NULL, /* readwrite */ 176 PORT_SSH, /* defport */ 177 CURLPROTO_SCP, /* protocol */ 178 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION /* flags */ 179}; 180 181 182/* 183 * SFTP protocol handler. 184 */ 185 186const struct Curl_handler Curl_handler_sftp = { 187 "SFTP", /* scheme */ 188 ZERO_NULL, /* setup_connection */ 189 ssh_do, /* do_it */ 190 sftp_done, /* done */ 191 ZERO_NULL, /* do_more */ 192 ssh_connect, /* connect_it */ 193 ssh_multi_statemach, /* connecting */ 194 sftp_doing, /* doing */ 195 ssh_getsock, /* proto_getsock */ 196 ssh_getsock, /* doing_getsock */ 197 ssh_perform_getsock, /* perform_getsock */ 198 sftp_disconnect, /* disconnect */ 199 ZERO_NULL, /* readwrite */ 200 PORT_SSH, /* defport */ 201 CURLPROTO_SFTP, /* protocol */ 202 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION /* flags */ 203}; 204 205 206static void 207kbd_callback(const char *name, int name_len, const char *instruction, 208 int instruction_len, int num_prompts, 209 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, 210 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, 211 void **abstract) 212{ 213 struct connectdata *conn = (struct connectdata *)*abstract; 214 215#ifdef CURL_LIBSSH2_DEBUG 216 fprintf(stderr, "name=%s\n", name); 217 fprintf(stderr, "name_len=%d\n", name_len); 218 fprintf(stderr, "instruction=%s\n", instruction); 219 fprintf(stderr, "instruction_len=%d\n", instruction_len); 220 fprintf(stderr, "num_prompts=%d\n", num_prompts); 221#else 222 (void)name; 223 (void)name_len; 224 (void)instruction; 225 (void)instruction_len; 226#endif /* CURL_LIBSSH2_DEBUG */ 227 if(num_prompts == 1) { 228 responses[0].text = strdup(conn->passwd); 229 responses[0].length = (unsigned int)strlen(conn->passwd); 230 } 231 (void)prompts; 232 (void)abstract; 233} /* kbd_callback */ 234 235static CURLcode sftp_libssh2_error_to_CURLE(int err) 236{ 237 switch (err) { 238 case LIBSSH2_FX_OK: 239 return CURLE_OK; 240 241 case LIBSSH2_FX_NO_SUCH_FILE: 242 case LIBSSH2_FX_NO_SUCH_PATH: 243 return CURLE_REMOTE_FILE_NOT_FOUND; 244 245 case LIBSSH2_FX_PERMISSION_DENIED: 246 case LIBSSH2_FX_WRITE_PROTECT: 247 case LIBSSH2_FX_LOCK_CONFlICT: 248 return CURLE_REMOTE_ACCESS_DENIED; 249 250 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: 251 case LIBSSH2_FX_QUOTA_EXCEEDED: 252 return CURLE_REMOTE_DISK_FULL; 253 254 case LIBSSH2_FX_FILE_ALREADY_EXISTS: 255 return CURLE_REMOTE_FILE_EXISTS; 256 257 case LIBSSH2_FX_DIR_NOT_EMPTY: 258 return CURLE_QUOTE_ERROR; 259 260 default: 261 break; 262 } 263 264 return CURLE_SSH; 265} 266 267static CURLcode libssh2_session_error_to_CURLE(int err) 268{ 269 switch (err) { 270 /* Ordered by order of appearance in libssh2.h */ 271 case LIBSSH2_ERROR_NONE: 272 return CURLE_OK; 273 274 case LIBSSH2_ERROR_SOCKET_NONE: 275 return CURLE_COULDNT_CONNECT; 276 277 case LIBSSH2_ERROR_ALLOC: 278 return CURLE_OUT_OF_MEMORY; 279 280 case LIBSSH2_ERROR_SOCKET_SEND: 281 return CURLE_SEND_ERROR; 282 283 case LIBSSH2_ERROR_HOSTKEY_INIT: 284 case LIBSSH2_ERROR_HOSTKEY_SIGN: 285 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: 286 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: 287 return CURLE_PEER_FAILED_VERIFICATION; 288 289 case LIBSSH2_ERROR_PASSWORD_EXPIRED: 290 return CURLE_LOGIN_DENIED; 291 292 case LIBSSH2_ERROR_SOCKET_TIMEOUT: 293 case LIBSSH2_ERROR_TIMEOUT: 294 return CURLE_OPERATION_TIMEDOUT; 295 296 case LIBSSH2_ERROR_EAGAIN: 297 return CURLE_AGAIN; 298 } 299 300 /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode 301 error code, and possibly add a few new SSH-related one. We must however 302 not return or even depend on libssh2 errors in the public libcurl API */ 303 304 return CURLE_SSH; 305} 306 307static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc) 308{ 309 (void)abstract; /* arg not used */ 310 return malloc(count); 311} 312 313static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc) 314{ 315 (void)abstract; /* arg not used */ 316 return realloc(ptr, count); 317} 318 319static LIBSSH2_FREE_FUNC(my_libssh2_free) 320{ 321 (void)abstract; /* arg not used */ 322 free(ptr); 323} 324 325/* 326 * SSH State machine related code 327 */ 328/* This is the ONLY way to change SSH state! */ 329static void state(struct connectdata *conn, sshstate nowstate) 330{ 331#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 332 /* for debug purposes */ 333 static const char * const names[] = { 334 "SSH_STOP", 335 "SSH_INIT", 336 "SSH_S_STARTUP", 337 "SSH_HOSTKEY", 338 "SSH_AUTHLIST", 339 "SSH_AUTH_PKEY_INIT", 340 "SSH_AUTH_PKEY", 341 "SSH_AUTH_PASS_INIT", 342 "SSH_AUTH_PASS", 343 "SSH_AUTH_HOST_INIT", 344 "SSH_AUTH_HOST", 345 "SSH_AUTH_KEY_INIT", 346 "SSH_AUTH_KEY", 347 "SSH_AUTH_DONE", 348 "SSH_SFTP_INIT", 349 "SSH_SFTP_REALPATH", 350 "SSH_SFTP_QUOTE_INIT", 351 "SSH_SFTP_POSTQUOTE_INIT", 352 "SSH_SFTP_QUOTE", 353 "SSH_SFTP_NEXT_QUOTE", 354 "SSH_SFTP_QUOTE_STAT", 355 "SSH_SFTP_QUOTE_SETSTAT", 356 "SSH_SFTP_QUOTE_SYMLINK", 357 "SSH_SFTP_QUOTE_MKDIR", 358 "SSH_SFTP_QUOTE_RENAME", 359 "SSH_SFTP_QUOTE_RMDIR", 360 "SSH_SFTP_QUOTE_UNLINK", 361 "SSH_SFTP_TRANS_INIT", 362 "SSH_SFTP_UPLOAD_INIT", 363 "SSH_SFTP_CREATE_DIRS_INIT", 364 "SSH_SFTP_CREATE_DIRS", 365 "SSH_SFTP_CREATE_DIRS_MKDIR", 366 "SSH_SFTP_READDIR_INIT", 367 "SSH_SFTP_READDIR", 368 "SSH_SFTP_READDIR_LINK", 369 "SSH_SFTP_READDIR_BOTTOM", 370 "SSH_SFTP_READDIR_DONE", 371 "SSH_SFTP_DOWNLOAD_INIT", 372 "SSH_SFTP_DOWNLOAD_STAT", 373 "SSH_SFTP_CLOSE", 374 "SSH_SFTP_SHUTDOWN", 375 "SSH_SCP_TRANS_INIT", 376 "SSH_SCP_UPLOAD_INIT", 377 "SSH_SCP_DOWNLOAD_INIT", 378 "SSH_SCP_DONE", 379 "SSH_SCP_SEND_EOF", 380 "SSH_SCP_WAIT_EOF", 381 "SSH_SCP_WAIT_CLOSE", 382 "SSH_SCP_CHANNEL_FREE", 383 "SSH_SESSION_DISCONNECT", 384 "SSH_SESSION_FREE", 385 "QUIT" 386 }; 387#endif 388 struct ssh_conn *sshc = &conn->proto.sshc; 389 390#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 391 if(sshc->state != nowstate) { 392 infof(conn->data, "SFTP %p state change from %s to %s\n", 393 sshc, names[sshc->state], names[nowstate]); 394 } 395#endif 396 397 sshc->state = nowstate; 398} 399 400/* figure out the path to work with in this particular request */ 401static CURLcode ssh_getworkingpath(struct connectdata *conn, 402 char *homedir, /* when SFTP is used */ 403 char **path) /* returns the allocated 404 real path to work with */ 405{ 406 struct SessionHandle *data = conn->data; 407 char *real_path = NULL; 408 char *working_path; 409 int working_path_len; 410 411 working_path = curl_easy_unescape(data, data->state.path, 0, 412 &working_path_len); 413 if(!working_path) 414 return CURLE_OUT_OF_MEMORY; 415 416 /* Check for /~/ , indicating relative to the user's home directory */ 417 if(conn->handler->protocol & CURLPROTO_SCP) { 418 real_path = malloc(working_path_len+1); 419 if(real_path == NULL) { 420 free(working_path); 421 return CURLE_OUT_OF_MEMORY; 422 } 423 if((working_path_len > 1) && (working_path[1] == '~')) 424 /* It is referenced to the home directory, so strip the leading '/' */ 425 memcpy(real_path, working_path+1, 1 + working_path_len-1); 426 else 427 memcpy(real_path, working_path, 1 + working_path_len); 428 } 429 else if(conn->handler->protocol & CURLPROTO_SFTP) { 430 if((working_path_len > 1) && (working_path[1] == '~')) { 431 size_t homelen = strlen(homedir); 432 real_path = malloc(homelen + working_path_len + 1); 433 if(real_path == NULL) { 434 free(working_path); 435 return CURLE_OUT_OF_MEMORY; 436 } 437 /* It is referenced to the home directory, so strip the 438 leading '/' */ 439 memcpy(real_path, homedir, homelen); 440 real_path[homelen] = '/'; 441 real_path[homelen+1] = '\0'; 442 if(working_path_len > 3) { 443 memcpy(real_path+homelen+1, working_path + 3, 444 1 + working_path_len -3); 445 } 446 } 447 else { 448 real_path = malloc(working_path_len+1); 449 if(real_path == NULL) { 450 free(working_path); 451 return CURLE_OUT_OF_MEMORY; 452 } 453 memcpy(real_path, working_path, 1+working_path_len); 454 } 455 } 456 457 free(working_path); 458 459 /* store the pointer for the caller to receive */ 460 *path = real_path; 461 462 return CURLE_OK; 463} 464 465#ifdef HAVE_LIBSSH2_KNOWNHOST_API 466static int sshkeycallback(CURL *easy, 467 const struct curl_khkey *knownkey, /* known */ 468 const struct curl_khkey *foundkey, /* found */ 469 enum curl_khmatch match, 470 void *clientp) 471{ 472 (void)easy; 473 (void)knownkey; 474 (void)foundkey; 475 (void)clientp; 476 477 /* we only allow perfect matches, and we reject everything else */ 478 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; 479} 480#endif 481 482/* 483 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions 484 * with 32bit size_t. 485 */ 486#ifdef HAVE_LIBSSH2_SFTP_SEEK64 487#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y) 488#else 489#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y) 490#endif 491 492/* 493 * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit 494 * architectures so we check of the necessary function is present. 495 */ 496#ifndef HAVE_LIBSSH2_SCP_SEND64 497#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0) 498#else 499#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \ 500 (libssh2_uint64_t)d, 0, 0) 501#endif 502 503/* 504 * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64. 505 */ 506#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE 507#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y) 508#endif 509 510static CURLcode ssh_knownhost(struct connectdata *conn) 511{ 512 CURLcode result = CURLE_OK; 513 514#ifdef HAVE_LIBSSH2_KNOWNHOST_API 515 struct SessionHandle *data = conn->data; 516 517 if(data->set.str[STRING_SSH_KNOWNHOSTS]) { 518 /* we're asked to verify the host against a file */ 519 struct ssh_conn *sshc = &conn->proto.sshc; 520 int rc; 521 int keytype; 522 size_t keylen; 523 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, 524 &keylen, &keytype); 525 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE; 526 int keybit = 0; 527 528 if(remotekey) { 529 /* 530 * A subject to figure out is what host name we need to pass in here. 531 * What host name does OpenSSH store in its file if an IDN name is 532 * used? 533 */ 534 struct libssh2_knownhost *host; 535 enum curl_khmatch keymatch; 536 curl_sshkeycallback func = 537 data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; 538 struct curl_khkey knownkey; 539 struct curl_khkey *knownkeyp = NULL; 540 struct curl_khkey foundkey; 541 542 keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? 543 LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; 544 545 keycheck = libssh2_knownhost_check(sshc->kh, 546 conn->host.name, 547 remotekey, keylen, 548 LIBSSH2_KNOWNHOST_TYPE_PLAIN| 549 LIBSSH2_KNOWNHOST_KEYENC_RAW| 550 keybit, 551 &host); 552 553 infof(data, "SSH host check: %d, key: %s\n", keycheck, 554 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? 555 host->key:"<none>"); 556 557 /* setup 'knownkey' */ 558 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { 559 knownkey.key = host->key; 560 knownkey.len = 0; 561 knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? 562 CURLKHTYPE_RSA : CURLKHTYPE_DSS; 563 knownkeyp = &knownkey; 564 } 565 566 /* setup 'foundkey' */ 567 foundkey.key = remotekey; 568 foundkey.len = keylen; 569 foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? 570 CURLKHTYPE_RSA : CURLKHTYPE_DSS; 571 572 /* 573 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the 574 * curl_khmatch enum are ever modified, we need to introduce a 575 * translation table here! 576 */ 577 keymatch = (enum curl_khmatch)keycheck; 578 579 /* Ask the callback how to behave */ 580 rc = func(data, knownkeyp, /* from the knownhosts file */ 581 &foundkey, /* from the remote host */ 582 keymatch, data->set.ssh_keyfunc_userp); 583 } 584 else 585 /* no remotekey means failure! */ 586 rc = CURLKHSTAT_REJECT; 587 588 switch(rc) { 589 default: /* unknown return codes will equal reject */ 590 case CURLKHSTAT_REJECT: 591 state(conn, SSH_SESSION_FREE); 592 case CURLKHSTAT_DEFER: 593 /* DEFER means bail out but keep the SSH_HOSTKEY state */ 594 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 595 break; 596 case CURLKHSTAT_FINE: 597 case CURLKHSTAT_FINE_ADD_TO_FILE: 598 /* proceed */ 599 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { 600 /* the found host+key didn't match but has been told to be fine 601 anyway so we add it in memory */ 602 int addrc = libssh2_knownhost_add(sshc->kh, 603 conn->host.name, NULL, 604 remotekey, keylen, 605 LIBSSH2_KNOWNHOST_TYPE_PLAIN| 606 LIBSSH2_KNOWNHOST_KEYENC_RAW| 607 keybit, NULL); 608 if(addrc) 609 infof(data, "Warning adding the known host %s failed!\n", 610 conn->host.name); 611 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { 612 /* now we write the entire in-memory list of known hosts to the 613 known_hosts file */ 614 int wrc = 615 libssh2_knownhost_writefile(sshc->kh, 616 data->set.str[STRING_SSH_KNOWNHOSTS], 617 LIBSSH2_KNOWNHOST_FILE_OPENSSH); 618 if(wrc) { 619 infof(data, "Warning, writing %s failed!\n", 620 data->set.str[STRING_SSH_KNOWNHOSTS]); 621 } 622 } 623 } 624 break; 625 } 626 } 627#else /* HAVE_LIBSSH2_KNOWNHOST_API */ 628 (void)conn; 629#endif 630 return result; 631} 632 633 634/* 635 * ssh_statemach_act() runs the SSH state machine as far as it can without 636 * blocking and without reaching the end. The data the pointer 'block' points 637 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN 638 * meaning it wants to be called again when the socket is ready 639 */ 640 641static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) 642{ 643 CURLcode result = CURLE_OK; 644 struct SessionHandle *data = conn->data; 645 struct SSHPROTO *sftp_scp = data->state.proto.ssh; 646 struct ssh_conn *sshc = &conn->proto.sshc; 647 curl_socket_t sock = conn->sock[FIRSTSOCKET]; 648#ifdef CURL_LIBSSH2_DEBUG 649 const char *fingerprint; 650#endif /* CURL_LIBSSH2_DEBUG */ 651 const char *host_public_key_md5; 652 int rc = LIBSSH2_ERROR_NONE, i; 653 int err; 654 int seekerr = CURL_SEEKFUNC_OK; 655 *block = 0; /* we're not blocking by default */ 656 657 do { 658 659 switch(sshc->state) { 660 case SSH_INIT: 661 sshc->secondCreateDirs = 0; 662 sshc->nextstate = SSH_NO_STATE; 663 sshc->actualcode = CURLE_OK; 664 665 /* Set libssh2 to non-blocking, since everything internally is 666 non-blocking */ 667 libssh2_session_set_blocking(sshc->ssh_session, 0); 668 669 state(conn, SSH_S_STARTUP); 670 /* fall-through */ 671 672 case SSH_S_STARTUP: 673 rc = libssh2_session_startup(sshc->ssh_session, sock); 674 if(rc == LIBSSH2_ERROR_EAGAIN) { 675 break; 676 } 677 else if(rc) { 678 failf(data, "Failure establishing ssh session"); 679 state(conn, SSH_SESSION_FREE); 680 sshc->actualcode = CURLE_FAILED_INIT; 681 break; 682 } 683 684 state(conn, SSH_HOSTKEY); 685 686 /* fall-through */ 687 case SSH_HOSTKEY: 688 689#ifdef CURL_LIBSSH2_DEBUG 690 /* 691 * Before we authenticate we should check the hostkey's fingerprint 692 * against our known hosts. How that is handled (reading from file, 693 * whatever) is up to us. As for know not much is implemented, besides 694 * showing how to get the fingerprint. 695 */ 696 fingerprint = libssh2_hostkey_hash(sshc->ssh_session, 697 LIBSSH2_HOSTKEY_HASH_MD5); 698 699 /* The fingerprint points to static storage (!), don't free() it. */ 700 infof(data, "Fingerprint: "); 701 for(rc = 0; rc < 16; rc++) 702 infof(data, "%02X ", (unsigned char) fingerprint[rc]); 703 infof(data, "\n"); 704#endif /* CURL_LIBSSH2_DEBUG */ 705 706 /* Before we authenticate we check the hostkey's MD5 fingerprint 707 * against a known fingerprint, if available. This implementation pulls 708 * it from the curl option. 709 */ 710 if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] && 711 strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) { 712 char buf[33]; 713 host_public_key_md5 = libssh2_hostkey_hash(sshc->ssh_session, 714 LIBSSH2_HOSTKEY_HASH_MD5); 715 for(i = 0; i < 16; i++) 716 snprintf(&buf[i*2], 3, "%02x", 717 (unsigned char) host_public_key_md5[i]); 718 if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) { 719 failf(data, 720 "Denied establishing ssh session: mismatch md5 fingerprint. " 721 "Remote %s is not equal to %s", 722 buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]); 723 state(conn, SSH_SESSION_FREE); 724 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 725 break; 726 } 727 } 728 729 result = ssh_knownhost(conn); 730 if(!result) 731 state(conn, SSH_AUTHLIST); 732 break; 733 734 case SSH_AUTHLIST: 735 /* 736 * Figure out authentication methods 737 * NB: As soon as we have provided a username to an openssh server we 738 * must never change it later. Thus, always specify the correct username 739 * here, even though the libssh2 docs kind of indicate that it should be 740 * possible to get a 'generic' list (not user-specific) of authentication 741 * methods, presumably with a blank username. That won't work in my 742 * experience. 743 * So always specify it here. 744 */ 745 sshc->authlist = libssh2_userauth_list(sshc->ssh_session, 746 conn->user, 747 (unsigned int)strlen(conn->user)); 748 749 if(!sshc->authlist) { 750 if((err = libssh2_session_last_errno(sshc->ssh_session)) == 751 LIBSSH2_ERROR_EAGAIN) { 752 rc = LIBSSH2_ERROR_EAGAIN; 753 break; 754 } 755 else { 756 state(conn, SSH_SESSION_FREE); 757 sshc->actualcode = libssh2_session_error_to_CURLE(err); 758 break; 759 } 760 } 761 infof(data, "SSH authentication methods available: %s\n", 762 sshc->authlist); 763 764 state(conn, SSH_AUTH_PKEY_INIT); 765 break; 766 767 case SSH_AUTH_PKEY_INIT: 768 /* 769 * Check the supported auth types in the order I feel is most secure 770 * with the requested type of authentication 771 */ 772 sshc->authed = FALSE; 773 774 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && 775 (strstr(sshc->authlist, "publickey") != NULL)) { 776 char *home; 777 778 sshc->rsa_pub = sshc->rsa = NULL; 779 780 /* To ponder about: should really the lib be messing about with the 781 HOME environment variable etc? */ 782 home = curl_getenv("HOME"); 783 784 if(data->set.str[STRING_SSH_PUBLIC_KEY]) 785 sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]); 786 else if(home) 787 sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home); 788 else 789 /* as a final resort, try current dir! */ 790 sshc->rsa_pub = strdup("id_dsa.pub"); 791 792 if(sshc->rsa_pub == NULL) { 793 Curl_safefree(home); 794 home = NULL; 795 state(conn, SSH_SESSION_FREE); 796 sshc->actualcode = CURLE_OUT_OF_MEMORY; 797 break; 798 } 799 800 if(data->set.str[STRING_SSH_PRIVATE_KEY]) 801 sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]); 802 else if(home) 803 sshc->rsa = aprintf("%s/.ssh/id_dsa", home); 804 else 805 /* as a final resort, try current dir! */ 806 sshc->rsa = strdup("id_dsa"); 807 808 if(sshc->rsa == NULL) { 809 Curl_safefree(home); 810 home = NULL; 811 Curl_safefree(sshc->rsa_pub); 812 sshc->rsa_pub = NULL; 813 state(conn, SSH_SESSION_FREE); 814 sshc->actualcode = CURLE_OUT_OF_MEMORY; 815 break; 816 } 817 818 sshc->passphrase = data->set.str[STRING_KEY_PASSWD]; 819 if(!sshc->passphrase) 820 sshc->passphrase = ""; 821 822 Curl_safefree(home); 823 home = NULL; 824 825 infof(data, "Using ssh public key file %s\n", sshc->rsa_pub); 826 infof(data, "Using ssh private key file %s\n", sshc->rsa); 827 828 state(conn, SSH_AUTH_PKEY); 829 } 830 else { 831 state(conn, SSH_AUTH_PASS_INIT); 832 } 833 break; 834 835 case SSH_AUTH_PKEY: 836 /* The function below checks if the files exists, no need to stat() here. 837 */ 838 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, 839 conn->user, 840 (unsigned int) 841 strlen(conn->user), 842 sshc->rsa_pub, 843 sshc->rsa, sshc->passphrase); 844 if(rc == LIBSSH2_ERROR_EAGAIN) { 845 break; 846 } 847 848 Curl_safefree(sshc->rsa_pub); 849 sshc->rsa_pub = NULL; 850 Curl_safefree(sshc->rsa); 851 sshc->rsa = NULL; 852 853 if(rc == 0) { 854 sshc->authed = TRUE; 855 infof(data, "Initialized SSH public key authentication\n"); 856 state(conn, SSH_AUTH_DONE); 857 } 858 else { 859 char *err_msg; 860 (void)libssh2_session_last_error(sshc->ssh_session, 861 &err_msg, NULL, 0); 862 infof(data, "SSH public key authentication failed: %s\n", err_msg); 863 state(conn, SSH_AUTH_PASS_INIT); 864 } 865 break; 866 867 case SSH_AUTH_PASS_INIT: 868 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && 869 (strstr(sshc->authlist, "password") != NULL)) { 870 state(conn, SSH_AUTH_PASS); 871 } 872 else { 873 state(conn, SSH_AUTH_HOST_INIT); 874 } 875 break; 876 877 case SSH_AUTH_PASS: 878 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user, 879 (unsigned int)strlen(conn->user), 880 conn->passwd, 881 (unsigned int)strlen(conn->passwd), 882 NULL); 883 if(rc == LIBSSH2_ERROR_EAGAIN) { 884 break; 885 } 886 else if(rc == 0) { 887 sshc->authed = TRUE; 888 infof(data, "Initialized password authentication\n"); 889 state(conn, SSH_AUTH_DONE); 890 } 891 else { 892 state(conn, SSH_AUTH_HOST_INIT); 893 } 894 break; 895 896 case SSH_AUTH_HOST_INIT: 897 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && 898 (strstr(sshc->authlist, "hostbased") != NULL)) { 899 state(conn, SSH_AUTH_HOST); 900 } 901 else { 902 state(conn, SSH_AUTH_KEY_INIT); 903 } 904 break; 905 906 case SSH_AUTH_HOST: 907 state(conn, SSH_AUTH_KEY_INIT); 908 break; 909 910 case SSH_AUTH_KEY_INIT: 911 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) 912 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { 913 state(conn, SSH_AUTH_KEY); 914 } 915 else { 916 state(conn, SSH_AUTH_DONE); 917 } 918 break; 919 920 case SSH_AUTH_KEY: 921 /* Authentication failed. Continue with keyboard-interactive now. */ 922 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session, 923 conn->user, 924 (unsigned int) 925 strlen(conn->user), 926 &kbd_callback); 927 if(rc == LIBSSH2_ERROR_EAGAIN) { 928 break; 929 } 930 else if(rc == 0) { 931 sshc->authed = TRUE; 932 infof(data, "Initialized keyboard interactive authentication\n"); 933 } 934 state(conn, SSH_AUTH_DONE); 935 break; 936 937 case SSH_AUTH_DONE: 938 if(!sshc->authed) { 939 failf(data, "Authentication failure"); 940 state(conn, SSH_SESSION_FREE); 941 sshc->actualcode = CURLE_LOGIN_DENIED; 942 break; 943 } 944 945 /* 946 * At this point we have an authenticated ssh session. 947 */ 948 infof(data, "Authentication complete\n"); 949 950 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ 951 952 conn->sockfd = sock; 953 conn->writesockfd = CURL_SOCKET_BAD; 954 955 if(conn->handler->protocol == CURLPROTO_SFTP) { 956 state(conn, SSH_SFTP_INIT); 957 break; 958 } 959 infof(data, "SSH CONNECT phase done\n"); 960 state(conn, SSH_STOP); 961 break; 962 963 case SSH_SFTP_INIT: 964 /* 965 * Start the libssh2 sftp session 966 */ 967 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); 968 if(!sshc->sftp_session) { 969 if(libssh2_session_last_errno(sshc->ssh_session) == 970 LIBSSH2_ERROR_EAGAIN) { 971 rc = LIBSSH2_ERROR_EAGAIN; 972 break; 973 } 974 else { 975 char *err_msg; 976 977 (void)libssh2_session_last_error(sshc->ssh_session, 978 &err_msg, NULL, 0); 979 failf(data, "Failure initializing sftp session: %s", err_msg); 980 state(conn, SSH_SESSION_FREE); 981 sshc->actualcode = CURLE_FAILED_INIT; 982 break; 983 } 984 } 985 state(conn, SSH_SFTP_REALPATH); 986 break; 987 988 case SSH_SFTP_REALPATH: 989 { 990 char tempHome[PATH_MAX]; 991 992 /* 993 * Get the "home" directory 994 */ 995 rc = libssh2_sftp_realpath(sshc->sftp_session, ".", 996 tempHome, PATH_MAX-1); 997 if(rc == LIBSSH2_ERROR_EAGAIN) { 998 break; 999 } 1000 else if(rc > 0) { 1001 /* It seems that this string is not always NULL terminated */ 1002 tempHome[rc] = '\0'; 1003 sshc->homedir = strdup(tempHome); 1004 if(!sshc->homedir) { 1005 state(conn, SSH_SFTP_CLOSE); 1006 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1007 break; 1008 } 1009 conn->data->state.most_recent_ftp_entrypath = sshc->homedir; 1010 } 1011 else { 1012 /* Return the error type */ 1013 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1014 result = sftp_libssh2_error_to_CURLE(err); 1015 sshc->actualcode = result?result:CURLE_SSH; 1016 DEBUGF(infof(data, "error = %d makes libcurl = %d\n", 1017 err, (int)result)); 1018 state(conn, SSH_STOP); 1019 break; 1020 } 1021 } 1022 /* This is the last step in the SFTP connect phase. Do note that while 1023 we get the homedir here, we get the "workingpath" in the DO action 1024 since the homedir will remain the same between request but the 1025 working path will not. */ 1026 DEBUGF(infof(data, "SSH CONNECT phase done\n")); 1027 state(conn, SSH_STOP); 1028 break; 1029 1030 case SSH_SFTP_QUOTE_INIT: 1031 1032 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path); 1033 if(result) { 1034 sshc->actualcode = result; 1035 state(conn, SSH_STOP); 1036 break; 1037 } 1038 1039 if(data->set.quote) { 1040 infof(data, "Sending quote commands\n"); 1041 sshc->quote_item = data->set.quote; 1042 state(conn, SSH_SFTP_QUOTE); 1043 } 1044 else { 1045 state(conn, SSH_SFTP_TRANS_INIT); 1046 } 1047 break; 1048 1049 case SSH_SFTP_POSTQUOTE_INIT: 1050 if(data->set.postquote) { 1051 infof(data, "Sending quote commands\n"); 1052 sshc->quote_item = data->set.postquote; 1053 state(conn, SSH_SFTP_QUOTE); 1054 } 1055 else { 1056 state(conn, SSH_STOP); 1057 } 1058 break; 1059 1060 case SSH_SFTP_QUOTE: 1061 /* Send any quote commands */ 1062 { 1063 const char *cp; 1064 1065 /* 1066 * Support some of the "FTP" commands 1067 */ 1068 if(curl_strequal("pwd", sshc->quote_item->data)) { 1069 /* output debug output if that is requested */ 1070 char *tmp = aprintf("257 \"%s\" is current directory.\n", 1071 sftp_scp->path); 1072 if(!tmp) { 1073 result = CURLE_OUT_OF_MEMORY; 1074 state(conn, SSH_SFTP_CLOSE); 1075 sshc->nextstate = SSH_NO_STATE; 1076 break; 1077 } 1078 if(data->set.verbose) { 1079 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn); 1080 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn); 1081 } 1082 /* this sends an FTP-like "header" to the header callback so that the 1083 current directory can be read very similar to how it is read when 1084 using ordinary FTP. */ 1085 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); 1086 free(tmp); 1087 state(conn, SSH_SFTP_NEXT_QUOTE); 1088 break; 1089 } 1090 else if(sshc->quote_item->data) { 1091 /* 1092 * the arguments following the command must be separated from the 1093 * command with a space so we can check for it unconditionally 1094 */ 1095 cp = strchr(sshc->quote_item->data, ' '); 1096 if(cp == NULL) { 1097 failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); 1098 state(conn, SSH_SFTP_CLOSE); 1099 sshc->nextstate = SSH_NO_STATE; 1100 sshc->actualcode = CURLE_QUOTE_ERROR; 1101 break; 1102 } 1103 1104 /* 1105 * also, every command takes at least one argument so we get that 1106 * first argument right now 1107 */ 1108 result = get_pathname(&cp, &sshc->quote_path1); 1109 if(result) { 1110 if(result == CURLE_OUT_OF_MEMORY) 1111 failf(data, "Out of memory"); 1112 else 1113 failf(data, "Syntax error: Bad first parameter"); 1114 state(conn, SSH_SFTP_CLOSE); 1115 sshc->nextstate = SSH_NO_STATE; 1116 sshc->actualcode = result; 1117 break; 1118 } 1119 1120 /* 1121 * SFTP is a binary protocol, so we don't send text commands to 1122 * the server. Instead, we scan for commands for commands used by 1123 * OpenSSH's sftp program and call the appropriate libssh2 1124 * functions. 1125 */ 1126 if(curl_strnequal(sshc->quote_item->data, "chgrp ", 6) || 1127 curl_strnequal(sshc->quote_item->data, "chmod ", 6) || 1128 curl_strnequal(sshc->quote_item->data, "chown ", 6) ) { 1129 /* attribute change */ 1130 1131 /* sshc->quote_path1 contains the mode to set */ 1132 /* get the destination */ 1133 result = get_pathname(&cp, &sshc->quote_path2); 1134 if(result) { 1135 if(result == CURLE_OUT_OF_MEMORY) 1136 failf(data, "Out of memory"); 1137 else 1138 failf(data, "Syntax error in chgrp/chmod/chown: " 1139 "Bad second parameter"); 1140 Curl_safefree(sshc->quote_path1); 1141 sshc->quote_path1 = NULL; 1142 state(conn, SSH_SFTP_CLOSE); 1143 sshc->nextstate = SSH_NO_STATE; 1144 sshc->actualcode = result; 1145 break; 1146 } 1147 memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); 1148 state(conn, SSH_SFTP_QUOTE_STAT); 1149 break; 1150 } 1151 else if(curl_strnequal(sshc->quote_item->data, "ln ", 3) || 1152 curl_strnequal(sshc->quote_item->data, "symlink ", 8)) { 1153 /* symbolic linking */ 1154 /* sshc->quote_path1 is the source */ 1155 /* get the destination */ 1156 result = get_pathname(&cp, &sshc->quote_path2); 1157 if(result) { 1158 if(result == CURLE_OUT_OF_MEMORY) 1159 failf(data, "Out of memory"); 1160 else 1161 failf(data, 1162 "Syntax error in ln/symlink: Bad second parameter"); 1163 Curl_safefree(sshc->quote_path1); 1164 sshc->quote_path1 = NULL; 1165 state(conn, SSH_SFTP_CLOSE); 1166 sshc->nextstate = SSH_NO_STATE; 1167 sshc->actualcode = result; 1168 break; 1169 } 1170 state(conn, SSH_SFTP_QUOTE_SYMLINK); 1171 break; 1172 } 1173 else if(curl_strnequal(sshc->quote_item->data, "mkdir ", 6)) { 1174 /* create dir */ 1175 state(conn, SSH_SFTP_QUOTE_MKDIR); 1176 break; 1177 } 1178 else if(curl_strnequal(sshc->quote_item->data, "rename ", 7)) { 1179 /* rename file */ 1180 /* first param is the source path */ 1181 /* second param is the dest. path */ 1182 result = get_pathname(&cp, &sshc->quote_path2); 1183 if(result) { 1184 if(result == CURLE_OUT_OF_MEMORY) 1185 failf(data, "Out of memory"); 1186 else 1187 failf(data, "Syntax error in rename: Bad second parameter"); 1188 Curl_safefree(sshc->quote_path1); 1189 sshc->quote_path1 = NULL; 1190 state(conn, SSH_SFTP_CLOSE); 1191 sshc->nextstate = SSH_NO_STATE; 1192 sshc->actualcode = result; 1193 break; 1194 } 1195 state(conn, SSH_SFTP_QUOTE_RENAME); 1196 break; 1197 } 1198 else if(curl_strnequal(sshc->quote_item->data, "rmdir ", 6)) { 1199 /* delete dir */ 1200 state(conn, SSH_SFTP_QUOTE_RMDIR); 1201 break; 1202 } 1203 else if(curl_strnequal(sshc->quote_item->data, "rm ", 3)) { 1204 state(conn, SSH_SFTP_QUOTE_UNLINK); 1205 break; 1206 } 1207 1208 failf(data, "Unknown SFTP command"); 1209 Curl_safefree(sshc->quote_path1); 1210 sshc->quote_path1 = NULL; 1211 Curl_safefree(sshc->quote_path2); 1212 sshc->quote_path2 = NULL; 1213 state(conn, SSH_SFTP_CLOSE); 1214 sshc->nextstate = SSH_NO_STATE; 1215 sshc->actualcode = CURLE_QUOTE_ERROR; 1216 break; 1217 } 1218 } 1219 if(!sshc->quote_item) { 1220 state(conn, SSH_SFTP_TRANS_INIT); 1221 } 1222 break; 1223 1224 case SSH_SFTP_NEXT_QUOTE: 1225 if(sshc->quote_path1) { 1226 Curl_safefree(sshc->quote_path1); 1227 sshc->quote_path1 = NULL; 1228 } 1229 if(sshc->quote_path2) { 1230 Curl_safefree(sshc->quote_path2); 1231 sshc->quote_path2 = NULL; 1232 } 1233 1234 sshc->quote_item = sshc->quote_item->next; 1235 1236 if(sshc->quote_item) { 1237 state(conn, SSH_SFTP_QUOTE); 1238 } 1239 else { 1240 if(sshc->nextstate != SSH_NO_STATE) { 1241 state(conn, sshc->nextstate); 1242 sshc->nextstate = SSH_NO_STATE; 1243 } 1244 else { 1245 state(conn, SSH_SFTP_TRANS_INIT); 1246 } 1247 } 1248 break; 1249 1250 case SSH_SFTP_QUOTE_STAT: 1251 if(!curl_strnequal(sshc->quote_item->data, "chmod", 5)) { 1252 /* Since chown and chgrp only set owner OR group but libssh2 wants to 1253 * set them both at once, we need to obtain the current ownership 1254 * first. This takes an extra protocol round trip. 1255 */ 1256 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, 1257 (unsigned int)strlen(sshc->quote_path2), 1258 LIBSSH2_SFTP_STAT, 1259 &sshc->quote_attrs); 1260 if(rc == LIBSSH2_ERROR_EAGAIN) { 1261 break; 1262 } 1263 else if(rc != 0) { /* get those attributes */ 1264 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1265 Curl_safefree(sshc->quote_path1); 1266 sshc->quote_path1 = NULL; 1267 Curl_safefree(sshc->quote_path2); 1268 sshc->quote_path2 = NULL; 1269 failf(data, "Attempt to get SFTP stats failed: %s", 1270 sftp_libssh2_strerror(err)); 1271 state(conn, SSH_SFTP_CLOSE); 1272 sshc->nextstate = SSH_NO_STATE; 1273 sshc->actualcode = CURLE_QUOTE_ERROR; 1274 break; 1275 } 1276 } 1277 1278 /* Now set the new attributes... */ 1279 if(curl_strnequal(sshc->quote_item->data, "chgrp", 5)) { 1280 sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); 1281 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; 1282 if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0])) { 1283 Curl_safefree(sshc->quote_path1); 1284 sshc->quote_path1 = NULL; 1285 Curl_safefree(sshc->quote_path2); 1286 sshc->quote_path2 = NULL; 1287 failf(data, "Syntax error: chgrp gid not a number"); 1288 state(conn, SSH_SFTP_CLOSE); 1289 sshc->nextstate = SSH_NO_STATE; 1290 sshc->actualcode = CURLE_QUOTE_ERROR; 1291 break; 1292 } 1293 } 1294 else if(curl_strnequal(sshc->quote_item->data, "chmod", 5)) { 1295 sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); 1296 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; 1297 /* permissions are octal */ 1298 if(sshc->quote_attrs.permissions == 0 && 1299 !ISDIGIT(sshc->quote_path1[0])) { 1300 Curl_safefree(sshc->quote_path1); 1301 sshc->quote_path1 = NULL; 1302 Curl_safefree(sshc->quote_path2); 1303 sshc->quote_path2 = NULL; 1304 failf(data, "Syntax error: chmod permissions not a number"); 1305 state(conn, SSH_SFTP_CLOSE); 1306 sshc->nextstate = SSH_NO_STATE; 1307 sshc->actualcode = CURLE_QUOTE_ERROR; 1308 break; 1309 } 1310 } 1311 else if(curl_strnequal(sshc->quote_item->data, "chown", 5)) { 1312 sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); 1313 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; 1314 if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0])) { 1315 Curl_safefree(sshc->quote_path1); 1316 sshc->quote_path1 = NULL; 1317 Curl_safefree(sshc->quote_path2); 1318 sshc->quote_path2 = NULL; 1319 failf(data, "Syntax error: chown uid not a number"); 1320 state(conn, SSH_SFTP_CLOSE); 1321 sshc->nextstate = SSH_NO_STATE; 1322 sshc->actualcode = CURLE_QUOTE_ERROR; 1323 break; 1324 } 1325 } 1326 1327 /* Now send the completed structure... */ 1328 state(conn, SSH_SFTP_QUOTE_SETSTAT); 1329 break; 1330 1331 case SSH_SFTP_QUOTE_SETSTAT: 1332 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, 1333 (unsigned int)strlen(sshc->quote_path2), 1334 LIBSSH2_SFTP_SETSTAT, 1335 &sshc->quote_attrs); 1336 if(rc == LIBSSH2_ERROR_EAGAIN) { 1337 break; 1338 } 1339 else if(rc != 0) { 1340 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1341 Curl_safefree(sshc->quote_path1); 1342 sshc->quote_path1 = NULL; 1343 Curl_safefree(sshc->quote_path2); 1344 sshc->quote_path2 = NULL; 1345 failf(data, "Attempt to set SFTP stats failed: %s", 1346 sftp_libssh2_strerror(err)); 1347 state(conn, SSH_SFTP_CLOSE); 1348 sshc->nextstate = SSH_NO_STATE; 1349 sshc->actualcode = CURLE_QUOTE_ERROR; 1350 break; 1351 } 1352 state(conn, SSH_SFTP_NEXT_QUOTE); 1353 break; 1354 1355 case SSH_SFTP_QUOTE_SYMLINK: 1356 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, 1357 (unsigned int)strlen(sshc->quote_path1), 1358 sshc->quote_path2, 1359 (unsigned int)strlen(sshc->quote_path2), 1360 LIBSSH2_SFTP_SYMLINK); 1361 if(rc == LIBSSH2_ERROR_EAGAIN) { 1362 break; 1363 } 1364 else if(rc != 0) { 1365 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1366 Curl_safefree(sshc->quote_path1); 1367 sshc->quote_path1 = NULL; 1368 Curl_safefree(sshc->quote_path2); 1369 sshc->quote_path2 = NULL; 1370 failf(data, "symlink command failed: %s", 1371 sftp_libssh2_strerror(err)); 1372 state(conn, SSH_SFTP_CLOSE); 1373 sshc->nextstate = SSH_NO_STATE; 1374 sshc->actualcode = CURLE_QUOTE_ERROR; 1375 break; 1376 } 1377 state(conn, SSH_SFTP_NEXT_QUOTE); 1378 break; 1379 1380 case SSH_SFTP_QUOTE_MKDIR: 1381 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, 1382 (unsigned int)strlen(sshc->quote_path1), 1383 0755); 1384 if(rc == LIBSSH2_ERROR_EAGAIN) { 1385 break; 1386 } 1387 else if(rc != 0) { 1388 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1389 Curl_safefree(sshc->quote_path1); 1390 sshc->quote_path1 = NULL; 1391 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); 1392 state(conn, SSH_SFTP_CLOSE); 1393 sshc->nextstate = SSH_NO_STATE; 1394 sshc->actualcode = CURLE_QUOTE_ERROR; 1395 break; 1396 } 1397 state(conn, SSH_SFTP_NEXT_QUOTE); 1398 break; 1399 1400 case SSH_SFTP_QUOTE_RENAME: 1401 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, 1402 (unsigned int)strlen(sshc->quote_path1), 1403 sshc->quote_path2, 1404 (unsigned int)strlen(sshc->quote_path2), 1405 LIBSSH2_SFTP_RENAME_OVERWRITE | 1406 LIBSSH2_SFTP_RENAME_ATOMIC | 1407 LIBSSH2_SFTP_RENAME_NATIVE); 1408 1409 if(rc == LIBSSH2_ERROR_EAGAIN) { 1410 break; 1411 } 1412 else if(rc != 0) { 1413 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1414 Curl_safefree(sshc->quote_path1); 1415 sshc->quote_path1 = NULL; 1416 Curl_safefree(sshc->quote_path2); 1417 sshc->quote_path2 = NULL; 1418 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err)); 1419 state(conn, SSH_SFTP_CLOSE); 1420 sshc->nextstate = SSH_NO_STATE; 1421 sshc->actualcode = CURLE_QUOTE_ERROR; 1422 break; 1423 } 1424 state(conn, SSH_SFTP_NEXT_QUOTE); 1425 break; 1426 1427 case SSH_SFTP_QUOTE_RMDIR: 1428 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, 1429 (unsigned int)strlen(sshc->quote_path1)); 1430 if(rc == LIBSSH2_ERROR_EAGAIN) { 1431 break; 1432 } 1433 else if(rc != 0) { 1434 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1435 Curl_safefree(sshc->quote_path1); 1436 sshc->quote_path1 = NULL; 1437 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); 1438 state(conn, SSH_SFTP_CLOSE); 1439 sshc->nextstate = SSH_NO_STATE; 1440 sshc->actualcode = CURLE_QUOTE_ERROR; 1441 break; 1442 } 1443 state(conn, SSH_SFTP_NEXT_QUOTE); 1444 break; 1445 1446 case SSH_SFTP_QUOTE_UNLINK: 1447 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, 1448 (unsigned int)strlen(sshc->quote_path1)); 1449 if(rc == LIBSSH2_ERROR_EAGAIN) { 1450 break; 1451 } 1452 else if(rc != 0) { 1453 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1454 Curl_safefree(sshc->quote_path1); 1455 sshc->quote_path1 = NULL; 1456 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); 1457 state(conn, SSH_SFTP_CLOSE); 1458 sshc->nextstate = SSH_NO_STATE; 1459 sshc->actualcode = CURLE_QUOTE_ERROR; 1460 break; 1461 } 1462 state(conn, SSH_SFTP_NEXT_QUOTE); 1463 break; 1464 1465 case SSH_SFTP_TRANS_INIT: 1466 if(data->set.upload) 1467 state(conn, SSH_SFTP_UPLOAD_INIT); 1468 else { 1469 if(data->set.opt_no_body) 1470 state(conn, SSH_STOP); 1471 else if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') 1472 state(conn, SSH_SFTP_READDIR_INIT); 1473 else 1474 state(conn, SSH_SFTP_DOWNLOAD_INIT); 1475 } 1476 break; 1477 1478 case SSH_SFTP_UPLOAD_INIT: 1479 { 1480 unsigned long flags; 1481 /* 1482 * NOTE!!! libssh2 requires that the destination path is a full path 1483 * that includes the destination file and name OR ends in a "/" 1484 * If this is not done the destination file will be named the 1485 * same name as the last directory in the path. 1486 */ 1487 1488 if(data->state.resume_from != 0) { 1489 LIBSSH2_SFTP_ATTRIBUTES attrs; 1490 if(data->state.resume_from < 0) { 1491 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, 1492 (unsigned int)strlen(sftp_scp->path), 1493 LIBSSH2_SFTP_STAT, &attrs); 1494 if(rc == LIBSSH2_ERROR_EAGAIN) { 1495 break; 1496 } 1497 else if(rc) { 1498 data->state.resume_from = 0; 1499 } 1500 else { 1501 curl_off_t size = attrs.filesize; 1502 if(size < 0) { 1503 failf(data, "Bad file size (%" FORMAT_OFF_T ")", size); 1504 return CURLE_BAD_DOWNLOAD_RESUME; 1505 } 1506 data->state.resume_from = attrs.filesize; 1507 } 1508 } 1509 } 1510 1511 if(data->set.ftp_append) 1512 /* Try to open for append, but create if nonexisting */ 1513 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; 1514 else if(data->state.resume_from > 0) 1515 /* If we have restart position then open for append */ 1516 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; 1517 else 1518 /* Clear file before writing (normal behaviour) */ 1519 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; 1520 1521 sshc->sftp_handle = 1522 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, 1523 (unsigned int)strlen(sftp_scp->path), 1524 flags, data->set.new_file_perms, 1525 LIBSSH2_SFTP_OPENFILE); 1526 1527 if(!sshc->sftp_handle) { 1528 rc = libssh2_session_last_errno(sshc->ssh_session); 1529 1530 if(LIBSSH2_ERROR_EAGAIN == rc) 1531 break; 1532 else { 1533 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) 1534 /* only when there was an SFTP protocol error can we extract 1535 the sftp error! */ 1536 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1537 else 1538 err = -1; /* not an sftp error at all */ 1539 1540 if(sshc->secondCreateDirs) { 1541 state(conn, SSH_SFTP_CLOSE); 1542 sshc->actualcode = err>= LIBSSH2_FX_OK? 1543 sftp_libssh2_error_to_CURLE(err):CURLE_SSH; 1544 failf(data, "Creating the dir/file failed: %s", 1545 sftp_libssh2_strerror(err)); 1546 break; 1547 } 1548 else if(((err == LIBSSH2_FX_NO_SUCH_FILE) || 1549 (err == LIBSSH2_FX_FAILURE) || 1550 (err == LIBSSH2_FX_NO_SUCH_PATH)) && 1551 (data->set.ftp_create_missing_dirs && 1552 (strlen(sftp_scp->path) > 1))) { 1553 /* try to create the path remotely */ 1554 sshc->secondCreateDirs = 1; 1555 state(conn, SSH_SFTP_CREATE_DIRS_INIT); 1556 break; 1557 } 1558 state(conn, SSH_SFTP_CLOSE); 1559 sshc->actualcode = err>= LIBSSH2_FX_OK? 1560 sftp_libssh2_error_to_CURLE(err):CURLE_SSH; 1561 if(!sshc->actualcode) { 1562 /* Sometimes, for some reason libssh2_sftp_last_error() returns 1563 zero even though libssh2_sftp_open() failed previously! We need 1564 to work around that! */ 1565 sshc->actualcode = CURLE_SSH; 1566 err=-1; 1567 } 1568 failf(data, "Upload failed: %s (%d/%d)", 1569 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", 1570 err, rc); 1571 break; 1572 } 1573 } 1574 1575 /* If we have restart point then we need to seek to the correct 1576 position. */ 1577 if(data->state.resume_from > 0) { 1578 /* Let's read off the proper amount of bytes from the input. */ 1579 if(conn->seek_func) { 1580 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, 1581 SEEK_SET); 1582 } 1583 1584 if(seekerr != CURL_SEEKFUNC_OK){ 1585 1586 if(seekerr != CURL_SEEKFUNC_CANTSEEK) { 1587 failf(data, "Could not seek stream"); 1588 return CURLE_FTP_COULDNT_USE_REST; 1589 } 1590 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ 1591 else { 1592 curl_off_t passed=0; 1593 do { 1594 size_t readthisamountnow = 1595 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? 1596 BUFSIZE : curlx_sotouz(data->state.resume_from - passed); 1597 1598 size_t actuallyread = 1599 conn->fread_func(data->state.buffer, 1, readthisamountnow, 1600 conn->fread_in); 1601 1602 passed += actuallyread; 1603 if((actuallyread == 0) || (actuallyread > readthisamountnow)) { 1604 /* this checks for greater-than only to make sure that the 1605 CURL_READFUNC_ABORT return code still aborts */ 1606 failf(data, "Failed to read data"); 1607 return CURLE_FTP_COULDNT_USE_REST; 1608 } 1609 } while(passed < data->state.resume_from); 1610 } 1611 } 1612 1613 /* now, decrease the size of the read */ 1614 if(data->set.infilesize > 0) { 1615 data->set.infilesize -= data->state.resume_from; 1616 data->req.size = data->set.infilesize; 1617 Curl_pgrsSetUploadSize(data, data->set.infilesize); 1618 } 1619 1620 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); 1621 } 1622 if(data->set.infilesize > 0) { 1623 data->req.size = data->set.infilesize; 1624 Curl_pgrsSetUploadSize(data, data->set.infilesize); 1625 } 1626 /* upload data */ 1627 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); 1628 1629 /* not set by Curl_setup_transfer to preserve keepon bits */ 1630 conn->sockfd = conn->writesockfd; 1631 1632 if(result) { 1633 state(conn, SSH_SFTP_CLOSE); 1634 sshc->actualcode = result; 1635 } 1636 else { 1637 /* store this original bitmask setup to use later on if we can't 1638 figure out a "real" bitmask */ 1639 sshc->orig_waitfor = data->req.keepon; 1640 1641 /* we want to use the _sending_ function even when the socket turns 1642 out readable as the underlying libssh2 sftp send function will deal 1643 with both accordingly */ 1644 conn->cselect_bits = CURL_CSELECT_OUT; 1645 1646 /* since we don't really wait for anything at this point, we want the 1647 state machine to move on as soon as possible so we set a very short 1648 timeout here */ 1649 Curl_expire(data, 1); 1650 1651 state(conn, SSH_STOP); 1652 } 1653 break; 1654 } 1655 1656 case SSH_SFTP_CREATE_DIRS_INIT: 1657 if(strlen(sftp_scp->path) > 1) { 1658 sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */ 1659 state(conn, SSH_SFTP_CREATE_DIRS); 1660 } 1661 else { 1662 state(conn, SSH_SFTP_UPLOAD_INIT); 1663 } 1664 break; 1665 1666 case SSH_SFTP_CREATE_DIRS: 1667 if((sshc->slash_pos = strchr(sshc->slash_pos, '/')) != NULL) { 1668 *sshc->slash_pos = 0; 1669 1670 infof(data, "Creating directory '%s'\n", sftp_scp->path); 1671 state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); 1672 break; 1673 } 1674 else { 1675 state(conn, SSH_SFTP_UPLOAD_INIT); 1676 } 1677 break; 1678 1679 case SSH_SFTP_CREATE_DIRS_MKDIR: 1680 /* 'mode' - parameter is preliminary - default to 0644 */ 1681 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path, 1682 (unsigned int)strlen(sftp_scp->path), 1683 data->set.new_directory_perms); 1684 if(rc == LIBSSH2_ERROR_EAGAIN) { 1685 break; 1686 } 1687 *sshc->slash_pos = '/'; 1688 ++sshc->slash_pos; 1689 if(rc == -1) { 1690 unsigned int sftp_err = 0; 1691 /* 1692 * Abort if failure wasn't that the dir already exists or the 1693 * permission was denied (creation might succeed further down the 1694 * path) - retry on unspecific FAILURE also 1695 */ 1696 sftp_err = (unsigned int)(libssh2_sftp_last_error(sshc->sftp_session)); 1697 if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && 1698 (sftp_err != LIBSSH2_FX_FAILURE) && 1699 (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) { 1700 result = sftp_libssh2_error_to_CURLE(sftp_err); 1701 state(conn, SSH_SFTP_CLOSE); 1702 sshc->actualcode = result?result:CURLE_SSH; 1703 break; 1704 } 1705 } 1706 state(conn, SSH_SFTP_CREATE_DIRS); 1707 break; 1708 1709 case SSH_SFTP_READDIR_INIT: 1710 /* 1711 * This is a directory that we are trying to get, so produce a directory 1712 * listing 1713 */ 1714 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, 1715 sftp_scp->path, 1716 (unsigned int) 1717 strlen(sftp_scp->path), 1718 0, 0, LIBSSH2_SFTP_OPENDIR); 1719 if(!sshc->sftp_handle) { 1720 if(libssh2_session_last_errno(sshc->ssh_session) == 1721 LIBSSH2_ERROR_EAGAIN) { 1722 rc = LIBSSH2_ERROR_EAGAIN; 1723 break; 1724 } 1725 else { 1726 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1727 failf(data, "Could not open directory for reading: %s", 1728 sftp_libssh2_strerror(err)); 1729 state(conn, SSH_SFTP_CLOSE); 1730 result = sftp_libssh2_error_to_CURLE(err); 1731 sshc->actualcode = result?result:CURLE_SSH; 1732 break; 1733 } 1734 } 1735 if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) { 1736 state(conn, SSH_SFTP_CLOSE); 1737 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1738 break; 1739 } 1740 if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) { 1741 Curl_safefree(sshc->readdir_filename); 1742 sshc->readdir_filename = NULL; 1743 state(conn, SSH_SFTP_CLOSE); 1744 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1745 break; 1746 } 1747 state(conn, SSH_SFTP_READDIR); 1748 break; 1749 1750 case SSH_SFTP_READDIR: 1751 sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle, 1752 sshc->readdir_filename, 1753 PATH_MAX, 1754 sshc->readdir_longentry, 1755 PATH_MAX, 1756 &sshc->readdir_attrs); 1757 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) { 1758 rc = LIBSSH2_ERROR_EAGAIN; 1759 break; 1760 } 1761 if(sshc->readdir_len > 0) { 1762 sshc->readdir_filename[sshc->readdir_len] = '\0'; 1763 1764 if(data->set.ftp_list_only) { 1765 char *tmpLine; 1766 1767 tmpLine = aprintf("%s\n", sshc->readdir_filename); 1768 if(tmpLine == NULL) { 1769 state(conn, SSH_SFTP_CLOSE); 1770 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1771 break; 1772 } 1773 result = Curl_client_write(conn, CLIENTWRITE_BODY, 1774 tmpLine, sshc->readdir_len+1); 1775 Curl_safefree(tmpLine); 1776 1777 if(result) { 1778 state(conn, SSH_STOP); 1779 break; 1780 } 1781 /* since this counts what we send to the client, we include the 1782 newline in this counter */ 1783 data->req.bytecount += sshc->readdir_len+1; 1784 1785 /* output debug output if that is requested */ 1786 if(data->set.verbose) { 1787 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename, 1788 sshc->readdir_len, conn); 1789 } 1790 } 1791 else { 1792 sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry); 1793 sshc->readdir_totalLen = 80 + sshc->readdir_currLen; 1794 sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); 1795 if(!sshc->readdir_line) { 1796 Curl_safefree(sshc->readdir_filename); 1797 sshc->readdir_filename = NULL; 1798 Curl_safefree(sshc->readdir_longentry); 1799 sshc->readdir_longentry = NULL; 1800 state(conn, SSH_SFTP_CLOSE); 1801 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1802 break; 1803 } 1804 1805 memcpy(sshc->readdir_line, sshc->readdir_longentry, 1806 sshc->readdir_currLen); 1807 if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && 1808 ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == 1809 LIBSSH2_SFTP_S_IFLNK)) { 1810 sshc->readdir_linkPath = malloc(PATH_MAX + 1); 1811 if(sshc->readdir_linkPath == NULL) { 1812 Curl_safefree(sshc->readdir_filename); 1813 sshc->readdir_filename = NULL; 1814 Curl_safefree(sshc->readdir_longentry); 1815 sshc->readdir_longentry = NULL; 1816 state(conn, SSH_SFTP_CLOSE); 1817 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1818 break; 1819 } 1820 1821 snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path, 1822 sshc->readdir_filename); 1823 state(conn, SSH_SFTP_READDIR_LINK); 1824 break; 1825 } 1826 state(conn, SSH_SFTP_READDIR_BOTTOM); 1827 break; 1828 } 1829 } 1830 else if(sshc->readdir_len == 0) { 1831 Curl_safefree(sshc->readdir_filename); 1832 sshc->readdir_filename = NULL; 1833 Curl_safefree(sshc->readdir_longentry); 1834 sshc->readdir_longentry = NULL; 1835 state(conn, SSH_SFTP_READDIR_DONE); 1836 break; 1837 } 1838 else if(sshc->readdir_len <= 0) { 1839 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1840 result = sftp_libssh2_error_to_CURLE(err); 1841 sshc->actualcode = result?result:CURLE_SSH; 1842 failf(data, "Could not open remote file for reading: %s :: %d", 1843 sftp_libssh2_strerror(err), 1844 libssh2_session_last_errno(sshc->ssh_session)); 1845 Curl_safefree(sshc->readdir_filename); 1846 sshc->readdir_filename = NULL; 1847 Curl_safefree(sshc->readdir_longentry); 1848 sshc->readdir_longentry = NULL; 1849 state(conn, SSH_SFTP_CLOSE); 1850 break; 1851 } 1852 break; 1853 1854 case SSH_SFTP_READDIR_LINK: 1855 sshc->readdir_len = 1856 libssh2_sftp_symlink_ex(sshc->sftp_session, 1857 sshc->readdir_linkPath, 1858 (unsigned int) strlen(sshc->readdir_linkPath), 1859 sshc->readdir_filename, 1860 PATH_MAX, LIBSSH2_SFTP_READLINK); 1861 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) { 1862 rc = LIBSSH2_ERROR_EAGAIN; 1863 break; 1864 } 1865 Curl_safefree(sshc->readdir_linkPath); 1866 sshc->readdir_linkPath = NULL; 1867 sshc->readdir_line = realloc(sshc->readdir_line, 1868 sshc->readdir_totalLen + 4 + 1869 sshc->readdir_len); 1870 if(!sshc->readdir_line) { 1871 Curl_safefree(sshc->readdir_filename); 1872 sshc->readdir_filename = NULL; 1873 Curl_safefree(sshc->readdir_longentry); 1874 sshc->readdir_longentry = NULL; 1875 state(conn, SSH_SFTP_CLOSE); 1876 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1877 break; 1878 } 1879 1880 sshc->readdir_currLen += snprintf(sshc->readdir_line + 1881 sshc->readdir_currLen, 1882 sshc->readdir_totalLen - 1883 sshc->readdir_currLen, 1884 " -> %s", 1885 sshc->readdir_filename); 1886 1887 state(conn, SSH_SFTP_READDIR_BOTTOM); 1888 break; 1889 1890 case SSH_SFTP_READDIR_BOTTOM: 1891 sshc->readdir_currLen += snprintf(sshc->readdir_line + 1892 sshc->readdir_currLen, 1893 sshc->readdir_totalLen - 1894 sshc->readdir_currLen, "\n"); 1895 result = Curl_client_write(conn, CLIENTWRITE_BODY, 1896 sshc->readdir_line, 1897 sshc->readdir_currLen); 1898 1899 if(result == CURLE_OK) { 1900 1901 /* output debug output if that is requested */ 1902 if(data->set.verbose) { 1903 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, 1904 sshc->readdir_currLen, conn); 1905 } 1906 data->req.bytecount += sshc->readdir_currLen; 1907 } 1908 Curl_safefree(sshc->readdir_line); 1909 sshc->readdir_line = NULL; 1910 if(result) { 1911 state(conn, SSH_STOP); 1912 } 1913 else 1914 state(conn, SSH_SFTP_READDIR); 1915 break; 1916 1917 case SSH_SFTP_READDIR_DONE: 1918 if(libssh2_sftp_closedir(sshc->sftp_handle) == 1919 LIBSSH2_ERROR_EAGAIN) { 1920 rc = LIBSSH2_ERROR_EAGAIN; 1921 break; 1922 } 1923 sshc->sftp_handle = NULL; 1924 Curl_safefree(sshc->readdir_filename); 1925 sshc->readdir_filename = NULL; 1926 Curl_safefree(sshc->readdir_longentry); 1927 sshc->readdir_longentry = NULL; 1928 1929 /* no data to transfer */ 1930 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); 1931 state(conn, SSH_STOP); 1932 break; 1933 1934 case SSH_SFTP_DOWNLOAD_INIT: 1935 /* 1936 * Work on getting the specified file 1937 */ 1938 sshc->sftp_handle = 1939 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, 1940 (unsigned int)strlen(sftp_scp->path), 1941 LIBSSH2_FXF_READ, data->set.new_file_perms, 1942 LIBSSH2_SFTP_OPENFILE); 1943 if(!sshc->sftp_handle) { 1944 if(libssh2_session_last_errno(sshc->ssh_session) == 1945 LIBSSH2_ERROR_EAGAIN) { 1946 rc = LIBSSH2_ERROR_EAGAIN; 1947 break; 1948 } 1949 else { 1950 err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); 1951 failf(data, "Could not open remote file for reading: %s", 1952 sftp_libssh2_strerror(err)); 1953 state(conn, SSH_SFTP_CLOSE); 1954 result = sftp_libssh2_error_to_CURLE(err); 1955 sshc->actualcode = result?result:CURLE_SSH; 1956 break; 1957 } 1958 } 1959 state(conn, SSH_SFTP_DOWNLOAD_STAT); 1960 break; 1961 1962 case SSH_SFTP_DOWNLOAD_STAT: 1963 { 1964 LIBSSH2_SFTP_ATTRIBUTES attrs; 1965 1966 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, 1967 (unsigned int)strlen(sftp_scp->path), 1968 LIBSSH2_SFTP_STAT, &attrs); 1969 if(rc == LIBSSH2_ERROR_EAGAIN) { 1970 break; 1971 } 1972 else if(rc) { 1973 /* 1974 * libssh2_sftp_open() didn't return an error, so maybe the server 1975 * just doesn't support stat() 1976 */ 1977 data->req.size = -1; 1978 data->req.maxdownload = -1; 1979 } 1980 else { 1981 curl_off_t size = attrs.filesize; 1982 1983 if(size < 0) { 1984 failf(data, "Bad file size (%" FORMAT_OFF_T ")", size); 1985 return CURLE_BAD_DOWNLOAD_RESUME; 1986 } 1987 if(conn->data->state.use_range) { 1988 curl_off_t from, to; 1989 char *ptr; 1990 char *ptr2; 1991 1992 from=curlx_strtoofft(conn->data->state.range, &ptr, 0); 1993 while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) 1994 ptr++; 1995 to=curlx_strtoofft(ptr, &ptr2, 0); 1996 if((ptr == ptr2) /* no "to" value given */ 1997 || (to >= size)) { 1998 to = size - 1; 1999 } 2000 if(from < 0) { 2001 /* from is relative to end of file */ 2002 from += size; 2003 } 2004 if(from >= size) { 2005 failf(data, "Offset (%" 2006 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")", 2007 from, attrs.filesize); 2008 return CURLE_BAD_DOWNLOAD_RESUME; 2009 } 2010 if(from > to) { 2011 from = to; 2012 size = 0; 2013 } 2014 else { 2015 size = to - from + 1; 2016 } 2017 2018 SFTP_SEEK(conn->proto.sshc.sftp_handle, from); 2019 } 2020 data->req.size = size; 2021 data->req.maxdownload = size; 2022 Curl_pgrsSetDownloadSize(data, size); 2023 } 2024 2025 /* We can resume if we can seek to the resume position */ 2026 if(data->state.resume_from) { 2027 if(data->state.resume_from < 0) { 2028 /* We're supposed to download the last abs(from) bytes */ 2029 if((curl_off_t)attrs.filesize < -data->state.resume_from) { 2030 failf(data, "Offset (%" 2031 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")", 2032 data->state.resume_from, attrs.filesize); 2033 return CURLE_BAD_DOWNLOAD_RESUME; 2034 } 2035 /* download from where? */ 2036 data->state.resume_from += attrs.filesize; 2037 } 2038 else { 2039 if((curl_off_t)attrs.filesize < data->state.resume_from) { 2040 failf(data, "Offset (%" FORMAT_OFF_T 2041 ") was beyond file size (%" FORMAT_OFF_T ")", 2042 data->state.resume_from, attrs.filesize); 2043 return CURLE_BAD_DOWNLOAD_RESUME; 2044 } 2045 } 2046 /* Does a completed file need to be seeked and started or closed ? */ 2047 /* Now store the number of bytes we are expected to download */ 2048 data->req.size = attrs.filesize - data->state.resume_from; 2049 data->req.maxdownload = attrs.filesize - data->state.resume_from; 2050 Curl_pgrsSetDownloadSize(data, 2051 attrs.filesize - data->state.resume_from); 2052 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); 2053 } 2054 } 2055 /* Setup the actual download */ 2056 if(data->req.size == 0) { 2057 /* no data to transfer */ 2058 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); 2059 infof(data, "File already completely downloaded\n"); 2060 state(conn, SSH_STOP); 2061 break; 2062 } 2063 else { 2064 Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, 2065 FALSE, NULL, -1, NULL); 2066 2067 /* not set by Curl_setup_transfer to preserve keepon bits */ 2068 conn->writesockfd = conn->sockfd; 2069 2070 /* we want to use the _receiving_ function even when the socket turns 2071 out writableable as the underlying libssh2 recv function will deal 2072 with both accordingly */ 2073 conn->cselect_bits = CURL_CSELECT_IN; 2074 } 2075 if(result) { 2076 state(conn, SSH_SFTP_CLOSE); 2077 sshc->actualcode = result; 2078 } 2079 else { 2080 state(conn, SSH_STOP); 2081 } 2082 break; 2083 2084 case SSH_SFTP_CLOSE: 2085 if(sshc->sftp_handle) { 2086 rc = libssh2_sftp_close(sshc->sftp_handle); 2087 if(rc == LIBSSH2_ERROR_EAGAIN) { 2088 break; 2089 } 2090 else if(rc < 0) { 2091 infof(data, "Failed to close libssh2 file\n"); 2092 } 2093 sshc->sftp_handle = NULL; 2094 } 2095 if(sftp_scp) { 2096 Curl_safefree(sftp_scp->path); 2097 sftp_scp->path = NULL; 2098 } 2099 2100 DEBUGF(infof(data, "SFTP DONE done\n")); 2101 2102 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT 2103 After nextstate is executed,the control should come back to 2104 SSH_SFTP_CLOSE to pass the correct result back */ 2105 if(sshc->nextstate != SSH_NO_STATE) { 2106 state(conn, sshc->nextstate); 2107 sshc->nextstate = SSH_SFTP_CLOSE; 2108 } 2109 else { 2110 state(conn, SSH_STOP); 2111 result = sshc->actualcode; 2112 } 2113 break; 2114 2115 case SSH_SFTP_SHUTDOWN: 2116 /* during times we get here due to a broken transfer and then the 2117 sftp_handle might not have been taken down so make sure that is done 2118 before we proceed */ 2119 2120 if(sshc->sftp_handle) { 2121 rc = libssh2_sftp_close(sshc->sftp_handle); 2122 if(rc == LIBSSH2_ERROR_EAGAIN) { 2123 break; 2124 } 2125 else if(rc < 0) { 2126 infof(data, "Failed to close libssh2 file\n"); 2127 } 2128 sshc->sftp_handle = NULL; 2129 } 2130 if(sshc->sftp_session) { 2131 rc = libssh2_sftp_shutdown(sshc->sftp_session); 2132 if(rc == LIBSSH2_ERROR_EAGAIN) { 2133 break; 2134 } 2135 else if(rc < 0) { 2136 infof(data, "Failed to stop libssh2 sftp subsystem\n"); 2137 } 2138 sshc->sftp_session = NULL; 2139 } 2140 2141 Curl_safefree(sshc->homedir); 2142 sshc->homedir = NULL; 2143 conn->data->state.most_recent_ftp_entrypath = NULL; 2144 2145 state(conn, SSH_SESSION_DISCONNECT); 2146 break; 2147 2148 case SSH_SCP_TRANS_INIT: 2149 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path); 2150 if(result) { 2151 sshc->actualcode = result; 2152 state(conn, SSH_STOP); 2153 break; 2154 } 2155 2156 if(data->set.upload) { 2157 if(data->set.infilesize < 0) { 2158 failf(data, "SCP requires a known file size for upload"); 2159 sshc->actualcode = CURLE_UPLOAD_FAILED; 2160 state(conn, SSH_SCP_CHANNEL_FREE); 2161 break; 2162 } 2163 state(conn, SSH_SCP_UPLOAD_INIT); 2164 } 2165 else { 2166 state(conn, SSH_SCP_DOWNLOAD_INIT); 2167 } 2168 break; 2169 2170 case SSH_SCP_UPLOAD_INIT: 2171 /* 2172 * libssh2 requires that the destination path is a full path that 2173 * includes the destination file and name OR ends in a "/" . If this is 2174 * not done the destination file will be named the same name as the last 2175 * directory in the path. 2176 */ 2177 sshc->ssh_channel = 2178 SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, 2179 data->set.infilesize); 2180 if(!sshc->ssh_channel) { 2181 if(libssh2_session_last_errno(sshc->ssh_session) == 2182 LIBSSH2_ERROR_EAGAIN) { 2183 rc = LIBSSH2_ERROR_EAGAIN; 2184 break; 2185 } 2186 else { 2187 int ssh_err; 2188 char *err_msg; 2189 2190 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, 2191 &err_msg, NULL, 0)); 2192 failf(conn->data, "%s", err_msg); 2193 state(conn, SSH_SCP_CHANNEL_FREE); 2194 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); 2195 break; 2196 } 2197 } 2198 2199 /* upload data */ 2200 Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, 2201 FIRSTSOCKET, NULL); 2202 2203 /* not set by Curl_setup_transfer to preserve keepon bits */ 2204 conn->sockfd = conn->writesockfd; 2205 2206 if(result) { 2207 state(conn, SSH_SCP_CHANNEL_FREE); 2208 sshc->actualcode = result; 2209 } 2210 else { 2211 /* we want to use the _sending_ function even when the socket turns 2212 out readable as the underlying libssh2 scp send function will deal 2213 with both accordingly */ 2214 conn->cselect_bits = CURL_CSELECT_OUT; 2215 2216 state(conn, SSH_STOP); 2217 } 2218 break; 2219 2220 case SSH_SCP_DOWNLOAD_INIT: 2221 { 2222 /* 2223 * We must check the remote file; if it is a directory no values will 2224 * be set in sb 2225 */ 2226 struct stat sb; 2227 curl_off_t bytecount; 2228 2229 /* clear the struct scp recv will fill in */ 2230 memset(&sb, 0, sizeof(struct stat)); 2231 2232 /* get a fresh new channel from the ssh layer */ 2233 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, 2234 sftp_scp->path, &sb); 2235 if(!sshc->ssh_channel) { 2236 if(libssh2_session_last_errno(sshc->ssh_session) == 2237 LIBSSH2_ERROR_EAGAIN) { 2238 rc = LIBSSH2_ERROR_EAGAIN; 2239 break; 2240 } 2241 else { 2242 int ssh_err; 2243 char *err_msg; 2244 2245 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, 2246 &err_msg, NULL, 0)); 2247 failf(conn->data, "%s", err_msg); 2248 state(conn, SSH_SCP_CHANNEL_FREE); 2249 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); 2250 break; 2251 } 2252 } 2253 2254 /* download data */ 2255 bytecount = (curl_off_t)sb.st_size; 2256 data->req.maxdownload = (curl_off_t)sb.st_size; 2257 Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL); 2258 2259 /* not set by Curl_setup_transfer to preserve keepon bits */ 2260 conn->writesockfd = conn->sockfd; 2261 2262 /* we want to use the _receiving_ function even when the socket turns 2263 out writableable as the underlying libssh2 recv function will deal 2264 with both accordingly */ 2265 conn->cselect_bits = CURL_CSELECT_IN; 2266 2267 if(result) { 2268 state(conn, SSH_SCP_CHANNEL_FREE); 2269 sshc->actualcode = result; 2270 } 2271 else 2272 state(conn, SSH_STOP); 2273 } 2274 break; 2275 2276 case SSH_SCP_DONE: 2277 if(data->set.upload) 2278 state(conn, SSH_SCP_SEND_EOF); 2279 else 2280 state(conn, SSH_SCP_CHANNEL_FREE); 2281 break; 2282 2283 case SSH_SCP_SEND_EOF: 2284 if(sshc->ssh_channel) { 2285 rc = libssh2_channel_send_eof(sshc->ssh_channel); 2286 if(rc == LIBSSH2_ERROR_EAGAIN) { 2287 break; 2288 } 2289 else if(rc) { 2290 infof(data, "Failed to send libssh2 channel EOF\n"); 2291 } 2292 } 2293 state(conn, SSH_SCP_WAIT_EOF); 2294 break; 2295 2296 case SSH_SCP_WAIT_EOF: 2297 if(sshc->ssh_channel) { 2298 rc = libssh2_channel_wait_eof(sshc->ssh_channel); 2299 if(rc == LIBSSH2_ERROR_EAGAIN) { 2300 break; 2301 } 2302 else if(rc) { 2303 infof(data, "Failed to get channel EOF: %d\n", rc); 2304 } 2305 } 2306 state(conn, SSH_SCP_WAIT_CLOSE); 2307 break; 2308 2309 case SSH_SCP_WAIT_CLOSE: 2310 if(sshc->ssh_channel) { 2311 rc = libssh2_channel_wait_closed(sshc->ssh_channel); 2312 if(rc == LIBSSH2_ERROR_EAGAIN) { 2313 break; 2314 } 2315 else if(rc) { 2316 infof(data, "Channel failed to close: %d\n", rc); 2317 } 2318 } 2319 state(conn, SSH_SCP_CHANNEL_FREE); 2320 break; 2321 2322 case SSH_SCP_CHANNEL_FREE: 2323 if(sshc->ssh_channel) { 2324 rc = libssh2_channel_free(sshc->ssh_channel); 2325 if(rc == LIBSSH2_ERROR_EAGAIN) { 2326 break; 2327 } 2328 else if(rc < 0) { 2329 infof(data, "Failed to free libssh2 scp subsystem\n"); 2330 } 2331 sshc->ssh_channel = NULL; 2332 } 2333 DEBUGF(infof(data, "SCP DONE phase complete\n")); 2334#if 0 /* PREV */ 2335 state(conn, SSH_SESSION_DISCONNECT); 2336#endif 2337 state(conn, SSH_STOP); 2338 result = sshc->actualcode; 2339 break; 2340 2341 case SSH_SESSION_DISCONNECT: 2342 /* during weird times when we've been prematurely aborted, the channel 2343 is still alive when we reach this state and we MUST kill the channel 2344 properly first */ 2345 if(sshc->ssh_channel) { 2346 rc = libssh2_channel_free(sshc->ssh_channel); 2347 if(rc == LIBSSH2_ERROR_EAGAIN) { 2348 break; 2349 } 2350 else if(rc < 0) { 2351 infof(data, "Failed to free libssh2 scp subsystem\n"); 2352 } 2353 sshc->ssh_channel = NULL; 2354 } 2355 2356 if(sshc->ssh_session) { 2357 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); 2358 if(rc == LIBSSH2_ERROR_EAGAIN) { 2359 break; 2360 } 2361 else if(rc < 0) { 2362 infof(data, "Failed to disconnect libssh2 session\n"); 2363 } 2364 } 2365 2366 Curl_safefree(sshc->homedir); 2367 sshc->homedir = NULL; 2368 conn->data->state.most_recent_ftp_entrypath = NULL; 2369 2370 state(conn, SSH_SESSION_FREE); 2371 break; 2372 2373 case SSH_SESSION_FREE: 2374#ifdef HAVE_LIBSSH2_KNOWNHOST_API 2375 if(sshc->kh) { 2376 libssh2_knownhost_free(sshc->kh); 2377 sshc->kh = NULL; 2378 } 2379#endif 2380 2381 if(sshc->ssh_session) { 2382 rc = libssh2_session_free(sshc->ssh_session); 2383 if(rc == LIBSSH2_ERROR_EAGAIN) { 2384 break; 2385 } 2386 else if(rc < 0) { 2387 infof(data, "Failed to free libssh2 session\n"); 2388 } 2389 sshc->ssh_session = NULL; 2390 } 2391 conn->bits.close = TRUE; 2392 sshc->nextstate = SSH_NO_STATE; 2393 state(conn, SSH_STOP); 2394 result = sshc->actualcode; 2395 break; 2396 2397 case SSH_QUIT: 2398 /* fallthrough, just stop! */ 2399 default: 2400 /* internal error */ 2401 sshc->nextstate = SSH_NO_STATE; 2402 state(conn, SSH_STOP); 2403 break; 2404 } 2405 2406 } while(!rc && (sshc->state != SSH_STOP)); 2407 2408 if(rc == LIBSSH2_ERROR_EAGAIN) { 2409 /* we would block, we need to wait for the socket to be ready (in the 2410 right direction too)! */ 2411 *block = TRUE; 2412 } 2413 2414 return result; 2415} 2416 2417/* called by the multi interface to figure out what socket(s) to wait for and 2418 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ 2419static int ssh_perform_getsock(const struct connectdata *conn, 2420 curl_socket_t *sock, /* points to numsocks 2421 number of sockets */ 2422 int numsocks) 2423{ 2424#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION 2425 int bitmap = GETSOCK_BLANK; 2426 (void)numsocks; 2427 2428 sock[0] = conn->sock[FIRSTSOCKET]; 2429 2430 if(conn->waitfor & KEEP_RECV) 2431 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); 2432 2433 if(conn->waitfor & KEEP_SEND) 2434 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); 2435 2436 return bitmap; 2437#else 2438 /* if we don't know the direction we can use the generic *_getsock() 2439 function even for the protocol_connect and doing states */ 2440 return Curl_single_getsock(conn, sock, numsocks); 2441#endif 2442} 2443 2444/* Generic function called by the multi interface to figure out what socket(s) 2445 to wait for and for what actions during the DOING and PROTOCONNECT states*/ 2446static int ssh_getsock(struct connectdata *conn, 2447 curl_socket_t *sock, /* points to numsocks number 2448 of sockets */ 2449 int numsocks) 2450{ 2451#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION 2452 (void)conn; 2453 (void)sock; 2454 (void)numsocks; 2455 /* if we don't know any direction we can just play along as we used to and 2456 not provide any sensible info */ 2457 return GETSOCK_BLANK; 2458#else 2459 /* if we know the direction we can use the generic *_getsock() function even 2460 for the protocol_connect and doing states */ 2461 return ssh_perform_getsock(conn, sock, numsocks); 2462#endif 2463} 2464 2465#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION 2466/* 2467 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this 2468 * function is used to figure out in what direction and stores this info so 2469 * that the multi interface can take advantage of it. Make sure to call this 2470 * function in all cases so that when it _doesn't_ return EAGAIN we can 2471 * restore the default wait bits. 2472 */ 2473static void ssh_block2waitfor(struct connectdata *conn, bool block) 2474{ 2475 struct ssh_conn *sshc = &conn->proto.sshc; 2476 int dir; 2477 if(!block) 2478 conn->waitfor = 0; 2479 else if((dir = libssh2_session_block_directions(sshc->ssh_session))) { 2480 /* translate the libssh2 define bits into our own bit defines */ 2481 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | 2482 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); 2483 } 2484 else 2485 /* It didn't block or libssh2 didn't reveal in which direction, put back 2486 the original set */ 2487 conn->waitfor = sshc->orig_waitfor; 2488} 2489#else 2490 /* no libssh2 directional support so we simply don't know */ 2491#define ssh_block2waitfor(x,y) 2492#endif 2493 2494/* called repeatedly until done from multi.c */ 2495static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) 2496{ 2497 struct ssh_conn *sshc = &conn->proto.sshc; 2498 CURLcode result = CURLE_OK; 2499 bool block; /* we store the status and use that to provide a ssh_getsock() 2500 implementation */ 2501 2502 result = ssh_statemach_act(conn, &block); 2503 *done = (bool)(sshc->state == SSH_STOP); 2504 ssh_block2waitfor(conn, block); 2505 2506 return result; 2507} 2508 2509static CURLcode ssh_easy_statemach(struct connectdata *conn, 2510 bool duringconnect) 2511{ 2512 struct ssh_conn *sshc = &conn->proto.sshc; 2513 CURLcode result = CURLE_OK; 2514 struct SessionHandle *data = conn->data; 2515 2516 while((sshc->state != SSH_STOP) && !result) { 2517 bool block; 2518 long left; 2519 2520 result = ssh_statemach_act(conn, &block); 2521 if(result) 2522 break; 2523 2524 if(Curl_pgrsUpdate(conn)) 2525 return CURLE_ABORTED_BY_CALLBACK; 2526 else { 2527 struct timeval now = Curl_tvnow(); 2528 result = Curl_speedcheck(data, now); 2529 if(result) 2530 break; 2531 } 2532 2533 left = Curl_timeleft(data, NULL, duringconnect); 2534 if(left < 0) { 2535 failf(data, "Operation timed out\n"); 2536 return CURLE_OPERATION_TIMEDOUT; 2537 } 2538 2539#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION 2540 if((CURLE_OK == result) && block) { 2541 int dir = libssh2_session_block_directions(sshc->ssh_session); 2542 curl_socket_t sock = conn->sock[FIRSTSOCKET]; 2543 curl_socket_t fd_read = CURL_SOCKET_BAD; 2544 curl_socket_t fd_write = CURL_SOCKET_BAD; 2545 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir) 2546 fd_read = sock; 2547 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) 2548 fd_write = sock; 2549 /* wait for the socket to become ready */ 2550 Curl_socket_ready(fd_read, fd_write, 2551 left>1000?1000:left); /* ignore result */ 2552 } 2553#endif 2554 2555 } 2556 2557 return result; 2558} 2559 2560/* 2561 * SSH setup and connection 2562 */ 2563static CURLcode ssh_init(struct connectdata *conn) 2564{ 2565 struct SessionHandle *data = conn->data; 2566 struct SSHPROTO *ssh; 2567 struct ssh_conn *sshc = &conn->proto.sshc; 2568 2569 sshc->actualcode = CURLE_OK; /* reset error code */ 2570 sshc->secondCreateDirs =0; /* reset the create dir attempt state 2571 variable */ 2572 2573 if(data->state.proto.ssh) 2574 return CURLE_OK; 2575 2576 ssh = calloc(1, sizeof(struct SSHPROTO)); 2577 if(!ssh) 2578 return CURLE_OUT_OF_MEMORY; 2579 2580 data->state.proto.ssh = ssh; 2581 2582 return CURLE_OK; 2583} 2584 2585static Curl_recv scp_recv, sftp_recv; 2586static Curl_send scp_send, sftp_send; 2587 2588/* 2589 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to 2590 * do protocol-specific actions at connect-time. 2591 */ 2592static CURLcode ssh_connect(struct connectdata *conn, bool *done) 2593{ 2594#ifdef CURL_LIBSSH2_DEBUG 2595 curl_socket_t sock; 2596#endif 2597 struct ssh_conn *ssh; 2598 CURLcode result; 2599 struct SessionHandle *data = conn->data; 2600 2601 /* We default to persistent connections. We set this already in this connect 2602 function to make the re-use checks properly be able to check this bit. */ 2603 conn->bits.close = FALSE; 2604 2605 /* If there already is a protocol-specific struct allocated for this 2606 sessionhandle, deal with it */ 2607 Curl_reset_reqproto(conn); 2608 2609 result = ssh_init(conn); 2610 if(result) 2611 return result; 2612 2613 if(conn->handler->protocol & CURLPROTO_SCP) { 2614 conn->recv[FIRSTSOCKET] = scp_recv; 2615 conn->send[FIRSTSOCKET] = scp_send; 2616 } 2617 else { 2618 conn->recv[FIRSTSOCKET] = sftp_recv; 2619 conn->send[FIRSTSOCKET] = sftp_send; 2620 } 2621 ssh = &conn->proto.sshc; 2622 2623#ifdef CURL_LIBSSH2_DEBUG 2624 if(conn->user) { 2625 infof(data, "User: %s\n", conn->user); 2626 } 2627 if(conn->passwd) { 2628 infof(data, "Password: %s\n", conn->passwd); 2629 } 2630 sock = conn->sock[FIRSTSOCKET]; 2631#endif /* CURL_LIBSSH2_DEBUG */ 2632 2633 ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, 2634 my_libssh2_free, 2635 my_libssh2_realloc, conn); 2636 if(ssh->ssh_session == NULL) { 2637 failf(data, "Failure initialising ssh session"); 2638 return CURLE_FAILED_INIT; 2639 } 2640 2641#ifdef HAVE_LIBSSH2_KNOWNHOST_API 2642 if(data->set.str[STRING_SSH_KNOWNHOSTS]) { 2643 int rc; 2644 ssh->kh = libssh2_knownhost_init(ssh->ssh_session); 2645 if(!ssh->kh) { 2646 /* eeek. TODO: free the ssh_session! */ 2647 return CURLE_FAILED_INIT; 2648 } 2649 2650 /* read all known hosts from there */ 2651 rc = libssh2_knownhost_readfile(ssh->kh, 2652 data->set.str[STRING_SSH_KNOWNHOSTS], 2653 LIBSSH2_KNOWNHOST_FILE_OPENSSH); 2654 if(rc < 0) 2655 infof(data, "Failed to read known hosts from %s\n", 2656 data->set.str[STRING_SSH_KNOWNHOSTS]); 2657 } 2658#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ 2659 2660#ifdef CURL_LIBSSH2_DEBUG 2661 libssh2_trace(ssh->ssh_session, ~0); 2662 infof(data, "SSH socket: %d\n", (int)sock); 2663#endif /* CURL_LIBSSH2_DEBUG */ 2664 2665 state(conn, SSH_INIT); 2666 2667 if(data->state.used_interface == Curl_if_multi) 2668 result = ssh_multi_statemach(conn, done); 2669 else { 2670 result = ssh_easy_statemach(conn, TRUE); 2671 if(!result) 2672 *done = TRUE; 2673 } 2674 2675 return result; 2676} 2677 2678/* 2679 *********************************************************************** 2680 * 2681 * scp_perform() 2682 * 2683 * This is the actual DO function for SCP. Get a file according to 2684 * the options previously setup. 2685 */ 2686 2687static 2688CURLcode scp_perform(struct connectdata *conn, 2689 bool *connected, 2690 bool *dophase_done) 2691{ 2692 CURLcode result = CURLE_OK; 2693 2694 DEBUGF(infof(conn->data, "DO phase starts\n")); 2695 2696 *dophase_done = FALSE; /* not done yet */ 2697 2698 /* start the first command in the DO phase */ 2699 state(conn, SSH_SCP_TRANS_INIT); 2700 2701 /* run the state-machine */ 2702 if(conn->data->state.used_interface == Curl_if_multi) { 2703 result = ssh_multi_statemach(conn, dophase_done); 2704 } 2705 else { 2706 result = ssh_easy_statemach(conn, FALSE); 2707 *dophase_done = TRUE; /* with the easy interface we are done here */ 2708 } 2709 *connected = conn->bits.tcpconnect; 2710 2711 if(*dophase_done) { 2712 DEBUGF(infof(conn->data, "DO phase is complete\n")); 2713 } 2714 2715 return result; 2716} 2717 2718/* called from multi.c while DOing */ 2719static CURLcode scp_doing(struct connectdata *conn, 2720 bool *dophase_done) 2721{ 2722 CURLcode result; 2723 result = ssh_multi_statemach(conn, dophase_done); 2724 2725 if(*dophase_done) { 2726 DEBUGF(infof(conn->data, "DO phase is complete\n")); 2727 } 2728 return result; 2729} 2730 2731/* 2732 * The DO function is generic for both protocols. There was previously two 2733 * separate ones but this way means less duplicated code. 2734 */ 2735 2736static CURLcode ssh_do(struct connectdata *conn, bool *done) 2737{ 2738 CURLcode res; 2739 bool connected = 0; 2740 struct SessionHandle *data = conn->data; 2741 2742 *done = FALSE; /* default to false */ 2743 2744 /* 2745 Since connections can be re-used between SessionHandles, this might be a 2746 connection already existing but on a fresh SessionHandle struct so we must 2747 make sure we have a good 'struct SSHPROTO' to play with. For new 2748 connections, the struct SSHPROTO is allocated and setup in the 2749 ssh_connect() function. 2750 */ 2751 Curl_reset_reqproto(conn); 2752 res = ssh_init(conn); 2753 if(res) 2754 return res; 2755 2756 data->req.size = -1; /* make sure this is unknown at this point */ 2757 2758 Curl_pgrsSetUploadCounter(data, 0); 2759 Curl_pgrsSetDownloadCounter(data, 0); 2760 Curl_pgrsSetUploadSize(data, 0); 2761 Curl_pgrsSetDownloadSize(data, 0); 2762 2763 if(conn->handler->protocol & CURLPROTO_SCP) 2764 res = scp_perform(conn, &connected, done); 2765 else 2766 res = sftp_perform(conn, &connected, done); 2767 2768 return res; 2769} 2770 2771/* BLOCKING, but the function is using the state machine so the only reason 2772 this is still blocking is that the multi interface code has no support for 2773 disconnecting operations that takes a while */ 2774static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) 2775{ 2776 CURLcode result = CURLE_OK; 2777 struct ssh_conn *ssh = &conn->proto.sshc; 2778 (void) dead_connection; 2779 2780 Curl_safefree(conn->data->state.proto.ssh); 2781 conn->data->state.proto.ssh = NULL; 2782 2783 if(ssh->ssh_session) { 2784 /* only if there's a session still around to use! */ 2785 2786 state(conn, SSH_SESSION_DISCONNECT); 2787 2788 result = ssh_easy_statemach(conn, FALSE); 2789 } 2790 2791 return result; 2792} 2793 2794/* generic done function for both SCP and SFTP called from their specific 2795 done functions */ 2796static CURLcode ssh_done(struct connectdata *conn, CURLcode status) 2797{ 2798 CURLcode result = CURLE_OK; 2799 struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh; 2800 2801 if(status == CURLE_OK) { 2802 /* run the state-machine 2803 2804 TODO: when the multi interface is used, this _really_ should be using 2805 the ssh_multi_statemach function but we have no general support for 2806 non-blocking DONE operations, not in the multi state machine and with 2807 Curl_done() invokes on several places in the code! 2808 */ 2809 result = ssh_easy_statemach(conn, FALSE); 2810 } 2811 else 2812 result = status; 2813 2814 if(sftp_scp) { 2815 Curl_safefree(sftp_scp->path); 2816 sftp_scp->path = NULL; 2817 } 2818 Curl_pgrsDone(conn); 2819 2820 conn->data->req.keepon = 0; /* clear all bits */ 2821 return result; 2822} 2823 2824 2825static CURLcode scp_done(struct connectdata *conn, CURLcode status, 2826 bool premature) 2827{ 2828 (void)premature; /* not used */ 2829 2830 if(status == CURLE_OK) 2831 state(conn, SSH_SCP_DONE); 2832 2833 return ssh_done(conn, status); 2834 2835} 2836 2837/* return number of received (decrypted) bytes */ 2838static ssize_t scp_send(struct connectdata *conn, int sockindex, 2839 const void *mem, size_t len, CURLcode *err) 2840{ 2841 ssize_t nwrite; 2842 (void)sockindex; /* we only support SCP on the fixed known primary socket */ 2843 2844 /* libssh2_channel_write() returns int! */ 2845 nwrite = (ssize_t) 2846 libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len); 2847 2848 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 2849 2850 if(nwrite == LIBSSH2_ERROR_EAGAIN) { 2851 *err = CURLE_AGAIN; 2852 nwrite = 0; 2853 } 2854 2855 return nwrite; 2856} 2857 2858/* 2859 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return 2860 * a regular CURLcode value. 2861 */ 2862static ssize_t scp_recv(struct connectdata *conn, int sockindex, 2863 char *mem, size_t len, CURLcode *err) 2864{ 2865 ssize_t nread; 2866 (void)sockindex; /* we only support SCP on the fixed known primary socket */ 2867 2868 /* libssh2_channel_read() returns int */ 2869 nread = (ssize_t) 2870 libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); 2871 2872 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 2873 if(nread == LIBSSH2_ERROR_EAGAIN) { 2874 *err = CURLE_AGAIN; 2875 nread = -1; 2876 } 2877 2878 return nread; 2879} 2880 2881/* 2882 * =============== SFTP =============== 2883 */ 2884 2885/* 2886 *********************************************************************** 2887 * 2888 * sftp_perform() 2889 * 2890 * This is the actual DO function for SFTP. Get a file/directory according to 2891 * the options previously setup. 2892 */ 2893 2894static 2895CURLcode sftp_perform(struct connectdata *conn, 2896 bool *connected, 2897 bool *dophase_done) 2898{ 2899 CURLcode result = CURLE_OK; 2900 2901 DEBUGF(infof(conn->data, "DO phase starts\n")); 2902 2903 *dophase_done = FALSE; /* not done yet */ 2904 2905 /* start the first command in the DO phase */ 2906 state(conn, SSH_SFTP_QUOTE_INIT); 2907 2908 /* run the state-machine */ 2909 if(conn->data->state.used_interface == Curl_if_multi) { 2910 result = ssh_multi_statemach(conn, dophase_done); 2911 } 2912 else { 2913 result = ssh_easy_statemach(conn, FALSE); 2914 *dophase_done = TRUE; /* with the easy interface we are done here */ 2915 } 2916 *connected = conn->bits.tcpconnect; 2917 2918 if(*dophase_done) { 2919 DEBUGF(infof(conn->data, "DO phase is complete\n")); 2920 } 2921 2922 return result; 2923} 2924 2925/* called from multi.c while DOing */ 2926static CURLcode sftp_doing(struct connectdata *conn, 2927 bool *dophase_done) 2928{ 2929 CURLcode result; 2930 result = ssh_multi_statemach(conn, dophase_done); 2931 2932 if(*dophase_done) { 2933 DEBUGF(infof(conn->data, "DO phase is complete\n")); 2934 } 2935 return result; 2936} 2937 2938/* BLOCKING, but the function is using the state machine so the only reason 2939 this is still blocking is that the multi interface code has no support for 2940 disconnecting operations that takes a while */ 2941static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) 2942{ 2943 CURLcode result = CURLE_OK; 2944 (void) dead_connection; 2945 2946 DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); 2947 2948 Curl_safefree(conn->data->state.proto.ssh); 2949 conn->data->state.proto.ssh = NULL; 2950 2951 if(conn->proto.sshc.ssh_session) { 2952 /* only if there's a session still around to use! */ 2953 state(conn, SSH_SFTP_SHUTDOWN); 2954 result = ssh_easy_statemach(conn, FALSE); 2955 } 2956 2957 DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); 2958 2959 return result; 2960 2961} 2962 2963static CURLcode sftp_done(struct connectdata *conn, CURLcode status, 2964 bool premature) 2965{ 2966 struct ssh_conn *sshc = &conn->proto.sshc; 2967 2968 if(status == CURLE_OK) { 2969 /* Post quote commands are executed after the SFTP_CLOSE state to avoid 2970 errors that could happen due to open file handles during POSTQUOTE 2971 operation */ 2972 if(!status && !premature && conn->data->set.postquote) { 2973 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; 2974 state(conn, SSH_SFTP_CLOSE); 2975 } 2976 else 2977 state(conn, SSH_SFTP_CLOSE); 2978 } 2979 return ssh_done(conn, status); 2980} 2981 2982/* return number of sent bytes */ 2983static ssize_t sftp_send(struct connectdata *conn, int sockindex, 2984 const void *mem, size_t len, CURLcode *err) 2985{ 2986 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 2987 but is changed to ssize_t in 0.15. These days we don't 2988 support libssh2 0.15*/ 2989 (void)sockindex; 2990 2991 nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); 2992 2993 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 2994 2995 if(nwrite == LIBSSH2_ERROR_EAGAIN) { 2996 *err = CURLE_AGAIN; 2997 nwrite = 0; 2998 } 2999 3000 return nwrite; 3001} 3002 3003/* 3004 * Return number of received (decrypted) bytes 3005 */ 3006static ssize_t sftp_recv(struct connectdata *conn, int sockindex, 3007 char *mem, size_t len, CURLcode *err) 3008{ 3009 ssize_t nread; 3010 (void)sockindex; 3011 3012 nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); 3013 3014 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 3015 3016 if(nread == LIBSSH2_ERROR_EAGAIN) { 3017 *err = CURLE_AGAIN; 3018 nread = -1; 3019 } 3020 return nread; 3021} 3022 3023/* The get_pathname() function is being borrowed from OpenSSH sftp.c 3024 version 4.6p1. */ 3025/* 3026 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3027 * 3028 * Permission to use, copy, modify, and distribute this software for any 3029 * purpose with or without fee is hereby granted, provided that the above 3030 * copyright notice and this permission notice appear in all copies. 3031 * 3032 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 3033 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 3034 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 3035 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 3036 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 3037 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 3038 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3039 */ 3040static CURLcode 3041get_pathname(const char **cpp, char **path) 3042{ 3043 const char *cp = *cpp, *end; 3044 char quot; 3045 unsigned int i, j; 3046 static const char WHITESPACE[] = " \t\r\n"; 3047 3048 cp += strspn(cp, WHITESPACE); 3049 if(!*cp) { 3050 *cpp = cp; 3051 *path = NULL; 3052 return CURLE_QUOTE_ERROR; 3053 } 3054 3055 *path = malloc(strlen(cp) + 1); 3056 if(*path == NULL) 3057 return CURLE_OUT_OF_MEMORY; 3058 3059 /* Check for quoted filenames */ 3060 if(*cp == '\"' || *cp == '\'') { 3061 quot = *cp++; 3062 3063 /* Search for terminating quote, unescape some chars */ 3064 for(i = j = 0; i <= strlen(cp); i++) { 3065 if(cp[i] == quot) { /* Found quote */ 3066 i++; 3067 (*path)[j] = '\0'; 3068 break; 3069 } 3070 if(cp[i] == '\0') { /* End of string */ 3071 /*error("Unterminated quote");*/ 3072 goto fail; 3073 } 3074 if(cp[i] == '\\') { /* Escaped characters */ 3075 i++; 3076 if(cp[i] != '\'' && cp[i] != '\"' && 3077 cp[i] != '\\') { 3078 /*error("Bad escaped character '\\%c'", 3079 cp[i]);*/ 3080 goto fail; 3081 } 3082 } 3083 (*path)[j++] = cp[i]; 3084 } 3085 3086 if(j == 0) { 3087 /*error("Empty quotes");*/ 3088 goto fail; 3089 } 3090 *cpp = cp + i + strspn(cp + i, WHITESPACE); 3091 } 3092 else { 3093 /* Read to end of filename */ 3094 end = strpbrk(cp, WHITESPACE); 3095 if(end == NULL) 3096 end = strchr(cp, '\0'); 3097 *cpp = end + strspn(end, WHITESPACE); 3098 3099 memcpy(*path, cp, end - cp); 3100 (*path)[end - cp] = '\0'; 3101 } 3102 return CURLE_OK; 3103 3104 fail: 3105 Curl_safefree(*path); 3106 *path = NULL; 3107 return CURLE_QUOTE_ERROR; 3108} 3109 3110 3111static const char *sftp_libssh2_strerror(unsigned long err) 3112{ 3113 switch (err) { 3114 case LIBSSH2_FX_NO_SUCH_FILE: 3115 return "No such file or directory"; 3116 3117 case LIBSSH2_FX_PERMISSION_DENIED: 3118 return "Permission denied"; 3119 3120 case LIBSSH2_FX_FAILURE: 3121 return "Operation failed"; 3122 3123 case LIBSSH2_FX_BAD_MESSAGE: 3124 return "Bad message from SFTP server"; 3125 3126 case LIBSSH2_FX_NO_CONNECTION: 3127 return "Not connected to SFTP server"; 3128 3129 case LIBSSH2_FX_CONNECTION_LOST: 3130 return "Connection to SFTP server lost"; 3131 3132 case LIBSSH2_FX_OP_UNSUPPORTED: 3133 return "Operation not supported by SFTP server"; 3134 3135 case LIBSSH2_FX_INVALID_HANDLE: 3136 return "Invalid handle"; 3137 3138 case LIBSSH2_FX_NO_SUCH_PATH: 3139 return "No such file or directory"; 3140 3141 case LIBSSH2_FX_FILE_ALREADY_EXISTS: 3142 return "File already exists"; 3143 3144 case LIBSSH2_FX_WRITE_PROTECT: 3145 return "File is write protected"; 3146 3147 case LIBSSH2_FX_NO_MEDIA: 3148 return "No media"; 3149 3150 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: 3151 return "Disk full"; 3152 3153 case LIBSSH2_FX_QUOTA_EXCEEDED: 3154 return "User quota exceeded"; 3155 3156 case LIBSSH2_FX_UNKNOWN_PRINCIPLE: 3157 return "Unknown principle"; 3158 3159 case LIBSSH2_FX_LOCK_CONFlICT: 3160 return "File lock conflict"; 3161 3162 case LIBSSH2_FX_DIR_NOT_EMPTY: 3163 return "Directory not empty"; 3164 3165 case LIBSSH2_FX_NOT_A_DIRECTORY: 3166 return "Not a directory"; 3167 3168 case LIBSSH2_FX_INVALID_FILENAME: 3169 return "Invalid filename"; 3170 3171 case LIBSSH2_FX_LINK_LOOP: 3172 return "Link points to itself"; 3173 } 3174 return "Unknown error in libssh2"; 3175} 3176 3177#endif /* USE_LIBSSH2 */ 3178