1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * SPDX-License-Identifier: curl
23 ***************************************************************************/
25 /* #define CURL_LIBSSH2_DEBUG */
27 #include "curl_setup.h"
34 #include <libssh2_sftp.h>
40 #ifdef HAVE_NETINET_IN_H
41 #include <netinet/in.h>
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
47 #include <sys/utsname.h>
57 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
59 #define in_addr_t unsigned long
62 #include <curl/curl.h>
69 #include "http.h" /* for HTTP proxy tunnel stuff */
72 #include "speedcheck.h"
76 #include "vtls/vtls.h"
78 #include "inet_ntop.h"
79 #include "parsedate.h" /* for the week day and month names */
80 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
81 #include "strtoofft.h"
85 #include "curl_path.h"
88 #include <curl_base64.h> /* for base64 encoding/decoding */
89 #include <curl_sha256.h>
92 /* The last 3 #include files should be in this order */
93 #include "curl_printf.h"
94 #include "curl_memory.h"
97 #if LIBSSH2_VERSION_NUM >= 0x010206
98 /* libssh2_sftp_statvfs and friends were added in 1.2.6 */
99 #define HAS_STATVFS_SUPPORT 1
102 #define sftp_libssh2_realpath(s,p,t,m) \
103 libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
104 (t), (m), LIBSSH2_SFTP_REALPATH)
106 /* Local functions: */
107 static const char *sftp_libssh2_strerror(unsigned long err);
108 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
109 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
110 static LIBSSH2_FREE_FUNC(my_libssh2_free);
112 static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
113 static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
114 static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
115 static CURLcode ssh_do(struct Curl_easy *data, bool *done);
116 static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);
117 static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
118 static CURLcode scp_disconnect(struct Curl_easy *data,
119 struct connectdata *conn, bool dead_connection);
120 static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);
121 static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);
122 static CURLcode sftp_disconnect(struct Curl_easy *data,
123 struct connectdata *conn, bool dead);
124 static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
126 static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
127 curl_socket_t *sock);
128 static CURLcode ssh_setup_connection(struct Curl_easy *data,
129 struct connectdata *conn);
130 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn);
133 * SCP protocol handler.
136 const struct Curl_handler Curl_handler_scp = {
138 ssh_setup_connection, /* setup_connection */
141 ZERO_NULL, /* do_more */
142 ssh_connect, /* connect_it */
143 ssh_multi_statemach, /* connecting */
144 scp_doing, /* doing */
145 ssh_getsock, /* proto_getsock */
146 ssh_getsock, /* doing_getsock */
147 ZERO_NULL, /* domore_getsock */
148 ssh_getsock, /* perform_getsock */
149 scp_disconnect, /* disconnect */
150 ZERO_NULL, /* readwrite */
151 ZERO_NULL, /* connection_check */
153 PORT_SSH, /* defport */
154 CURLPROTO_SCP, /* protocol */
155 CURLPROTO_SCP, /* family */
156 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
157 | PROTOPT_NOURLQUERY /* flags */
162 * SFTP protocol handler.
165 const struct Curl_handler Curl_handler_sftp = {
167 ssh_setup_connection, /* setup_connection */
169 sftp_done, /* done */
170 ZERO_NULL, /* do_more */
171 ssh_connect, /* connect_it */
172 ssh_multi_statemach, /* connecting */
173 sftp_doing, /* doing */
174 ssh_getsock, /* proto_getsock */
175 ssh_getsock, /* doing_getsock */
176 ZERO_NULL, /* domore_getsock */
177 ssh_getsock, /* perform_getsock */
178 sftp_disconnect, /* disconnect */
179 ZERO_NULL, /* readwrite */
180 ZERO_NULL, /* connection_check */
182 PORT_SSH, /* defport */
183 CURLPROTO_SFTP, /* protocol */
184 CURLPROTO_SFTP, /* family */
185 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
186 | PROTOPT_NOURLQUERY /* flags */
190 kbd_callback(const char *name, int name_len, const char *instruction,
191 int instruction_len, int num_prompts,
192 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
193 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
196 struct Curl_easy *data = (struct Curl_easy *)*abstract;
198 #ifdef CURL_LIBSSH2_DEBUG
199 fprintf(stderr, "name=%s\n", name);
200 fprintf(stderr, "name_len=%d\n", name_len);
201 fprintf(stderr, "instruction=%s\n", instruction);
202 fprintf(stderr, "instruction_len=%d\n", instruction_len);
203 fprintf(stderr, "num_prompts=%d\n", num_prompts);
208 (void)instruction_len;
209 #endif /* CURL_LIBSSH2_DEBUG */
210 if(num_prompts == 1) {
211 struct connectdata *conn = data->conn;
212 responses[0].text = strdup(conn->passwd);
213 responses[0].length = curlx_uztoui(strlen(conn->passwd));
218 static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
224 case LIBSSH2_FX_NO_SUCH_FILE:
225 case LIBSSH2_FX_NO_SUCH_PATH:
226 return CURLE_REMOTE_FILE_NOT_FOUND;
228 case LIBSSH2_FX_PERMISSION_DENIED:
229 case LIBSSH2_FX_WRITE_PROTECT:
230 case LIBSSH2_FX_LOCK_CONFlICT:
231 return CURLE_REMOTE_ACCESS_DENIED;
233 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
234 case LIBSSH2_FX_QUOTA_EXCEEDED:
235 return CURLE_REMOTE_DISK_FULL;
237 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
238 return CURLE_REMOTE_FILE_EXISTS;
240 case LIBSSH2_FX_DIR_NOT_EMPTY:
241 return CURLE_QUOTE_ERROR;
250 static CURLcode libssh2_session_error_to_CURLE(int err)
253 /* Ordered by order of appearance in libssh2.h */
254 case LIBSSH2_ERROR_NONE:
257 /* This is the error returned by libssh2_scp_recv2
259 case LIBSSH2_ERROR_SCP_PROTOCOL:
260 return CURLE_REMOTE_FILE_NOT_FOUND;
262 case LIBSSH2_ERROR_SOCKET_NONE:
263 return CURLE_COULDNT_CONNECT;
265 case LIBSSH2_ERROR_ALLOC:
266 return CURLE_OUT_OF_MEMORY;
268 case LIBSSH2_ERROR_SOCKET_SEND:
269 return CURLE_SEND_ERROR;
271 case LIBSSH2_ERROR_HOSTKEY_INIT:
272 case LIBSSH2_ERROR_HOSTKEY_SIGN:
273 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
274 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
275 return CURLE_PEER_FAILED_VERIFICATION;
277 case LIBSSH2_ERROR_PASSWORD_EXPIRED:
278 return CURLE_LOGIN_DENIED;
280 case LIBSSH2_ERROR_SOCKET_TIMEOUT:
281 case LIBSSH2_ERROR_TIMEOUT:
282 return CURLE_OPERATION_TIMEDOUT;
284 case LIBSSH2_ERROR_EAGAIN:
291 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
293 (void)abstract; /* arg not used */
294 return malloc(count);
297 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
299 (void)abstract; /* arg not used */
300 return realloc(ptr, count);
303 static LIBSSH2_FREE_FUNC(my_libssh2_free)
305 (void)abstract; /* arg not used */
306 if(ptr) /* ssh2 agent sometimes call free with null ptr */
311 * SSH State machine related code
313 /* This is the ONLY way to change SSH state! */
314 static void state(struct Curl_easy *data, sshstate nowstate)
316 struct connectdata *conn = data->conn;
317 struct ssh_conn *sshc = &conn->proto.sshc;
318 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
319 /* for debug purposes */
320 static const char * const names[] = {
326 "SSH_AUTH_PKEY_INIT",
328 "SSH_AUTH_PASS_INIT",
330 "SSH_AUTH_AGENT_INIT",
331 "SSH_AUTH_AGENT_LIST",
333 "SSH_AUTH_HOST_INIT",
341 "SSH_SFTP_QUOTE_INIT",
342 "SSH_SFTP_POSTQUOTE_INIT",
344 "SSH_SFTP_NEXT_QUOTE",
345 "SSH_SFTP_QUOTE_STAT",
346 "SSH_SFTP_QUOTE_SETSTAT",
347 "SSH_SFTP_QUOTE_SYMLINK",
348 "SSH_SFTP_QUOTE_MKDIR",
349 "SSH_SFTP_QUOTE_RENAME",
350 "SSH_SFTP_QUOTE_RMDIR",
351 "SSH_SFTP_QUOTE_UNLINK",
352 "SSH_SFTP_QUOTE_STATVFS",
355 "SSH_SFTP_TRANS_INIT",
356 "SSH_SFTP_UPLOAD_INIT",
357 "SSH_SFTP_CREATE_DIRS_INIT",
358 "SSH_SFTP_CREATE_DIRS",
359 "SSH_SFTP_CREATE_DIRS_MKDIR",
360 "SSH_SFTP_READDIR_INIT",
362 "SSH_SFTP_READDIR_LINK",
363 "SSH_SFTP_READDIR_BOTTOM",
364 "SSH_SFTP_READDIR_DONE",
365 "SSH_SFTP_DOWNLOAD_INIT",
366 "SSH_SFTP_DOWNLOAD_STAT",
369 "SSH_SCP_TRANS_INIT",
370 "SSH_SCP_UPLOAD_INIT",
371 "SSH_SCP_DOWNLOAD_INIT",
376 "SSH_SCP_WAIT_CLOSE",
377 "SSH_SCP_CHANNEL_FREE",
378 "SSH_SESSION_DISCONNECT",
383 /* a precaution to make sure the lists are in sync */
384 DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
386 if(sshc->state != nowstate) {
387 infof(data, "SFTP %p state change from %s to %s",
388 (void *)sshc, names[sshc->state], names[nowstate]);
392 sshc->state = nowstate;
396 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
397 static int sshkeycallback(struct Curl_easy *easy,
398 const struct curl_khkey *knownkey, /* known */
399 const struct curl_khkey *foundkey, /* found */
400 enum curl_khmatch match,
408 /* we only allow perfect matches, and we reject everything else */
409 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
414 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
417 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
418 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
420 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
424 * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
425 * architectures so we check of the necessary function is present.
427 #ifndef HAVE_LIBSSH2_SCP_SEND64
428 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
430 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
431 (libssh2_uint64_t)d, 0, 0)
435 * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
437 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
438 #define session_startup(x,y) libssh2_session_handshake(x, y)
440 #define session_startup(x,y) libssh2_session_startup(x, (int)y)
442 static int convert_ssh2_keytype(int sshkeytype)
444 int keytype = CURLKHTYPE_UNKNOWN;
446 case LIBSSH2_HOSTKEY_TYPE_RSA:
447 keytype = CURLKHTYPE_RSA;
449 case LIBSSH2_HOSTKEY_TYPE_DSS:
450 keytype = CURLKHTYPE_DSS;
452 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
453 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
454 keytype = CURLKHTYPE_ECDSA;
457 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
458 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
459 keytype = CURLKHTYPE_ECDSA;
462 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
463 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
464 keytype = CURLKHTYPE_ECDSA;
467 #ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
468 case LIBSSH2_HOSTKEY_TYPE_ED25519:
469 keytype = CURLKHTYPE_ED25519;
476 static CURLcode ssh_knownhost(struct Curl_easy *data)
481 CURLcode result = CURLE_OK;
483 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
484 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
485 /* we're asked to verify the host against a file */
486 struct connectdata *conn = data->conn;
487 struct ssh_conn *sshc = &conn->proto.sshc;
488 struct libssh2_knownhost *host = NULL;
489 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
490 &keylen, &sshkeytype);
491 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
496 * A subject to figure out is what host name we need to pass in here.
497 * What host name does OpenSSH store in its file if an IDN name is
500 enum curl_khmatch keymatch;
501 curl_sshkeycallback func =
502 data->set.ssh_keyfunc ? data->set.ssh_keyfunc : sshkeycallback;
503 struct curl_khkey knownkey;
504 struct curl_khkey *knownkeyp = NULL;
505 struct curl_khkey foundkey;
508 case LIBSSH2_HOSTKEY_TYPE_RSA:
509 keybit = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
511 case LIBSSH2_HOSTKEY_TYPE_DSS:
512 keybit = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
514 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
515 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
516 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_256;
519 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
520 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
521 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_384;
524 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
525 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
526 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_521;
529 #ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
530 case LIBSSH2_HOSTKEY_TYPE_ED25519:
531 keybit = LIBSSH2_KNOWNHOST_KEY_ED25519;
535 infof(data, "unsupported key type, can't check knownhosts");
540 /* no check means failure! */
541 rc = CURLKHSTAT_REJECT;
543 #ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
544 keycheck = libssh2_knownhost_checkp(sshc->kh,
546 (conn->remote_port != PORT_SSH)?
547 conn->remote_port:-1,
549 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
550 LIBSSH2_KNOWNHOST_KEYENC_RAW|
554 keycheck = libssh2_knownhost_check(sshc->kh,
557 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
558 LIBSSH2_KNOWNHOST_KEYENC_RAW|
563 infof(data, "SSH host check: %d, key: %s", keycheck,
564 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
567 /* setup 'knownkey' */
568 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
569 knownkey.key = host->key;
571 knownkey.keytype = convert_ssh2_keytype(sshkeytype);
572 knownkeyp = &knownkey;
575 /* setup 'foundkey' */
576 foundkey.key = remotekey;
577 foundkey.len = keylen;
578 foundkey.keytype = convert_ssh2_keytype(sshkeytype);
581 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
582 * curl_khmatch enum are ever modified, we need to introduce a
583 * translation table here!
585 keymatch = (enum curl_khmatch)keycheck;
587 /* Ask the callback how to behave */
588 Curl_set_in_callback(data, true);
589 rc = func(data, knownkeyp, /* from the knownhosts file */
590 &foundkey, /* from the remote host */
591 keymatch, data->set.ssh_keyfunc_userp);
592 Curl_set_in_callback(data, false);
596 /* no remotekey means failure! */
597 rc = CURLKHSTAT_REJECT;
600 default: /* unknown return codes will equal reject */
602 case CURLKHSTAT_REJECT:
603 state(data, SSH_SESSION_FREE);
605 case CURLKHSTAT_DEFER:
606 /* DEFER means bail out but keep the SSH_HOSTKEY state */
607 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
609 case CURLKHSTAT_FINE_REPLACE:
610 /* remove old host+key that doesn't match */
612 libssh2_knownhost_del(sshc->kh, host);
614 case CURLKHSTAT_FINE:
616 case CURLKHSTAT_FINE_ADD_TO_FILE:
618 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
619 /* the found host+key didn't match but has been told to be fine
620 anyway so we add it in memory */
621 int addrc = libssh2_knownhost_add(sshc->kh,
622 conn->host.name, NULL,
624 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
625 LIBSSH2_KNOWNHOST_KEYENC_RAW|
628 infof(data, "WARNING: adding the known host %s failed",
630 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
631 rc == CURLKHSTAT_FINE_REPLACE) {
632 /* now we write the entire in-memory list of known hosts to the
635 libssh2_knownhost_writefile(sshc->kh,
636 data->set.str[STRING_SSH_KNOWNHOSTS],
637 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
639 infof(data, "WARNING: writing %s failed",
640 data->set.str[STRING_SSH_KNOWNHOSTS]);
647 #else /* HAVE_LIBSSH2_KNOWNHOST_API */
653 static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
655 struct connectdata *conn = data->conn;
656 struct ssh_conn *sshc = &conn->proto.sshc;
657 const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
658 const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
660 infof(data, "SSH MD5 public key: %s",
661 pubkey_md5 != NULL ? pubkey_md5 : "NULL");
662 infof(data, "SSH SHA256 public key: %s",
663 pubkey_sha256 != NULL ? pubkey_sha256 : "NULL");
666 const char *fingerprint = NULL;
667 char *fingerprint_b64 = NULL;
668 size_t fingerprint_b64_len;
672 #ifdef LIBSSH2_HOSTKEY_HASH_SHA256
673 /* The fingerprint points to static storage (!), don't free() it. */
674 fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
675 LIBSSH2_HOSTKEY_HASH_SHA256);
679 unsigned char hash[32];
681 hostkey = libssh2_session_hostkey(sshc->ssh_session, &len, NULL);
683 if(!Curl_sha256it(hash, (const unsigned char *) hostkey, len))
684 fingerprint = (char *) hash;
690 "Denied establishing ssh session: sha256 fingerprint "
692 state(data, SSH_SESSION_FREE);
693 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
694 return sshc->actualcode;
697 /* The length of fingerprint is 32 bytes for SHA256.
698 * See libssh2_hostkey_hash documentation. */
699 if(Curl_base64_encode(fingerprint, 32, &fingerprint_b64,
700 &fingerprint_b64_len) != CURLE_OK) {
701 state(data, SSH_SESSION_FREE);
702 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
703 return sshc->actualcode;
706 if(!fingerprint_b64) {
707 failf(data, "sha256 fingerprint could not be encoded");
708 state(data, SSH_SESSION_FREE);
709 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
710 return sshc->actualcode;
713 infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64);
715 /* Find the position of any = padding characters in the public key */
716 while((pubkey_sha256[pub_pos] != '=') && pubkey_sha256[pub_pos]) {
720 /* Find the position of any = padding characters in the base64 coded
721 * hostkey fingerprint */
722 while((fingerprint_b64[b64_pos] != '=') && fingerprint_b64[b64_pos]) {
726 /* Before we authenticate we check the hostkey's sha256 fingerprint
727 * against a known fingerprint, if available.
729 if((pub_pos != b64_pos) ||
730 strncmp(fingerprint_b64, pubkey_sha256, pub_pos)) {
731 free(fingerprint_b64);
734 "Denied establishing ssh session: mismatch sha256 fingerprint. "
735 "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
736 state(data, SSH_SESSION_FREE);
737 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
738 return sshc->actualcode;
741 free(fingerprint_b64);
743 infof(data, "SHA256 checksum match");
748 const char *fingerprint = NULL;
750 fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
751 LIBSSH2_HOSTKEY_HASH_MD5);
754 /* The fingerprint points to static storage (!), don't free() it. */
756 for(i = 0; i < 16; i++) {
757 msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
760 infof(data, "SSH MD5 fingerprint: %s", md5buffer);
763 /* This does NOT verify the length of 'pubkey_md5' separately, which will
764 make the comparison below fail unless it is exactly 32 characters */
765 if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
768 "Denied establishing ssh session: mismatch md5 fingerprint. "
769 "Remote %s is not equal to %s", md5buffer, pubkey_md5);
773 "Denied establishing ssh session: md5 fingerprint "
776 state(data, SSH_SESSION_FREE);
777 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
778 return sshc->actualcode;
780 infof(data, "MD5 checksum match");
783 if(!pubkey_md5 && !pubkey_sha256) {
784 if(data->set.ssh_hostkeyfunc) {
788 /* we handle the process to the callback*/
789 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
790 &keylen, &sshkeytype);
792 int keytype = convert_ssh2_keytype(sshkeytype);
793 Curl_set_in_callback(data, true);
794 rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp,
795 keytype, remotekey, keylen);
796 Curl_set_in_callback(data, false);
797 if(rc!= CURLKHMATCH_OK) {
798 state(data, SSH_SESSION_FREE);
802 state(data, SSH_SESSION_FREE);
807 return ssh_knownhost(data);
811 /* as we already matched, we skip the check for known hosts */
817 * ssh_force_knownhost_key_type() will check the known hosts file and try to
818 * force a specific public key type from the server if an entry is found.
820 static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
822 CURLcode result = CURLE_OK;
824 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
826 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
827 static const char * const hostkey_method_ssh_ed25519
830 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
831 static const char * const hostkey_method_ssh_ecdsa_521
832 = "ecdsa-sha2-nistp521";
834 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
835 static const char * const hostkey_method_ssh_ecdsa_384
836 = "ecdsa-sha2-nistp384";
838 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
839 static const char * const hostkey_method_ssh_ecdsa_256
840 = "ecdsa-sha2-nistp256";
842 static const char * const hostkey_method_ssh_rsa
844 static const char * const hostkey_method_ssh_dss
847 const char *hostkey_method = NULL;
848 struct connectdata *conn = data->conn;
849 struct ssh_conn *sshc = &conn->proto.sshc;
850 struct libssh2_knownhost* store = NULL;
851 const char *kh_name_end = NULL;
852 size_t kh_name_size = 0;
856 if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
857 /* lets try to find our host in the known hosts file */
858 while(!libssh2_knownhost_get(sshc->kh, &store, store)) {
859 /* For non-standard ports, the name will be enclosed in */
860 /* square brackets, followed by a colon and the port */
863 if(store->name[0] == '[') {
864 kh_name_end = strstr(store->name, "]:");
866 infof(data, "Invalid host pattern %s in %s",
867 store->name, data->set.str[STRING_SSH_KNOWNHOSTS]);
870 port = atoi(kh_name_end + 2);
871 if(kh_name_end && (port == conn->remote_port)) {
872 kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end);
873 if(strncmp(store->name + 1,
874 conn->host.name, kh_name_size) == 0) {
880 else if(strcmp(store->name, conn->host.name) == 0) {
893 infof(data, "Found host %s in %s",
894 conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
896 switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
897 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
898 case LIBSSH2_KNOWNHOST_KEY_ED25519:
899 hostkey_method = hostkey_method_ssh_ed25519;
902 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
903 case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
904 hostkey_method = hostkey_method_ssh_ecdsa_521;
907 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
908 case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
909 hostkey_method = hostkey_method_ssh_ecdsa_384;
912 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
913 case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
914 hostkey_method = hostkey_method_ssh_ecdsa_256;
917 case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
918 hostkey_method = hostkey_method_ssh_rsa;
920 case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
921 hostkey_method = hostkey_method_ssh_dss;
923 case LIBSSH2_KNOWNHOST_KEY_RSA1:
924 failf(data, "Found host key type RSA1 which is not supported");
927 failf(data, "Unknown host key type: %i",
928 (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
932 infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method);
933 result = libssh2_session_error_to_CURLE(
934 libssh2_session_method_pref(
935 sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
938 infof(data, "Did not find host %s in %s",
939 conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
943 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
949 * ssh_statemach_act() runs the SSH state machine as far as it can without
950 * blocking and without reaching the end. The data the pointer 'block' points
951 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
952 * meaning it wants to be called again when the socket is ready
955 static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
957 CURLcode result = CURLE_OK;
958 struct connectdata *conn = data->conn;
959 struct SSHPROTO *sshp = data->req.p.ssh;
960 struct ssh_conn *sshc = &conn->proto.sshc;
961 curl_socket_t sock = conn->sock[FIRSTSOCKET];
962 int rc = LIBSSH2_ERROR_NONE;
964 unsigned long sftperr;
965 int seekerr = CURL_SEEKFUNC_OK;
967 *block = 0; /* we're not blocking by default */
970 switch(sshc->state) {
972 sshc->secondCreateDirs = 0;
973 sshc->nextstate = SSH_NO_STATE;
974 sshc->actualcode = CURLE_OK;
976 /* Set libssh2 to non-blocking, since everything internally is
978 libssh2_session_set_blocking(sshc->ssh_session, 0);
980 result = ssh_force_knownhost_key_type(data);
982 state(data, SSH_SESSION_FREE);
983 sshc->actualcode = result;
987 state(data, SSH_S_STARTUP);
991 rc = session_startup(sshc->ssh_session, sock);
992 if(rc == LIBSSH2_ERROR_EAGAIN) {
996 char *err_msg = NULL;
997 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
998 failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
1000 state(data, SSH_SESSION_FREE);
1001 sshc->actualcode = CURLE_FAILED_INIT;
1005 state(data, SSH_HOSTKEY);
1010 * Before we authenticate we should check the hostkey's fingerprint
1011 * against our known hosts. How that is handled (reading from file,
1012 * whatever) is up to us.
1014 result = ssh_check_fingerprint(data);
1016 state(data, SSH_AUTHLIST);
1017 /* ssh_check_fingerprint sets state appropriately on error */
1022 * Figure out authentication methods
1023 * NB: As soon as we have provided a username to an openssh server we
1024 * must never change it later. Thus, always specify the correct username
1025 * here, even though the libssh2 docs kind of indicate that it should be
1026 * possible to get a 'generic' list (not user-specific) of authentication
1027 * methods, presumably with a blank username. That won't work in my
1029 * So always specify it here.
1031 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
1033 curlx_uztoui(strlen(conn->user)));
1035 if(!sshc->authlist) {
1036 if(libssh2_userauth_authenticated(sshc->ssh_session)) {
1037 sshc->authed = TRUE;
1038 infof(data, "SSH user accepted with no authentication");
1039 state(data, SSH_AUTH_DONE);
1042 ssherr = libssh2_session_last_errno(sshc->ssh_session);
1043 if(ssherr == LIBSSH2_ERROR_EAGAIN)
1044 rc = LIBSSH2_ERROR_EAGAIN;
1046 state(data, SSH_SESSION_FREE);
1047 sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
1051 infof(data, "SSH authentication methods available: %s",
1054 state(data, SSH_AUTH_PKEY_INIT);
1057 case SSH_AUTH_PKEY_INIT:
1059 * Check the supported auth types in the order I feel is most secure
1060 * with the requested type of authentication
1062 sshc->authed = FALSE;
1064 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
1065 (strstr(sshc->authlist, "publickey") != NULL)) {
1066 bool out_of_memory = FALSE;
1068 sshc->rsa_pub = sshc->rsa = NULL;
1070 if(data->set.str[STRING_SSH_PRIVATE_KEY])
1071 sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
1073 /* To ponder about: should really the lib be messing about with the
1074 HOME environment variable etc? */
1075 char *home = curl_getenv("HOME");
1077 /* If no private key file is specified, try some common paths. */
1079 /* Try ~/.ssh first. */
1080 sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
1082 out_of_memory = TRUE;
1083 else if(access(sshc->rsa, R_OK) != 0) {
1084 Curl_safefree(sshc->rsa);
1085 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
1087 out_of_memory = TRUE;
1088 else if(access(sshc->rsa, R_OK) != 0) {
1089 Curl_safefree(sshc->rsa);
1094 if(!out_of_memory && !sshc->rsa) {
1095 /* Nothing found; try the current dir. */
1096 sshc->rsa = strdup("id_rsa");
1097 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
1098 Curl_safefree(sshc->rsa);
1099 sshc->rsa = strdup("id_dsa");
1100 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
1101 Curl_safefree(sshc->rsa);
1102 /* Out of guesses. Set to the empty string to avoid
1103 * surprising info messages. */
1104 sshc->rsa = strdup("");
1111 * Unless the user explicitly specifies a public key file, let
1112 * libssh2 extract the public key from the private key file.
1113 * This is done by simply passing sshc->rsa_pub = NULL.
1115 if(data->set.str[STRING_SSH_PUBLIC_KEY]
1116 /* treat empty string the same way as NULL */
1117 && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
1118 sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
1120 out_of_memory = TRUE;
1123 if(out_of_memory || !sshc->rsa) {
1124 Curl_safefree(sshc->rsa);
1125 Curl_safefree(sshc->rsa_pub);
1126 state(data, SSH_SESSION_FREE);
1127 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1131 sshc->passphrase = data->set.ssl.key_passwd;
1132 if(!sshc->passphrase)
1133 sshc->passphrase = "";
1136 infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
1137 infof(data, "Using SSH private key file '%s'", sshc->rsa);
1139 state(data, SSH_AUTH_PKEY);
1142 state(data, SSH_AUTH_PASS_INIT);
1147 /* The function below checks if the files exists, no need to stat() here.
1149 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
1152 strlen(conn->user)),
1154 sshc->rsa, sshc->passphrase);
1155 if(rc == LIBSSH2_ERROR_EAGAIN) {
1159 Curl_safefree(sshc->rsa_pub);
1160 Curl_safefree(sshc->rsa);
1163 sshc->authed = TRUE;
1164 infof(data, "Initialized SSH public key authentication");
1165 state(data, SSH_AUTH_DONE);
1168 char *err_msg = NULL;
1169 (void)libssh2_session_last_error(sshc->ssh_session,
1171 infof(data, "SSH public key authentication failed: %s", err_msg);
1172 state(data, SSH_AUTH_PASS_INIT);
1173 rc = 0; /* clear rc and continue */
1177 case SSH_AUTH_PASS_INIT:
1178 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
1179 (strstr(sshc->authlist, "password") != NULL)) {
1180 state(data, SSH_AUTH_PASS);
1183 state(data, SSH_AUTH_HOST_INIT);
1184 rc = 0; /* clear rc and continue */
1189 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
1190 curlx_uztoui(strlen(conn->user)),
1192 curlx_uztoui(strlen(conn->passwd)),
1194 if(rc == LIBSSH2_ERROR_EAGAIN) {
1198 sshc->authed = TRUE;
1199 infof(data, "Initialized password authentication");
1200 state(data, SSH_AUTH_DONE);
1203 state(data, SSH_AUTH_HOST_INIT);
1204 rc = 0; /* clear rc and continue */
1208 case SSH_AUTH_HOST_INIT:
1209 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
1210 (strstr(sshc->authlist, "hostbased") != NULL)) {
1211 state(data, SSH_AUTH_HOST);
1214 state(data, SSH_AUTH_AGENT_INIT);
1219 state(data, SSH_AUTH_AGENT_INIT);
1222 case SSH_AUTH_AGENT_INIT:
1223 #ifdef HAVE_LIBSSH2_AGENT_API
1224 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
1225 && (strstr(sshc->authlist, "publickey") != NULL)) {
1227 /* Connect to the ssh-agent */
1228 /* The agent could be shared by a curl thread i believe
1229 but nothing obvious as keys can be added/removed at any time */
1230 if(!sshc->ssh_agent) {
1231 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
1232 if(!sshc->ssh_agent) {
1233 infof(data, "Could not create agent object");
1235 state(data, SSH_AUTH_KEY_INIT);
1240 rc = libssh2_agent_connect(sshc->ssh_agent);
1241 if(rc == LIBSSH2_ERROR_EAGAIN)
1244 infof(data, "Failure connecting to agent");
1245 state(data, SSH_AUTH_KEY_INIT);
1246 rc = 0; /* clear rc and continue */
1249 state(data, SSH_AUTH_AGENT_LIST);
1253 #endif /* HAVE_LIBSSH2_AGENT_API */
1254 state(data, SSH_AUTH_KEY_INIT);
1257 case SSH_AUTH_AGENT_LIST:
1258 #ifdef HAVE_LIBSSH2_AGENT_API
1259 rc = libssh2_agent_list_identities(sshc->ssh_agent);
1261 if(rc == LIBSSH2_ERROR_EAGAIN)
1264 infof(data, "Failure requesting identities to agent");
1265 state(data, SSH_AUTH_KEY_INIT);
1266 rc = 0; /* clear rc and continue */
1269 state(data, SSH_AUTH_AGENT);
1270 sshc->sshagent_prev_identity = NULL;
1275 case SSH_AUTH_AGENT:
1276 #ifdef HAVE_LIBSSH2_AGENT_API
1277 /* as prev_identity evolves only after an identity user auth finished we
1278 can safely request it again as long as EAGAIN is returned here or by
1279 libssh2_agent_userauth */
1280 rc = libssh2_agent_get_identity(sshc->ssh_agent,
1281 &sshc->sshagent_identity,
1282 sshc->sshagent_prev_identity);
1283 if(rc == LIBSSH2_ERROR_EAGAIN)
1287 rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
1288 sshc->sshagent_identity);
1291 if(rc != LIBSSH2_ERROR_EAGAIN) {
1292 /* tried and failed? go to next identity */
1293 sshc->sshagent_prev_identity = sshc->sshagent_identity;
1300 infof(data, "Failure requesting identities to agent");
1302 infof(data, "No identity would match");
1304 if(rc == LIBSSH2_ERROR_NONE) {
1305 sshc->authed = TRUE;
1306 infof(data, "Agent based authentication successful");
1307 state(data, SSH_AUTH_DONE);
1310 state(data, SSH_AUTH_KEY_INIT);
1311 rc = 0; /* clear rc and continue */
1316 case SSH_AUTH_KEY_INIT:
1317 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
1318 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
1319 state(data, SSH_AUTH_KEY);
1322 state(data, SSH_AUTH_DONE);
1327 /* Authentication failed. Continue with keyboard-interactive now. */
1328 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
1331 strlen(conn->user)),
1333 if(rc == LIBSSH2_ERROR_EAGAIN) {
1337 sshc->authed = TRUE;
1338 infof(data, "Initialized keyboard interactive authentication");
1340 state(data, SSH_AUTH_DONE);
1345 failf(data, "Authentication failure");
1346 state(data, SSH_SESSION_FREE);
1347 sshc->actualcode = CURLE_LOGIN_DENIED;
1352 * At this point we have an authenticated ssh session.
1354 infof(data, "Authentication complete");
1356 Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
1358 conn->sockfd = sock;
1359 conn->writesockfd = CURL_SOCKET_BAD;
1361 if(conn->handler->protocol == CURLPROTO_SFTP) {
1362 state(data, SSH_SFTP_INIT);
1365 infof(data, "SSH CONNECT phase done");
1366 state(data, SSH_STOP);
1371 * Start the libssh2 sftp session
1373 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
1374 if(!sshc->sftp_session) {
1375 char *err_msg = NULL;
1376 if(libssh2_session_last_errno(sshc->ssh_session) ==
1377 LIBSSH2_ERROR_EAGAIN) {
1378 rc = LIBSSH2_ERROR_EAGAIN;
1382 (void)libssh2_session_last_error(sshc->ssh_session,
1384 failf(data, "Failure initializing sftp session: %s", err_msg);
1385 state(data, SSH_SESSION_FREE);
1386 sshc->actualcode = CURLE_FAILED_INIT;
1389 state(data, SSH_SFTP_REALPATH);
1392 case SSH_SFTP_REALPATH:
1394 char tempHome[PATH_MAX];
1397 * Get the "home" directory
1399 rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
1400 tempHome, PATH_MAX-1);
1401 if(rc == LIBSSH2_ERROR_EAGAIN) {
1405 /* It seems that this string is not always NULL terminated */
1406 tempHome[rc] = '\0';
1407 sshc->homedir = strdup(tempHome);
1408 if(!sshc->homedir) {
1409 state(data, SSH_SFTP_CLOSE);
1410 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1413 data->state.most_recent_ftp_entrypath = sshc->homedir;
1416 /* Return the error type */
1417 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1419 result = sftp_libssh2_error_to_CURLE(sftperr);
1421 /* in this case, the error wasn't in the SFTP level but for example
1422 a time-out or similar */
1424 sshc->actualcode = result;
1425 DEBUGF(infof(data, "error = %lu makes libcurl = %d",
1426 sftperr, (int)result));
1427 state(data, SSH_STOP);
1431 /* This is the last step in the SFTP connect phase. Do note that while
1432 we get the homedir here, we get the "workingpath" in the DO action
1433 since the homedir will remain the same between request but the
1434 working path will not. */
1435 DEBUGF(infof(data, "SSH CONNECT phase done"));
1436 state(data, SSH_STOP);
1439 case SSH_SFTP_QUOTE_INIT:
1441 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
1443 sshc->actualcode = result;
1444 state(data, SSH_STOP);
1448 if(data->set.quote) {
1449 infof(data, "Sending quote commands");
1450 sshc->quote_item = data->set.quote;
1451 state(data, SSH_SFTP_QUOTE);
1454 state(data, SSH_SFTP_GETINFO);
1458 case SSH_SFTP_POSTQUOTE_INIT:
1459 if(data->set.postquote) {
1460 infof(data, "Sending quote commands");
1461 sshc->quote_item = data->set.postquote;
1462 state(data, SSH_SFTP_QUOTE);
1465 state(data, SSH_STOP);
1469 case SSH_SFTP_QUOTE:
1470 /* Send any quote commands */
1475 * Support some of the "FTP" commands
1477 * 'sshc->quote_item' is already verified to be non-NULL before it
1478 * switched to this state.
1480 char *cmd = sshc->quote_item->data;
1481 sshc->acceptfail = FALSE;
1483 /* if a command starts with an asterisk, which a legal SFTP command never
1484 can, the command will be allowed to fail without it causing any
1485 aborts or cancels etc. It will cause libcurl to act as if the command
1486 is successful, whatever the server reponds. */
1490 sshc->acceptfail = TRUE;
1493 if(strcasecompare("pwd", cmd)) {
1494 /* output debug output if that is requested */
1495 char *tmp = aprintf("257 \"%s\" is current directory.\n",
1498 result = CURLE_OUT_OF_MEMORY;
1499 state(data, SSH_SFTP_CLOSE);
1500 sshc->nextstate = SSH_NO_STATE;
1503 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
1504 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
1506 /* this sends an FTP-like "header" to the header callback so that the
1507 current directory can be read very similar to how it is read when
1508 using ordinary FTP. */
1509 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1512 state(data, SSH_SFTP_CLOSE);
1513 sshc->nextstate = SSH_NO_STATE;
1514 sshc->actualcode = result;
1517 state(data, SSH_SFTP_NEXT_QUOTE);
1522 * the arguments following the command must be separated from the
1523 * command with a space so we can check for it unconditionally
1525 cp = strchr(cmd, ' ');
1527 failf(data, "Syntax error command '%s', missing parameter",
1529 state(data, SSH_SFTP_CLOSE);
1530 sshc->nextstate = SSH_NO_STATE;
1531 sshc->actualcode = CURLE_QUOTE_ERROR;
1536 * also, every command takes at least one argument so we get that
1537 * first argument right now
1539 result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
1541 if(result == CURLE_OUT_OF_MEMORY)
1542 failf(data, "Out of memory");
1544 failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
1545 state(data, SSH_SFTP_CLOSE);
1546 sshc->nextstate = SSH_NO_STATE;
1547 sshc->actualcode = result;
1552 * SFTP is a binary protocol, so we don't send text commands
1553 * to the server. Instead, we scan for commands used by
1554 * OpenSSH's sftp program and call the appropriate libssh2
1557 if(strncasecompare(cmd, "chgrp ", 6) ||
1558 strncasecompare(cmd, "chmod ", 6) ||
1559 strncasecompare(cmd, "chown ", 6) ||
1560 strncasecompare(cmd, "atime ", 6) ||
1561 strncasecompare(cmd, "mtime ", 6)) {
1562 /* attribute change */
1564 /* sshc->quote_path1 contains the mode to set */
1565 /* get the destination */
1566 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1568 if(result == CURLE_OUT_OF_MEMORY)
1569 failf(data, "Out of memory");
1571 failf(data, "Syntax error in %s: Bad second parameter", cmd);
1572 Curl_safefree(sshc->quote_path1);
1573 state(data, SSH_SFTP_CLOSE);
1574 sshc->nextstate = SSH_NO_STATE;
1575 sshc->actualcode = result;
1578 memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1579 state(data, SSH_SFTP_QUOTE_STAT);
1582 if(strncasecompare(cmd, "ln ", 3) ||
1583 strncasecompare(cmd, "symlink ", 8)) {
1584 /* symbolic linking */
1585 /* sshc->quote_path1 is the source */
1586 /* get the destination */
1587 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1589 if(result == CURLE_OUT_OF_MEMORY)
1590 failf(data, "Out of memory");
1593 "Syntax error in ln/symlink: Bad second parameter");
1594 Curl_safefree(sshc->quote_path1);
1595 state(data, SSH_SFTP_CLOSE);
1596 sshc->nextstate = SSH_NO_STATE;
1597 sshc->actualcode = result;
1600 state(data, SSH_SFTP_QUOTE_SYMLINK);
1603 else if(strncasecompare(cmd, "mkdir ", 6)) {
1605 state(data, SSH_SFTP_QUOTE_MKDIR);
1608 else if(strncasecompare(cmd, "rename ", 7)) {
1610 /* first param is the source path */
1611 /* second param is the dest. path */
1612 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1614 if(result == CURLE_OUT_OF_MEMORY)
1615 failf(data, "Out of memory");
1617 failf(data, "Syntax error in rename: Bad second parameter");
1618 Curl_safefree(sshc->quote_path1);
1619 state(data, SSH_SFTP_CLOSE);
1620 sshc->nextstate = SSH_NO_STATE;
1621 sshc->actualcode = result;
1624 state(data, SSH_SFTP_QUOTE_RENAME);
1627 else if(strncasecompare(cmd, "rmdir ", 6)) {
1629 state(data, SSH_SFTP_QUOTE_RMDIR);
1632 else if(strncasecompare(cmd, "rm ", 3)) {
1633 state(data, SSH_SFTP_QUOTE_UNLINK);
1636 #ifdef HAS_STATVFS_SUPPORT
1637 else if(strncasecompare(cmd, "statvfs ", 8)) {
1638 state(data, SSH_SFTP_QUOTE_STATVFS);
1643 failf(data, "Unknown SFTP command");
1644 Curl_safefree(sshc->quote_path1);
1645 Curl_safefree(sshc->quote_path2);
1646 state(data, SSH_SFTP_CLOSE);
1647 sshc->nextstate = SSH_NO_STATE;
1648 sshc->actualcode = CURLE_QUOTE_ERROR;
1654 case SSH_SFTP_NEXT_QUOTE:
1655 Curl_safefree(sshc->quote_path1);
1656 Curl_safefree(sshc->quote_path2);
1658 sshc->quote_item = sshc->quote_item->next;
1660 if(sshc->quote_item) {
1661 state(data, SSH_SFTP_QUOTE);
1664 if(sshc->nextstate != SSH_NO_STATE) {
1665 state(data, sshc->nextstate);
1666 sshc->nextstate = SSH_NO_STATE;
1669 state(data, SSH_SFTP_GETINFO);
1674 case SSH_SFTP_QUOTE_STAT:
1676 char *cmd = sshc->quote_item->data;
1677 sshc->acceptfail = FALSE;
1679 /* if a command starts with an asterisk, which a legal SFTP command never
1680 can, the command will be allowed to fail without it causing any
1681 aborts or cancels etc. It will cause libcurl to act as if the command
1682 is successful, whatever the server reponds. */
1686 sshc->acceptfail = TRUE;
1689 if(!strncasecompare(cmd, "chmod", 5)) {
1690 /* Since chown and chgrp only set owner OR group but libssh2 wants to
1691 * set them both at once, we need to obtain the current ownership
1692 * first. This takes an extra protocol round trip.
1694 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1695 curlx_uztoui(strlen(sshc->quote_path2)),
1697 &sshp->quote_attrs);
1698 if(rc == LIBSSH2_ERROR_EAGAIN) {
1701 if(rc && !sshc->acceptfail) { /* get those attributes */
1702 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1703 Curl_safefree(sshc->quote_path1);
1704 Curl_safefree(sshc->quote_path2);
1705 failf(data, "Attempt to get SFTP stats failed: %s",
1706 sftp_libssh2_strerror(sftperr));
1707 state(data, SSH_SFTP_CLOSE);
1708 sshc->nextstate = SSH_NO_STATE;
1709 sshc->actualcode = CURLE_QUOTE_ERROR;
1714 /* Now set the new attributes... */
1715 if(strncasecompare(cmd, "chgrp", 5)) {
1716 sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
1717 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1718 if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1719 !sshc->acceptfail) {
1720 Curl_safefree(sshc->quote_path1);
1721 Curl_safefree(sshc->quote_path2);
1722 failf(data, "Syntax error: chgrp gid not a number");
1723 state(data, SSH_SFTP_CLOSE);
1724 sshc->nextstate = SSH_NO_STATE;
1725 sshc->actualcode = CURLE_QUOTE_ERROR;
1729 else if(strncasecompare(cmd, "chmod", 5)) {
1730 sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
1731 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1732 /* permissions are octal */
1733 if(sshp->quote_attrs.permissions == 0 &&
1734 !ISDIGIT(sshc->quote_path1[0])) {
1735 Curl_safefree(sshc->quote_path1);
1736 Curl_safefree(sshc->quote_path2);
1737 failf(data, "Syntax error: chmod permissions not a number");
1738 state(data, SSH_SFTP_CLOSE);
1739 sshc->nextstate = SSH_NO_STATE;
1740 sshc->actualcode = CURLE_QUOTE_ERROR;
1744 else if(strncasecompare(cmd, "chown", 5)) {
1745 sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
1746 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1747 if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1748 !sshc->acceptfail) {
1749 Curl_safefree(sshc->quote_path1);
1750 Curl_safefree(sshc->quote_path2);
1751 failf(data, "Syntax error: chown uid not a number");
1752 state(data, SSH_SFTP_CLOSE);
1753 sshc->nextstate = SSH_NO_STATE;
1754 sshc->actualcode = CURLE_QUOTE_ERROR;
1758 else if(strncasecompare(cmd, "atime", 5) ||
1759 strncasecompare(cmd, "mtime", 5)) {
1760 time_t date = Curl_getdate_capped(sshc->quote_path1);
1764 failf(data, "incorrect date format for %.*s", 5, cmd);
1767 #if SIZEOF_TIME_T > SIZEOF_LONG
1768 if(date > 0xffffffff) {
1769 /* if 'long' can't old >32bit, this date cannot be sent */
1770 failf(data, "date overflow");
1775 Curl_safefree(sshc->quote_path1);
1776 Curl_safefree(sshc->quote_path2);
1777 state(data, SSH_SFTP_CLOSE);
1778 sshc->nextstate = SSH_NO_STATE;
1779 sshc->actualcode = CURLE_QUOTE_ERROR;
1782 if(strncasecompare(cmd, "atime", 5))
1783 sshp->quote_attrs.atime = (unsigned long)date;
1785 sshp->quote_attrs.mtime = (unsigned long)date;
1787 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
1790 /* Now send the completed structure... */
1791 state(data, SSH_SFTP_QUOTE_SETSTAT);
1795 case SSH_SFTP_QUOTE_SETSTAT:
1796 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1797 curlx_uztoui(strlen(sshc->quote_path2)),
1798 LIBSSH2_SFTP_SETSTAT,
1799 &sshp->quote_attrs);
1800 if(rc == LIBSSH2_ERROR_EAGAIN) {
1803 if(rc && !sshc->acceptfail) {
1804 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1805 Curl_safefree(sshc->quote_path1);
1806 Curl_safefree(sshc->quote_path2);
1807 failf(data, "Attempt to set SFTP stats failed: %s",
1808 sftp_libssh2_strerror(sftperr));
1809 state(data, SSH_SFTP_CLOSE);
1810 sshc->nextstate = SSH_NO_STATE;
1811 sshc->actualcode = CURLE_QUOTE_ERROR;
1814 state(data, SSH_SFTP_NEXT_QUOTE);
1817 case SSH_SFTP_QUOTE_SYMLINK:
1818 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
1819 curlx_uztoui(strlen(sshc->quote_path1)),
1821 curlx_uztoui(strlen(sshc->quote_path2)),
1822 LIBSSH2_SFTP_SYMLINK);
1823 if(rc == LIBSSH2_ERROR_EAGAIN) {
1826 if(rc && !sshc->acceptfail) {
1827 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1828 Curl_safefree(sshc->quote_path1);
1829 Curl_safefree(sshc->quote_path2);
1830 failf(data, "symlink command failed: %s",
1831 sftp_libssh2_strerror(sftperr));
1832 state(data, SSH_SFTP_CLOSE);
1833 sshc->nextstate = SSH_NO_STATE;
1834 sshc->actualcode = CURLE_QUOTE_ERROR;
1837 state(data, SSH_SFTP_NEXT_QUOTE);
1840 case SSH_SFTP_QUOTE_MKDIR:
1841 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
1842 curlx_uztoui(strlen(sshc->quote_path1)),
1843 data->set.new_directory_perms);
1844 if(rc == LIBSSH2_ERROR_EAGAIN) {
1847 if(rc && !sshc->acceptfail) {
1848 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1849 Curl_safefree(sshc->quote_path1);
1850 failf(data, "mkdir command failed: %s",
1851 sftp_libssh2_strerror(sftperr));
1852 state(data, SSH_SFTP_CLOSE);
1853 sshc->nextstate = SSH_NO_STATE;
1854 sshc->actualcode = CURLE_QUOTE_ERROR;
1857 state(data, SSH_SFTP_NEXT_QUOTE);
1860 case SSH_SFTP_QUOTE_RENAME:
1861 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
1862 curlx_uztoui(strlen(sshc->quote_path1)),
1864 curlx_uztoui(strlen(sshc->quote_path2)),
1865 LIBSSH2_SFTP_RENAME_OVERWRITE |
1866 LIBSSH2_SFTP_RENAME_ATOMIC |
1867 LIBSSH2_SFTP_RENAME_NATIVE);
1869 if(rc == LIBSSH2_ERROR_EAGAIN) {
1872 if(rc && !sshc->acceptfail) {
1873 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1874 Curl_safefree(sshc->quote_path1);
1875 Curl_safefree(sshc->quote_path2);
1876 failf(data, "rename command failed: %s",
1877 sftp_libssh2_strerror(sftperr));
1878 state(data, SSH_SFTP_CLOSE);
1879 sshc->nextstate = SSH_NO_STATE;
1880 sshc->actualcode = CURLE_QUOTE_ERROR;
1883 state(data, SSH_SFTP_NEXT_QUOTE);
1886 case SSH_SFTP_QUOTE_RMDIR:
1887 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
1888 curlx_uztoui(strlen(sshc->quote_path1)));
1889 if(rc == LIBSSH2_ERROR_EAGAIN) {
1892 if(rc && !sshc->acceptfail) {
1893 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1894 Curl_safefree(sshc->quote_path1);
1895 failf(data, "rmdir command failed: %s",
1896 sftp_libssh2_strerror(sftperr));
1897 state(data, SSH_SFTP_CLOSE);
1898 sshc->nextstate = SSH_NO_STATE;
1899 sshc->actualcode = CURLE_QUOTE_ERROR;
1902 state(data, SSH_SFTP_NEXT_QUOTE);
1905 case SSH_SFTP_QUOTE_UNLINK:
1906 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
1907 curlx_uztoui(strlen(sshc->quote_path1)));
1908 if(rc == LIBSSH2_ERROR_EAGAIN) {
1911 if(rc && !sshc->acceptfail) {
1912 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1913 Curl_safefree(sshc->quote_path1);
1914 failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
1915 state(data, SSH_SFTP_CLOSE);
1916 sshc->nextstate = SSH_NO_STATE;
1917 sshc->actualcode = CURLE_QUOTE_ERROR;
1920 state(data, SSH_SFTP_NEXT_QUOTE);
1923 #ifdef HAS_STATVFS_SUPPORT
1924 case SSH_SFTP_QUOTE_STATVFS:
1926 LIBSSH2_SFTP_STATVFS statvfs;
1927 rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
1928 curlx_uztoui(strlen(sshc->quote_path1)),
1931 if(rc == LIBSSH2_ERROR_EAGAIN) {
1934 if(rc && !sshc->acceptfail) {
1935 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1936 Curl_safefree(sshc->quote_path1);
1937 failf(data, "statvfs command failed: %s",
1938 sftp_libssh2_strerror(sftperr));
1939 state(data, SSH_SFTP_CLOSE);
1940 sshc->nextstate = SSH_NO_STATE;
1941 sshc->actualcode = CURLE_QUOTE_ERROR;
1945 char *tmp = aprintf("statvfs:\n"
1946 "f_bsize: %llu\n" "f_frsize: %llu\n"
1947 "f_blocks: %llu\n" "f_bfree: %llu\n"
1948 "f_bavail: %llu\n" "f_files: %llu\n"
1949 "f_ffree: %llu\n" "f_favail: %llu\n"
1950 "f_fsid: %llu\n" "f_flag: %llu\n"
1951 "f_namemax: %llu\n",
1952 statvfs.f_bsize, statvfs.f_frsize,
1953 statvfs.f_blocks, statvfs.f_bfree,
1954 statvfs.f_bavail, statvfs.f_files,
1955 statvfs.f_ffree, statvfs.f_favail,
1956 statvfs.f_fsid, statvfs.f_flag,
1959 result = CURLE_OUT_OF_MEMORY;
1960 state(data, SSH_SFTP_CLOSE);
1961 sshc->nextstate = SSH_NO_STATE;
1965 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1968 state(data, SSH_SFTP_CLOSE);
1969 sshc->nextstate = SSH_NO_STATE;
1970 sshc->actualcode = result;
1973 state(data, SSH_SFTP_NEXT_QUOTE);
1977 case SSH_SFTP_GETINFO:
1979 if(data->set.get_filetime) {
1980 state(data, SSH_SFTP_FILETIME);
1983 state(data, SSH_SFTP_TRANS_INIT);
1988 case SSH_SFTP_FILETIME:
1990 LIBSSH2_SFTP_ATTRIBUTES attrs;
1992 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
1993 curlx_uztoui(strlen(sshp->path)),
1994 LIBSSH2_SFTP_STAT, &attrs);
1995 if(rc == LIBSSH2_ERROR_EAGAIN) {
1999 data->info.filetime = attrs.mtime;
2002 state(data, SSH_SFTP_TRANS_INIT);
2006 case SSH_SFTP_TRANS_INIT:
2007 if(data->set.upload)
2008 state(data, SSH_SFTP_UPLOAD_INIT);
2010 if(sshp->path[strlen(sshp->path)-1] == '/')
2011 state(data, SSH_SFTP_READDIR_INIT);
2013 state(data, SSH_SFTP_DOWNLOAD_INIT);
2017 case SSH_SFTP_UPLOAD_INIT:
2019 unsigned long flags;
2021 * NOTE!!! libssh2 requires that the destination path is a full path
2022 * that includes the destination file and name OR ends in a "/"
2023 * If this is not done the destination file will be named the
2024 * same name as the last directory in the path.
2027 if(data->state.resume_from) {
2028 LIBSSH2_SFTP_ATTRIBUTES attrs;
2029 if(data->state.resume_from < 0) {
2030 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2031 curlx_uztoui(strlen(sshp->path)),
2032 LIBSSH2_SFTP_STAT, &attrs);
2033 if(rc == LIBSSH2_ERROR_EAGAIN) {
2037 data->state.resume_from = 0;
2040 curl_off_t size = attrs.filesize;
2042 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
2043 return CURLE_BAD_DOWNLOAD_RESUME;
2045 data->state.resume_from = attrs.filesize;
2050 if(data->set.remote_append)
2051 /* Try to open for append, but create if nonexisting */
2052 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
2053 else if(data->state.resume_from > 0)
2054 /* If we have restart position then open for append */
2055 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
2057 /* Clear file before writing (normal behavior) */
2058 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
2061 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2062 curlx_uztoui(strlen(sshp->path)),
2063 flags, data->set.new_file_perms,
2064 LIBSSH2_SFTP_OPENFILE);
2066 if(!sshc->sftp_handle) {
2067 rc = libssh2_session_last_errno(sshc->ssh_session);
2069 if(LIBSSH2_ERROR_EAGAIN == rc)
2072 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
2073 /* only when there was an SFTP protocol error can we extract
2075 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2077 sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
2079 if(sshc->secondCreateDirs) {
2080 state(data, SSH_SFTP_CLOSE);
2081 sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
2082 sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
2083 failf(data, "Creating the dir/file failed: %s",
2084 sftp_libssh2_strerror(sftperr));
2087 if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
2088 (sftperr == LIBSSH2_FX_FAILURE) ||
2089 (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
2090 (data->set.ftp_create_missing_dirs &&
2091 (strlen(sshp->path) > 1))) {
2092 /* try to create the path remotely */
2093 rc = 0; /* clear rc and continue */
2094 sshc->secondCreateDirs = 1;
2095 state(data, SSH_SFTP_CREATE_DIRS_INIT);
2098 state(data, SSH_SFTP_CLOSE);
2099 sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
2100 sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
2101 if(!sshc->actualcode) {
2102 /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
2103 even though libssh2_sftp_open() failed previously! We need to
2104 work around that! */
2105 sshc->actualcode = CURLE_SSH;
2106 sftperr = LIBSSH2_FX_OK;
2108 failf(data, "Upload failed: %s (%lu/%d)",
2109 sftperr != LIBSSH2_FX_OK ?
2110 sftp_libssh2_strerror(sftperr):"ssh error",
2115 /* If we have a restart point then we need to seek to the correct
2117 if(data->state.resume_from > 0) {
2118 /* Let's read off the proper amount of bytes from the input. */
2119 if(conn->seek_func) {
2120 Curl_set_in_callback(data, true);
2121 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2123 Curl_set_in_callback(data, false);
2126 if(seekerr != CURL_SEEKFUNC_OK) {
2127 curl_off_t passed = 0;
2129 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2130 failf(data, "Could not seek stream");
2131 return CURLE_FTP_COULDNT_USE_REST;
2133 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2135 size_t readthisamountnow =
2136 (data->state.resume_from - passed > data->set.buffer_size) ?
2137 (size_t)data->set.buffer_size :
2138 curlx_sotouz(data->state.resume_from - passed);
2140 size_t actuallyread;
2141 Curl_set_in_callback(data, true);
2142 actuallyread = data->state.fread_func(data->state.buffer, 1,
2145 Curl_set_in_callback(data, false);
2147 passed += actuallyread;
2148 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2149 /* this checks for greater-than only to make sure that the
2150 CURL_READFUNC_ABORT return code still aborts */
2151 failf(data, "Failed to read data");
2152 return CURLE_FTP_COULDNT_USE_REST;
2154 } while(passed < data->state.resume_from);
2157 /* now, decrease the size of the read */
2158 if(data->state.infilesize > 0) {
2159 data->state.infilesize -= data->state.resume_from;
2160 data->req.size = data->state.infilesize;
2161 Curl_pgrsSetUploadSize(data, data->state.infilesize);
2164 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2166 if(data->state.infilesize > 0) {
2167 data->req.size = data->state.infilesize;
2168 Curl_pgrsSetUploadSize(data, data->state.infilesize);
2171 Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
2173 /* not set by Curl_setup_transfer to preserve keepon bits */
2174 conn->sockfd = conn->writesockfd;
2177 state(data, SSH_SFTP_CLOSE);
2178 sshc->actualcode = result;
2181 /* store this original bitmask setup to use later on if we can't
2182 figure out a "real" bitmask */
2183 sshc->orig_waitfor = data->req.keepon;
2185 /* we want to use the _sending_ function even when the socket turns
2186 out readable as the underlying libssh2 sftp send function will deal
2187 with both accordingly */
2188 conn->cselect_bits = CURL_CSELECT_OUT;
2190 /* since we don't really wait for anything at this point, we want the
2191 state machine to move on as soon as possible so we set a very short
2193 Curl_expire(data, 0, EXPIRE_RUN_NOW);
2195 state(data, SSH_STOP);
2200 case SSH_SFTP_CREATE_DIRS_INIT:
2201 if(strlen(sshp->path) > 1) {
2202 sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
2203 state(data, SSH_SFTP_CREATE_DIRS);
2206 state(data, SSH_SFTP_UPLOAD_INIT);
2210 case SSH_SFTP_CREATE_DIRS:
2211 sshc->slash_pos = strchr(sshc->slash_pos, '/');
2212 if(sshc->slash_pos) {
2213 *sshc->slash_pos = 0;
2215 infof(data, "Creating directory '%s'", sshp->path);
2216 state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
2219 state(data, SSH_SFTP_UPLOAD_INIT);
2222 case SSH_SFTP_CREATE_DIRS_MKDIR:
2223 /* 'mode' - parameter is preliminary - default to 0644 */
2224 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
2225 curlx_uztoui(strlen(sshp->path)),
2226 data->set.new_directory_perms);
2227 if(rc == LIBSSH2_ERROR_EAGAIN) {
2230 *sshc->slash_pos = '/';
2234 * Abort if failure wasn't that the dir already exists or the
2235 * permission was denied (creation might succeed further down the
2236 * path) - retry on unspecific FAILURE also
2238 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2239 if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
2240 (sftperr != LIBSSH2_FX_FAILURE) &&
2241 (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
2242 result = sftp_libssh2_error_to_CURLE(sftperr);
2243 state(data, SSH_SFTP_CLOSE);
2244 sshc->actualcode = result?result:CURLE_SSH;
2247 rc = 0; /* clear rc and continue */
2249 state(data, SSH_SFTP_CREATE_DIRS);
2252 case SSH_SFTP_READDIR_INIT:
2253 Curl_pgrsSetDownloadSize(data, -1);
2254 if(data->set.opt_no_body) {
2255 state(data, SSH_STOP);
2260 * This is a directory that we are trying to get, so produce a directory
2263 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
2266 strlen(sshp->path)),
2267 0, 0, LIBSSH2_SFTP_OPENDIR);
2268 if(!sshc->sftp_handle) {
2269 if(libssh2_session_last_errno(sshc->ssh_session) ==
2270 LIBSSH2_ERROR_EAGAIN) {
2271 rc = LIBSSH2_ERROR_EAGAIN;
2274 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2275 failf(data, "Could not open directory for reading: %s",
2276 sftp_libssh2_strerror(sftperr));
2277 state(data, SSH_SFTP_CLOSE);
2278 result = sftp_libssh2_error_to_CURLE(sftperr);
2279 sshc->actualcode = result?result:CURLE_SSH;
2282 sshp->readdir_filename = malloc(PATH_MAX + 1);
2283 if(!sshp->readdir_filename) {
2284 state(data, SSH_SFTP_CLOSE);
2285 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2288 sshp->readdir_longentry = malloc(PATH_MAX + 1);
2289 if(!sshp->readdir_longentry) {
2290 Curl_safefree(sshp->readdir_filename);
2291 state(data, SSH_SFTP_CLOSE);
2292 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2295 Curl_dyn_init(&sshp->readdir, PATH_MAX * 2);
2296 state(data, SSH_SFTP_READDIR);
2299 case SSH_SFTP_READDIR:
2300 rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
2301 sshp->readdir_filename,
2303 sshp->readdir_longentry,
2305 &sshp->readdir_attrs);
2306 if(rc == LIBSSH2_ERROR_EAGAIN) {
2310 readdir_len = (size_t) rc;
2311 sshp->readdir_filename[readdir_len] = '\0';
2313 if(data->set.list_only) {
2314 result = Curl_client_write(data, CLIENTWRITE_BODY,
2315 sshp->readdir_filename,
2318 result = Curl_client_write(data, CLIENTWRITE_BODY,
2321 state(data, SSH_STOP);
2324 /* since this counts what we send to the client, we include the
2325 newline in this counter */
2326 data->req.bytecount += readdir_len + 1;
2328 /* output debug output if that is requested */
2329 Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
2331 Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
2334 result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
2337 if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
2338 ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
2339 LIBSSH2_SFTP_S_IFLNK)) {
2340 Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
2341 result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
2342 sshp->readdir_filename);
2343 state(data, SSH_SFTP_READDIR_LINK);
2348 state(data, SSH_SFTP_READDIR_BOTTOM);
2352 sshc->actualcode = result;
2353 state(data, SSH_SFTP_CLOSE);
2358 Curl_safefree(sshp->readdir_filename);
2359 Curl_safefree(sshp->readdir_longentry);
2360 state(data, SSH_SFTP_READDIR_DONE);
2364 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2365 result = sftp_libssh2_error_to_CURLE(sftperr);
2366 sshc->actualcode = result?result:CURLE_SSH;
2367 failf(data, "Could not open remote file for reading: %s :: %d",
2368 sftp_libssh2_strerror(sftperr),
2369 libssh2_session_last_errno(sshc->ssh_session));
2370 Curl_safefree(sshp->readdir_filename);
2371 Curl_safefree(sshp->readdir_longentry);
2372 state(data, SSH_SFTP_CLOSE);
2377 case SSH_SFTP_READDIR_LINK:
2379 libssh2_sftp_symlink_ex(sshc->sftp_session,
2380 Curl_dyn_ptr(&sshp->readdir_link),
2381 (int)Curl_dyn_len(&sshp->readdir_link),
2382 sshp->readdir_filename,
2383 PATH_MAX, LIBSSH2_SFTP_READLINK);
2384 if(rc == LIBSSH2_ERROR_EAGAIN) {
2387 Curl_dyn_free(&sshp->readdir_link);
2389 /* append filename and extra output */
2390 result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
2393 sshc->readdir_line = NULL;
2394 Curl_safefree(sshp->readdir_filename);
2395 Curl_safefree(sshp->readdir_longentry);
2396 state(data, SSH_SFTP_CLOSE);
2397 sshc->actualcode = result;
2401 state(data, SSH_SFTP_READDIR_BOTTOM);
2404 case SSH_SFTP_READDIR_BOTTOM:
2405 result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
2407 result = Curl_client_write(data, CLIENTWRITE_BODY,
2408 Curl_dyn_ptr(&sshp->readdir),
2409 Curl_dyn_len(&sshp->readdir));
2412 /* output debug output if that is requested */
2413 Curl_debug(data, CURLINFO_DATA_IN,
2414 Curl_dyn_ptr(&sshp->readdir),
2415 Curl_dyn_len(&sshp->readdir));
2416 data->req.bytecount += Curl_dyn_len(&sshp->readdir);
2419 Curl_dyn_free(&sshp->readdir);
2420 state(data, SSH_STOP);
2423 Curl_dyn_reset(&sshp->readdir);
2424 state(data, SSH_SFTP_READDIR);
2428 case SSH_SFTP_READDIR_DONE:
2429 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2430 LIBSSH2_ERROR_EAGAIN) {
2431 rc = LIBSSH2_ERROR_EAGAIN;
2434 sshc->sftp_handle = NULL;
2435 Curl_safefree(sshp->readdir_filename);
2436 Curl_safefree(sshp->readdir_longentry);
2438 /* no data to transfer */
2439 Curl_setup_transfer(data, -1, -1, FALSE, -1);
2440 state(data, SSH_STOP);
2443 case SSH_SFTP_DOWNLOAD_INIT:
2445 * Work on getting the specified file
2448 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2449 curlx_uztoui(strlen(sshp->path)),
2450 LIBSSH2_FXF_READ, data->set.new_file_perms,
2451 LIBSSH2_SFTP_OPENFILE);
2452 if(!sshc->sftp_handle) {
2453 if(libssh2_session_last_errno(sshc->ssh_session) ==
2454 LIBSSH2_ERROR_EAGAIN) {
2455 rc = LIBSSH2_ERROR_EAGAIN;
2458 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2459 failf(data, "Could not open remote file for reading: %s",
2460 sftp_libssh2_strerror(sftperr));
2461 state(data, SSH_SFTP_CLOSE);
2462 result = sftp_libssh2_error_to_CURLE(sftperr);
2463 sshc->actualcode = result?result:CURLE_SSH;
2466 state(data, SSH_SFTP_DOWNLOAD_STAT);
2469 case SSH_SFTP_DOWNLOAD_STAT:
2471 LIBSSH2_SFTP_ATTRIBUTES attrs;
2473 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2474 curlx_uztoui(strlen(sshp->path)),
2475 LIBSSH2_SFTP_STAT, &attrs);
2476 if(rc == LIBSSH2_ERROR_EAGAIN) {
2480 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
2481 (attrs.filesize == 0)) {
2483 * libssh2_sftp_open() didn't return an error, so maybe the server
2484 * just doesn't support stat()
2485 * OR the server doesn't return a file size with a stat()
2488 data->req.size = -1;
2489 data->req.maxdownload = -1;
2490 Curl_pgrsSetDownloadSize(data, -1);
2493 curl_off_t size = attrs.filesize;
2496 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
2497 return CURLE_BAD_DOWNLOAD_RESUME;
2499 if(data->state.use_range) {
2500 curl_off_t from, to;
2506 from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
2507 if(from_t == CURL_OFFT_FLOW)
2508 return CURLE_RANGE_ERROR;
2509 while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
2511 to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
2512 if(to_t == CURL_OFFT_FLOW)
2513 return CURLE_RANGE_ERROR;
2514 if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
2519 /* from is relative to end of file */
2524 failf(data, "Offset (%"
2525 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
2526 CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
2527 return CURLE_BAD_DOWNLOAD_RESUME;
2534 size = to - from + 1;
2537 SFTP_SEEK(sshc->sftp_handle, from);
2539 data->req.size = size;
2540 data->req.maxdownload = size;
2541 Curl_pgrsSetDownloadSize(data, size);
2544 /* We can resume if we can seek to the resume position */
2545 if(data->state.resume_from) {
2546 if(data->state.resume_from < 0) {
2547 /* We're supposed to download the last abs(from) bytes */
2548 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
2549 failf(data, "Offset (%"
2550 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
2551 CURL_FORMAT_CURL_OFF_T ")",
2552 data->state.resume_from, attrs.filesize);
2553 return CURLE_BAD_DOWNLOAD_RESUME;
2555 /* download from where? */
2556 data->state.resume_from += attrs.filesize;
2559 if((curl_off_t)attrs.filesize < data->state.resume_from) {
2560 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2561 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
2562 data->state.resume_from, attrs.filesize);
2563 return CURLE_BAD_DOWNLOAD_RESUME;
2566 /* Now store the number of bytes we are expected to download */
2567 data->req.size = attrs.filesize - data->state.resume_from;
2568 data->req.maxdownload = attrs.filesize - data->state.resume_from;
2569 Curl_pgrsSetDownloadSize(data,
2570 attrs.filesize - data->state.resume_from);
2571 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2575 /* Setup the actual download */
2576 if(data->req.size == 0) {
2577 /* no data to transfer */
2578 Curl_setup_transfer(data, -1, -1, FALSE, -1);
2579 infof(data, "File already completely downloaded");
2580 state(data, SSH_STOP);
2583 Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
2585 /* not set by Curl_setup_transfer to preserve keepon bits */
2586 conn->writesockfd = conn->sockfd;
2588 /* we want to use the _receiving_ function even when the socket turns
2589 out writableable as the underlying libssh2 recv function will deal
2590 with both accordingly */
2591 conn->cselect_bits = CURL_CSELECT_IN;
2594 /* this should never occur; the close state should be entered
2595 at the time the error occurs */
2596 state(data, SSH_SFTP_CLOSE);
2597 sshc->actualcode = result;
2600 state(data, SSH_STOP);
2604 case SSH_SFTP_CLOSE:
2605 if(sshc->sftp_handle) {
2606 rc = libssh2_sftp_close(sshc->sftp_handle);
2607 if(rc == LIBSSH2_ERROR_EAGAIN) {
2611 char *err_msg = NULL;
2612 (void)libssh2_session_last_error(sshc->ssh_session,
2614 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2616 sshc->sftp_handle = NULL;
2619 Curl_safefree(sshp->path);
2621 DEBUGF(infof(data, "SFTP DONE done"));
2623 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2624 After nextstate is executed, the control should come back to
2625 SSH_SFTP_CLOSE to pass the correct result back */
2626 if(sshc->nextstate != SSH_NO_STATE &&
2627 sshc->nextstate != SSH_SFTP_CLOSE) {
2628 state(data, sshc->nextstate);
2629 sshc->nextstate = SSH_SFTP_CLOSE;
2632 state(data, SSH_STOP);
2633 result = sshc->actualcode;
2637 case SSH_SFTP_SHUTDOWN:
2638 /* during times we get here due to a broken transfer and then the
2639 sftp_handle might not have been taken down so make sure that is done
2640 before we proceed */
2642 if(sshc->sftp_handle) {
2643 rc = libssh2_sftp_close(sshc->sftp_handle);
2644 if(rc == LIBSSH2_ERROR_EAGAIN) {
2648 char *err_msg = NULL;
2649 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
2651 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2653 sshc->sftp_handle = NULL;
2655 if(sshc->sftp_session) {
2656 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2657 if(rc == LIBSSH2_ERROR_EAGAIN) {
2661 infof(data, "Failed to stop libssh2 sftp subsystem");
2663 sshc->sftp_session = NULL;
2666 Curl_safefree(sshc->homedir);
2667 data->state.most_recent_ftp_entrypath = NULL;
2669 state(data, SSH_SESSION_DISCONNECT);
2672 case SSH_SCP_TRANS_INIT:
2673 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
2675 sshc->actualcode = result;
2676 state(data, SSH_STOP);
2680 if(data->set.upload) {
2681 if(data->state.infilesize < 0) {
2682 failf(data, "SCP requires a known file size for upload");
2683 sshc->actualcode = CURLE_UPLOAD_FAILED;
2684 state(data, SSH_SCP_CHANNEL_FREE);
2687 state(data, SSH_SCP_UPLOAD_INIT);
2690 state(data, SSH_SCP_DOWNLOAD_INIT);
2694 case SSH_SCP_UPLOAD_INIT:
2696 * libssh2 requires that the destination path is a full path that
2697 * includes the destination file and name OR ends in a "/" . If this is
2698 * not done the destination file will be named the same name as the last
2699 * directory in the path.
2702 SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
2703 data->state.infilesize);
2704 if(!sshc->ssh_channel) {
2706 char *err_msg = NULL;
2708 if(libssh2_session_last_errno(sshc->ssh_session) ==
2709 LIBSSH2_ERROR_EAGAIN) {
2710 rc = LIBSSH2_ERROR_EAGAIN;
2714 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2715 &err_msg, NULL, 0));
2716 failf(data, "%s", err_msg);
2717 state(data, SSH_SCP_CHANNEL_FREE);
2718 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2719 /* Map generic errors to upload failed */
2720 if(sshc->actualcode == CURLE_SSH ||
2721 sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
2722 sshc->actualcode = CURLE_UPLOAD_FAILED;
2727 data->req.size = data->state.infilesize;
2728 Curl_pgrsSetUploadSize(data, data->state.infilesize);
2729 Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
2731 /* not set by Curl_setup_transfer to preserve keepon bits */
2732 conn->sockfd = conn->writesockfd;
2735 state(data, SSH_SCP_CHANNEL_FREE);
2736 sshc->actualcode = result;
2739 /* store this original bitmask setup to use later on if we can't
2740 figure out a "real" bitmask */
2741 sshc->orig_waitfor = data->req.keepon;
2743 /* we want to use the _sending_ function even when the socket turns
2744 out readable as the underlying libssh2 scp send function will deal
2745 with both accordingly */
2746 conn->cselect_bits = CURL_CSELECT_OUT;
2748 state(data, SSH_STOP);
2752 case SSH_SCP_DOWNLOAD_INIT:
2754 curl_off_t bytecount;
2757 * We must check the remote file; if it is a directory no values will
2762 * If support for >2GB files exists, use it.
2765 /* get a fresh new channel from the ssh layer */
2766 #if LIBSSH2_VERSION_NUM < 0x010700
2768 memset(&sb, 0, sizeof(struct stat));
2769 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2772 libssh2_struct_stat sb;
2773 memset(&sb, 0, sizeof(libssh2_struct_stat));
2774 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
2778 if(!sshc->ssh_channel) {
2780 char *err_msg = NULL;
2782 if(libssh2_session_last_errno(sshc->ssh_session) ==
2783 LIBSSH2_ERROR_EAGAIN) {
2784 rc = LIBSSH2_ERROR_EAGAIN;
2789 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2790 &err_msg, NULL, 0));
2791 failf(data, "%s", err_msg);
2792 state(data, SSH_SCP_CHANNEL_FREE);
2793 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2798 bytecount = (curl_off_t)sb.st_size;
2799 data->req.maxdownload = (curl_off_t)sb.st_size;
2800 Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
2802 /* not set by Curl_setup_transfer to preserve keepon bits */
2803 conn->writesockfd = conn->sockfd;
2805 /* we want to use the _receiving_ function even when the socket turns
2806 out writableable as the underlying libssh2 recv function will deal
2807 with both accordingly */
2808 conn->cselect_bits = CURL_CSELECT_IN;
2811 state(data, SSH_SCP_CHANNEL_FREE);
2812 sshc->actualcode = result;
2815 state(data, SSH_STOP);
2820 if(data->set.upload)
2821 state(data, SSH_SCP_SEND_EOF);
2823 state(data, SSH_SCP_CHANNEL_FREE);
2826 case SSH_SCP_SEND_EOF:
2827 if(sshc->ssh_channel) {
2828 rc = libssh2_channel_send_eof(sshc->ssh_channel);
2829 if(rc == LIBSSH2_ERROR_EAGAIN) {
2833 char *err_msg = NULL;
2834 (void)libssh2_session_last_error(sshc->ssh_session,
2836 infof(data, "Failed to send libssh2 channel EOF: %d %s",
2840 state(data, SSH_SCP_WAIT_EOF);
2843 case SSH_SCP_WAIT_EOF:
2844 if(sshc->ssh_channel) {
2845 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2846 if(rc == LIBSSH2_ERROR_EAGAIN) {
2850 char *err_msg = NULL;
2851 (void)libssh2_session_last_error(sshc->ssh_session,
2853 infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
2856 state(data, SSH_SCP_WAIT_CLOSE);
2859 case SSH_SCP_WAIT_CLOSE:
2860 if(sshc->ssh_channel) {
2861 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2862 if(rc == LIBSSH2_ERROR_EAGAIN) {
2866 char *err_msg = NULL;
2867 (void)libssh2_session_last_error(sshc->ssh_session,
2869 infof(data, "Channel failed to close: %d %s", rc, err_msg);
2872 state(data, SSH_SCP_CHANNEL_FREE);
2875 case SSH_SCP_CHANNEL_FREE:
2876 if(sshc->ssh_channel) {
2877 rc = libssh2_channel_free(sshc->ssh_channel);
2878 if(rc == LIBSSH2_ERROR_EAGAIN) {
2882 char *err_msg = NULL;
2883 (void)libssh2_session_last_error(sshc->ssh_session,
2885 infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2888 sshc->ssh_channel = NULL;
2890 DEBUGF(infof(data, "SCP DONE phase complete"));
2892 state(data, SSH_SESSION_DISCONNECT);
2894 state(data, SSH_STOP);
2895 result = sshc->actualcode;
2898 case SSH_SESSION_DISCONNECT:
2899 /* during weird times when we've been prematurely aborted, the channel
2900 is still alive when we reach this state and we MUST kill the channel
2902 if(sshc->ssh_channel) {
2903 rc = libssh2_channel_free(sshc->ssh_channel);
2904 if(rc == LIBSSH2_ERROR_EAGAIN) {
2908 char *err_msg = NULL;
2909 (void)libssh2_session_last_error(sshc->ssh_session,
2911 infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2914 sshc->ssh_channel = NULL;
2917 if(sshc->ssh_session) {
2918 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2919 if(rc == LIBSSH2_ERROR_EAGAIN) {
2923 char *err_msg = NULL;
2924 (void)libssh2_session_last_error(sshc->ssh_session,
2926 infof(data, "Failed to disconnect libssh2 session: %d %s",
2931 Curl_safefree(sshc->homedir);
2932 data->state.most_recent_ftp_entrypath = NULL;
2934 state(data, SSH_SESSION_FREE);
2937 case SSH_SESSION_FREE:
2938 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2940 libssh2_knownhost_free(sshc->kh);
2945 #ifdef HAVE_LIBSSH2_AGENT_API
2946 if(sshc->ssh_agent) {
2947 rc = libssh2_agent_disconnect(sshc->ssh_agent);
2948 if(rc == LIBSSH2_ERROR_EAGAIN) {
2952 char *err_msg = NULL;
2953 (void)libssh2_session_last_error(sshc->ssh_session,
2955 infof(data, "Failed to disconnect from libssh2 agent: %d %s",
2958 libssh2_agent_free(sshc->ssh_agent);
2959 sshc->ssh_agent = NULL;
2961 /* NB: there is no need to free identities, they are part of internal
2963 sshc->sshagent_identity = NULL;
2964 sshc->sshagent_prev_identity = NULL;
2968 if(sshc->ssh_session) {
2969 rc = libssh2_session_free(sshc->ssh_session);
2970 if(rc == LIBSSH2_ERROR_EAGAIN) {
2974 char *err_msg = NULL;
2975 (void)libssh2_session_last_error(sshc->ssh_session,
2977 infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
2979 sshc->ssh_session = NULL;
2982 /* worst-case scenario cleanup */
2984 DEBUGASSERT(sshc->ssh_session == NULL);
2985 DEBUGASSERT(sshc->ssh_channel == NULL);
2986 DEBUGASSERT(sshc->sftp_session == NULL);
2987 DEBUGASSERT(sshc->sftp_handle == NULL);
2988 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2989 DEBUGASSERT(sshc->kh == NULL);
2991 #ifdef HAVE_LIBSSH2_AGENT_API
2992 DEBUGASSERT(sshc->ssh_agent == NULL);
2995 Curl_safefree(sshc->rsa_pub);
2996 Curl_safefree(sshc->rsa);
2998 Curl_safefree(sshc->quote_path1);
2999 Curl_safefree(sshc->quote_path2);
3001 Curl_safefree(sshc->homedir);
3002 Curl_safefree(sshc->readdir_line);
3004 /* the code we are about to return */
3005 result = sshc->actualcode;
3007 memset(sshc, 0, sizeof(struct ssh_conn));
3009 connclose(conn, "SSH session free");
3010 sshc->state = SSH_SESSION_FREE; /* current */
3011 sshc->nextstate = SSH_NO_STATE;
3012 state(data, SSH_STOP);
3016 /* fallthrough, just stop! */
3018 /* internal error */
3019 sshc->nextstate = SSH_NO_STATE;
3020 state(data, SSH_STOP);
3024 } while(!rc && (sshc->state != SSH_STOP));
3026 if(rc == LIBSSH2_ERROR_EAGAIN) {
3027 /* we would block, we need to wait for the socket to be ready (in the
3028 right direction too)! */
3035 /* called by the multi interface to figure out what socket(s) to wait for and
3036 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
3037 static int ssh_getsock(struct Curl_easy *data,
3038 struct connectdata *conn,
3039 curl_socket_t *sock)
3041 int bitmap = GETSOCK_BLANK;
3044 sock[0] = conn->sock[FIRSTSOCKET];
3046 if(conn->waitfor & KEEP_RECV)
3047 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
3049 if(conn->waitfor & KEEP_SEND)
3050 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
3056 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
3057 * function is used to figure out in what direction and stores this info so
3058 * that the multi interface can take advantage of it. Make sure to call this
3059 * function in all cases so that when it _doesn't_ return EAGAIN we can
3060 * restore the default wait bits.
3062 static void ssh_block2waitfor(struct Curl_easy *data, bool block)
3064 struct connectdata *conn = data->conn;
3065 struct ssh_conn *sshc = &conn->proto.sshc;
3068 dir = libssh2_session_block_directions(sshc->ssh_session);
3070 /* translate the libssh2 define bits into our own bit defines */
3071 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
3072 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
3076 /* It didn't block or libssh2 didn't reveal in which direction, put back
3078 conn->waitfor = sshc->orig_waitfor;
3081 /* called repeatedly until done from multi.c */
3082 static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
3084 struct connectdata *conn = data->conn;
3085 struct ssh_conn *sshc = &conn->proto.sshc;
3086 CURLcode result = CURLE_OK;
3087 bool block; /* we store the status and use that to provide a ssh_getsock()
3090 result = ssh_statemach_act(data, &block);
3091 *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
3092 /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
3094 } while(!result && !*done && !block);
3095 ssh_block2waitfor(data, block);
3100 static CURLcode ssh_block_statemach(struct Curl_easy *data,
3101 struct connectdata *conn,
3104 struct ssh_conn *sshc = &conn->proto.sshc;
3105 CURLcode result = CURLE_OK;
3106 struct curltime dis = Curl_now();
3108 while((sshc->state != SSH_STOP) && !result) {
3110 timediff_t left = 1000;
3111 struct curltime now = Curl_now();
3113 result = ssh_statemach_act(data, &block);
3118 if(Curl_pgrsUpdate(data))
3119 return CURLE_ABORTED_BY_CALLBACK;
3121 result = Curl_speedcheck(data, now);
3125 left = Curl_timeleft(data, NULL, FALSE);
3127 failf(data, "Operation timed out");
3128 return CURLE_OPERATION_TIMEDOUT;
3131 else if(Curl_timediff(now, dis) > 1000) {
3132 /* disconnect timeout */
3133 failf(data, "Disconnect timed out");
3139 int dir = libssh2_session_block_directions(sshc->ssh_session);
3140 curl_socket_t sock = conn->sock[FIRSTSOCKET];
3141 curl_socket_t fd_read = CURL_SOCKET_BAD;
3142 curl_socket_t fd_write = CURL_SOCKET_BAD;
3143 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
3145 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
3147 /* wait for the socket to become ready */
3148 (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
3149 left>1000?1000:left);
3157 * SSH setup and connection
3159 static CURLcode ssh_setup_connection(struct Curl_easy *data,
3160 struct connectdata *conn)
3162 struct SSHPROTO *ssh;
3165 data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
3167 return CURLE_OUT_OF_MEMORY;
3172 static Curl_recv scp_recv, sftp_recv;
3173 static Curl_send scp_send, sftp_send;
3175 #ifndef CURL_DISABLE_PROXY
3176 static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
3177 size_t length, int flags, void **abstract)
3179 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3182 struct connectdata *conn = data->conn;
3183 Curl_recv *backup = conn->recv[0];
3184 struct ssh_conn *ssh = &conn->proto.sshc;
3187 /* swap in the TLS reader function for this call only, and then swap back
3188 the SSH one again */
3189 conn->recv[0] = ssh->tls_recv;
3190 result = Curl_read(data, sock, buffer, length, &nread);
3191 conn->recv[0] = backup;
3192 if(result == CURLE_AGAIN)
3193 return -EAGAIN; /* magic return code for libssh2 */
3195 return -1; /* generic error */
3196 Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
3200 static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
3201 size_t length, int flags, void **abstract)
3203 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3206 struct connectdata *conn = data->conn;
3207 Curl_send *backup = conn->send[0];
3208 struct ssh_conn *ssh = &conn->proto.sshc;
3211 /* swap in the TLS writer function for this call only, and then swap back
3212 the SSH one again */
3213 conn->send[0] = ssh->tls_send;
3214 result = Curl_write(data, sock, buffer, length, &nwrite);
3215 conn->send[0] = backup;
3216 if(result == CURLE_AGAIN)
3217 return -EAGAIN; /* magic return code for libssh2 */
3219 return -1; /* error */
3220 Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
3226 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
3227 * do protocol-specific actions at connect-time.
3229 static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
3231 #ifdef CURL_LIBSSH2_DEBUG
3234 struct ssh_conn *sshc;
3236 struct connectdata *conn = data->conn;
3238 /* initialize per-handle data if not already */
3239 if(!data->req.p.ssh) {
3240 result = ssh_setup_connection(data, conn);
3245 /* We default to persistent connections. We set this already in this connect
3246 function to make the re-use checks properly be able to check this bit. */
3247 connkeep(conn, "SSH default");
3249 sshc = &conn->proto.sshc;
3251 #ifdef CURL_LIBSSH2_DEBUG
3253 infof(data, "User: %s", conn->user);
3256 infof(data, "Password: %s", conn->passwd);
3258 sock = conn->sock[FIRSTSOCKET];
3259 #endif /* CURL_LIBSSH2_DEBUG */
3261 sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
3263 my_libssh2_realloc, data);
3264 if(!sshc->ssh_session) {
3265 failf(data, "Failure initialising ssh session");
3266 return CURLE_FAILED_INIT;
3269 #ifndef CURL_DISABLE_PROXY
3270 if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
3272 * This crazy union dance is here to avoid assigning a void pointer a
3273 * function pointer as it is invalid C. The problem is of course that
3274 * libssh2 has such an API...
3278 ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
3282 ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
3284 union receive sshrecv;
3285 union transfer sshsend;
3287 sshrecv.recvptr = ssh_tls_recv;
3288 sshsend.sendptr = ssh_tls_send;
3290 infof(data, "Uses HTTPS proxy");
3292 Setup libssh2 callbacks to make it read/write TLS from the socket.
3295 recvcb(libssh2_socket_t sock, void *buffer, size_t length,
3296 int flags, void **abstract);
3299 sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
3300 int flags, void **abstract);
3303 libssh2_session_callback_set(sshc->ssh_session,
3304 LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
3305 libssh2_session_callback_set(sshc->ssh_session,
3306 LIBSSH2_CALLBACK_SEND, sshsend.sendp);
3308 /* Store the underlying TLS recv/send function pointers to be used when
3309 reading from the proxy */
3310 sshc->tls_recv = conn->recv[FIRSTSOCKET];
3311 sshc->tls_send = conn->send[FIRSTSOCKET];
3314 #endif /* CURL_DISABLE_PROXY */
3315 if(conn->handler->protocol & CURLPROTO_SCP) {
3316 conn->recv[FIRSTSOCKET] = scp_recv;
3317 conn->send[FIRSTSOCKET] = scp_send;
3320 conn->recv[FIRSTSOCKET] = sftp_recv;
3321 conn->send[FIRSTSOCKET] = sftp_send;
3324 if(data->set.ssh_compression) {
3325 #if LIBSSH2_VERSION_NUM >= 0x010208
3326 if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
3328 infof(data, "Failed to enable compression for ssh session");
3331 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
3332 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
3334 sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
3336 libssh2_session_free(sshc->ssh_session);
3337 sshc->ssh_session = NULL;
3338 return CURLE_FAILED_INIT;
3341 /* read all known hosts from there */
3342 rc = libssh2_knownhost_readfile(sshc->kh,
3343 data->set.str[STRING_SSH_KNOWNHOSTS],
3344 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
3346 infof(data, "Failed to read known hosts from %s",
3347 data->set.str[STRING_SSH_KNOWNHOSTS]);
3349 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
3351 #ifdef CURL_LIBSSH2_DEBUG
3352 libssh2_trace(sshc->ssh_session, ~0);
3353 infof(data, "SSH socket: %d", (int)sock);
3354 #endif /* CURL_LIBSSH2_DEBUG */
3356 state(data, SSH_INIT);
3358 result = ssh_multi_statemach(data, done);
3364 ***********************************************************************
3368 * This is the actual DO function for SCP. Get a file according to
3369 * the options previously setup.
3373 CURLcode scp_perform(struct Curl_easy *data,
3377 CURLcode result = CURLE_OK;
3378 struct connectdata *conn = data->conn;
3380 DEBUGF(infof(data, "DO phase starts"));
3382 *dophase_done = FALSE; /* not done yet */
3384 /* start the first command in the DO phase */
3385 state(data, SSH_SCP_TRANS_INIT);
3387 /* run the state-machine */
3388 result = ssh_multi_statemach(data, dophase_done);
3390 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
3393 DEBUGF(infof(data, "DO phase is complete"));
3399 /* called from multi.c while DOing */
3400 static CURLcode scp_doing(struct Curl_easy *data,
3404 result = ssh_multi_statemach(data, dophase_done);
3407 DEBUGF(infof(data, "DO phase is complete"));
3413 * The DO function is generic for both protocols. There was previously two
3414 * separate ones but this way means less duplicated code.
3417 static CURLcode ssh_do(struct Curl_easy *data, bool *done)
3421 struct connectdata *conn = data->conn;
3422 struct ssh_conn *sshc = &conn->proto.sshc;
3424 *done = FALSE; /* default to false */
3426 data->req.size = -1; /* make sure this is unknown at this point */
3428 sshc->actualcode = CURLE_OK; /* reset error code */
3429 sshc->secondCreateDirs = 0; /* reset the create dir attempt state
3432 Curl_pgrsSetUploadCounter(data, 0);
3433 Curl_pgrsSetDownloadCounter(data, 0);
3434 Curl_pgrsSetUploadSize(data, -1);
3435 Curl_pgrsSetDownloadSize(data, -1);
3437 if(conn->handler->protocol & CURLPROTO_SCP)
3438 result = scp_perform(data, &connected, done);
3440 result = sftp_perform(data, &connected, done);
3445 /* BLOCKING, but the function is using the state machine so the only reason
3446 this is still blocking is that the multi interface code has no support for
3447 disconnecting operations that takes a while */
3448 static CURLcode scp_disconnect(struct Curl_easy *data,
3449 struct connectdata *conn,
3450 bool dead_connection)
3452 CURLcode result = CURLE_OK;
3453 struct ssh_conn *sshc = &conn->proto.sshc;
3454 (void) dead_connection;
3456 if(sshc->ssh_session) {
3457 /* only if there's a session still around to use! */
3458 state(data, SSH_SESSION_DISCONNECT);
3459 result = ssh_block_statemach(data, conn, TRUE);
3465 /* generic done function for both SCP and SFTP called from their specific
3467 static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
3469 CURLcode result = CURLE_OK;
3470 struct SSHPROTO *sshp = data->req.p.ssh;
3471 struct connectdata *conn = data->conn;
3474 /* run the state-machine */
3475 result = ssh_block_statemach(data, conn, FALSE);
3479 Curl_safefree(sshp->path);
3480 Curl_safefree(sshp->readdir_filename);
3481 Curl_safefree(sshp->readdir_longentry);
3482 Curl_dyn_free(&sshp->readdir);
3484 if(Curl_pgrsDone(data))
3485 return CURLE_ABORTED_BY_CALLBACK;
3487 data->req.keepon = 0; /* clear all bits */
3492 static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
3495 (void)premature; /* not used */
3498 state(data, SSH_SCP_DONE);
3500 return ssh_done(data, status);
3504 static ssize_t scp_send(struct Curl_easy *data, int sockindex,
3505 const void *mem, size_t len, CURLcode *err)
3508 struct connectdata *conn = data->conn;
3509 struct ssh_conn *sshc = &conn->proto.sshc;
3510 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3512 /* libssh2_channel_write() returns int! */
3513 nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
3515 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3517 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3521 else if(nwrite < LIBSSH2_ERROR_NONE) {
3522 *err = libssh2_session_error_to_CURLE((int)nwrite);
3529 static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
3530 char *mem, size_t len, CURLcode *err)
3533 struct connectdata *conn = data->conn;
3534 struct ssh_conn *sshc = &conn->proto.sshc;
3535 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3537 /* libssh2_channel_read() returns int */
3538 nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
3540 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3541 if(nread == LIBSSH2_ERROR_EAGAIN) {
3550 * =============== SFTP ===============
3554 ***********************************************************************
3558 * This is the actual DO function for SFTP. Get a file/directory according to
3559 * the options previously setup.
3563 CURLcode sftp_perform(struct Curl_easy *data,
3567 CURLcode result = CURLE_OK;
3569 DEBUGF(infof(data, "DO phase starts"));
3571 *dophase_done = FALSE; /* not done yet */
3573 /* start the first command in the DO phase */
3574 state(data, SSH_SFTP_QUOTE_INIT);
3576 /* run the state-machine */
3577 result = ssh_multi_statemach(data, dophase_done);
3579 *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
3582 DEBUGF(infof(data, "DO phase is complete"));
3588 /* called from multi.c while DOing */
3589 static CURLcode sftp_doing(struct Curl_easy *data,
3592 CURLcode result = ssh_multi_statemach(data, dophase_done);
3595 DEBUGF(infof(data, "DO phase is complete"));
3600 /* BLOCKING, but the function is using the state machine so the only reason
3601 this is still blocking is that the multi interface code has no support for
3602 disconnecting operations that takes a while */
3603 static CURLcode sftp_disconnect(struct Curl_easy *data,
3604 struct connectdata *conn, bool dead_connection)
3606 CURLcode result = CURLE_OK;
3607 struct ssh_conn *sshc = &conn->proto.sshc;
3608 (void) dead_connection;
3610 DEBUGF(infof(data, "SSH DISCONNECT starts now"));
3612 if(sshc->ssh_session) {
3613 /* only if there's a session still around to use! */
3614 state(data, SSH_SFTP_SHUTDOWN);
3615 result = ssh_block_statemach(data, conn, TRUE);
3618 DEBUGF(infof(data, "SSH DISCONNECT is done"));
3624 static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
3627 struct connectdata *conn = data->conn;
3628 struct ssh_conn *sshc = &conn->proto.sshc;
3631 /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3632 errors that could happen due to open file handles during POSTQUOTE
3634 if(!premature && data->set.postquote && !conn->bits.retry)
3635 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3636 state(data, SSH_SFTP_CLOSE);
3638 return ssh_done(data, status);
3641 /* return number of sent bytes */
3642 static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
3643 const void *mem, size_t len, CURLcode *err)
3646 struct connectdata *conn = data->conn;
3647 struct ssh_conn *sshc = &conn->proto.sshc;
3650 nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
3652 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3654 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3658 else if(nwrite < LIBSSH2_ERROR_NONE) {
3659 *err = libssh2_session_error_to_CURLE((int)nwrite);
3667 * Return number of received (decrypted) bytes
3670 static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
3671 char *mem, size_t len, CURLcode *err)
3674 struct connectdata *conn = data->conn;
3675 struct ssh_conn *sshc = &conn->proto.sshc;
3678 nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
3680 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3682 if(nread == LIBSSH2_ERROR_EAGAIN) {
3687 else if(nread < 0) {
3688 *err = libssh2_session_error_to_CURLE((int)nread);
3693 static const char *sftp_libssh2_strerror(unsigned long err)
3696 case LIBSSH2_FX_NO_SUCH_FILE:
3697 return "No such file or directory";
3699 case LIBSSH2_FX_PERMISSION_DENIED:
3700 return "Permission denied";
3702 case LIBSSH2_FX_FAILURE:
3703 return "Operation failed";
3705 case LIBSSH2_FX_BAD_MESSAGE:
3706 return "Bad message from SFTP server";
3708 case LIBSSH2_FX_NO_CONNECTION:
3709 return "Not connected to SFTP server";
3711 case LIBSSH2_FX_CONNECTION_LOST:
3712 return "Connection to SFTP server lost";
3714 case LIBSSH2_FX_OP_UNSUPPORTED:
3715 return "Operation not supported by SFTP server";
3717 case LIBSSH2_FX_INVALID_HANDLE:
3718 return "Invalid handle";
3720 case LIBSSH2_FX_NO_SUCH_PATH:
3721 return "No such file or directory";
3723 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3724 return "File already exists";
3726 case LIBSSH2_FX_WRITE_PROTECT:
3727 return "File is write protected";
3729 case LIBSSH2_FX_NO_MEDIA:
3732 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3735 case LIBSSH2_FX_QUOTA_EXCEEDED:
3736 return "User quota exceeded";
3738 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3739 return "Unknown principle";
3741 case LIBSSH2_FX_LOCK_CONFlICT:
3742 return "File lock conflict";
3744 case LIBSSH2_FX_DIR_NOT_EMPTY:
3745 return "Directory not empty";
3747 case LIBSSH2_FX_NOT_A_DIRECTORY:
3748 return "Not a directory";
3750 case LIBSSH2_FX_INVALID_FILENAME:
3751 return "Invalid filename";
3753 case LIBSSH2_FX_LINK_LOOP:
3754 return "Link points to itself";
3756 return "Unknown error in libssh2";
3759 CURLcode Curl_ssh_init(void)
3761 #ifdef HAVE_LIBSSH2_INIT
3762 if(libssh2_init(0)) {
3763 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
3764 return CURLE_FAILED_INIT;
3770 void Curl_ssh_cleanup(void)
3772 #ifdef HAVE_LIBSSH2_EXIT
3773 (void)libssh2_exit();
3777 void Curl_ssh_version(char *buffer, size_t buflen)
3779 (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION);
3782 /* The SSH session is associated with the *CONNECTION* but the callback user
3783 * pointer is an easy handle pointer. This function allows us to reassign the
3784 * user pointer to the *CURRENT* (new) easy handle.
3786 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
3790 if(conn->handler->protocol & PROTO_FAMILY_SSH) {
3791 struct ssh_conn *sshc = &conn->proto.sshc;
3792 if(sshc->ssh_session) {
3793 /* only re-attach if the session already exists */
3794 void **abstract = libssh2_session_abstract(sshc->ssh_session);
3799 #endif /* USE_LIBSSH2 */