1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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 https://curl.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25/* #define CURL_LIBSSH2_DEBUG */ 26 27#include "curl_setup.h" 28 29#ifdef USE_LIBSSH2 30 31#include <limits.h> 32 33#include <libssh2.h> 34#include <libssh2_sftp.h> 35 36#ifdef HAVE_FCNTL_H 37#include <fcntl.h> 38#endif 39 40#ifdef HAVE_NETINET_IN_H 41#include <netinet/in.h> 42#endif 43#ifdef HAVE_ARPA_INET_H 44#include <arpa/inet.h> 45#endif 46#ifdef HAVE_NETDB_H 47#include <netdb.h> 48#endif 49#ifdef __VMS 50#include <in.h> 51#include <inet.h> 52#endif 53 54#include <curl/curl.h> 55#include "urldata.h" 56#include "sendf.h" 57#include "hostip.h" 58#include "progress.h" 59#include "transfer.h" 60#include "escape.h" 61#include "http.h" /* for HTTP proxy tunnel stuff */ 62#include "ssh.h" 63#include "url.h" 64#include "speedcheck.h" 65#include "getinfo.h" 66#include "strdup.h" 67#include "strcase.h" 68#include "vtls/vtls.h" 69#include "cfilters.h" 70#include "connect.h" 71#include "inet_ntop.h" 72#include "parsedate.h" /* for the week day and month names */ 73#include "sockaddr.h" /* required for Curl_sockaddr_storage */ 74#include "strtoofft.h" 75#include "multiif.h" 76#include "select.h" 77#include "warnless.h" 78#include "curl_path.h" 79 80#include <curl_base64.h> /* for base64 encoding/decoding */ 81#include <curl_sha256.h> 82 83 84/* The last 3 #include files should be in this order */ 85#include "curl_printf.h" 86#include "curl_memory.h" 87#include "memdebug.h" 88 89#if LIBSSH2_VERSION_NUM >= 0x010206 90/* libssh2_sftp_statvfs and friends were added in 1.2.6 */ 91#define HAS_STATVFS_SUPPORT 1 92#endif 93 94#define sftp_libssh2_realpath(s,p,t,m) \ 95 libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \ 96 (t), (m), LIBSSH2_SFTP_REALPATH) 97 98/* Local functions: */ 99static const char *sftp_libssh2_strerror(unsigned long err); 100static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); 101static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); 102static LIBSSH2_FREE_FUNC(my_libssh2_free); 103static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data); 104static CURLcode ssh_connect(struct Curl_easy *data, bool *done); 105static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done); 106static CURLcode ssh_do(struct Curl_easy *data, bool *done); 107static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature); 108static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done); 109static CURLcode scp_disconnect(struct Curl_easy *data, 110 struct connectdata *conn, bool dead_connection); 111static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature); 112static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done); 113static CURLcode sftp_disconnect(struct Curl_easy *data, 114 struct connectdata *conn, bool dead); 115static CURLcode sftp_perform(struct Curl_easy *data, bool *connected, 116 bool *dophase_done); 117static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn, 118 curl_socket_t *sock); 119static CURLcode ssh_setup_connection(struct Curl_easy *data, 120 struct connectdata *conn); 121static void ssh_attach(struct Curl_easy *data, struct connectdata *conn); 122 123/* 124 * SCP protocol handler. 125 */ 126 127const struct Curl_handler Curl_handler_scp = { 128 "SCP", /* scheme */ 129 ssh_setup_connection, /* setup_connection */ 130 ssh_do, /* do_it */ 131 scp_done, /* done */ 132 ZERO_NULL, /* do_more */ 133 ssh_connect, /* connect_it */ 134 ssh_multi_statemach, /* connecting */ 135 scp_doing, /* doing */ 136 ssh_getsock, /* proto_getsock */ 137 ssh_getsock, /* doing_getsock */ 138 ZERO_NULL, /* domore_getsock */ 139 ssh_getsock, /* perform_getsock */ 140 scp_disconnect, /* disconnect */ 141 ZERO_NULL, /* write_resp */ 142 ZERO_NULL, /* connection_check */ 143 ssh_attach, /* attach */ 144 PORT_SSH, /* defport */ 145 CURLPROTO_SCP, /* protocol */ 146 CURLPROTO_SCP, /* family */ 147 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION 148 | PROTOPT_NOURLQUERY /* flags */ 149}; 150 151 152/* 153 * SFTP protocol handler. 154 */ 155 156const struct Curl_handler Curl_handler_sftp = { 157 "SFTP", /* scheme */ 158 ssh_setup_connection, /* setup_connection */ 159 ssh_do, /* do_it */ 160 sftp_done, /* done */ 161 ZERO_NULL, /* do_more */ 162 ssh_connect, /* connect_it */ 163 ssh_multi_statemach, /* connecting */ 164 sftp_doing, /* doing */ 165 ssh_getsock, /* proto_getsock */ 166 ssh_getsock, /* doing_getsock */ 167 ZERO_NULL, /* domore_getsock */ 168 ssh_getsock, /* perform_getsock */ 169 sftp_disconnect, /* disconnect */ 170 ZERO_NULL, /* write_resp */ 171 ZERO_NULL, /* connection_check */ 172 ssh_attach, /* attach */ 173 PORT_SSH, /* defport */ 174 CURLPROTO_SFTP, /* protocol */ 175 CURLPROTO_SFTP, /* family */ 176 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION 177 | PROTOPT_NOURLQUERY /* flags */ 178}; 179 180static void 181kbd_callback(const char *name, int name_len, const char *instruction, 182 int instruction_len, int num_prompts, 183 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, 184 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, 185 void **abstract) 186{ 187 struct Curl_easy *data = (struct Curl_easy *)*abstract; 188 189#ifdef CURL_LIBSSH2_DEBUG 190 fprintf(stderr, "name=%s\n", name); 191 fprintf(stderr, "name_len=%d\n", name_len); 192 fprintf(stderr, "instruction=%s\n", instruction); 193 fprintf(stderr, "instruction_len=%d\n", instruction_len); 194 fprintf(stderr, "num_prompts=%d\n", num_prompts); 195#else 196 (void)name; 197 (void)name_len; 198 (void)instruction; 199 (void)instruction_len; 200#endif /* CURL_LIBSSH2_DEBUG */ 201 if(num_prompts == 1) { 202 struct connectdata *conn = data->conn; 203 responses[0].text = strdup(conn->passwd); 204 responses[0].length = curlx_uztoui(strlen(conn->passwd)); 205 } 206 (void)prompts; 207} /* kbd_callback */ 208 209static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err) 210{ 211 switch(err) { 212 case LIBSSH2_FX_OK: 213 return CURLE_OK; 214 215 case LIBSSH2_FX_NO_SUCH_FILE: 216 case LIBSSH2_FX_NO_SUCH_PATH: 217 return CURLE_REMOTE_FILE_NOT_FOUND; 218 219 case LIBSSH2_FX_PERMISSION_DENIED: 220 case LIBSSH2_FX_WRITE_PROTECT: 221 case LIBSSH2_FX_LOCK_CONFlICT: 222 return CURLE_REMOTE_ACCESS_DENIED; 223 224 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: 225 case LIBSSH2_FX_QUOTA_EXCEEDED: 226 return CURLE_REMOTE_DISK_FULL; 227 228 case LIBSSH2_FX_FILE_ALREADY_EXISTS: 229 return CURLE_REMOTE_FILE_EXISTS; 230 231 case LIBSSH2_FX_DIR_NOT_EMPTY: 232 return CURLE_QUOTE_ERROR; 233 234 default: 235 break; 236 } 237 238 return CURLE_SSH; 239} 240 241static CURLcode libssh2_session_error_to_CURLE(int err) 242{ 243 switch(err) { 244 /* Ordered by order of appearance in libssh2.h */ 245 case LIBSSH2_ERROR_NONE: 246 return CURLE_OK; 247 248 /* This is the error returned by libssh2_scp_recv2 249 * on unknown file */ 250 case LIBSSH2_ERROR_SCP_PROTOCOL: 251 return CURLE_REMOTE_FILE_NOT_FOUND; 252 253 case LIBSSH2_ERROR_SOCKET_NONE: 254 return CURLE_COULDNT_CONNECT; 255 256 case LIBSSH2_ERROR_ALLOC: 257 return CURLE_OUT_OF_MEMORY; 258 259 case LIBSSH2_ERROR_SOCKET_SEND: 260 return CURLE_SEND_ERROR; 261 262 case LIBSSH2_ERROR_HOSTKEY_INIT: 263 case LIBSSH2_ERROR_HOSTKEY_SIGN: 264 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: 265 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: 266 return CURLE_PEER_FAILED_VERIFICATION; 267 268 case LIBSSH2_ERROR_PASSWORD_EXPIRED: 269 return CURLE_LOGIN_DENIED; 270 271 case LIBSSH2_ERROR_SOCKET_TIMEOUT: 272 case LIBSSH2_ERROR_TIMEOUT: 273 return CURLE_OPERATION_TIMEDOUT; 274 275 case LIBSSH2_ERROR_EAGAIN: 276 return CURLE_AGAIN; 277 } 278 279 return CURLE_SSH; 280} 281 282static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc) 283{ 284 (void)abstract; /* arg not used */ 285 return malloc(count); 286} 287 288static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc) 289{ 290 (void)abstract; /* arg not used */ 291 return realloc(ptr, count); 292} 293 294static LIBSSH2_FREE_FUNC(my_libssh2_free) 295{ 296 (void)abstract; /* arg not used */ 297 if(ptr) /* ssh2 agent sometimes call free with null ptr */ 298 free(ptr); 299} 300 301/* 302 * SSH State machine related code 303 */ 304/* This is the ONLY way to change SSH state! */ 305static void state(struct Curl_easy *data, sshstate nowstate) 306{ 307 struct connectdata *conn = data->conn; 308 struct ssh_conn *sshc = &conn->proto.sshc; 309#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 310 /* for debug purposes */ 311 static const char * const names[] = { 312 "SSH_STOP", 313 "SSH_INIT", 314 "SSH_S_STARTUP", 315 "SSH_HOSTKEY", 316 "SSH_AUTHLIST", 317 "SSH_AUTH_PKEY_INIT", 318 "SSH_AUTH_PKEY", 319 "SSH_AUTH_PASS_INIT", 320 "SSH_AUTH_PASS", 321 "SSH_AUTH_AGENT_INIT", 322 "SSH_AUTH_AGENT_LIST", 323 "SSH_AUTH_AGENT", 324 "SSH_AUTH_HOST_INIT", 325 "SSH_AUTH_HOST", 326 "SSH_AUTH_KEY_INIT", 327 "SSH_AUTH_KEY", 328 "SSH_AUTH_GSSAPI", 329 "SSH_AUTH_DONE", 330 "SSH_SFTP_INIT", 331 "SSH_SFTP_REALPATH", 332 "SSH_SFTP_QUOTE_INIT", 333 "SSH_SFTP_POSTQUOTE_INIT", 334 "SSH_SFTP_QUOTE", 335 "SSH_SFTP_NEXT_QUOTE", 336 "SSH_SFTP_QUOTE_STAT", 337 "SSH_SFTP_QUOTE_SETSTAT", 338 "SSH_SFTP_QUOTE_SYMLINK", 339 "SSH_SFTP_QUOTE_MKDIR", 340 "SSH_SFTP_QUOTE_RENAME", 341 "SSH_SFTP_QUOTE_RMDIR", 342 "SSH_SFTP_QUOTE_UNLINK", 343 "SSH_SFTP_QUOTE_STATVFS", 344 "SSH_SFTP_GETINFO", 345 "SSH_SFTP_FILETIME", 346 "SSH_SFTP_TRANS_INIT", 347 "SSH_SFTP_UPLOAD_INIT", 348 "SSH_SFTP_CREATE_DIRS_INIT", 349 "SSH_SFTP_CREATE_DIRS", 350 "SSH_SFTP_CREATE_DIRS_MKDIR", 351 "SSH_SFTP_READDIR_INIT", 352 "SSH_SFTP_READDIR", 353 "SSH_SFTP_READDIR_LINK", 354 "SSH_SFTP_READDIR_BOTTOM", 355 "SSH_SFTP_READDIR_DONE", 356 "SSH_SFTP_DOWNLOAD_INIT", 357 "SSH_SFTP_DOWNLOAD_STAT", 358 "SSH_SFTP_CLOSE", 359 "SSH_SFTP_SHUTDOWN", 360 "SSH_SCP_TRANS_INIT", 361 "SSH_SCP_UPLOAD_INIT", 362 "SSH_SCP_DOWNLOAD_INIT", 363 "SSH_SCP_DOWNLOAD", 364 "SSH_SCP_DONE", 365 "SSH_SCP_SEND_EOF", 366 "SSH_SCP_WAIT_EOF", 367 "SSH_SCP_WAIT_CLOSE", 368 "SSH_SCP_CHANNEL_FREE", 369 "SSH_SESSION_DISCONNECT", 370 "SSH_SESSION_FREE", 371 "QUIT" 372 }; 373 374 /* a precaution to make sure the lists are in sync */ 375 DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); 376 377 if(sshc->state != nowstate) { 378 infof(data, "SFTP %p state change from %s to %s", 379 (void *)sshc, names[sshc->state], names[nowstate]); 380 } 381#endif 382 383 sshc->state = nowstate; 384} 385 386 387#ifdef HAVE_LIBSSH2_KNOWNHOST_API 388static int sshkeycallback(struct Curl_easy *easy, 389 const struct curl_khkey *knownkey, /* known */ 390 const struct curl_khkey *foundkey, /* found */ 391 enum curl_khmatch match, 392 void *clientp) 393{ 394 (void)easy; 395 (void)knownkey; 396 (void)foundkey; 397 (void)clientp; 398 399 /* we only allow perfect matches, and we reject everything else */ 400 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; 401} 402#endif 403 404/* 405 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions 406 * with 32bit size_t. 407 */ 408#ifdef HAVE_LIBSSH2_SFTP_SEEK64 409#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y) 410#else 411#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y) 412#endif 413 414/* 415 * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit 416 * architectures so we check of the necessary function is present. 417 */ 418#ifndef HAVE_LIBSSH2_SCP_SEND64 419#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0) 420#else 421#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \ 422 (libssh2_uint64_t)d, 0, 0) 423#endif 424 425/* 426 * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64. 427 */ 428#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE 429#define session_startup(x,y) libssh2_session_handshake(x, y) 430#else 431#define session_startup(x,y) libssh2_session_startup(x, (int)y) 432#endif 433static int convert_ssh2_keytype(int sshkeytype) 434{ 435 int keytype = CURLKHTYPE_UNKNOWN; 436 switch(sshkeytype) { 437 case LIBSSH2_HOSTKEY_TYPE_RSA: 438 keytype = CURLKHTYPE_RSA; 439 break; 440 case LIBSSH2_HOSTKEY_TYPE_DSS: 441 keytype = CURLKHTYPE_DSS; 442 break; 443#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256 444 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256: 445 keytype = CURLKHTYPE_ECDSA; 446 break; 447#endif 448#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384 449 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384: 450 keytype = CURLKHTYPE_ECDSA; 451 break; 452#endif 453#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521 454 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521: 455 keytype = CURLKHTYPE_ECDSA; 456 break; 457#endif 458#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519 459 case LIBSSH2_HOSTKEY_TYPE_ED25519: 460 keytype = CURLKHTYPE_ED25519; 461 break; 462#endif 463 } 464 return keytype; 465} 466 467static CURLcode ssh_knownhost(struct Curl_easy *data) 468{ 469 int sshkeytype = 0; 470 size_t keylen = 0; 471 int rc = 0; 472 CURLcode result = CURLE_OK; 473 474#ifdef HAVE_LIBSSH2_KNOWNHOST_API 475 if(data->set.str[STRING_SSH_KNOWNHOSTS]) { 476 /* we're asked to verify the host against a file */ 477 struct connectdata *conn = data->conn; 478 struct ssh_conn *sshc = &conn->proto.sshc; 479 struct libssh2_knownhost *host = NULL; 480 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, 481 &keylen, &sshkeytype); 482 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE; 483 int keybit = 0; 484 485 if(remotekey) { 486 /* 487 * A subject to figure out is what host name we need to pass in here. 488 * What host name does OpenSSH store in its file if an IDN name is 489 * used? 490 */ 491 enum curl_khmatch keymatch; 492 curl_sshkeycallback func = 493 data->set.ssh_keyfunc ? data->set.ssh_keyfunc : sshkeycallback; 494 struct curl_khkey knownkey; 495 struct curl_khkey *knownkeyp = NULL; 496 struct curl_khkey foundkey; 497 498 switch(sshkeytype) { 499 case LIBSSH2_HOSTKEY_TYPE_RSA: 500 keybit = LIBSSH2_KNOWNHOST_KEY_SSHRSA; 501 break; 502 case LIBSSH2_HOSTKEY_TYPE_DSS: 503 keybit = LIBSSH2_KNOWNHOST_KEY_SSHDSS; 504 break; 505#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256 506 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256: 507 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_256; 508 break; 509#endif 510#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384 511 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384: 512 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_384; 513 break; 514#endif 515#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521 516 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521: 517 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_521; 518 break; 519#endif 520#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519 521 case LIBSSH2_HOSTKEY_TYPE_ED25519: 522 keybit = LIBSSH2_KNOWNHOST_KEY_ED25519; 523 break; 524#endif 525 default: 526 infof(data, "unsupported key type, can't check knownhosts"); 527 keybit = 0; 528 break; 529 } 530 if(!keybit) 531 /* no check means failure! */ 532 rc = CURLKHSTAT_REJECT; 533 else { 534#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP 535 keycheck = libssh2_knownhost_checkp(sshc->kh, 536 conn->host.name, 537 (conn->remote_port != PORT_SSH)? 538 conn->remote_port:-1, 539 remotekey, keylen, 540 LIBSSH2_KNOWNHOST_TYPE_PLAIN| 541 LIBSSH2_KNOWNHOST_KEYENC_RAW| 542 keybit, 543 &host); 544#else 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#endif 553 554 infof(data, "SSH host check: %d, key: %s", keycheck, 555 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? 556 host->key:"<none>"); 557 558 /* setup 'knownkey' */ 559 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { 560 knownkey.key = host->key; 561 knownkey.len = 0; 562 knownkey.keytype = convert_ssh2_keytype(sshkeytype); 563 knownkeyp = &knownkey; 564 } 565 566 /* setup 'foundkey' */ 567 foundkey.key = remotekey; 568 foundkey.len = keylen; 569 foundkey.keytype = convert_ssh2_keytype(sshkeytype); 570 571 /* 572 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the 573 * curl_khmatch enum are ever modified, we need to introduce a 574 * translation table here! 575 */ 576 keymatch = (enum curl_khmatch)keycheck; 577 578 /* Ask the callback how to behave */ 579 Curl_set_in_callback(data, true); 580 rc = func(data, knownkeyp, /* from the knownhosts file */ 581 &foundkey, /* from the remote host */ 582 keymatch, data->set.ssh_keyfunc_userp); 583 Curl_set_in_callback(data, false); 584 } 585 } 586 else 587 /* no remotekey means failure! */ 588 rc = CURLKHSTAT_REJECT; 589 590 switch(rc) { 591 default: /* unknown return codes will equal reject */ 592 case CURLKHSTAT_REJECT: 593 state(data, SSH_SESSION_FREE); 594 FALLTHROUGH(); 595 case CURLKHSTAT_DEFER: 596 /* DEFER means bail out but keep the SSH_HOSTKEY state */ 597 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 598 break; 599 case CURLKHSTAT_FINE_REPLACE: 600 /* remove old host+key that doesn't match */ 601 if(host) 602 libssh2_knownhost_del(sshc->kh, host); 603 FALLTHROUGH(); 604 case CURLKHSTAT_FINE: 605 case CURLKHSTAT_FINE_ADD_TO_FILE: 606 /* proceed */ 607 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { 608 /* the found host+key didn't match but has been told to be fine 609 anyway so we add it in memory */ 610 int addrc = libssh2_knownhost_add(sshc->kh, 611 conn->host.name, NULL, 612 remotekey, keylen, 613 LIBSSH2_KNOWNHOST_TYPE_PLAIN| 614 LIBSSH2_KNOWNHOST_KEYENC_RAW| 615 keybit, NULL); 616 if(addrc) 617 infof(data, "WARNING: adding the known host %s failed", 618 conn->host.name); 619 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE || 620 rc == CURLKHSTAT_FINE_REPLACE) { 621 /* now we write the entire in-memory list of known hosts to the 622 known_hosts file */ 623 int wrc = 624 libssh2_knownhost_writefile(sshc->kh, 625 data->set.str[STRING_SSH_KNOWNHOSTS], 626 LIBSSH2_KNOWNHOST_FILE_OPENSSH); 627 if(wrc) { 628 infof(data, "WARNING: writing %s failed", 629 data->set.str[STRING_SSH_KNOWNHOSTS]); 630 } 631 } 632 } 633 break; 634 } 635 } 636#else /* HAVE_LIBSSH2_KNOWNHOST_API */ 637 (void)data; 638#endif 639 return result; 640} 641 642static CURLcode ssh_check_fingerprint(struct Curl_easy *data) 643{ 644 struct connectdata *conn = data->conn; 645 struct ssh_conn *sshc = &conn->proto.sshc; 646 const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; 647 const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]; 648 649 infof(data, "SSH MD5 public key: %s", 650 pubkey_md5 != NULL ? pubkey_md5 : "NULL"); 651 infof(data, "SSH SHA256 public key: %s", 652 pubkey_sha256 != NULL ? pubkey_sha256 : "NULL"); 653 654 if(pubkey_sha256) { 655 const char *fingerprint = NULL; 656 char *fingerprint_b64 = NULL; 657 size_t fingerprint_b64_len; 658 size_t pub_pos = 0; 659 size_t b64_pos = 0; 660 661#ifdef LIBSSH2_HOSTKEY_HASH_SHA256 662 /* The fingerprint points to static storage (!), don't free() it. */ 663 fingerprint = libssh2_hostkey_hash(sshc->ssh_session, 664 LIBSSH2_HOSTKEY_HASH_SHA256); 665#else 666 const char *hostkey; 667 size_t len = 0; 668 unsigned char hash[32]; 669 670 hostkey = libssh2_session_hostkey(sshc->ssh_session, &len, NULL); 671 if(hostkey) { 672 if(!Curl_sha256it(hash, (const unsigned char *) hostkey, len)) 673 fingerprint = (char *) hash; 674 } 675#endif 676 677 if(!fingerprint) { 678 failf(data, 679 "Denied establishing ssh session: sha256 fingerprint " 680 "not available"); 681 state(data, SSH_SESSION_FREE); 682 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 683 return sshc->actualcode; 684 } 685 686 /* The length of fingerprint is 32 bytes for SHA256. 687 * See libssh2_hostkey_hash documentation. */ 688 if(Curl_base64_encode(fingerprint, 32, &fingerprint_b64, 689 &fingerprint_b64_len) != CURLE_OK) { 690 state(data, SSH_SESSION_FREE); 691 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 692 return sshc->actualcode; 693 } 694 695 if(!fingerprint_b64) { 696 failf(data, "sha256 fingerprint could not be encoded"); 697 state(data, SSH_SESSION_FREE); 698 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 699 return sshc->actualcode; 700 } 701 702 infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64); 703 704 /* Find the position of any = padding characters in the public key */ 705 while((pubkey_sha256[pub_pos] != '=') && pubkey_sha256[pub_pos]) { 706 pub_pos++; 707 } 708 709 /* Find the position of any = padding characters in the base64 coded 710 * hostkey fingerprint */ 711 while((fingerprint_b64[b64_pos] != '=') && fingerprint_b64[b64_pos]) { 712 b64_pos++; 713 } 714 715 /* Before we authenticate we check the hostkey's sha256 fingerprint 716 * against a known fingerprint, if available. 717 */ 718 if((pub_pos != b64_pos) || 719 strncmp(fingerprint_b64, pubkey_sha256, pub_pos)) { 720 failf(data, 721 "Denied establishing ssh session: mismatch sha256 fingerprint. " 722 "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256); 723 free(fingerprint_b64); 724 state(data, SSH_SESSION_FREE); 725 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 726 return sshc->actualcode; 727 } 728 729 free(fingerprint_b64); 730 731 infof(data, "SHA256 checksum match"); 732 } 733 734 if(pubkey_md5) { 735 char md5buffer[33]; 736 const char *fingerprint = NULL; 737 738 fingerprint = libssh2_hostkey_hash(sshc->ssh_session, 739 LIBSSH2_HOSTKEY_HASH_MD5); 740 741 if(fingerprint) { 742 /* The fingerprint points to static storage (!), don't free() it. */ 743 int i; 744 for(i = 0; i < 16; i++) { 745 msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); 746 } 747 748 infof(data, "SSH MD5 fingerprint: %s", md5buffer); 749 } 750 751 /* This does NOT verify the length of 'pubkey_md5' separately, which will 752 make the comparison below fail unless it is exactly 32 characters */ 753 if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { 754 if(fingerprint) { 755 failf(data, 756 "Denied establishing ssh session: mismatch md5 fingerprint. " 757 "Remote %s is not equal to %s", md5buffer, pubkey_md5); 758 } 759 else { 760 failf(data, 761 "Denied establishing ssh session: md5 fingerprint " 762 "not available"); 763 } 764 state(data, SSH_SESSION_FREE); 765 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 766 return sshc->actualcode; 767 } 768 infof(data, "MD5 checksum match"); 769 } 770 771 if(!pubkey_md5 && !pubkey_sha256) { 772 if(data->set.ssh_hostkeyfunc) { 773 size_t keylen = 0; 774 int sshkeytype = 0; 775 int rc = 0; 776 /* we handle the process to the callback */ 777 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, 778 &keylen, &sshkeytype); 779 if(remotekey) { 780 int keytype = convert_ssh2_keytype(sshkeytype); 781 Curl_set_in_callback(data, true); 782 rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp, 783 keytype, remotekey, keylen); 784 Curl_set_in_callback(data, false); 785 if(rc!= CURLKHMATCH_OK) { 786 state(data, SSH_SESSION_FREE); 787 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 788 return sshc->actualcode; 789 } 790 } 791 else { 792 state(data, SSH_SESSION_FREE); 793 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; 794 return sshc->actualcode; 795 } 796 return CURLE_OK; 797 } 798 else { 799 return ssh_knownhost(data); 800 } 801 } 802 else { 803 /* as we already matched, we skip the check for known hosts */ 804 return CURLE_OK; 805 } 806} 807 808/* 809 * ssh_force_knownhost_key_type() will check the known hosts file and try to 810 * force a specific public key type from the server if an entry is found. 811 */ 812static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) 813{ 814 CURLcode result = CURLE_OK; 815 816#ifdef HAVE_LIBSSH2_KNOWNHOST_API 817 818#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519 819 static const char * const hostkey_method_ssh_ed25519 820 = "ssh-ed25519"; 821#endif 822#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521 823 static const char * const hostkey_method_ssh_ecdsa_521 824 = "ecdsa-sha2-nistp521"; 825#endif 826#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384 827 static const char * const hostkey_method_ssh_ecdsa_384 828 = "ecdsa-sha2-nistp384"; 829#endif 830#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256 831 static const char * const hostkey_method_ssh_ecdsa_256 832 = "ecdsa-sha2-nistp256"; 833#endif 834 static const char * const hostkey_method_ssh_rsa 835 = "ssh-rsa"; 836 static const char * const hostkey_method_ssh_rsa_all 837 = "rsa-sha2-256,rsa-sha2-512,ssh-rsa"; 838 static const char * const hostkey_method_ssh_dss 839 = "ssh-dss"; 840 841 const char *hostkey_method = NULL; 842 struct connectdata *conn = data->conn; 843 struct ssh_conn *sshc = &conn->proto.sshc; 844 struct libssh2_knownhost* store = NULL; 845 const char *kh_name_end = NULL; 846 size_t kh_name_size = 0; 847 int port = 0; 848 bool found = false; 849 850 if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) { 851 /* lets try to find our host in the known hosts file */ 852 while(!libssh2_knownhost_get(sshc->kh, &store, store)) { 853 /* For non-standard ports, the name will be enclosed in */ 854 /* square brackets, followed by a colon and the port */ 855 if(store) { 856 if(store->name) { 857 if(store->name[0] == '[') { 858 kh_name_end = strstr(store->name, "]:"); 859 if(!kh_name_end) { 860 infof(data, "Invalid host pattern %s in %s", 861 store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); 862 continue; 863 } 864 port = atoi(kh_name_end + 2); 865 if(kh_name_end && (port == conn->remote_port)) { 866 kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end); 867 if(strncmp(store->name + 1, 868 conn->host.name, kh_name_size) == 0) { 869 found = true; 870 break; 871 } 872 } 873 } 874 else if(strcmp(store->name, conn->host.name) == 0) { 875 found = true; 876 break; 877 } 878 } 879 else { 880 found = true; 881 break; 882 } 883 } 884 } 885 886 if(found) { 887 int rc; 888 infof(data, "Found host %s in %s", 889 conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); 890 891 switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) { 892#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519 893 case LIBSSH2_KNOWNHOST_KEY_ED25519: 894 hostkey_method = hostkey_method_ssh_ed25519; 895 break; 896#endif 897#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521 898 case LIBSSH2_KNOWNHOST_KEY_ECDSA_521: 899 hostkey_method = hostkey_method_ssh_ecdsa_521; 900 break; 901#endif 902#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384 903 case LIBSSH2_KNOWNHOST_KEY_ECDSA_384: 904 hostkey_method = hostkey_method_ssh_ecdsa_384; 905 break; 906#endif 907#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256 908 case LIBSSH2_KNOWNHOST_KEY_ECDSA_256: 909 hostkey_method = hostkey_method_ssh_ecdsa_256; 910 break; 911#endif 912 case LIBSSH2_KNOWNHOST_KEY_SSHRSA: 913#ifdef HAVE_LIBSSH2_VERSION 914 if(libssh2_version(0x010900)) 915 /* since 1.9.0 libssh2_session_method_pref() works as expected */ 916 hostkey_method = hostkey_method_ssh_rsa_all; 917 else 918#endif 919 /* old libssh2 which cannot correctly remove unsupported methods due 920 * to bug in src/kex.c or does not support the new methods anyways. 921 */ 922 hostkey_method = hostkey_method_ssh_rsa; 923 break; 924 case LIBSSH2_KNOWNHOST_KEY_SSHDSS: 925 hostkey_method = hostkey_method_ssh_dss; 926 break; 927 case LIBSSH2_KNOWNHOST_KEY_RSA1: 928 failf(data, "Found host key type RSA1 which is not supported"); 929 return CURLE_SSH; 930 default: 931 failf(data, "Unknown host key type: %i", 932 (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK)); 933 return CURLE_SSH; 934 } 935 936 infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method); 937 rc = libssh2_session_method_pref(sshc->ssh_session, 938 LIBSSH2_METHOD_HOSTKEY, hostkey_method); 939 if(rc) { 940 char *errmsg = NULL; 941 int errlen; 942 libssh2_session_last_error(sshc->ssh_session, &errmsg, &errlen, 0); 943 failf(data, "libssh2: %s", errmsg); 944 result = libssh2_session_error_to_CURLE(rc); 945 } 946 } 947 else { 948 infof(data, "Did not find host %s in %s", 949 conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); 950 } 951 } 952 953#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ 954 955 return result; 956} 957 958/* 959 * ssh_statemach_act() runs the SSH state machine as far as it can without 960 * blocking and without reaching the end. The data the pointer 'block' points 961 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN 962 * meaning it wants to be called again when the socket is ready 963 */ 964 965static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) 966{ 967 CURLcode result = CURLE_OK; 968 struct connectdata *conn = data->conn; 969 struct SSHPROTO *sshp = data->req.p.ssh; 970 struct ssh_conn *sshc = &conn->proto.sshc; 971 curl_socket_t sock = conn->sock[FIRSTSOCKET]; 972 int rc = LIBSSH2_ERROR_NONE; 973 int ssherr; 974 unsigned long sftperr; 975 int seekerr = CURL_SEEKFUNC_OK; 976 size_t readdir_len; 977 *block = 0; /* we're not blocking by default */ 978 979 do { 980 switch(sshc->state) { 981 case SSH_INIT: 982 sshc->secondCreateDirs = 0; 983 sshc->nextstate = SSH_NO_STATE; 984 sshc->actualcode = CURLE_OK; 985 986 /* Set libssh2 to non-blocking, since everything internally is 987 non-blocking */ 988 libssh2_session_set_blocking(sshc->ssh_session, 0); 989 990 result = ssh_force_knownhost_key_type(data); 991 if(result) { 992 state(data, SSH_SESSION_FREE); 993 sshc->actualcode = result; 994 break; 995 } 996 997 state(data, SSH_S_STARTUP); 998 FALLTHROUGH(); 999 1000 case SSH_S_STARTUP: 1001 rc = session_startup(sshc->ssh_session, sock); 1002 if(rc == LIBSSH2_ERROR_EAGAIN) { 1003 break; 1004 } 1005 if(rc) { 1006 char *err_msg = NULL; 1007 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); 1008 failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg); 1009 1010 state(data, SSH_SESSION_FREE); 1011 sshc->actualcode = CURLE_FAILED_INIT; 1012 break; 1013 } 1014 1015 state(data, SSH_HOSTKEY); 1016 1017 FALLTHROUGH(); 1018 case SSH_HOSTKEY: 1019 /* 1020 * Before we authenticate we should check the hostkey's fingerprint 1021 * against our known hosts. How that is handled (reading from file, 1022 * whatever) is up to us. 1023 */ 1024 result = ssh_check_fingerprint(data); 1025 if(!result) 1026 state(data, SSH_AUTHLIST); 1027 /* ssh_check_fingerprint sets state appropriately on error */ 1028 break; 1029 1030 case SSH_AUTHLIST: 1031 /* 1032 * Figure out authentication methods 1033 * NB: As soon as we have provided a username to an openssh server we 1034 * must never change it later. Thus, always specify the correct username 1035 * here, even though the libssh2 docs kind of indicate that it should be 1036 * possible to get a 'generic' list (not user-specific) of authentication 1037 * methods, presumably with a blank username. That won't work in my 1038 * experience. 1039 * So always specify it here. 1040 */ 1041 sshc->authlist = libssh2_userauth_list(sshc->ssh_session, 1042 conn->user, 1043 curlx_uztoui(strlen(conn->user))); 1044 1045 if(!sshc->authlist) { 1046 if(libssh2_userauth_authenticated(sshc->ssh_session)) { 1047 sshc->authed = TRUE; 1048 infof(data, "SSH user accepted with no authentication"); 1049 state(data, SSH_AUTH_DONE); 1050 break; 1051 } 1052 ssherr = libssh2_session_last_errno(sshc->ssh_session); 1053 if(ssherr == LIBSSH2_ERROR_EAGAIN) 1054 rc = LIBSSH2_ERROR_EAGAIN; 1055 else { 1056 state(data, SSH_SESSION_FREE); 1057 sshc->actualcode = libssh2_session_error_to_CURLE(ssherr); 1058 } 1059 break; 1060 } 1061 infof(data, "SSH authentication methods available: %s", 1062 sshc->authlist); 1063 1064 state(data, SSH_AUTH_PKEY_INIT); 1065 break; 1066 1067 case SSH_AUTH_PKEY_INIT: 1068 /* 1069 * Check the supported auth types in the order I feel is most secure 1070 * with the requested type of authentication 1071 */ 1072 sshc->authed = FALSE; 1073 1074 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && 1075 (strstr(sshc->authlist, "publickey") != NULL)) { 1076 bool out_of_memory = FALSE; 1077 1078 sshc->rsa_pub = sshc->rsa = NULL; 1079 1080 if(data->set.str[STRING_SSH_PRIVATE_KEY]) 1081 sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); 1082 else { 1083 /* To ponder about: should really the lib be messing about with the 1084 HOME environment variable etc? */ 1085 char *home = curl_getenv("HOME"); 1086 1087 /* If no private key file is specified, try some common paths. */ 1088 if(home) { 1089 /* Try ~/.ssh first. */ 1090 sshc->rsa = aprintf("%s/.ssh/id_rsa", home); 1091 if(!sshc->rsa) 1092 out_of_memory = TRUE; 1093 else if(access(sshc->rsa, R_OK) != 0) { 1094 Curl_safefree(sshc->rsa); 1095 sshc->rsa = aprintf("%s/.ssh/id_dsa", home); 1096 if(!sshc->rsa) 1097 out_of_memory = TRUE; 1098 else if(access(sshc->rsa, R_OK) != 0) { 1099 Curl_safefree(sshc->rsa); 1100 } 1101 } 1102 free(home); 1103 } 1104 if(!out_of_memory && !sshc->rsa) { 1105 /* Nothing found; try the current dir. */ 1106 sshc->rsa = strdup("id_rsa"); 1107 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { 1108 Curl_safefree(sshc->rsa); 1109 sshc->rsa = strdup("id_dsa"); 1110 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { 1111 Curl_safefree(sshc->rsa); 1112 /* Out of guesses. Set to the empty string to avoid 1113 * surprising info messages. */ 1114 sshc->rsa = strdup(""); 1115 } 1116 } 1117 } 1118 } 1119 1120 /* 1121 * Unless the user explicitly specifies a public key file, let 1122 * libssh2 extract the public key from the private key file. 1123 * This is done by simply passing sshc->rsa_pub = NULL. 1124 */ 1125 if(data->set.str[STRING_SSH_PUBLIC_KEY] 1126 /* treat empty string the same way as NULL */ 1127 && data->set.str[STRING_SSH_PUBLIC_KEY][0]) { 1128 sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); 1129 if(!sshc->rsa_pub) 1130 out_of_memory = TRUE; 1131 } 1132 1133 if(out_of_memory || !sshc->rsa) { 1134 Curl_safefree(sshc->rsa); 1135 Curl_safefree(sshc->rsa_pub); 1136 state(data, SSH_SESSION_FREE); 1137 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1138 break; 1139 } 1140 1141 sshc->passphrase = data->set.ssl.key_passwd; 1142 if(!sshc->passphrase) 1143 sshc->passphrase = ""; 1144 1145 if(sshc->rsa_pub) 1146 infof(data, "Using SSH public key file '%s'", sshc->rsa_pub); 1147 infof(data, "Using SSH private key file '%s'", sshc->rsa); 1148 1149 state(data, SSH_AUTH_PKEY); 1150 } 1151 else { 1152 state(data, SSH_AUTH_PASS_INIT); 1153 } 1154 break; 1155 1156 case SSH_AUTH_PKEY: 1157 /* The function below checks if the files exists, no need to stat() here. 1158 */ 1159 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, 1160 conn->user, 1161 curlx_uztoui( 1162 strlen(conn->user)), 1163 sshc->rsa_pub, 1164 sshc->rsa, sshc->passphrase); 1165 if(rc == LIBSSH2_ERROR_EAGAIN) { 1166 break; 1167 } 1168 1169 Curl_safefree(sshc->rsa_pub); 1170 Curl_safefree(sshc->rsa); 1171 1172 if(rc == 0) { 1173 sshc->authed = TRUE; 1174 infof(data, "Initialized SSH public key authentication"); 1175 state(data, SSH_AUTH_DONE); 1176 } 1177 else { 1178 char *err_msg = NULL; 1179 char unknown[] = "Reason unknown (-1)"; 1180 if(rc == -1) { 1181 /* No error message has been set and the last set error message, if 1182 any, is from a previous error so ignore it. #11837 */ 1183 err_msg = unknown; 1184 } 1185 else { 1186 (void)libssh2_session_last_error(sshc->ssh_session, 1187 &err_msg, NULL, 0); 1188 } 1189 infof(data, "SSH public key authentication failed: %s", err_msg); 1190 state(data, SSH_AUTH_PASS_INIT); 1191 rc = 0; /* clear rc and continue */ 1192 } 1193 break; 1194 1195 case SSH_AUTH_PASS_INIT: 1196 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && 1197 (strstr(sshc->authlist, "password") != NULL)) { 1198 state(data, SSH_AUTH_PASS); 1199 } 1200 else { 1201 state(data, SSH_AUTH_HOST_INIT); 1202 rc = 0; /* clear rc and continue */ 1203 } 1204 break; 1205 1206 case SSH_AUTH_PASS: 1207 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user, 1208 curlx_uztoui(strlen(conn->user)), 1209 conn->passwd, 1210 curlx_uztoui(strlen(conn->passwd)), 1211 NULL); 1212 if(rc == LIBSSH2_ERROR_EAGAIN) { 1213 break; 1214 } 1215 if(rc == 0) { 1216 sshc->authed = TRUE; 1217 infof(data, "Initialized password authentication"); 1218 state(data, SSH_AUTH_DONE); 1219 } 1220 else { 1221 state(data, SSH_AUTH_HOST_INIT); 1222 rc = 0; /* clear rc and continue */ 1223 } 1224 break; 1225 1226 case SSH_AUTH_HOST_INIT: 1227 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && 1228 (strstr(sshc->authlist, "hostbased") != NULL)) { 1229 state(data, SSH_AUTH_HOST); 1230 } 1231 else { 1232 state(data, SSH_AUTH_AGENT_INIT); 1233 } 1234 break; 1235 1236 case SSH_AUTH_HOST: 1237 state(data, SSH_AUTH_AGENT_INIT); 1238 break; 1239 1240 case SSH_AUTH_AGENT_INIT: 1241#ifdef HAVE_LIBSSH2_AGENT_API 1242 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) 1243 && (strstr(sshc->authlist, "publickey") != NULL)) { 1244 1245 /* Connect to the ssh-agent */ 1246 /* The agent could be shared by a curl thread i believe 1247 but nothing obvious as keys can be added/removed at any time */ 1248 if(!sshc->ssh_agent) { 1249 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session); 1250 if(!sshc->ssh_agent) { 1251 infof(data, "Could not create agent object"); 1252 1253 state(data, SSH_AUTH_KEY_INIT); 1254 break; 1255 } 1256 } 1257 1258 rc = libssh2_agent_connect(sshc->ssh_agent); 1259 if(rc == LIBSSH2_ERROR_EAGAIN) 1260 break; 1261 if(rc < 0) { 1262 infof(data, "Failure connecting to agent"); 1263 state(data, SSH_AUTH_KEY_INIT); 1264 rc = 0; /* clear rc and continue */ 1265 } 1266 else { 1267 state(data, SSH_AUTH_AGENT_LIST); 1268 } 1269 } 1270 else 1271#endif /* HAVE_LIBSSH2_AGENT_API */ 1272 state(data, SSH_AUTH_KEY_INIT); 1273 break; 1274 1275 case SSH_AUTH_AGENT_LIST: 1276#ifdef HAVE_LIBSSH2_AGENT_API 1277 rc = libssh2_agent_list_identities(sshc->ssh_agent); 1278 1279 if(rc == LIBSSH2_ERROR_EAGAIN) 1280 break; 1281 if(rc < 0) { 1282 infof(data, "Failure requesting identities to agent"); 1283 state(data, SSH_AUTH_KEY_INIT); 1284 rc = 0; /* clear rc and continue */ 1285 } 1286 else { 1287 state(data, SSH_AUTH_AGENT); 1288 sshc->sshagent_prev_identity = NULL; 1289 } 1290#endif 1291 break; 1292 1293 case SSH_AUTH_AGENT: 1294#ifdef HAVE_LIBSSH2_AGENT_API 1295 /* as prev_identity evolves only after an identity user auth finished we 1296 can safely request it again as long as EAGAIN is returned here or by 1297 libssh2_agent_userauth */ 1298 rc = libssh2_agent_get_identity(sshc->ssh_agent, 1299 &sshc->sshagent_identity, 1300 sshc->sshagent_prev_identity); 1301 if(rc == LIBSSH2_ERROR_EAGAIN) 1302 break; 1303 1304 if(rc == 0) { 1305 rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user, 1306 sshc->sshagent_identity); 1307 1308 if(rc < 0) { 1309 if(rc != LIBSSH2_ERROR_EAGAIN) { 1310 /* tried and failed? go to next identity */ 1311 sshc->sshagent_prev_identity = sshc->sshagent_identity; 1312 } 1313 break; 1314 } 1315 } 1316 1317 if(rc < 0) 1318 infof(data, "Failure requesting identities to agent"); 1319 else if(rc == 1) 1320 infof(data, "No identity would match"); 1321 1322 if(rc == LIBSSH2_ERROR_NONE) { 1323 sshc->authed = TRUE; 1324 infof(data, "Agent based authentication successful"); 1325 state(data, SSH_AUTH_DONE); 1326 } 1327 else { 1328 state(data, SSH_AUTH_KEY_INIT); 1329 rc = 0; /* clear rc and continue */ 1330 } 1331#endif 1332 break; 1333 1334 case SSH_AUTH_KEY_INIT: 1335 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) 1336 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { 1337 state(data, SSH_AUTH_KEY); 1338 } 1339 else { 1340 state(data, SSH_AUTH_DONE); 1341 } 1342 break; 1343 1344 case SSH_AUTH_KEY: 1345 /* Authentication failed. Continue with keyboard-interactive now. */ 1346 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session, 1347 conn->user, 1348 curlx_uztoui( 1349 strlen(conn->user)), 1350 &kbd_callback); 1351 if(rc == LIBSSH2_ERROR_EAGAIN) { 1352 break; 1353 } 1354 if(rc == 0) { 1355 sshc->authed = TRUE; 1356 infof(data, "Initialized keyboard interactive authentication"); 1357 } 1358 state(data, SSH_AUTH_DONE); 1359 break; 1360 1361 case SSH_AUTH_DONE: 1362 if(!sshc->authed) { 1363 failf(data, "Authentication failure"); 1364 state(data, SSH_SESSION_FREE); 1365 sshc->actualcode = CURLE_LOGIN_DENIED; 1366 break; 1367 } 1368 1369 /* 1370 * At this point we have an authenticated ssh session. 1371 */ 1372 infof(data, "Authentication complete"); 1373 1374 Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */ 1375 1376 conn->sockfd = sock; 1377 conn->writesockfd = CURL_SOCKET_BAD; 1378 1379 if(conn->handler->protocol == CURLPROTO_SFTP) { 1380 state(data, SSH_SFTP_INIT); 1381 break; 1382 } 1383 infof(data, "SSH CONNECT phase done"); 1384 state(data, SSH_STOP); 1385 break; 1386 1387 case SSH_SFTP_INIT: 1388 /* 1389 * Start the libssh2 sftp session 1390 */ 1391 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); 1392 if(!sshc->sftp_session) { 1393 char *err_msg = NULL; 1394 if(libssh2_session_last_errno(sshc->ssh_session) == 1395 LIBSSH2_ERROR_EAGAIN) { 1396 rc = LIBSSH2_ERROR_EAGAIN; 1397 break; 1398 } 1399 1400 (void)libssh2_session_last_error(sshc->ssh_session, 1401 &err_msg, NULL, 0); 1402 failf(data, "Failure initializing sftp session: %s", err_msg); 1403 state(data, SSH_SESSION_FREE); 1404 sshc->actualcode = CURLE_FAILED_INIT; 1405 break; 1406 } 1407 state(data, SSH_SFTP_REALPATH); 1408 break; 1409 1410 case SSH_SFTP_REALPATH: 1411 { 1412 char tempHome[PATH_MAX]; 1413 1414 /* 1415 * Get the "home" directory 1416 */ 1417 rc = sftp_libssh2_realpath(sshc->sftp_session, ".", 1418 tempHome, PATH_MAX-1); 1419 if(rc == LIBSSH2_ERROR_EAGAIN) { 1420 break; 1421 } 1422 if(rc > 0) { 1423 /* It seems that this string is not always NULL terminated */ 1424 tempHome[rc] = '\0'; 1425 sshc->homedir = strdup(tempHome); 1426 if(!sshc->homedir) { 1427 state(data, SSH_SFTP_CLOSE); 1428 sshc->actualcode = CURLE_OUT_OF_MEMORY; 1429 break; 1430 } 1431 data->state.most_recent_ftp_entrypath = sshc->homedir; 1432 } 1433 else { 1434 /* Return the error type */ 1435 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1436 if(sftperr) 1437 result = sftp_libssh2_error_to_CURLE(sftperr); 1438 else 1439 /* in this case, the error wasn't in the SFTP level but for example 1440 a time-out or similar */ 1441 result = CURLE_SSH; 1442 sshc->actualcode = result; 1443 DEBUGF(infof(data, "error = %lu makes libcurl = %d", 1444 sftperr, (int)result)); 1445 state(data, SSH_STOP); 1446 break; 1447 } 1448 } 1449 /* This is the last step in the SFTP connect phase. Do note that while 1450 we get the homedir here, we get the "workingpath" in the DO action 1451 since the homedir will remain the same between request but the 1452 working path will not. */ 1453 DEBUGF(infof(data, "SSH CONNECT phase done")); 1454 state(data, SSH_STOP); 1455 break; 1456 1457 case SSH_SFTP_QUOTE_INIT: 1458 1459 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); 1460 if(result) { 1461 sshc->actualcode = result; 1462 state(data, SSH_STOP); 1463 break; 1464 } 1465 1466 if(data->set.quote) { 1467 infof(data, "Sending quote commands"); 1468 sshc->quote_item = data->set.quote; 1469 state(data, SSH_SFTP_QUOTE); 1470 } 1471 else { 1472 state(data, SSH_SFTP_GETINFO); 1473 } 1474 break; 1475 1476 case SSH_SFTP_POSTQUOTE_INIT: 1477 if(data->set.postquote) { 1478 infof(data, "Sending quote commands"); 1479 sshc->quote_item = data->set.postquote; 1480 state(data, SSH_SFTP_QUOTE); 1481 } 1482 else { 1483 state(data, SSH_STOP); 1484 } 1485 break; 1486 1487 case SSH_SFTP_QUOTE: 1488 /* Send any quote commands */ 1489 { 1490 const char *cp; 1491 1492 /* 1493 * Support some of the "FTP" commands 1494 * 1495 * 'sshc->quote_item' is already verified to be non-NULL before it 1496 * switched to this state. 1497 */ 1498 char *cmd = sshc->quote_item->data; 1499 sshc->acceptfail = FALSE; 1500 1501 /* if a command starts with an asterisk, which a legal SFTP command never 1502 can, the command will be allowed to fail without it causing any 1503 aborts or cancels etc. It will cause libcurl to act as if the command 1504 is successful, whatever the server responds. */ 1505 1506 if(cmd[0] == '*') { 1507 cmd++; 1508 sshc->acceptfail = TRUE; 1509 } 1510 1511 if(strcasecompare("pwd", cmd)) { 1512 /* output debug output if that is requested */ 1513 char *tmp = aprintf("257 \"%s\" is current directory.\n", 1514 sshp->path); 1515 if(!tmp) { 1516 result = CURLE_OUT_OF_MEMORY; 1517 state(data, SSH_SFTP_CLOSE); 1518 sshc->nextstate = SSH_NO_STATE; 1519 break; 1520 } 1521 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4); 1522 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); 1523 1524 /* this sends an FTP-like "header" to the header callback so that the 1525 current directory can be read very similar to how it is read when 1526 using ordinary FTP. */ 1527 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); 1528 free(tmp); 1529 if(result) { 1530 state(data, SSH_SFTP_CLOSE); 1531 sshc->nextstate = SSH_NO_STATE; 1532 sshc->actualcode = result; 1533 } 1534 else 1535 state(data, SSH_SFTP_NEXT_QUOTE); 1536 break; 1537 } 1538 1539 /* 1540 * the arguments following the command must be separated from the 1541 * command with a space so we can check for it unconditionally 1542 */ 1543 cp = strchr(cmd, ' '); 1544 if(!cp) { 1545 failf(data, "Syntax error command '%s', missing parameter", 1546 cmd); 1547 state(data, SSH_SFTP_CLOSE); 1548 sshc->nextstate = SSH_NO_STATE; 1549 sshc->actualcode = CURLE_QUOTE_ERROR; 1550 break; 1551 } 1552 1553 /* 1554 * also, every command takes at least one argument so we get that 1555 * first argument right now 1556 */ 1557 result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); 1558 if(result) { 1559 if(result == CURLE_OUT_OF_MEMORY) 1560 failf(data, "Out of memory"); 1561 else 1562 failf(data, "Syntax error: Bad first parameter to '%s'", cmd); 1563 state(data, SSH_SFTP_CLOSE); 1564 sshc->nextstate = SSH_NO_STATE; 1565 sshc->actualcode = result; 1566 break; 1567 } 1568 1569 /* 1570 * SFTP is a binary protocol, so we don't send text commands 1571 * to the server. Instead, we scan for commands used by 1572 * OpenSSH's sftp program and call the appropriate libssh2 1573 * functions. 1574 */ 1575 if(strncasecompare(cmd, "chgrp ", 6) || 1576 strncasecompare(cmd, "chmod ", 6) || 1577 strncasecompare(cmd, "chown ", 6) || 1578 strncasecompare(cmd, "atime ", 6) || 1579 strncasecompare(cmd, "mtime ", 6)) { 1580 /* attribute change */ 1581 1582 /* sshc->quote_path1 contains the mode to set */ 1583 /* get the destination */ 1584 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); 1585 if(result) { 1586 if(result == CURLE_OUT_OF_MEMORY) 1587 failf(data, "Out of memory"); 1588 else 1589 failf(data, "Syntax error in %s: Bad second parameter", cmd); 1590 Curl_safefree(sshc->quote_path1); 1591 state(data, SSH_SFTP_CLOSE); 1592 sshc->nextstate = SSH_NO_STATE; 1593 sshc->actualcode = result; 1594 break; 1595 } 1596 memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); 1597 state(data, SSH_SFTP_QUOTE_STAT); 1598 break; 1599 } 1600 if(strncasecompare(cmd, "ln ", 3) || 1601 strncasecompare(cmd, "symlink ", 8)) { 1602 /* symbolic linking */ 1603 /* sshc->quote_path1 is the source */ 1604 /* get the destination */ 1605 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); 1606 if(result) { 1607 if(result == CURLE_OUT_OF_MEMORY) 1608 failf(data, "Out of memory"); 1609 else 1610 failf(data, 1611 "Syntax error in ln/symlink: Bad second parameter"); 1612 Curl_safefree(sshc->quote_path1); 1613 state(data, SSH_SFTP_CLOSE); 1614 sshc->nextstate = SSH_NO_STATE; 1615 sshc->actualcode = result; 1616 break; 1617 } 1618 state(data, SSH_SFTP_QUOTE_SYMLINK); 1619 break; 1620 } 1621 else if(strncasecompare(cmd, "mkdir ", 6)) { 1622 /* create dir */ 1623 state(data, SSH_SFTP_QUOTE_MKDIR); 1624 break; 1625 } 1626 else if(strncasecompare(cmd, "rename ", 7)) { 1627 /* rename file */ 1628 /* first param is the source path */ 1629 /* second param is the dest. path */ 1630 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); 1631 if(result) { 1632 if(result == CURLE_OUT_OF_MEMORY) 1633 failf(data, "Out of memory"); 1634 else 1635 failf(data, "Syntax error in rename: Bad second parameter"); 1636 Curl_safefree(sshc->quote_path1); 1637 state(data, SSH_SFTP_CLOSE); 1638 sshc->nextstate = SSH_NO_STATE; 1639 sshc->actualcode = result; 1640 break; 1641 } 1642 state(data, SSH_SFTP_QUOTE_RENAME); 1643 break; 1644 } 1645 else if(strncasecompare(cmd, "rmdir ", 6)) { 1646 /* delete dir */ 1647 state(data, SSH_SFTP_QUOTE_RMDIR); 1648 break; 1649 } 1650 else if(strncasecompare(cmd, "rm ", 3)) { 1651 state(data, SSH_SFTP_QUOTE_UNLINK); 1652 break; 1653 } 1654#ifdef HAS_STATVFS_SUPPORT 1655 else if(strncasecompare(cmd, "statvfs ", 8)) { 1656 state(data, SSH_SFTP_QUOTE_STATVFS); 1657 break; 1658 } 1659#endif 1660 1661 failf(data, "Unknown SFTP command"); 1662 Curl_safefree(sshc->quote_path1); 1663 Curl_safefree(sshc->quote_path2); 1664 state(data, SSH_SFTP_CLOSE); 1665 sshc->nextstate = SSH_NO_STATE; 1666 sshc->actualcode = CURLE_QUOTE_ERROR; 1667 break; 1668 } 1669 1670 case SSH_SFTP_NEXT_QUOTE: 1671 Curl_safefree(sshc->quote_path1); 1672 Curl_safefree(sshc->quote_path2); 1673 1674 sshc->quote_item = sshc->quote_item->next; 1675 1676 if(sshc->quote_item) { 1677 state(data, SSH_SFTP_QUOTE); 1678 } 1679 else { 1680 if(sshc->nextstate != SSH_NO_STATE) { 1681 state(data, sshc->nextstate); 1682 sshc->nextstate = SSH_NO_STATE; 1683 } 1684 else { 1685 state(data, SSH_SFTP_GETINFO); 1686 } 1687 } 1688 break; 1689 1690 case SSH_SFTP_QUOTE_STAT: 1691 { 1692 char *cmd = sshc->quote_item->data; 1693 sshc->acceptfail = FALSE; 1694 1695 /* if a command starts with an asterisk, which a legal SFTP command never 1696 can, the command will be allowed to fail without it causing any 1697 aborts or cancels etc. It will cause libcurl to act as if the command 1698 is successful, whatever the server responds. */ 1699 1700 if(cmd[0] == '*') { 1701 cmd++; 1702 sshc->acceptfail = TRUE; 1703 } 1704 1705 if(!strncasecompare(cmd, "chmod", 5)) { 1706 /* Since chown and chgrp only set owner OR group but libssh2 wants to 1707 * set them both at once, we need to obtain the current ownership 1708 * first. This takes an extra protocol round trip. 1709 */ 1710 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, 1711 curlx_uztoui(strlen(sshc->quote_path2)), 1712 LIBSSH2_SFTP_STAT, 1713 &sshp->quote_attrs); 1714 if(rc == LIBSSH2_ERROR_EAGAIN) { 1715 break; 1716 } 1717 if(rc && !sshc->acceptfail) { /* get those attributes */ 1718 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1719 Curl_safefree(sshc->quote_path1); 1720 Curl_safefree(sshc->quote_path2); 1721 failf(data, "Attempt to get SFTP stats failed: %s", 1722 sftp_libssh2_strerror(sftperr)); 1723 state(data, SSH_SFTP_CLOSE); 1724 sshc->nextstate = SSH_NO_STATE; 1725 sshc->actualcode = CURLE_QUOTE_ERROR; 1726 break; 1727 } 1728 } 1729 1730 /* Now set the new attributes... */ 1731 if(strncasecompare(cmd, "chgrp", 5)) { 1732 sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); 1733 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; 1734 if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && 1735 !sshc->acceptfail) { 1736 Curl_safefree(sshc->quote_path1); 1737 Curl_safefree(sshc->quote_path2); 1738 failf(data, "Syntax error: chgrp gid not a number"); 1739 state(data, SSH_SFTP_CLOSE); 1740 sshc->nextstate = SSH_NO_STATE; 1741 sshc->actualcode = CURLE_QUOTE_ERROR; 1742 break; 1743 } 1744 } 1745 else if(strncasecompare(cmd, "chmod", 5)) { 1746 sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); 1747 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; 1748 /* permissions are octal */ 1749 if(sshp->quote_attrs.permissions == 0 && 1750 !ISDIGIT(sshc->quote_path1[0])) { 1751 Curl_safefree(sshc->quote_path1); 1752 Curl_safefree(sshc->quote_path2); 1753 failf(data, "Syntax error: chmod permissions not a number"); 1754 state(data, SSH_SFTP_CLOSE); 1755 sshc->nextstate = SSH_NO_STATE; 1756 sshc->actualcode = CURLE_QUOTE_ERROR; 1757 break; 1758 } 1759 } 1760 else if(strncasecompare(cmd, "chown", 5)) { 1761 sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); 1762 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; 1763 if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && 1764 !sshc->acceptfail) { 1765 Curl_safefree(sshc->quote_path1); 1766 Curl_safefree(sshc->quote_path2); 1767 failf(data, "Syntax error: chown uid not a number"); 1768 state(data, SSH_SFTP_CLOSE); 1769 sshc->nextstate = SSH_NO_STATE; 1770 sshc->actualcode = CURLE_QUOTE_ERROR; 1771 break; 1772 } 1773 } 1774 else if(strncasecompare(cmd, "atime", 5) || 1775 strncasecompare(cmd, "mtime", 5)) { 1776 time_t date = Curl_getdate_capped(sshc->quote_path1); 1777 bool fail = FALSE; 1778 1779 if(date == -1) { 1780 failf(data, "incorrect date format for %.*s", 5, cmd); 1781 fail = TRUE; 1782 } 1783#if SIZEOF_TIME_T > SIZEOF_LONG 1784 if(date > 0xffffffff) { 1785 /* if 'long' can't old >32bit, this date cannot be sent */ 1786 failf(data, "date overflow"); 1787 fail = TRUE; 1788 } 1789#endif 1790 if(fail) { 1791 Curl_safefree(sshc->quote_path1); 1792 Curl_safefree(sshc->quote_path2); 1793 state(data, SSH_SFTP_CLOSE); 1794 sshc->nextstate = SSH_NO_STATE; 1795 sshc->actualcode = CURLE_QUOTE_ERROR; 1796 break; 1797 } 1798 if(strncasecompare(cmd, "atime", 5)) 1799 sshp->quote_attrs.atime = (unsigned long)date; 1800 else /* mtime */ 1801 sshp->quote_attrs.mtime = (unsigned long)date; 1802 1803 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME; 1804 } 1805 1806 /* Now send the completed structure... */ 1807 state(data, SSH_SFTP_QUOTE_SETSTAT); 1808 break; 1809 } 1810 1811 case SSH_SFTP_QUOTE_SETSTAT: 1812 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, 1813 curlx_uztoui(strlen(sshc->quote_path2)), 1814 LIBSSH2_SFTP_SETSTAT, 1815 &sshp->quote_attrs); 1816 if(rc == LIBSSH2_ERROR_EAGAIN) { 1817 break; 1818 } 1819 if(rc && !sshc->acceptfail) { 1820 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1821 Curl_safefree(sshc->quote_path1); 1822 Curl_safefree(sshc->quote_path2); 1823 failf(data, "Attempt to set SFTP stats failed: %s", 1824 sftp_libssh2_strerror(sftperr)); 1825 state(data, SSH_SFTP_CLOSE); 1826 sshc->nextstate = SSH_NO_STATE; 1827 sshc->actualcode = CURLE_QUOTE_ERROR; 1828 break; 1829 } 1830 state(data, SSH_SFTP_NEXT_QUOTE); 1831 break; 1832 1833 case SSH_SFTP_QUOTE_SYMLINK: 1834 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, 1835 curlx_uztoui(strlen(sshc->quote_path1)), 1836 sshc->quote_path2, 1837 curlx_uztoui(strlen(sshc->quote_path2)), 1838 LIBSSH2_SFTP_SYMLINK); 1839 if(rc == LIBSSH2_ERROR_EAGAIN) { 1840 break; 1841 } 1842 if(rc && !sshc->acceptfail) { 1843 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1844 Curl_safefree(sshc->quote_path1); 1845 Curl_safefree(sshc->quote_path2); 1846 failf(data, "symlink command failed: %s", 1847 sftp_libssh2_strerror(sftperr)); 1848 state(data, SSH_SFTP_CLOSE); 1849 sshc->nextstate = SSH_NO_STATE; 1850 sshc->actualcode = CURLE_QUOTE_ERROR; 1851 break; 1852 } 1853 state(data, SSH_SFTP_NEXT_QUOTE); 1854 break; 1855 1856 case SSH_SFTP_QUOTE_MKDIR: 1857 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, 1858 curlx_uztoui(strlen(sshc->quote_path1)), 1859 data->set.new_directory_perms); 1860 if(rc == LIBSSH2_ERROR_EAGAIN) { 1861 break; 1862 } 1863 if(rc && !sshc->acceptfail) { 1864 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1865 Curl_safefree(sshc->quote_path1); 1866 failf(data, "mkdir command failed: %s", 1867 sftp_libssh2_strerror(sftperr)); 1868 state(data, SSH_SFTP_CLOSE); 1869 sshc->nextstate = SSH_NO_STATE; 1870 sshc->actualcode = CURLE_QUOTE_ERROR; 1871 break; 1872 } 1873 state(data, SSH_SFTP_NEXT_QUOTE); 1874 break; 1875 1876 case SSH_SFTP_QUOTE_RENAME: 1877 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, 1878 curlx_uztoui(strlen(sshc->quote_path1)), 1879 sshc->quote_path2, 1880 curlx_uztoui(strlen(sshc->quote_path2)), 1881 LIBSSH2_SFTP_RENAME_OVERWRITE | 1882 LIBSSH2_SFTP_RENAME_ATOMIC | 1883 LIBSSH2_SFTP_RENAME_NATIVE); 1884 1885 if(rc == LIBSSH2_ERROR_EAGAIN) { 1886 break; 1887 } 1888 if(rc && !sshc->acceptfail) { 1889 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1890 Curl_safefree(sshc->quote_path1); 1891 Curl_safefree(sshc->quote_path2); 1892 failf(data, "rename command failed: %s", 1893 sftp_libssh2_strerror(sftperr)); 1894 state(data, SSH_SFTP_CLOSE); 1895 sshc->nextstate = SSH_NO_STATE; 1896 sshc->actualcode = CURLE_QUOTE_ERROR; 1897 break; 1898 } 1899 state(data, SSH_SFTP_NEXT_QUOTE); 1900 break; 1901 1902 case SSH_SFTP_QUOTE_RMDIR: 1903 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, 1904 curlx_uztoui(strlen(sshc->quote_path1))); 1905 if(rc == LIBSSH2_ERROR_EAGAIN) { 1906 break; 1907 } 1908 if(rc && !sshc->acceptfail) { 1909 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1910 Curl_safefree(sshc->quote_path1); 1911 failf(data, "rmdir command failed: %s", 1912 sftp_libssh2_strerror(sftperr)); 1913 state(data, SSH_SFTP_CLOSE); 1914 sshc->nextstate = SSH_NO_STATE; 1915 sshc->actualcode = CURLE_QUOTE_ERROR; 1916 break; 1917 } 1918 state(data, SSH_SFTP_NEXT_QUOTE); 1919 break; 1920 1921 case SSH_SFTP_QUOTE_UNLINK: 1922 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, 1923 curlx_uztoui(strlen(sshc->quote_path1))); 1924 if(rc == LIBSSH2_ERROR_EAGAIN) { 1925 break; 1926 } 1927 if(rc && !sshc->acceptfail) { 1928 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1929 Curl_safefree(sshc->quote_path1); 1930 failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr)); 1931 state(data, SSH_SFTP_CLOSE); 1932 sshc->nextstate = SSH_NO_STATE; 1933 sshc->actualcode = CURLE_QUOTE_ERROR; 1934 break; 1935 } 1936 state(data, SSH_SFTP_NEXT_QUOTE); 1937 break; 1938 1939#ifdef HAS_STATVFS_SUPPORT 1940 case SSH_SFTP_QUOTE_STATVFS: 1941 { 1942 LIBSSH2_SFTP_STATVFS statvfs; 1943 rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1, 1944 curlx_uztoui(strlen(sshc->quote_path1)), 1945 &statvfs); 1946 1947 if(rc == LIBSSH2_ERROR_EAGAIN) { 1948 break; 1949 } 1950 if(rc && !sshc->acceptfail) { 1951 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 1952 Curl_safefree(sshc->quote_path1); 1953 failf(data, "statvfs command failed: %s", 1954 sftp_libssh2_strerror(sftperr)); 1955 state(data, SSH_SFTP_CLOSE); 1956 sshc->nextstate = SSH_NO_STATE; 1957 sshc->actualcode = CURLE_QUOTE_ERROR; 1958 break; 1959 } 1960 else if(rc == 0) { 1961 #ifdef _MSC_VER 1962 #define CURL_LIBSSH2_VFS_SIZE_MASK "I64u" 1963 #else 1964 #define CURL_LIBSSH2_VFS_SIZE_MASK "llu" 1965 #endif 1966 char *tmp = aprintf("statvfs:\n" 1967 "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1968 "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1969 "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1970 "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1971 "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1972 "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1973 "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1974 "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1975 "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1976 "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n" 1977 "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n", 1978 statvfs.f_bsize, statvfs.f_frsize, 1979 statvfs.f_blocks, statvfs.f_bfree, 1980 statvfs.f_bavail, statvfs.f_files, 1981 statvfs.f_ffree, statvfs.f_favail, 1982 statvfs.f_fsid, statvfs.f_flag, 1983 statvfs.f_namemax); 1984 if(!tmp) { 1985 result = CURLE_OUT_OF_MEMORY; 1986 state(data, SSH_SFTP_CLOSE); 1987 sshc->nextstate = SSH_NO_STATE; 1988 break; 1989 } 1990 1991 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); 1992 free(tmp); 1993 if(result) { 1994 state(data, SSH_SFTP_CLOSE); 1995 sshc->nextstate = SSH_NO_STATE; 1996 sshc->actualcode = result; 1997 } 1998 } 1999 state(data, SSH_SFTP_NEXT_QUOTE); 2000 break; 2001 } 2002#endif 2003 case SSH_SFTP_GETINFO: 2004 { 2005 if(data->set.get_filetime) { 2006 state(data, SSH_SFTP_FILETIME); 2007 } 2008 else { 2009 state(data, SSH_SFTP_TRANS_INIT); 2010 } 2011 break; 2012 } 2013 2014 case SSH_SFTP_FILETIME: 2015 { 2016 LIBSSH2_SFTP_ATTRIBUTES attrs; 2017 2018 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, 2019 curlx_uztoui(strlen(sshp->path)), 2020 LIBSSH2_SFTP_STAT, &attrs); 2021 if(rc == LIBSSH2_ERROR_EAGAIN) { 2022 break; 2023 } 2024 if(rc == 0) { 2025 data->info.filetime = attrs.mtime; 2026 } 2027 2028 state(data, SSH_SFTP_TRANS_INIT); 2029 break; 2030 } 2031 2032 case SSH_SFTP_TRANS_INIT: 2033 if(data->state.upload) 2034 state(data, SSH_SFTP_UPLOAD_INIT); 2035 else { 2036 if(sshp->path[strlen(sshp->path)-1] == '/') 2037 state(data, SSH_SFTP_READDIR_INIT); 2038 else 2039 state(data, SSH_SFTP_DOWNLOAD_INIT); 2040 } 2041 break; 2042 2043 case SSH_SFTP_UPLOAD_INIT: 2044 { 2045 unsigned long flags; 2046 /* 2047 * NOTE!!! libssh2 requires that the destination path is a full path 2048 * that includes the destination file and name OR ends in a "/" 2049 * If this is not done the destination file will be named the 2050 * same name as the last directory in the path. 2051 */ 2052 2053 if(data->state.resume_from) { 2054 LIBSSH2_SFTP_ATTRIBUTES attrs; 2055 if(data->state.resume_from < 0) { 2056 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, 2057 curlx_uztoui(strlen(sshp->path)), 2058 LIBSSH2_SFTP_STAT, &attrs); 2059 if(rc == LIBSSH2_ERROR_EAGAIN) { 2060 break; 2061 } 2062 if(rc) { 2063 data->state.resume_from = 0; 2064 } 2065 else { 2066 curl_off_t size = attrs.filesize; 2067 if(size < 0) { 2068 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); 2069 return CURLE_BAD_DOWNLOAD_RESUME; 2070 } 2071 data->state.resume_from = attrs.filesize; 2072 } 2073 } 2074 } 2075 2076 if(data->set.remote_append) 2077 /* Try to open for append, but create if nonexisting */ 2078 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; 2079 else if(data->state.resume_from > 0) 2080 /* If we have restart position then open for append */ 2081 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; 2082 else 2083 /* Clear file before writing (normal behavior) */ 2084 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; 2085 2086 sshc->sftp_handle = 2087 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path, 2088 curlx_uztoui(strlen(sshp->path)), 2089 flags, data->set.new_file_perms, 2090 LIBSSH2_SFTP_OPENFILE); 2091 2092 if(!sshc->sftp_handle) { 2093 rc = libssh2_session_last_errno(sshc->ssh_session); 2094 2095 if(LIBSSH2_ERROR_EAGAIN == rc) 2096 break; 2097 2098 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) 2099 /* only when there was an SFTP protocol error can we extract 2100 the sftp error! */ 2101 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 2102 else 2103 sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */ 2104 2105 if(sshc->secondCreateDirs) { 2106 state(data, SSH_SFTP_CLOSE); 2107 sshc->actualcode = sftperr != LIBSSH2_FX_OK ? 2108 sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH; 2109 failf(data, "Creating the dir/file failed: %s", 2110 sftp_libssh2_strerror(sftperr)); 2111 break; 2112 } 2113 if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) || 2114 (sftperr == LIBSSH2_FX_FAILURE) || 2115 (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) && 2116 (data->set.ftp_create_missing_dirs && 2117 (strlen(sshp->path) > 1))) { 2118 /* try to create the path remotely */ 2119 rc = 0; /* clear rc and continue */ 2120 sshc->secondCreateDirs = 1; 2121 state(data, SSH_SFTP_CREATE_DIRS_INIT); 2122 break; 2123 } 2124 state(data, SSH_SFTP_CLOSE); 2125 sshc->actualcode = sftperr != LIBSSH2_FX_OK ? 2126 sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH; 2127 if(!sshc->actualcode) { 2128 /* Sometimes, for some reason libssh2_sftp_last_error() returns zero 2129 even though libssh2_sftp_open() failed previously! We need to 2130 work around that! */ 2131 sshc->actualcode = CURLE_SSH; 2132 sftperr = LIBSSH2_FX_OK; 2133 } 2134 failf(data, "Upload failed: %s (%lu/%d)", 2135 sftperr != LIBSSH2_FX_OK ? 2136 sftp_libssh2_strerror(sftperr):"ssh error", 2137 sftperr, rc); 2138 break; 2139 } 2140 2141 /* If we have a restart point then we need to seek to the correct 2142 position. */ 2143 if(data->state.resume_from > 0) { 2144 /* Let's read off the proper amount of bytes from the input. */ 2145 if(conn->seek_func) { 2146 Curl_set_in_callback(data, true); 2147 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, 2148 SEEK_SET); 2149 Curl_set_in_callback(data, false); 2150 } 2151 2152 if(seekerr != CURL_SEEKFUNC_OK) { 2153 curl_off_t passed = 0; 2154 2155 if(seekerr != CURL_SEEKFUNC_CANTSEEK) { 2156 failf(data, "Could not seek stream"); 2157 return CURLE_FTP_COULDNT_USE_REST; 2158 } 2159 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ 2160 do { 2161 char scratch[4*1024]; 2162 size_t readthisamountnow = 2163 (data->state.resume_from - passed > 2164 (curl_off_t)sizeof(scratch)) ? 2165 sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed); 2166 2167 size_t actuallyread; 2168 Curl_set_in_callback(data, true); 2169 actuallyread = data->state.fread_func(scratch, 1, 2170 readthisamountnow, 2171 data->state.in); 2172 Curl_set_in_callback(data, false); 2173 2174 passed += actuallyread; 2175 if((actuallyread == 0) || (actuallyread > readthisamountnow)) { 2176 /* this checks for greater-than only to make sure that the 2177 CURL_READFUNC_ABORT return code still aborts */ 2178 failf(data, "Failed to read data"); 2179 return CURLE_FTP_COULDNT_USE_REST; 2180 } 2181 } while(passed < data->state.resume_from); 2182 } 2183 2184 /* now, decrease the size of the read */ 2185 if(data->state.infilesize > 0) { 2186 data->state.infilesize -= data->state.resume_from; 2187 data->req.size = data->state.infilesize; 2188 Curl_pgrsSetUploadSize(data, data->state.infilesize); 2189 } 2190 2191 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); 2192 } 2193 if(data->state.infilesize > 0) { 2194 data->req.size = data->state.infilesize; 2195 Curl_pgrsSetUploadSize(data, data->state.infilesize); 2196 } 2197 /* upload data */ 2198 Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); 2199 2200 /* not set by Curl_setup_transfer to preserve keepon bits */ 2201 conn->sockfd = conn->writesockfd; 2202 2203 if(result) { 2204 state(data, SSH_SFTP_CLOSE); 2205 sshc->actualcode = result; 2206 } 2207 else { 2208 /* store this original bitmask setup to use later on if we can't 2209 figure out a "real" bitmask */ 2210 sshc->orig_waitfor = data->req.keepon; 2211 2212 /* we want to use the _sending_ function even when the socket turns 2213 out readable as the underlying libssh2 sftp send function will deal 2214 with both accordingly */ 2215 data->state.select_bits = CURL_CSELECT_OUT; 2216 2217 /* since we don't really wait for anything at this point, we want the 2218 state machine to move on as soon as possible so we set a very short 2219 timeout here */ 2220 Curl_expire(data, 0, EXPIRE_RUN_NOW); 2221 2222 state(data, SSH_STOP); 2223 } 2224 break; 2225 } 2226 2227 case SSH_SFTP_CREATE_DIRS_INIT: 2228 if(strlen(sshp->path) > 1) { 2229 sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */ 2230 state(data, SSH_SFTP_CREATE_DIRS); 2231 } 2232 else { 2233 state(data, SSH_SFTP_UPLOAD_INIT); 2234 } 2235 break; 2236 2237 case SSH_SFTP_CREATE_DIRS: 2238 sshc->slash_pos = strchr(sshc->slash_pos, '/'); 2239 if(sshc->slash_pos) { 2240 *sshc->slash_pos = 0; 2241 2242 infof(data, "Creating directory '%s'", sshp->path); 2243 state(data, SSH_SFTP_CREATE_DIRS_MKDIR); 2244 break; 2245 } 2246 state(data, SSH_SFTP_UPLOAD_INIT); 2247 break; 2248 2249 case SSH_SFTP_CREATE_DIRS_MKDIR: 2250 /* 'mode' - parameter is preliminary - default to 0644 */ 2251 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path, 2252 curlx_uztoui(strlen(sshp->path)), 2253 data->set.new_directory_perms); 2254 if(rc == LIBSSH2_ERROR_EAGAIN) { 2255 break; 2256 } 2257 *sshc->slash_pos = '/'; 2258 ++sshc->slash_pos; 2259 if(rc < 0) { 2260 /* 2261 * Abort if failure wasn't that the dir already exists or the 2262 * permission was denied (creation might succeed further down the 2263 * path) - retry on unspecific FAILURE also 2264 */ 2265 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 2266 if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) && 2267 (sftperr != LIBSSH2_FX_FAILURE) && 2268 (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) { 2269 result = sftp_libssh2_error_to_CURLE(sftperr); 2270 state(data, SSH_SFTP_CLOSE); 2271 sshc->actualcode = result?result:CURLE_SSH; 2272 break; 2273 } 2274 rc = 0; /* clear rc and continue */ 2275 } 2276 state(data, SSH_SFTP_CREATE_DIRS); 2277 break; 2278 2279 case SSH_SFTP_READDIR_INIT: 2280 Curl_pgrsSetDownloadSize(data, -1); 2281 if(data->req.no_body) { 2282 state(data, SSH_STOP); 2283 break; 2284 } 2285 2286 /* 2287 * This is a directory that we are trying to get, so produce a directory 2288 * listing 2289 */ 2290 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, 2291 sshp->path, 2292 curlx_uztoui( 2293 strlen(sshp->path)), 2294 0, 0, LIBSSH2_SFTP_OPENDIR); 2295 if(!sshc->sftp_handle) { 2296 if(libssh2_session_last_errno(sshc->ssh_session) == 2297 LIBSSH2_ERROR_EAGAIN) { 2298 rc = LIBSSH2_ERROR_EAGAIN; 2299 break; 2300 } 2301 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 2302 failf(data, "Could not open directory for reading: %s", 2303 sftp_libssh2_strerror(sftperr)); 2304 state(data, SSH_SFTP_CLOSE); 2305 result = sftp_libssh2_error_to_CURLE(sftperr); 2306 sshc->actualcode = result?result:CURLE_SSH; 2307 break; 2308 } 2309 sshp->readdir_filename = malloc(PATH_MAX + 1); 2310 if(!sshp->readdir_filename) { 2311 state(data, SSH_SFTP_CLOSE); 2312 sshc->actualcode = CURLE_OUT_OF_MEMORY; 2313 break; 2314 } 2315 sshp->readdir_longentry = malloc(PATH_MAX + 1); 2316 if(!sshp->readdir_longentry) { 2317 Curl_safefree(sshp->readdir_filename); 2318 state(data, SSH_SFTP_CLOSE); 2319 sshc->actualcode = CURLE_OUT_OF_MEMORY; 2320 break; 2321 } 2322 Curl_dyn_init(&sshp->readdir, PATH_MAX * 2); 2323 state(data, SSH_SFTP_READDIR); 2324 break; 2325 2326 case SSH_SFTP_READDIR: 2327 rc = libssh2_sftp_readdir_ex(sshc->sftp_handle, 2328 sshp->readdir_filename, 2329 PATH_MAX, 2330 sshp->readdir_longentry, 2331 PATH_MAX, 2332 &sshp->readdir_attrs); 2333 if(rc == LIBSSH2_ERROR_EAGAIN) { 2334 break; 2335 } 2336 if(rc > 0) { 2337 readdir_len = (size_t) rc; 2338 sshp->readdir_filename[readdir_len] = '\0'; 2339 2340 if(data->set.list_only) { 2341 result = Curl_client_write(data, CLIENTWRITE_BODY, 2342 sshp->readdir_filename, 2343 readdir_len); 2344 if(!result) 2345 result = Curl_client_write(data, CLIENTWRITE_BODY, 2346 (char *)"\n", 1); 2347 if(result) { 2348 state(data, SSH_STOP); 2349 break; 2350 } 2351 2352 } 2353 else { 2354 result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry); 2355 2356 if(!result) { 2357 if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && 2358 ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == 2359 LIBSSH2_SFTP_S_IFLNK)) { 2360 Curl_dyn_init(&sshp->readdir_link, PATH_MAX); 2361 result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path, 2362 sshp->readdir_filename); 2363 state(data, SSH_SFTP_READDIR_LINK); 2364 if(!result) 2365 break; 2366 } 2367 else { 2368 state(data, SSH_SFTP_READDIR_BOTTOM); 2369 break; 2370 } 2371 } 2372 sshc->actualcode = result; 2373 state(data, SSH_SFTP_CLOSE); 2374 break; 2375 } 2376 } 2377 else if(rc == 0) { 2378 Curl_safefree(sshp->readdir_filename); 2379 Curl_safefree(sshp->readdir_longentry); 2380 state(data, SSH_SFTP_READDIR_DONE); 2381 break; 2382 } 2383 else if(rc < 0) { 2384 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 2385 result = sftp_libssh2_error_to_CURLE(sftperr); 2386 sshc->actualcode = result?result:CURLE_SSH; 2387 failf(data, "Could not open remote file for reading: %s :: %d", 2388 sftp_libssh2_strerror(sftperr), 2389 libssh2_session_last_errno(sshc->ssh_session)); 2390 Curl_safefree(sshp->readdir_filename); 2391 Curl_safefree(sshp->readdir_longentry); 2392 state(data, SSH_SFTP_CLOSE); 2393 break; 2394 } 2395 break; 2396 2397 case SSH_SFTP_READDIR_LINK: 2398 rc = 2399 libssh2_sftp_symlink_ex(sshc->sftp_session, 2400 Curl_dyn_ptr(&sshp->readdir_link), 2401 (int)Curl_dyn_len(&sshp->readdir_link), 2402 sshp->readdir_filename, 2403 PATH_MAX, LIBSSH2_SFTP_READLINK); 2404 if(rc == LIBSSH2_ERROR_EAGAIN) { 2405 break; 2406 } 2407 Curl_dyn_free(&sshp->readdir_link); 2408 2409 /* append filename and extra output */ 2410 result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename); 2411 2412 if(result) { 2413 Curl_safefree(sshp->readdir_filename); 2414 Curl_safefree(sshp->readdir_longentry); 2415 state(data, SSH_SFTP_CLOSE); 2416 sshc->actualcode = result; 2417 break; 2418 } 2419 2420 state(data, SSH_SFTP_READDIR_BOTTOM); 2421 break; 2422 2423 case SSH_SFTP_READDIR_BOTTOM: 2424 result = Curl_dyn_addn(&sshp->readdir, "\n", 1); 2425 if(!result) 2426 result = Curl_client_write(data, CLIENTWRITE_BODY, 2427 Curl_dyn_ptr(&sshp->readdir), 2428 Curl_dyn_len(&sshp->readdir)); 2429 2430 if(result) { 2431 Curl_dyn_free(&sshp->readdir); 2432 state(data, SSH_STOP); 2433 } 2434 else { 2435 Curl_dyn_reset(&sshp->readdir); 2436 state(data, SSH_SFTP_READDIR); 2437 } 2438 break; 2439 2440 case SSH_SFTP_READDIR_DONE: 2441 if(libssh2_sftp_closedir(sshc->sftp_handle) == 2442 LIBSSH2_ERROR_EAGAIN) { 2443 rc = LIBSSH2_ERROR_EAGAIN; 2444 break; 2445 } 2446 sshc->sftp_handle = NULL; 2447 Curl_safefree(sshp->readdir_filename); 2448 Curl_safefree(sshp->readdir_longentry); 2449 2450 /* no data to transfer */ 2451 Curl_setup_transfer(data, -1, -1, FALSE, -1); 2452 state(data, SSH_STOP); 2453 break; 2454 2455 case SSH_SFTP_DOWNLOAD_INIT: 2456 /* 2457 * Work on getting the specified file 2458 */ 2459 sshc->sftp_handle = 2460 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path, 2461 curlx_uztoui(strlen(sshp->path)), 2462 LIBSSH2_FXF_READ, data->set.new_file_perms, 2463 LIBSSH2_SFTP_OPENFILE); 2464 if(!sshc->sftp_handle) { 2465 if(libssh2_session_last_errno(sshc->ssh_session) == 2466 LIBSSH2_ERROR_EAGAIN) { 2467 rc = LIBSSH2_ERROR_EAGAIN; 2468 break; 2469 } 2470 sftperr = libssh2_sftp_last_error(sshc->sftp_session); 2471 failf(data, "Could not open remote file for reading: %s", 2472 sftp_libssh2_strerror(sftperr)); 2473 state(data, SSH_SFTP_CLOSE); 2474 result = sftp_libssh2_error_to_CURLE(sftperr); 2475 sshc->actualcode = result?result:CURLE_SSH; 2476 break; 2477 } 2478 state(data, SSH_SFTP_DOWNLOAD_STAT); 2479 break; 2480 2481 case SSH_SFTP_DOWNLOAD_STAT: 2482 { 2483 LIBSSH2_SFTP_ATTRIBUTES attrs; 2484 2485 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, 2486 curlx_uztoui(strlen(sshp->path)), 2487 LIBSSH2_SFTP_STAT, &attrs); 2488 if(rc == LIBSSH2_ERROR_EAGAIN) { 2489 break; 2490 } 2491 if(rc || 2492 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) || 2493 (attrs.filesize == 0)) { 2494 /* 2495 * libssh2_sftp_open() didn't return an error, so maybe the server 2496 * just doesn't support stat() 2497 * OR the server doesn't return a file size with a stat() 2498 * OR file size is 0 2499 */ 2500 data->req.size = -1; 2501 data->req.maxdownload = -1; 2502 Curl_pgrsSetDownloadSize(data, -1); 2503 } 2504 else { 2505 curl_off_t size = attrs.filesize; 2506 2507 if(size < 0) { 2508 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); 2509 return CURLE_BAD_DOWNLOAD_RESUME; 2510 } 2511 if(data->state.use_range) { 2512 curl_off_t from, to; 2513 char *ptr; 2514 char *ptr2; 2515 CURLofft to_t; 2516 CURLofft from_t; 2517 2518 from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from); 2519 if(from_t == CURL_OFFT_FLOW) 2520 return CURLE_RANGE_ERROR; 2521 while(*ptr && (ISBLANK(*ptr) || (*ptr == '-'))) 2522 ptr++; 2523 to_t = curlx_strtoofft(ptr, &ptr2, 10, &to); 2524 if(to_t == CURL_OFFT_FLOW) 2525 return CURLE_RANGE_ERROR; 2526 if((to_t == CURL_OFFT_INVAL) /* no "to" value given */ 2527 || (to >= size)) { 2528 to = size - 1; 2529 } 2530 if(from_t) { 2531 /* from is relative to end of file */ 2532 from = size - to; 2533 to = size - 1; 2534 } 2535 if(from > size) { 2536 failf(data, "Offset (%" 2537 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" 2538 CURL_FORMAT_CURL_OFF_T ")", from, 2539 (curl_off_t)attrs.filesize); 2540 return CURLE_BAD_DOWNLOAD_RESUME; 2541 } 2542 if(from > to) { 2543 from = to; 2544 size = 0; 2545 } 2546 else { 2547 size = to - from + 1; 2548 } 2549 2550 SFTP_SEEK(sshc->sftp_handle, from); 2551 } 2552 data->req.size = size; 2553 data->req.maxdownload = size; 2554 Curl_pgrsSetDownloadSize(data, size); 2555 } 2556 2557 /* We can resume if we can seek to the resume position */ 2558 if(data->state.resume_from) { 2559 if(data->state.resume_from < 0) { 2560 /* We're supposed to download the last abs(from) bytes */ 2561 if((curl_off_t)attrs.filesize < -data->state.resume_from) { 2562 failf(data, "Offset (%" 2563 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" 2564 CURL_FORMAT_CURL_OFF_T ")", 2565 data->state.resume_from, (curl_off_t)attrs.filesize); 2566 return CURLE_BAD_DOWNLOAD_RESUME; 2567 } 2568 /* download from where? */ 2569 data->state.resume_from += attrs.filesize; 2570 } 2571 else { 2572 if((curl_off_t)attrs.filesize < data->state.resume_from) { 2573 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T 2574 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", 2575 data->state.resume_from, (curl_off_t)attrs.filesize); 2576 return CURLE_BAD_DOWNLOAD_RESUME; 2577 } 2578 } 2579 /* Now store the number of bytes we are expected to download */ 2580 data->req.size = attrs.filesize - data->state.resume_from; 2581 data->req.maxdownload = attrs.filesize - data->state.resume_from; 2582 Curl_pgrsSetDownloadSize(data, 2583 attrs.filesize - data->state.resume_from); 2584 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); 2585 } 2586 } 2587 2588 /* Setup the actual download */ 2589 if(data->req.size == 0) { 2590 /* no data to transfer */ 2591 Curl_setup_transfer(data, -1, -1, FALSE, -1); 2592 infof(data, "File already completely downloaded"); 2593 state(data, SSH_STOP); 2594 break; 2595 } 2596 Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); 2597 2598 /* not set by Curl_setup_transfer to preserve keepon bits */ 2599 conn->writesockfd = conn->sockfd; 2600 2601 /* we want to use the _receiving_ function even when the socket turns 2602 out writableable as the underlying libssh2 recv function will deal 2603 with both accordingly */ 2604 data->state.select_bits = CURL_CSELECT_IN; 2605 2606 if(result) { 2607 /* this should never occur; the close state should be entered 2608 at the time the error occurs */ 2609 state(data, SSH_SFTP_CLOSE); 2610 sshc->actualcode = result; 2611 } 2612 else { 2613 state(data, SSH_STOP); 2614 } 2615 break; 2616 2617 case SSH_SFTP_CLOSE: 2618 if(sshc->sftp_handle) { 2619 rc = libssh2_sftp_close(sshc->sftp_handle); 2620 if(rc == LIBSSH2_ERROR_EAGAIN) { 2621 break; 2622 } 2623 if(rc < 0) { 2624 char *err_msg = NULL; 2625 (void)libssh2_session_last_error(sshc->ssh_session, 2626 &err_msg, NULL, 0); 2627 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); 2628 } 2629 sshc->sftp_handle = NULL; 2630 } 2631 2632 Curl_safefree(sshp->path); 2633 2634 DEBUGF(infof(data, "SFTP DONE done")); 2635 2636 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT 2637 After nextstate is executed, the control should come back to 2638 SSH_SFTP_CLOSE to pass the correct result back */ 2639 if(sshc->nextstate != SSH_NO_STATE && 2640 sshc->nextstate != SSH_SFTP_CLOSE) { 2641 state(data, sshc->nextstate); 2642 sshc->nextstate = SSH_SFTP_CLOSE; 2643 } 2644 else { 2645 state(data, SSH_STOP); 2646 result = sshc->actualcode; 2647 } 2648 break; 2649 2650 case SSH_SFTP_SHUTDOWN: 2651 /* during times we get here due to a broken transfer and then the 2652 sftp_handle might not have been taken down so make sure that is done 2653 before we proceed */ 2654 2655 if(sshc->sftp_handle) { 2656 rc = libssh2_sftp_close(sshc->sftp_handle); 2657 if(rc == LIBSSH2_ERROR_EAGAIN) { 2658 break; 2659 } 2660 if(rc < 0) { 2661 char *err_msg = NULL; 2662 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, 2663 NULL, 0); 2664 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); 2665 } 2666 sshc->sftp_handle = NULL; 2667 } 2668 if(sshc->sftp_session) { 2669 rc = libssh2_sftp_shutdown(sshc->sftp_session); 2670 if(rc == LIBSSH2_ERROR_EAGAIN) { 2671 break; 2672 } 2673 if(rc < 0) { 2674 infof(data, "Failed to stop libssh2 sftp subsystem"); 2675 } 2676 sshc->sftp_session = NULL; 2677 } 2678 2679 Curl_safefree(sshc->homedir); 2680 data->state.most_recent_ftp_entrypath = NULL; 2681 2682 state(data, SSH_SESSION_DISCONNECT); 2683 break; 2684 2685 case SSH_SCP_TRANS_INIT: 2686 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); 2687 if(result) { 2688 sshc->actualcode = result; 2689 state(data, SSH_STOP); 2690 break; 2691 } 2692 2693 if(data->state.upload) { 2694 if(data->state.infilesize < 0) { 2695 failf(data, "SCP requires a known file size for upload"); 2696 sshc->actualcode = CURLE_UPLOAD_FAILED; 2697 state(data, SSH_SCP_CHANNEL_FREE); 2698 break; 2699 } 2700 state(data, SSH_SCP_UPLOAD_INIT); 2701 } 2702 else { 2703 state(data, SSH_SCP_DOWNLOAD_INIT); 2704 } 2705 break; 2706 2707 case SSH_SCP_UPLOAD_INIT: 2708 /* 2709 * libssh2 requires that the destination path is a full path that 2710 * includes the destination file and name OR ends in a "/" . If this is 2711 * not done the destination file will be named the same name as the last 2712 * directory in the path. 2713 */ 2714 sshc->ssh_channel = 2715 SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms, 2716 data->state.infilesize); 2717 if(!sshc->ssh_channel) { 2718 int ssh_err; 2719 char *err_msg = NULL; 2720 2721 if(libssh2_session_last_errno(sshc->ssh_session) == 2722 LIBSSH2_ERROR_EAGAIN) { 2723 rc = LIBSSH2_ERROR_EAGAIN; 2724 break; 2725 } 2726 2727 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, 2728 &err_msg, NULL, 0)); 2729 failf(data, "%s", err_msg); 2730 state(data, SSH_SCP_CHANNEL_FREE); 2731 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); 2732 /* Map generic errors to upload failed */ 2733 if(sshc->actualcode == CURLE_SSH || 2734 sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND) 2735 sshc->actualcode = CURLE_UPLOAD_FAILED; 2736 break; 2737 } 2738 2739 /* upload data */ 2740 data->req.size = data->state.infilesize; 2741 Curl_pgrsSetUploadSize(data, data->state.infilesize); 2742 Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); 2743 2744 /* not set by Curl_setup_transfer to preserve keepon bits */ 2745 conn->sockfd = conn->writesockfd; 2746 2747 if(result) { 2748 state(data, SSH_SCP_CHANNEL_FREE); 2749 sshc->actualcode = result; 2750 } 2751 else { 2752 /* store this original bitmask setup to use later on if we can't 2753 figure out a "real" bitmask */ 2754 sshc->orig_waitfor = data->req.keepon; 2755 2756 /* we want to use the _sending_ function even when the socket turns 2757 out readable as the underlying libssh2 scp send function will deal 2758 with both accordingly */ 2759 data->state.select_bits = CURL_CSELECT_OUT; 2760 2761 state(data, SSH_STOP); 2762 } 2763 break; 2764 2765 case SSH_SCP_DOWNLOAD_INIT: 2766 { 2767 curl_off_t bytecount; 2768 2769 /* 2770 * We must check the remote file; if it is a directory no values will 2771 * be set in sb 2772 */ 2773 2774 /* 2775 * If support for >2GB files exists, use it. 2776 */ 2777 2778 /* get a fresh new channel from the ssh layer */ 2779#if LIBSSH2_VERSION_NUM < 0x010700 2780 struct stat sb; 2781 memset(&sb, 0, sizeof(struct stat)); 2782 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, 2783 sshp->path, &sb); 2784#else 2785 libssh2_struct_stat sb; 2786 memset(&sb, 0, sizeof(libssh2_struct_stat)); 2787 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session, 2788 sshp->path, &sb); 2789#endif 2790 2791 if(!sshc->ssh_channel) { 2792 int ssh_err; 2793 char *err_msg = NULL; 2794 2795 if(libssh2_session_last_errno(sshc->ssh_session) == 2796 LIBSSH2_ERROR_EAGAIN) { 2797 rc = LIBSSH2_ERROR_EAGAIN; 2798 break; 2799 } 2800 2801 2802 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, 2803 &err_msg, NULL, 0)); 2804 failf(data, "%s", err_msg); 2805 state(data, SSH_SCP_CHANNEL_FREE); 2806 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); 2807 break; 2808 } 2809 2810 /* download data */ 2811 bytecount = (curl_off_t)sb.st_size; 2812 data->req.maxdownload = (curl_off_t)sb.st_size; 2813 Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); 2814 2815 /* not set by Curl_setup_transfer to preserve keepon bits */ 2816 conn->writesockfd = conn->sockfd; 2817 2818 /* we want to use the _receiving_ function even when the socket turns 2819 out writableable as the underlying libssh2 recv function will deal 2820 with both accordingly */ 2821 data->state.select_bits = CURL_CSELECT_IN; 2822 2823 if(result) { 2824 state(data, SSH_SCP_CHANNEL_FREE); 2825 sshc->actualcode = result; 2826 } 2827 else 2828 state(data, SSH_STOP); 2829 } 2830 break; 2831 2832 case SSH_SCP_DONE: 2833 if(data->state.upload) 2834 state(data, SSH_SCP_SEND_EOF); 2835 else 2836 state(data, SSH_SCP_CHANNEL_FREE); 2837 break; 2838 2839 case SSH_SCP_SEND_EOF: 2840 if(sshc->ssh_channel) { 2841 rc = libssh2_channel_send_eof(sshc->ssh_channel); 2842 if(rc == LIBSSH2_ERROR_EAGAIN) { 2843 break; 2844 } 2845 if(rc) { 2846 char *err_msg = NULL; 2847 (void)libssh2_session_last_error(sshc->ssh_session, 2848 &err_msg, NULL, 0); 2849 infof(data, "Failed to send libssh2 channel EOF: %d %s", 2850 rc, err_msg); 2851 } 2852 } 2853 state(data, SSH_SCP_WAIT_EOF); 2854 break; 2855 2856 case SSH_SCP_WAIT_EOF: 2857 if(sshc->ssh_channel) { 2858 rc = libssh2_channel_wait_eof(sshc->ssh_channel); 2859 if(rc == LIBSSH2_ERROR_EAGAIN) { 2860 break; 2861 } 2862 if(rc) { 2863 char *err_msg = NULL; 2864 (void)libssh2_session_last_error(sshc->ssh_session, 2865 &err_msg, NULL, 0); 2866 infof(data, "Failed to get channel EOF: %d %s", rc, err_msg); 2867 } 2868 } 2869 state(data, SSH_SCP_WAIT_CLOSE); 2870 break; 2871 2872 case SSH_SCP_WAIT_CLOSE: 2873 if(sshc->ssh_channel) { 2874 rc = libssh2_channel_wait_closed(sshc->ssh_channel); 2875 if(rc == LIBSSH2_ERROR_EAGAIN) { 2876 break; 2877 } 2878 if(rc) { 2879 char *err_msg = NULL; 2880 (void)libssh2_session_last_error(sshc->ssh_session, 2881 &err_msg, NULL, 0); 2882 infof(data, "Channel failed to close: %d %s", rc, err_msg); 2883 } 2884 } 2885 state(data, SSH_SCP_CHANNEL_FREE); 2886 break; 2887 2888 case SSH_SCP_CHANNEL_FREE: 2889 if(sshc->ssh_channel) { 2890 rc = libssh2_channel_free(sshc->ssh_channel); 2891 if(rc == LIBSSH2_ERROR_EAGAIN) { 2892 break; 2893 } 2894 if(rc < 0) { 2895 char *err_msg = NULL; 2896 (void)libssh2_session_last_error(sshc->ssh_session, 2897 &err_msg, NULL, 0); 2898 infof(data, "Failed to free libssh2 scp subsystem: %d %s", 2899 rc, err_msg); 2900 } 2901 sshc->ssh_channel = NULL; 2902 } 2903 DEBUGF(infof(data, "SCP DONE phase complete")); 2904#if 0 /* PREV */ 2905 state(data, SSH_SESSION_DISCONNECT); 2906#endif 2907 state(data, SSH_STOP); 2908 result = sshc->actualcode; 2909 break; 2910 2911 case SSH_SESSION_DISCONNECT: 2912 /* during weird times when we've been prematurely aborted, the channel 2913 is still alive when we reach this state and we MUST kill the channel 2914 properly first */ 2915 if(sshc->ssh_channel) { 2916 rc = libssh2_channel_free(sshc->ssh_channel); 2917 if(rc == LIBSSH2_ERROR_EAGAIN) { 2918 break; 2919 } 2920 if(rc < 0) { 2921 char *err_msg = NULL; 2922 (void)libssh2_session_last_error(sshc->ssh_session, 2923 &err_msg, NULL, 0); 2924 infof(data, "Failed to free libssh2 scp subsystem: %d %s", 2925 rc, err_msg); 2926 } 2927 sshc->ssh_channel = NULL; 2928 } 2929 2930 if(sshc->ssh_session) { 2931 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); 2932 if(rc == LIBSSH2_ERROR_EAGAIN) { 2933 break; 2934 } 2935 if(rc < 0) { 2936 char *err_msg = NULL; 2937 (void)libssh2_session_last_error(sshc->ssh_session, 2938 &err_msg, NULL, 0); 2939 infof(data, "Failed to disconnect libssh2 session: %d %s", 2940 rc, err_msg); 2941 } 2942 } 2943 2944 Curl_safefree(sshc->homedir); 2945 data->state.most_recent_ftp_entrypath = NULL; 2946 2947 state(data, SSH_SESSION_FREE); 2948 break; 2949 2950 case SSH_SESSION_FREE: 2951#ifdef HAVE_LIBSSH2_KNOWNHOST_API 2952 if(sshc->kh) { 2953 libssh2_knownhost_free(sshc->kh); 2954 sshc->kh = NULL; 2955 } 2956#endif 2957 2958#ifdef HAVE_LIBSSH2_AGENT_API 2959 if(sshc->ssh_agent) { 2960 rc = libssh2_agent_disconnect(sshc->ssh_agent); 2961 if(rc == LIBSSH2_ERROR_EAGAIN) { 2962 break; 2963 } 2964 if(rc < 0) { 2965 char *err_msg = NULL; 2966 (void)libssh2_session_last_error(sshc->ssh_session, 2967 &err_msg, NULL, 0); 2968 infof(data, "Failed to disconnect from libssh2 agent: %d %s", 2969 rc, err_msg); 2970 } 2971 libssh2_agent_free(sshc->ssh_agent); 2972 sshc->ssh_agent = NULL; 2973 2974 /* NB: there is no need to free identities, they are part of internal 2975 agent stuff */ 2976 sshc->sshagent_identity = NULL; 2977 sshc->sshagent_prev_identity = NULL; 2978 } 2979#endif 2980 2981 if(sshc->ssh_session) { 2982 rc = libssh2_session_free(sshc->ssh_session); 2983 if(rc == LIBSSH2_ERROR_EAGAIN) { 2984 break; 2985 } 2986 if(rc < 0) { 2987 char *err_msg = NULL; 2988 (void)libssh2_session_last_error(sshc->ssh_session, 2989 &err_msg, NULL, 0); 2990 infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg); 2991 } 2992 sshc->ssh_session = NULL; 2993 } 2994 2995 /* worst-case scenario cleanup */ 2996 2997 DEBUGASSERT(sshc->ssh_session == NULL); 2998 DEBUGASSERT(sshc->ssh_channel == NULL); 2999 DEBUGASSERT(sshc->sftp_session == NULL); 3000 DEBUGASSERT(sshc->sftp_handle == NULL); 3001#ifdef HAVE_LIBSSH2_KNOWNHOST_API 3002 DEBUGASSERT(sshc->kh == NULL); 3003#endif 3004#ifdef HAVE_LIBSSH2_AGENT_API 3005 DEBUGASSERT(sshc->ssh_agent == NULL); 3006#endif 3007 3008 Curl_safefree(sshc->rsa_pub); 3009 Curl_safefree(sshc->rsa); 3010 Curl_safefree(sshc->quote_path1); 3011 Curl_safefree(sshc->quote_path2); 3012 Curl_safefree(sshc->homedir); 3013 3014 /* the code we are about to return */ 3015 result = sshc->actualcode; 3016 3017 memset(sshc, 0, sizeof(struct ssh_conn)); 3018 3019 connclose(conn, "SSH session free"); 3020 sshc->state = SSH_SESSION_FREE; /* current */ 3021 sshc->nextstate = SSH_NO_STATE; 3022 state(data, SSH_STOP); 3023 break; 3024 3025 case SSH_QUIT: 3026 default: 3027 /* internal error */ 3028 sshc->nextstate = SSH_NO_STATE; 3029 state(data, SSH_STOP); 3030 break; 3031 } 3032 3033 } while(!rc && (sshc->state != SSH_STOP)); 3034 3035 if(rc == LIBSSH2_ERROR_EAGAIN) { 3036 /* we would block, we need to wait for the socket to be ready (in the 3037 right direction too)! */ 3038 *block = TRUE; 3039 } 3040 3041 return result; 3042} 3043 3044/* called by the multi interface to figure out what socket(s) to wait for and 3045 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ 3046static int ssh_getsock(struct Curl_easy *data, 3047 struct connectdata *conn, 3048 curl_socket_t *sock) 3049{ 3050 int bitmap = GETSOCK_BLANK; 3051 (void)data; 3052 3053 sock[0] = conn->sock[FIRSTSOCKET]; 3054 3055 if(conn->waitfor & KEEP_RECV) 3056 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); 3057 3058 if(conn->waitfor & KEEP_SEND) 3059 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); 3060 3061 return bitmap; 3062} 3063 3064/* 3065 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this 3066 * function is used to figure out in what direction and stores this info so 3067 * that the multi interface can take advantage of it. Make sure to call this 3068 * function in all cases so that when it _doesn't_ return EAGAIN we can 3069 * restore the default wait bits. 3070 */ 3071static void ssh_block2waitfor(struct Curl_easy *data, bool block) 3072{ 3073 struct connectdata *conn = data->conn; 3074 struct ssh_conn *sshc = &conn->proto.sshc; 3075 int dir = 0; 3076 if(block) { 3077 dir = libssh2_session_block_directions(sshc->ssh_session); 3078 if(dir) { 3079 /* translate the libssh2 define bits into our own bit defines */ 3080 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | 3081 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); 3082 } 3083 } 3084 if(!dir) 3085 /* It didn't block or libssh2 didn't reveal in which direction, put back 3086 the original set */ 3087 conn->waitfor = sshc->orig_waitfor; 3088} 3089 3090/* called repeatedly until done from multi.c */ 3091static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done) 3092{ 3093 struct connectdata *conn = data->conn; 3094 struct ssh_conn *sshc = &conn->proto.sshc; 3095 CURLcode result = CURLE_OK; 3096 bool block; /* we store the status and use that to provide a ssh_getsock() 3097 implementation */ 3098 do { 3099 result = ssh_statemach_act(data, &block); 3100 *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; 3101 /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then 3102 try again */ 3103 } while(!result && !*done && !block); 3104 ssh_block2waitfor(data, block); 3105 3106 return result; 3107} 3108 3109static CURLcode ssh_block_statemach(struct Curl_easy *data, 3110 struct connectdata *conn, 3111 bool disconnect) 3112{ 3113 struct ssh_conn *sshc = &conn->proto.sshc; 3114 CURLcode result = CURLE_OK; 3115 struct curltime dis = Curl_now(); 3116 3117 while((sshc->state != SSH_STOP) && !result) { 3118 bool block; 3119 timediff_t left = 1000; 3120 struct curltime now = Curl_now(); 3121 3122 result = ssh_statemach_act(data, &block); 3123 if(result) 3124 break; 3125 3126 if(!disconnect) { 3127 if(Curl_pgrsUpdate(data)) 3128 return CURLE_ABORTED_BY_CALLBACK; 3129 3130 result = Curl_speedcheck(data, now); 3131 if(result) 3132 break; 3133 3134 left = Curl_timeleft(data, NULL, FALSE); 3135 if(left < 0) { 3136 failf(data, "Operation timed out"); 3137 return CURLE_OPERATION_TIMEDOUT; 3138 } 3139 } 3140 else if(Curl_timediff(now, dis) > 1000) { 3141 /* disconnect timeout */ 3142 failf(data, "Disconnect timed out"); 3143 result = CURLE_OK; 3144 break; 3145 } 3146 3147 if(block) { 3148 int dir = libssh2_session_block_directions(sshc->ssh_session); 3149 curl_socket_t sock = conn->sock[FIRSTSOCKET]; 3150 curl_socket_t fd_read = CURL_SOCKET_BAD; 3151 curl_socket_t fd_write = CURL_SOCKET_BAD; 3152 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir) 3153 fd_read = sock; 3154 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) 3155 fd_write = sock; 3156 /* wait for the socket to become ready */ 3157 (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 3158 left>1000?1000:left); 3159 } 3160 } 3161 3162 return result; 3163} 3164 3165/* 3166 * SSH setup and connection 3167 */ 3168static CURLcode ssh_setup_connection(struct Curl_easy *data, 3169 struct connectdata *conn) 3170{ 3171 struct SSHPROTO *ssh; 3172 (void)conn; 3173 3174 data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); 3175 if(!ssh) 3176 return CURLE_OUT_OF_MEMORY; 3177 3178 return CURLE_OK; 3179} 3180 3181static Curl_recv scp_recv, sftp_recv; 3182static Curl_send scp_send, sftp_send; 3183 3184#ifndef CURL_DISABLE_PROXY 3185static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer, 3186 size_t length, int flags, void **abstract) 3187{ 3188 struct Curl_easy *data = (struct Curl_easy *)*abstract; 3189 ssize_t nread; 3190 CURLcode result; 3191 struct connectdata *conn = data->conn; 3192 Curl_recv *backup = conn->recv[0]; 3193 struct ssh_conn *ssh = &conn->proto.sshc; 3194 (void)flags; 3195 3196 /* swap in the TLS reader function for this call only, and then swap back 3197 the SSH one again */ 3198 conn->recv[0] = ssh->tls_recv; 3199 result = Curl_read(data, sock, buffer, length, &nread); 3200 conn->recv[0] = backup; 3201 if(result == CURLE_AGAIN) 3202 return -EAGAIN; /* magic return code for libssh2 */ 3203 else if(result) 3204 return -1; /* generic error */ 3205 Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread); 3206 return nread; 3207} 3208 3209static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, 3210 size_t length, int flags, void **abstract) 3211{ 3212 struct Curl_easy *data = (struct Curl_easy *)*abstract; 3213 ssize_t nwrite; 3214 CURLcode result; 3215 struct connectdata *conn = data->conn; 3216 Curl_send *backup = conn->send[0]; 3217 struct ssh_conn *ssh = &conn->proto.sshc; 3218 (void)flags; 3219 3220 /* swap in the TLS writer function for this call only, and then swap back 3221 the SSH one again */ 3222 conn->send[0] = ssh->tls_send; 3223 result = Curl_write(data, sock, buffer, length, &nwrite); 3224 conn->send[0] = backup; 3225 if(result == CURLE_AGAIN) 3226 return -EAGAIN; /* magic return code for libssh2 */ 3227 else if(result) 3228 return -1; /* error */ 3229 Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite); 3230 return nwrite; 3231} 3232#endif 3233 3234/* 3235 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to 3236 * do protocol-specific actions at connect-time. 3237 */ 3238static CURLcode ssh_connect(struct Curl_easy *data, bool *done) 3239{ 3240#ifdef CURL_LIBSSH2_DEBUG 3241 curl_socket_t sock; 3242#endif 3243 struct ssh_conn *sshc; 3244 CURLcode result; 3245 struct connectdata *conn = data->conn; 3246 3247 /* initialize per-handle data if not already */ 3248 if(!data->req.p.ssh) { 3249 result = ssh_setup_connection(data, conn); 3250 if(result) 3251 return result; 3252 } 3253 3254 /* We default to persistent connections. We set this already in this connect 3255 function to make the reuse checks properly be able to check this bit. */ 3256 connkeep(conn, "SSH default"); 3257 3258 sshc = &conn->proto.sshc; 3259 3260#ifdef CURL_LIBSSH2_DEBUG 3261 if(conn->user) { 3262 infof(data, "User: %s", conn->user); 3263 } 3264 if(conn->passwd) { 3265 infof(data, "Password: %s", conn->passwd); 3266 } 3267 sock = conn->sock[FIRSTSOCKET]; 3268#endif /* CURL_LIBSSH2_DEBUG */ 3269 3270 /* libcurl MUST to set custom memory functions so that the kbd_callback 3271 funciton's memory allocations can be properled freed */ 3272 sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, 3273 my_libssh2_free, 3274 my_libssh2_realloc, data); 3275 3276 if(!sshc->ssh_session) { 3277 failf(data, "Failure initialising ssh session"); 3278 return CURLE_FAILED_INIT; 3279 } 3280 3281#ifdef HAVE_LIBSSH2_VERSION 3282 /* Set the packet read timeout if the libssh2 version supports it */ 3283#if LIBSSH2_VERSION_NUM >= 0x010B00 3284 if(data->set.server_response_timeout > 0) { 3285 libssh2_session_set_read_timeout(sshc->ssh_session, 3286 data->set.server_response_timeout / 1000); 3287 } 3288#endif 3289#endif 3290 3291#ifndef CURL_DISABLE_PROXY 3292 if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { 3293 /* 3294 Setup libssh2 callbacks to make it read/write TLS from the socket. 3295 3296 ssize_t 3297 recvcb(libssh2_socket_t sock, void *buffer, size_t length, 3298 int flags, void **abstract); 3299 3300 ssize_t 3301 sendcb(libssh2_socket_t sock, const void *buffer, size_t length, 3302 int flags, void **abstract); 3303 3304 */ 3305#if LIBSSH2_VERSION_NUM >= 0x010b01 3306 infof(data, "Uses HTTPS proxy"); 3307 libssh2_session_callback_set2(sshc->ssh_session, 3308 LIBSSH2_CALLBACK_RECV, 3309 (libssh2_cb_generic *)ssh_tls_recv); 3310 libssh2_session_callback_set2(sshc->ssh_session, 3311 LIBSSH2_CALLBACK_SEND, 3312 (libssh2_cb_generic *)ssh_tls_send); 3313#else 3314 /* 3315 * This crazy union dance is here to avoid assigning a void pointer a 3316 * function pointer as it is invalid C. The problem is of course that 3317 * libssh2 has such an API... 3318 */ 3319 union receive { 3320 void *recvp; 3321 ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **); 3322 }; 3323 union transfer { 3324 void *sendp; 3325 ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **); 3326 }; 3327 union receive sshrecv; 3328 union transfer sshsend; 3329 3330 sshrecv.recvptr = ssh_tls_recv; 3331 sshsend.sendptr = ssh_tls_send; 3332 3333 infof(data, "Uses HTTPS proxy"); 3334 libssh2_session_callback_set(sshc->ssh_session, 3335 LIBSSH2_CALLBACK_RECV, sshrecv.recvp); 3336 libssh2_session_callback_set(sshc->ssh_session, 3337 LIBSSH2_CALLBACK_SEND, sshsend.sendp); 3338#endif 3339 3340 /* Store the underlying TLS recv/send function pointers to be used when 3341 reading from the proxy */ 3342 sshc->tls_recv = conn->recv[FIRSTSOCKET]; 3343 sshc->tls_send = conn->send[FIRSTSOCKET]; 3344 } 3345 3346#endif /* CURL_DISABLE_PROXY */ 3347 if(conn->handler->protocol & CURLPROTO_SCP) { 3348 conn->recv[FIRSTSOCKET] = scp_recv; 3349 conn->send[FIRSTSOCKET] = scp_send; 3350 } 3351 else { 3352 conn->recv[FIRSTSOCKET] = sftp_recv; 3353 conn->send[FIRSTSOCKET] = sftp_send; 3354 } 3355 3356 if(data->set.ssh_compression) { 3357#if LIBSSH2_VERSION_NUM >= 0x010208 3358 if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) 3359#endif 3360 infof(data, "Failed to enable compression for ssh session"); 3361 } 3362 3363#ifdef HAVE_LIBSSH2_KNOWNHOST_API 3364 if(data->set.str[STRING_SSH_KNOWNHOSTS]) { 3365 int rc; 3366 sshc->kh = libssh2_knownhost_init(sshc->ssh_session); 3367 if(!sshc->kh) { 3368 libssh2_session_free(sshc->ssh_session); 3369 sshc->ssh_session = NULL; 3370 return CURLE_FAILED_INIT; 3371 } 3372 3373 /* read all known hosts from there */ 3374 rc = libssh2_knownhost_readfile(sshc->kh, 3375 data->set.str[STRING_SSH_KNOWNHOSTS], 3376 LIBSSH2_KNOWNHOST_FILE_OPENSSH); 3377 if(rc < 0) 3378 infof(data, "Failed to read known hosts from %s", 3379 data->set.str[STRING_SSH_KNOWNHOSTS]); 3380 } 3381#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ 3382 3383#ifdef CURL_LIBSSH2_DEBUG 3384 libssh2_trace(sshc->ssh_session, ~0); 3385 infof(data, "SSH socket: %d", (int)sock); 3386#endif /* CURL_LIBSSH2_DEBUG */ 3387 3388 state(data, SSH_INIT); 3389 3390 result = ssh_multi_statemach(data, done); 3391 3392 return result; 3393} 3394 3395/* 3396 *********************************************************************** 3397 * 3398 * scp_perform() 3399 * 3400 * This is the actual DO function for SCP. Get a file according to 3401 * the options previously setup. 3402 */ 3403 3404static 3405CURLcode scp_perform(struct Curl_easy *data, 3406 bool *connected, 3407 bool *dophase_done) 3408{ 3409 CURLcode result = CURLE_OK; 3410 3411 DEBUGF(infof(data, "DO phase starts")); 3412 3413 *dophase_done = FALSE; /* not done yet */ 3414 3415 /* start the first command in the DO phase */ 3416 state(data, SSH_SCP_TRANS_INIT); 3417 3418 /* run the state-machine */ 3419 result = ssh_multi_statemach(data, dophase_done); 3420 3421 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); 3422 3423 if(*dophase_done) { 3424 DEBUGF(infof(data, "DO phase is complete")); 3425 } 3426 3427 return result; 3428} 3429 3430/* called from multi.c while DOing */ 3431static CURLcode scp_doing(struct Curl_easy *data, 3432 bool *dophase_done) 3433{ 3434 CURLcode result; 3435 result = ssh_multi_statemach(data, dophase_done); 3436 3437 if(*dophase_done) { 3438 DEBUGF(infof(data, "DO phase is complete")); 3439 } 3440 return result; 3441} 3442 3443/* 3444 * The DO function is generic for both protocols. There was previously two 3445 * separate ones but this way means less duplicated code. 3446 */ 3447 3448static CURLcode ssh_do(struct Curl_easy *data, bool *done) 3449{ 3450 CURLcode result; 3451 bool connected = 0; 3452 struct connectdata *conn = data->conn; 3453 struct ssh_conn *sshc = &conn->proto.sshc; 3454 3455 *done = FALSE; /* default to false */ 3456 3457 data->req.size = -1; /* make sure this is unknown at this point */ 3458 3459 sshc->actualcode = CURLE_OK; /* reset error code */ 3460 sshc->secondCreateDirs = 0; /* reset the create dir attempt state 3461 variable */ 3462 3463 Curl_pgrsSetUploadCounter(data, 0); 3464 Curl_pgrsSetDownloadCounter(data, 0); 3465 Curl_pgrsSetUploadSize(data, -1); 3466 Curl_pgrsSetDownloadSize(data, -1); 3467 3468 if(conn->handler->protocol & CURLPROTO_SCP) 3469 result = scp_perform(data, &connected, done); 3470 else 3471 result = sftp_perform(data, &connected, done); 3472 3473 return result; 3474} 3475 3476/* BLOCKING, but the function is using the state machine so the only reason 3477 this is still blocking is that the multi interface code has no support for 3478 disconnecting operations that takes a while */ 3479static CURLcode scp_disconnect(struct Curl_easy *data, 3480 struct connectdata *conn, 3481 bool dead_connection) 3482{ 3483 CURLcode result = CURLE_OK; 3484 struct ssh_conn *sshc = &conn->proto.sshc; 3485 (void) dead_connection; 3486 3487 if(sshc->ssh_session) { 3488 /* only if there's a session still around to use! */ 3489 state(data, SSH_SESSION_DISCONNECT); 3490 result = ssh_block_statemach(data, conn, TRUE); 3491 } 3492 3493 return result; 3494} 3495 3496/* generic done function for both SCP and SFTP called from their specific 3497 done functions */ 3498static CURLcode ssh_done(struct Curl_easy *data, CURLcode status) 3499{ 3500 CURLcode result = CURLE_OK; 3501 struct SSHPROTO *sshp = data->req.p.ssh; 3502 struct connectdata *conn = data->conn; 3503 3504 if(!status) 3505 /* run the state-machine */ 3506 result = ssh_block_statemach(data, conn, FALSE); 3507 else 3508 result = status; 3509 3510 Curl_safefree(sshp->path); 3511 Curl_safefree(sshp->readdir_filename); 3512 Curl_safefree(sshp->readdir_longentry); 3513 Curl_dyn_free(&sshp->readdir); 3514 3515 if(Curl_pgrsDone(data)) 3516 return CURLE_ABORTED_BY_CALLBACK; 3517 3518 data->req.keepon = 0; /* clear all bits */ 3519 return result; 3520} 3521 3522 3523static CURLcode scp_done(struct Curl_easy *data, CURLcode status, 3524 bool premature) 3525{ 3526 (void)premature; /* not used */ 3527 3528 if(!status) 3529 state(data, SSH_SCP_DONE); 3530 3531 return ssh_done(data, status); 3532 3533} 3534 3535static ssize_t scp_send(struct Curl_easy *data, int sockindex, 3536 const void *mem, size_t len, CURLcode *err) 3537{ 3538 ssize_t nwrite; 3539 struct connectdata *conn = data->conn; 3540 struct ssh_conn *sshc = &conn->proto.sshc; 3541 (void)sockindex; /* we only support SCP on the fixed known primary socket */ 3542 3543 /* libssh2_channel_write() returns int! */ 3544 nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len); 3545 3546 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 3547 3548 if(nwrite == LIBSSH2_ERROR_EAGAIN) { 3549 *err = CURLE_AGAIN; 3550 nwrite = 0; 3551 } 3552 else if(nwrite < LIBSSH2_ERROR_NONE) { 3553 *err = libssh2_session_error_to_CURLE((int)nwrite); 3554 nwrite = -1; 3555 } 3556 3557 return nwrite; 3558} 3559 3560static ssize_t scp_recv(struct Curl_easy *data, int sockindex, 3561 char *mem, size_t len, CURLcode *err) 3562{ 3563 ssize_t nread; 3564 struct connectdata *conn = data->conn; 3565 struct ssh_conn *sshc = &conn->proto.sshc; 3566 (void)sockindex; /* we only support SCP on the fixed known primary socket */ 3567 3568 /* libssh2_channel_read() returns int */ 3569 nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len); 3570 3571 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 3572 if(nread == LIBSSH2_ERROR_EAGAIN) { 3573 *err = CURLE_AGAIN; 3574 nread = -1; 3575 } 3576 3577 return nread; 3578} 3579 3580/* 3581 * =============== SFTP =============== 3582 */ 3583 3584/* 3585 *********************************************************************** 3586 * 3587 * sftp_perform() 3588 * 3589 * This is the actual DO function for SFTP. Get a file/directory according to 3590 * the options previously setup. 3591 */ 3592 3593static 3594CURLcode sftp_perform(struct Curl_easy *data, 3595 bool *connected, 3596 bool *dophase_done) 3597{ 3598 CURLcode result = CURLE_OK; 3599 3600 DEBUGF(infof(data, "DO phase starts")); 3601 3602 *dophase_done = FALSE; /* not done yet */ 3603 3604 /* start the first command in the DO phase */ 3605 state(data, SSH_SFTP_QUOTE_INIT); 3606 3607 /* run the state-machine */ 3608 result = ssh_multi_statemach(data, dophase_done); 3609 3610 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); 3611 3612 if(*dophase_done) { 3613 DEBUGF(infof(data, "DO phase is complete")); 3614 } 3615 3616 return result; 3617} 3618 3619/* called from multi.c while DOing */ 3620static CURLcode sftp_doing(struct Curl_easy *data, 3621 bool *dophase_done) 3622{ 3623 CURLcode result = ssh_multi_statemach(data, dophase_done); 3624 3625 if(*dophase_done) { 3626 DEBUGF(infof(data, "DO phase is complete")); 3627 } 3628 return result; 3629} 3630 3631/* BLOCKING, but the function is using the state machine so the only reason 3632 this is still blocking is that the multi interface code has no support for 3633 disconnecting operations that takes a while */ 3634static CURLcode sftp_disconnect(struct Curl_easy *data, 3635 struct connectdata *conn, bool dead_connection) 3636{ 3637 CURLcode result = CURLE_OK; 3638 struct ssh_conn *sshc = &conn->proto.sshc; 3639 (void) dead_connection; 3640 3641 DEBUGF(infof(data, "SSH DISCONNECT starts now")); 3642 3643 if(sshc->ssh_session) { 3644 /* only if there's a session still around to use! */ 3645 state(data, SSH_SFTP_SHUTDOWN); 3646 result = ssh_block_statemach(data, conn, TRUE); 3647 } 3648 3649 DEBUGF(infof(data, "SSH DISCONNECT is done")); 3650 3651 return result; 3652 3653} 3654 3655static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, 3656 bool premature) 3657{ 3658 struct connectdata *conn = data->conn; 3659 struct ssh_conn *sshc = &conn->proto.sshc; 3660 3661 if(!status) { 3662 /* Post quote commands are executed after the SFTP_CLOSE state to avoid 3663 errors that could happen due to open file handles during POSTQUOTE 3664 operation */ 3665 if(!premature && data->set.postquote && !conn->bits.retry) 3666 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; 3667 state(data, SSH_SFTP_CLOSE); 3668 } 3669 return ssh_done(data, status); 3670} 3671 3672/* return number of sent bytes */ 3673static ssize_t sftp_send(struct Curl_easy *data, int sockindex, 3674 const void *mem, size_t len, CURLcode *err) 3675{ 3676 ssize_t nwrite; 3677 struct connectdata *conn = data->conn; 3678 struct ssh_conn *sshc = &conn->proto.sshc; 3679 (void)sockindex; 3680 3681 nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len); 3682 3683 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 3684 3685 if(nwrite == LIBSSH2_ERROR_EAGAIN) { 3686 *err = CURLE_AGAIN; 3687 nwrite = 0; 3688 } 3689 else if(nwrite < LIBSSH2_ERROR_NONE) { 3690 *err = libssh2_session_error_to_CURLE((int)nwrite); 3691 nwrite = -1; 3692 } 3693 3694 return nwrite; 3695} 3696 3697/* 3698 * Return number of received (decrypted) bytes 3699 * or <0 on error 3700 */ 3701static ssize_t sftp_recv(struct Curl_easy *data, int sockindex, 3702 char *mem, size_t len, CURLcode *err) 3703{ 3704 ssize_t nread; 3705 struct connectdata *conn = data->conn; 3706 struct ssh_conn *sshc = &conn->proto.sshc; 3707 (void)sockindex; 3708 3709 nread = libssh2_sftp_read(sshc->sftp_handle, mem, len); 3710 3711 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); 3712 3713 if(nread == LIBSSH2_ERROR_EAGAIN) { 3714 *err = CURLE_AGAIN; 3715 nread = -1; 3716 3717 } 3718 else if(nread < 0) { 3719 *err = libssh2_session_error_to_CURLE((int)nread); 3720 } 3721 return nread; 3722} 3723 3724static const char *sftp_libssh2_strerror(unsigned long err) 3725{ 3726 switch(err) { 3727 case LIBSSH2_FX_NO_SUCH_FILE: 3728 return "No such file or directory"; 3729 3730 case LIBSSH2_FX_PERMISSION_DENIED: 3731 return "Permission denied"; 3732 3733 case LIBSSH2_FX_FAILURE: 3734 return "Operation failed"; 3735 3736 case LIBSSH2_FX_BAD_MESSAGE: 3737 return "Bad message from SFTP server"; 3738 3739 case LIBSSH2_FX_NO_CONNECTION: 3740 return "Not connected to SFTP server"; 3741 3742 case LIBSSH2_FX_CONNECTION_LOST: 3743 return "Connection to SFTP server lost"; 3744 3745 case LIBSSH2_FX_OP_UNSUPPORTED: 3746 return "Operation not supported by SFTP server"; 3747 3748 case LIBSSH2_FX_INVALID_HANDLE: 3749 return "Invalid handle"; 3750 3751 case LIBSSH2_FX_NO_SUCH_PATH: 3752 return "No such file or directory"; 3753 3754 case LIBSSH2_FX_FILE_ALREADY_EXISTS: 3755 return "File already exists"; 3756 3757 case LIBSSH2_FX_WRITE_PROTECT: 3758 return "File is write protected"; 3759 3760 case LIBSSH2_FX_NO_MEDIA: 3761 return "No media"; 3762 3763 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: 3764 return "Disk full"; 3765 3766 case LIBSSH2_FX_QUOTA_EXCEEDED: 3767 return "User quota exceeded"; 3768 3769 case LIBSSH2_FX_UNKNOWN_PRINCIPLE: 3770 return "Unknown principle"; 3771 3772 case LIBSSH2_FX_LOCK_CONFlICT: 3773 return "File lock conflict"; 3774 3775 case LIBSSH2_FX_DIR_NOT_EMPTY: 3776 return "Directory not empty"; 3777 3778 case LIBSSH2_FX_NOT_A_DIRECTORY: 3779 return "Not a directory"; 3780 3781 case LIBSSH2_FX_INVALID_FILENAME: 3782 return "Invalid filename"; 3783 3784 case LIBSSH2_FX_LINK_LOOP: 3785 return "Link points to itself"; 3786 } 3787 return "Unknown error in libssh2"; 3788} 3789 3790CURLcode Curl_ssh_init(void) 3791{ 3792#ifdef HAVE_LIBSSH2_INIT 3793 if(libssh2_init(0)) { 3794 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); 3795 return CURLE_FAILED_INIT; 3796 } 3797#endif 3798 return CURLE_OK; 3799} 3800 3801void Curl_ssh_cleanup(void) 3802{ 3803#ifdef HAVE_LIBSSH2_EXIT 3804 (void)libssh2_exit(); 3805#endif 3806} 3807 3808void Curl_ssh_version(char *buffer, size_t buflen) 3809{ 3810 (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION); 3811} 3812 3813/* The SSH session is associated with the *CONNECTION* but the callback user 3814 * pointer is an easy handle pointer. This function allows us to reassign the 3815 * user pointer to the *CURRENT* (new) easy handle. 3816 */ 3817static void ssh_attach(struct Curl_easy *data, struct connectdata *conn) 3818{ 3819 DEBUGASSERT(data); 3820 DEBUGASSERT(conn); 3821 if(conn->handler->protocol & PROTO_FAMILY_SSH) { 3822 struct ssh_conn *sshc = &conn->proto.sshc; 3823 if(sshc->ssh_session) { 3824 /* only re-attach if the session already exists */ 3825 void **abstract = libssh2_session_abstract(sshc->ssh_session); 3826 *abstract = data; 3827 } 3828 } 3829} 3830#endif /* USE_LIBSSH2 */ 3831