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