1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2011, 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 http://curl.haxx.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 ***************************************************************************/
23 /* #define CURL_LIBSSH2_DEBUG */
38 #include <libssh2_sftp.h>
53 #ifdef HAVE_SYS_SOCKET_H
54 #include <sys/socket.h>
56 #ifdef HAVE_NETINET_IN_H
57 #include <netinet/in.h>
59 #ifdef HAVE_ARPA_INET_H
60 #include <arpa/inet.h>
63 #include <sys/utsname.h>
74 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
76 #define in_addr_t unsigned long
79 #include <curl/curl.h>
82 #include "easyif.h" /* for Curl_convert_... prototypes */
88 #include "http.h" /* for HTTP proxy tunnel stuff */
91 #include "speedcheck.h"
98 #include "inet_ntop.h"
99 #include "parsedate.h" /* for the week day and month names */
100 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
101 #include "strtoofft.h"
104 #include "warnless.h"
106 #define _MPRINTF_REPLACE /* use our functions only */
107 #include <curl/mprintf.h>
109 #include "curl_memory.h"
110 /* The last #include file should be: */
111 #include "memdebug.h"
114 #define PATH_MAX 1024 /* just an extra precaution since there are systems that
115 have their definition hidden well */
118 /* Local functions: */
119 static const char *sftp_libssh2_strerror(unsigned long err);
120 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
121 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
122 static LIBSSH2_FREE_FUNC(my_libssh2_free);
124 static CURLcode get_pathname(const char **cpp, char **path);
126 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
127 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
128 static CURLcode ssh_do(struct connectdata *conn, bool *done);
130 static CURLcode ssh_getworkingpath(struct connectdata *conn,
131 char *homedir, /* when SFTP is used */
134 static CURLcode scp_done(struct connectdata *conn,
135 CURLcode, bool premature);
136 static CURLcode scp_doing(struct connectdata *conn,
138 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
140 static CURLcode sftp_done(struct connectdata *conn,
141 CURLcode, bool premature);
142 static CURLcode sftp_doing(struct connectdata *conn,
144 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection);
146 CURLcode sftp_perform(struct connectdata *conn,
150 static int ssh_getsock(struct connectdata *conn,
151 curl_socket_t *sock, /* points to numsocks number
155 static int ssh_perform_getsock(const struct connectdata *conn,
156 curl_socket_t *sock, /* points to numsocks
161 * SCP protocol handler.
164 const struct Curl_handler Curl_handler_scp = {
166 ZERO_NULL, /* setup_connection */
169 ZERO_NULL, /* do_more */
170 ssh_connect, /* connect_it */
171 ssh_multi_statemach, /* connecting */
172 scp_doing, /* doing */
173 ssh_getsock, /* proto_getsock */
174 ssh_getsock, /* doing_getsock */
175 ssh_perform_getsock, /* perform_getsock */
176 scp_disconnect, /* disconnect */
177 PORT_SSH, /* defport */
178 PROT_SCP /* protocol */
183 * SFTP protocol handler.
186 const struct Curl_handler Curl_handler_sftp = {
188 ZERO_NULL, /* setup_connection */
190 sftp_done, /* done */
191 ZERO_NULL, /* do_more */
192 ssh_connect, /* connect_it */
193 ssh_multi_statemach, /* connecting */
194 sftp_doing, /* doing */
195 ssh_getsock, /* proto_getsock */
196 ssh_getsock, /* doing_getsock */
197 ssh_perform_getsock, /* perform_getsock */
198 sftp_disconnect, /* disconnect */
199 PORT_SSH, /* defport */
200 PROT_SFTP /* protocol */
205 kbd_callback(const char *name, int name_len, const char *instruction,
206 int instruction_len, int num_prompts,
207 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
208 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
211 struct connectdata *conn = (struct connectdata *)*abstract;
213 #ifdef CURL_LIBSSH2_DEBUG
214 fprintf(stderr, "name=%s\n", name);
215 fprintf(stderr, "name_len=%d\n", name_len);
216 fprintf(stderr, "instruction=%s\n", instruction);
217 fprintf(stderr, "instruction_len=%d\n", instruction_len);
218 fprintf(stderr, "num_prompts=%d\n", num_prompts);
223 (void)instruction_len;
224 #endif /* CURL_LIBSSH2_DEBUG */
225 if(num_prompts == 1) {
226 responses[0].text = strdup(conn->passwd);
227 responses[0].length = (unsigned int)strlen(conn->passwd);
233 static CURLcode sftp_libssh2_error_to_CURLE(int err)
239 case LIBSSH2_FX_NO_SUCH_FILE:
240 case LIBSSH2_FX_NO_SUCH_PATH:
241 return CURLE_REMOTE_FILE_NOT_FOUND;
243 case LIBSSH2_FX_PERMISSION_DENIED:
244 case LIBSSH2_FX_WRITE_PROTECT:
245 case LIBSSH2_FX_LOCK_CONFlICT:
246 return CURLE_REMOTE_ACCESS_DENIED;
248 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
249 case LIBSSH2_FX_QUOTA_EXCEEDED:
250 return CURLE_REMOTE_DISK_FULL;
252 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
253 return CURLE_REMOTE_FILE_EXISTS;
255 case LIBSSH2_FX_DIR_NOT_EMPTY:
256 return CURLE_QUOTE_ERROR;
265 static CURLcode libssh2_session_error_to_CURLE(int err)
268 /* Ordered by order of appearance in libssh2.h */
269 case LIBSSH2_ERROR_NONE:
272 case LIBSSH2_ERROR_SOCKET_NONE:
273 return CURLE_COULDNT_CONNECT;
275 case LIBSSH2_ERROR_ALLOC:
276 return CURLE_OUT_OF_MEMORY;
278 case LIBSSH2_ERROR_SOCKET_SEND:
279 return CURLE_SEND_ERROR;
281 case LIBSSH2_ERROR_HOSTKEY_INIT:
282 case LIBSSH2_ERROR_HOSTKEY_SIGN:
283 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
284 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
285 return CURLE_PEER_FAILED_VERIFICATION;
287 case LIBSSH2_ERROR_PASSWORD_EXPIRED:
288 return CURLE_LOGIN_DENIED;
290 case LIBSSH2_ERROR_SOCKET_TIMEOUT:
291 case LIBSSH2_ERROR_TIMEOUT:
292 return CURLE_OPERATION_TIMEDOUT;
294 case LIBSSH2_ERROR_EAGAIN:
298 /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
299 error code, and possibly add a few new SSH-related one. We must however
300 not return or even depend on libssh2 errors in the public libcurl API */
305 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
307 (void)abstract; /* arg not used */
308 return malloc(count);
311 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
313 (void)abstract; /* arg not used */
314 return realloc(ptr, count);
317 static LIBSSH2_FREE_FUNC(my_libssh2_free)
319 (void)abstract; /* arg not used */
324 * SSH State machine related code
326 /* This is the ONLY way to change SSH state! */
327 static void state(struct connectdata *conn, sshstate nowstate)
329 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
330 /* for debug purposes */
331 static const char * const names[] = {
336 "SSH_AUTH_PKEY_INIT",
338 "SSH_AUTH_PASS_INIT",
340 "SSH_AUTH_HOST_INIT",
347 "SSH_SFTP_QUOTE_INIT",
348 "SSH_SFTP_POSTQUOTE_INIT",
350 "SSH_SFTP_NEXT_QUOTE",
351 "SSH_SFTP_QUOTE_STAT",
352 "SSH_SFTP_QUOTE_SETSTAT",
353 "SSH_SFTP_QUOTE_SYMLINK",
354 "SSH_SFTP_QUOTE_MKDIR",
355 "SSH_SFTP_QUOTE_RENAME",
356 "SSH_SFTP_QUOTE_RMDIR",
357 "SSH_SFTP_QUOTE_UNLINK",
358 "SSH_SFTP_TRANS_INIT",
359 "SSH_SFTP_UPLOAD_INIT",
360 "SSH_SFTP_CREATE_DIRS_INIT",
361 "SSH_SFTP_CREATE_DIRS",
362 "SSH_SFTP_CREATE_DIRS_MKDIR",
363 "SSH_SFTP_READDIR_INIT",
365 "SSH_SFTP_READDIR_LINK",
366 "SSH_SFTP_READDIR_BOTTOM",
367 "SSH_SFTP_READDIR_DONE",
368 "SSH_SFTP_DOWNLOAD_INIT",
369 "SSH_SFTP_DOWNLOAD_STAT",
372 "SSH_SCP_TRANS_INIT",
373 "SSH_SCP_UPLOAD_INIT",
374 "SSH_SCP_DOWNLOAD_INIT",
378 "SSH_SCP_WAIT_CLOSE",
379 "SSH_SCP_CHANNEL_FREE",
380 "SSH_SESSION_DISCONNECT",
385 struct ssh_conn *sshc = &conn->proto.sshc;
387 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
388 if(sshc->state != nowstate) {
389 infof(conn->data, "SFTP %p state change from %s to %s\n",
390 sshc, names[sshc->state], names[nowstate]);
394 sshc->state = nowstate;
397 /* figure out the path to work with in this particular request */
398 static CURLcode ssh_getworkingpath(struct connectdata *conn,
399 char *homedir, /* when SFTP is used */
400 char **path) /* returns the allocated
401 real path to work with */
403 struct SessionHandle *data = conn->data;
404 char *real_path = NULL;
406 int working_path_len;
408 working_path = curl_easy_unescape(data, data->state.path, 0,
411 return CURLE_OUT_OF_MEMORY;
413 /* Check for /~/ , indicating relative to the user's home directory */
414 if(conn->protocol & PROT_SCP) {
415 real_path = malloc(working_path_len+1);
416 if(real_path == NULL) {
418 return CURLE_OUT_OF_MEMORY;
420 if((working_path_len > 1) && (working_path[1] == '~'))
421 /* It is referenced to the home directory, so strip the leading '/' */
422 memcpy(real_path, working_path+1, 1 + working_path_len-1);
424 memcpy(real_path, working_path, 1 + working_path_len);
426 else if(conn->protocol & PROT_SFTP) {
427 if((working_path_len > 1) && (working_path[1] == '~')) {
428 size_t homelen = strlen(homedir);
429 real_path = malloc(homelen + working_path_len + 1);
430 if(real_path == NULL) {
432 return CURLE_OUT_OF_MEMORY;
434 /* It is referenced to the home directory, so strip the
436 memcpy(real_path, homedir, homelen);
437 real_path[homelen] = '/';
438 real_path[homelen+1] = '\0';
439 if(working_path_len > 3) {
440 memcpy(real_path+homelen+1, working_path + 3,
441 1 + working_path_len -3);
445 real_path = malloc(working_path_len+1);
446 if(real_path == NULL) {
448 return CURLE_OUT_OF_MEMORY;
450 memcpy(real_path, working_path, 1+working_path_len);
456 /* store the pointer for the caller to receive */
462 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
463 static int sshkeycallback(CURL *easy,
464 const struct curl_khkey *knownkey, /* known */
465 const struct curl_khkey *foundkey, /* found */
466 enum curl_khmatch match,
474 /* we only allow perfect matches, and we reject everything else */
475 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
480 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
483 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
484 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
486 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
490 * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
491 * architectures so we check of the necessary function is present.
493 #ifndef HAVE_LIBSSH2_SCP_SEND64
494 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
496 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
497 (libssh2_uint64_t)d, 0, 0)
501 * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
503 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
504 #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
508 * ssh_statemach_act() runs the SSH state machine as far as it can without
509 * blocking and without reaching the end. The data the pointer 'block' points
510 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
511 * meaning it wants to be called again when the socket is ready
514 static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
516 CURLcode result = CURLE_OK;
517 struct SessionHandle *data = conn->data;
518 struct SSHPROTO *sftp_scp = data->state.proto.ssh;
519 struct ssh_conn *sshc = &conn->proto.sshc;
520 curl_socket_t sock = conn->sock[FIRSTSOCKET];
521 #ifdef CURL_LIBSSH2_DEBUG
522 const char *fingerprint;
523 #endif /* CURL_LIBSSH2_DEBUG */
524 const char *host_public_key_md5;
525 int rc = LIBSSH2_ERROR_NONE, i;
527 int seekerr = CURL_SEEKFUNC_OK;
528 *block = 0; /* we're not blocking by default */
532 switch(sshc->state) {
534 sshc->secondCreateDirs = 0;
535 sshc->nextstate = SSH_NO_STATE;
536 sshc->actualcode = CURLE_OK;
538 rc = libssh2_session_startup(sshc->ssh_session, sock);
539 if(rc == LIBSSH2_ERROR_EAGAIN) {
543 failf(data, "Failure establishing ssh session");
544 state(conn, SSH_SESSION_FREE);
545 sshc->actualcode = CURLE_FAILED_INIT;
549 /* Set libssh2 to non-blocking, since everything internally is
551 libssh2_session_set_blocking(sshc->ssh_session, 0);
553 state(conn, SSH_HOSTKEY);
558 #ifdef CURL_LIBSSH2_DEBUG
560 * Before we authenticate we should check the hostkey's fingerprint
561 * against our known hosts. How that is handled (reading from file,
562 * whatever) is up to us. As for know not much is implemented, besides
563 * showing how to get the fingerprint.
565 fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
566 LIBSSH2_HOSTKEY_HASH_MD5);
568 /* The fingerprint points to static storage (!), don't free() it. */
569 infof(data, "Fingerprint: ");
570 for (rc = 0; rc < 16; rc++) {
571 infof(data, "%02X ", (unsigned char) fingerprint[rc]);
574 #endif /* CURL_LIBSSH2_DEBUG */
576 /* Before we authenticate we check the hostkey's MD5 fingerprint
577 * against a known fingerprint, if available. This implementation pulls
578 * it from the curl option.
580 if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
581 strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) {
583 host_public_key_md5 = libssh2_hostkey_hash(sshc->ssh_session,
584 LIBSSH2_HOSTKEY_HASH_MD5);
585 for (i = 0; i < 16; i++)
586 snprintf(&buf[i*2], 3, "%02x",
587 (unsigned char) host_public_key_md5[i]);
588 if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) {
590 "Denied establishing ssh session: mismatch md5 fingerprint. "
591 "Remote %s is not equal to %s",
592 buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]);
593 state(conn, SSH_SESSION_FREE);
594 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
599 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
600 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
601 /* we're asked to verify the host against a file */
604 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
611 * A subject to figure out is what host name we need to pass in here.
612 * What host name does OpenSSH store in its file if an IDN name is
615 struct libssh2_knownhost *host;
616 enum curl_khmatch keymatch;
617 curl_sshkeycallback func =
618 data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
619 struct curl_khkey knownkey;
620 struct curl_khkey *knownkeyp = NULL;
621 struct curl_khkey foundkey;
623 keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
624 LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
626 keycheck = libssh2_knownhost_check(sshc->kh,
629 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
630 LIBSSH2_KNOWNHOST_KEYENC_RAW|
634 infof(data, "SSH host check: %d, key: %s\n", keycheck,
635 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
638 /* setup 'knownkey' */
639 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
640 knownkey.key = host->key;
642 knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
643 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
644 knownkeyp = &knownkey;
647 /* setup 'foundkey' */
648 foundkey.key = remotekey;
649 foundkey.len = keylen;
650 foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
651 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
654 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
655 * curl_khmatch enum are ever modified, we need to introduce a
656 * translation table here!
658 keymatch = (enum curl_khmatch)keycheck;
660 /* Ask the callback how to behave */
661 rc = func(data, knownkeyp, /* from the knownhosts file */
662 &foundkey, /* from the remote host */
663 keymatch, data->set.ssh_keyfunc_userp);
666 /* no remotekey means failure! */
667 rc = CURLKHSTAT_REJECT;
670 default: /* unknown return codes will equal reject */
671 case CURLKHSTAT_REJECT:
672 state(conn, SSH_SESSION_FREE);
673 case CURLKHSTAT_DEFER:
674 /* DEFER means bail out but keep the SSH_HOSTKEY state */
675 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
677 case CURLKHSTAT_FINE:
678 case CURLKHSTAT_FINE_ADD_TO_FILE:
680 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
681 /* the found host+key didn't match but has been told to be fine
682 anyway so we add it in memory */
683 int addrc = libssh2_knownhost_add(sshc->kh,
684 conn->host.name, NULL,
686 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
687 LIBSSH2_KNOWNHOST_KEYENC_RAW|
690 infof(data, "Warning adding the known host %s failed!\n",
692 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
693 /* now we write the entire in-memory list of known hosts to the
696 libssh2_knownhost_writefile(sshc->kh,
697 data->set.str[STRING_SSH_KNOWNHOSTS],
698 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
700 infof(data, "Warning, writing %s failed!\n",
701 data->set.str[STRING_SSH_KNOWNHOSTS]);
708 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
710 state(conn, SSH_AUTHLIST);
715 * Figure out authentication methods
716 * NB: As soon as we have provided a username to an openssh server we
717 * must never change it later. Thus, always specify the correct username
718 * here, even though the libssh2 docs kind of indicate that it should be
719 * possible to get a 'generic' list (not user-specific) of authentication
720 * methods, presumably with a blank username. That won't work in my
722 * So always specify it here.
724 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
726 (unsigned int)strlen(conn->user));
728 if(!sshc->authlist) {
729 if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
730 LIBSSH2_ERROR_EAGAIN) {
731 rc = LIBSSH2_ERROR_EAGAIN;
735 state(conn, SSH_SESSION_FREE);
736 sshc->actualcode = libssh2_session_error_to_CURLE(err);
740 infof(data, "SSH authentication methods available: %s\n",
743 state(conn, SSH_AUTH_PKEY_INIT);
746 case SSH_AUTH_PKEY_INIT:
748 * Check the supported auth types in the order I feel is most secure
749 * with the requested type of authentication
751 sshc->authed = FALSE;
753 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
754 (strstr(sshc->authlist, "publickey") != NULL)) {
757 sshc->rsa_pub = sshc->rsa = NULL;
759 /* To ponder about: should really the lib be messing about with the
760 HOME environment variable etc? */
761 home = curl_getenv("HOME");
763 if(data->set.str[STRING_SSH_PUBLIC_KEY])
764 sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]);
766 sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
768 /* as a final resort, try current dir! */
769 sshc->rsa_pub = strdup("id_dsa.pub");
771 if(sshc->rsa_pub == NULL) {
774 state(conn, SSH_SESSION_FREE);
775 sshc->actualcode = CURLE_OUT_OF_MEMORY;
779 if(data->set.str[STRING_SSH_PRIVATE_KEY])
780 sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]);
782 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
784 /* as a final resort, try current dir! */
785 sshc->rsa = strdup("id_dsa");
787 if(sshc->rsa == NULL) {
790 Curl_safefree(sshc->rsa_pub);
791 sshc->rsa_pub = NULL;
792 state(conn, SSH_SESSION_FREE);
793 sshc->actualcode = CURLE_OUT_OF_MEMORY;
797 sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
798 if(!sshc->passphrase)
799 sshc->passphrase = "";
804 infof(data, "Using ssh public key file %s\n", sshc->rsa_pub);
805 infof(data, "Using ssh private key file %s\n", sshc->rsa);
807 state(conn, SSH_AUTH_PKEY);
810 state(conn, SSH_AUTH_PASS_INIT);
815 /* The function below checks if the files exists, no need to stat() here.
817 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
822 sshc->rsa, sshc->passphrase);
823 if(rc == LIBSSH2_ERROR_EAGAIN) {
827 Curl_safefree(sshc->rsa_pub);
828 sshc->rsa_pub = NULL;
829 Curl_safefree(sshc->rsa);
834 infof(data, "Initialized SSH public key authentication\n");
835 state(conn, SSH_AUTH_DONE);
839 (void)libssh2_session_last_error(sshc->ssh_session,
841 infof(data, "SSH public key authentication failed: %s\n", err_msg);
842 state(conn, SSH_AUTH_PASS_INIT);
846 case SSH_AUTH_PASS_INIT:
847 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
848 (strstr(sshc->authlist, "password") != NULL)) {
849 state(conn, SSH_AUTH_PASS);
852 state(conn, SSH_AUTH_HOST_INIT);
857 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
858 (unsigned int)strlen(conn->user),
860 (unsigned int)strlen(conn->passwd),
862 if(rc == LIBSSH2_ERROR_EAGAIN) {
867 infof(data, "Initialized password authentication\n");
868 state(conn, SSH_AUTH_DONE);
871 state(conn, SSH_AUTH_HOST_INIT);
875 case SSH_AUTH_HOST_INIT:
876 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
877 (strstr(sshc->authlist, "hostbased") != NULL)) {
878 state(conn, SSH_AUTH_HOST);
881 state(conn, SSH_AUTH_KEY_INIT);
886 state(conn, SSH_AUTH_KEY_INIT);
889 case SSH_AUTH_KEY_INIT:
890 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
891 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
892 state(conn, SSH_AUTH_KEY);
895 state(conn, SSH_AUTH_DONE);
900 /* Authentication failed. Continue with keyboard-interactive now. */
901 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
906 if(rc == LIBSSH2_ERROR_EAGAIN) {
911 infof(data, "Initialized keyboard interactive authentication\n");
913 state(conn, SSH_AUTH_DONE);
918 failf(data, "Authentication failure");
919 state(conn, SSH_SESSION_FREE);
920 sshc->actualcode = CURLE_LOGIN_DENIED;
925 * At this point we have an authenticated ssh session.
927 infof(data, "Authentication complete\n");
929 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
932 conn->writesockfd = CURL_SOCKET_BAD;
934 if(conn->protocol == PROT_SFTP) {
935 state(conn, SSH_SFTP_INIT);
938 infof(data, "SSH CONNECT phase done\n");
939 state(conn, SSH_STOP);
944 * Start the libssh2 sftp session
946 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
947 if(!sshc->sftp_session) {
948 if(libssh2_session_last_errno(sshc->ssh_session) ==
949 LIBSSH2_ERROR_EAGAIN) {
950 rc = LIBSSH2_ERROR_EAGAIN;
956 (void)libssh2_session_last_error(sshc->ssh_session,
958 failf(data, "Failure initializing sftp session: %s", err_msg);
959 state(conn, SSH_SESSION_FREE);
960 sshc->actualcode = CURLE_FAILED_INIT;
964 state(conn, SSH_SFTP_REALPATH);
967 case SSH_SFTP_REALPATH:
969 char tempHome[PATH_MAX];
972 * Get the "home" directory
974 rc = libssh2_sftp_realpath(sshc->sftp_session, ".",
975 tempHome, PATH_MAX-1);
976 if(rc == LIBSSH2_ERROR_EAGAIN) {
980 /* It seems that this string is not always NULL terminated */
982 sshc->homedir = strdup(tempHome);
984 state(conn, SSH_SFTP_CLOSE);
985 sshc->actualcode = CURLE_OUT_OF_MEMORY;
988 conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
991 /* Return the error type */
992 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
993 result = sftp_libssh2_error_to_CURLE(err);
994 sshc->actualcode = result?result:CURLE_SSH;
995 DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
997 state(conn, SSH_STOP);
1001 /* This is the last step in the SFTP connect phase. Do note that while
1002 we get the homedir here, we get the "workingpath" in the DO action
1003 since the homedir will remain the same between request but the
1004 working path will not. */
1005 DEBUGF(infof(data, "SSH CONNECT phase done\n"));
1006 state(conn, SSH_STOP);
1009 case SSH_SFTP_QUOTE_INIT:
1011 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
1013 sshc->actualcode = result;
1014 state(conn, SSH_STOP);
1018 if(data->set.quote) {
1019 infof(data, "Sending quote commands\n");
1020 sshc->quote_item = data->set.quote;
1021 state(conn, SSH_SFTP_QUOTE);
1024 state(conn, SSH_SFTP_TRANS_INIT);
1028 case SSH_SFTP_POSTQUOTE_INIT:
1029 if(data->set.postquote) {
1030 infof(data, "Sending quote commands\n");
1031 sshc->quote_item = data->set.postquote;
1032 state(conn, SSH_SFTP_QUOTE);
1035 state(conn, SSH_STOP);
1039 case SSH_SFTP_QUOTE:
1040 /* Send any quote commands */
1045 * Support some of the "FTP" commands
1047 if(curl_strequal("pwd", sshc->quote_item->data)) {
1048 /* output debug output if that is requested */
1049 char *tmp = aprintf("257 \"%s\" is current directory.\n",
1052 result = CURLE_OUT_OF_MEMORY;
1053 state(conn, SSH_SFTP_CLOSE);
1056 if(data->set.verbose) {
1057 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
1058 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
1060 /* this sends an FTP-like "header" to the header callback so that the
1061 current directory can be read very similar to how it is read when
1062 using ordinary FTP. */
1063 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1065 state(conn, SSH_SFTP_NEXT_QUOTE);
1068 else if(sshc->quote_item->data) {
1070 * the arguments following the command must be separated from the
1071 * command with a space so we can check for it unconditionally
1073 cp = strchr(sshc->quote_item->data, ' ');
1075 failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
1076 state(conn, SSH_SFTP_CLOSE);
1077 sshc->actualcode = CURLE_QUOTE_ERROR;
1082 * also, every command takes at least one argument so we get that
1083 * first argument right now
1085 result = get_pathname(&cp, &sshc->quote_path1);
1087 if(result == CURLE_OUT_OF_MEMORY)
1088 failf(data, "Out of memory");
1090 failf(data, "Syntax error: Bad first parameter");
1091 state(conn, SSH_SFTP_CLOSE);
1092 sshc->actualcode = result;
1097 * SFTP is a binary protocol, so we don't send text commands to
1098 * the server. Instead, we scan for commands for commands used by
1099 * OpenSSH's sftp program and call the appropriate libssh2
1102 if(curl_strnequal(sshc->quote_item->data, "chgrp ", 6) ||
1103 curl_strnequal(sshc->quote_item->data, "chmod ", 6) ||
1104 curl_strnequal(sshc->quote_item->data, "chown ", 6) ) {
1105 /* attribute change */
1107 /* sshc->quote_path1 contains the mode to set */
1108 /* get the destination */
1109 result = get_pathname(&cp, &sshc->quote_path2);
1111 if(result == CURLE_OUT_OF_MEMORY)
1112 failf(data, "Out of memory");
1114 failf(data, "Syntax error in chgrp/chmod/chown: "
1115 "Bad second parameter");
1116 Curl_safefree(sshc->quote_path1);
1117 sshc->quote_path1 = NULL;
1118 state(conn, SSH_SFTP_CLOSE);
1119 sshc->actualcode = result;
1122 memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1123 state(conn, SSH_SFTP_QUOTE_STAT);
1126 else if(curl_strnequal(sshc->quote_item->data, "ln ", 3) ||
1127 curl_strnequal(sshc->quote_item->data, "symlink ", 8)) {
1128 /* symbolic linking */
1129 /* sshc->quote_path1 is the source */
1130 /* get the destination */
1131 result = get_pathname(&cp, &sshc->quote_path2);
1133 if(result == CURLE_OUT_OF_MEMORY)
1134 failf(data, "Out of memory");
1137 "Syntax error in ln/symlink: Bad second parameter");
1138 Curl_safefree(sshc->quote_path1);
1139 sshc->quote_path1 = NULL;
1140 state(conn, SSH_SFTP_CLOSE);
1141 sshc->actualcode = result;
1144 state(conn, SSH_SFTP_QUOTE_SYMLINK);
1147 else if(curl_strnequal(sshc->quote_item->data, "mkdir ", 6)) {
1149 state(conn, SSH_SFTP_QUOTE_MKDIR);
1152 else if(curl_strnequal(sshc->quote_item->data, "rename ", 7)) {
1154 /* first param is the source path */
1155 /* second param is the dest. path */
1156 result = get_pathname(&cp, &sshc->quote_path2);
1158 if(result == CURLE_OUT_OF_MEMORY)
1159 failf(data, "Out of memory");
1161 failf(data, "Syntax error in rename: Bad second parameter");
1162 Curl_safefree(sshc->quote_path1);
1163 sshc->quote_path1 = NULL;
1164 state(conn, SSH_SFTP_CLOSE);
1165 sshc->actualcode = result;
1168 state(conn, SSH_SFTP_QUOTE_RENAME);
1171 else if(curl_strnequal(sshc->quote_item->data, "rmdir ", 6)) {
1173 state(conn, SSH_SFTP_QUOTE_RMDIR);
1176 else if(curl_strnequal(sshc->quote_item->data, "rm ", 3)) {
1177 state(conn, SSH_SFTP_QUOTE_UNLINK);
1181 failf(data, "Unknown SFTP command");
1182 Curl_safefree(sshc->quote_path1);
1183 sshc->quote_path1 = NULL;
1184 Curl_safefree(sshc->quote_path2);
1185 sshc->quote_path2 = NULL;
1186 state(conn, SSH_SFTP_CLOSE);
1187 sshc->actualcode = CURLE_QUOTE_ERROR;
1191 if(!sshc->quote_item) {
1192 state(conn, SSH_SFTP_TRANS_INIT);
1196 case SSH_SFTP_NEXT_QUOTE:
1197 if(sshc->quote_path1) {
1198 Curl_safefree(sshc->quote_path1);
1199 sshc->quote_path1 = NULL;
1201 if(sshc->quote_path2) {
1202 Curl_safefree(sshc->quote_path2);
1203 sshc->quote_path2 = NULL;
1206 sshc->quote_item = sshc->quote_item->next;
1208 if(sshc->quote_item) {
1209 state(conn, SSH_SFTP_QUOTE);
1212 if(sshc->nextstate != SSH_NO_STATE) {
1213 state(conn, sshc->nextstate);
1214 sshc->nextstate = SSH_NO_STATE;
1217 state(conn, SSH_SFTP_TRANS_INIT);
1222 case SSH_SFTP_QUOTE_STAT:
1223 if(!curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
1224 /* Since chown and chgrp only set owner OR group but libssh2 wants to
1225 * set them both at once, we need to obtain the current ownership
1226 * first. This takes an extra protocol round trip.
1228 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1229 (unsigned int)strlen(sshc->quote_path2),
1231 &sshc->quote_attrs);
1232 if(rc == LIBSSH2_ERROR_EAGAIN) {
1235 else if(rc != 0) { /* get those attributes */
1236 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1237 Curl_safefree(sshc->quote_path1);
1238 sshc->quote_path1 = NULL;
1239 Curl_safefree(sshc->quote_path2);
1240 sshc->quote_path2 = NULL;
1241 failf(data, "Attempt to get SFTP stats failed: %s",
1242 sftp_libssh2_strerror(err));
1243 state(conn, SSH_SFTP_CLOSE);
1244 sshc->actualcode = CURLE_QUOTE_ERROR;
1249 /* Now set the new attributes... */
1250 if(curl_strnequal(sshc->quote_item->data, "chgrp", 5)) {
1251 sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
1252 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1253 if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
1254 Curl_safefree(sshc->quote_path1);
1255 sshc->quote_path1 = NULL;
1256 Curl_safefree(sshc->quote_path2);
1257 sshc->quote_path2 = NULL;
1258 failf(data, "Syntax error: chgrp gid not a number");
1259 state(conn, SSH_SFTP_CLOSE);
1260 sshc->actualcode = CURLE_QUOTE_ERROR;
1264 else if(curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
1265 sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
1266 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1267 /* permissions are octal */
1268 if(sshc->quote_attrs.permissions == 0 &&
1269 !ISDIGIT(sshc->quote_path1[0])) {
1270 Curl_safefree(sshc->quote_path1);
1271 sshc->quote_path1 = NULL;
1272 Curl_safefree(sshc->quote_path2);
1273 sshc->quote_path2 = NULL;
1274 failf(data, "Syntax error: chmod permissions not a number");
1275 state(conn, SSH_SFTP_CLOSE);
1276 sshc->actualcode = CURLE_QUOTE_ERROR;
1280 else if(curl_strnequal(sshc->quote_item->data, "chown", 5)) {
1281 sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
1282 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1283 if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
1284 Curl_safefree(sshc->quote_path1);
1285 sshc->quote_path1 = NULL;
1286 Curl_safefree(sshc->quote_path2);
1287 sshc->quote_path2 = NULL;
1288 failf(data, "Syntax error: chown uid not a number");
1289 state(conn, SSH_SFTP_CLOSE);
1290 sshc->actualcode = CURLE_QUOTE_ERROR;
1295 /* Now send the completed structure... */
1296 state(conn, SSH_SFTP_QUOTE_SETSTAT);
1299 case SSH_SFTP_QUOTE_SETSTAT:
1300 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1301 (unsigned int)strlen(sshc->quote_path2),
1302 LIBSSH2_SFTP_SETSTAT,
1303 &sshc->quote_attrs);
1304 if(rc == LIBSSH2_ERROR_EAGAIN) {
1308 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1309 Curl_safefree(sshc->quote_path1);
1310 sshc->quote_path1 = NULL;
1311 Curl_safefree(sshc->quote_path2);
1312 sshc->quote_path2 = NULL;
1313 failf(data, "Attempt to set SFTP stats failed: %s",
1314 sftp_libssh2_strerror(err));
1315 state(conn, SSH_SFTP_CLOSE);
1316 sshc->actualcode = CURLE_QUOTE_ERROR;
1319 state(conn, SSH_SFTP_NEXT_QUOTE);
1322 case SSH_SFTP_QUOTE_SYMLINK:
1323 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
1324 (unsigned int)strlen(sshc->quote_path1),
1326 (unsigned int)strlen(sshc->quote_path2),
1327 LIBSSH2_SFTP_SYMLINK);
1328 if(rc == LIBSSH2_ERROR_EAGAIN) {
1332 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1333 Curl_safefree(sshc->quote_path1);
1334 sshc->quote_path1 = NULL;
1335 Curl_safefree(sshc->quote_path2);
1336 sshc->quote_path2 = NULL;
1337 failf(data, "symlink command failed: %s",
1338 sftp_libssh2_strerror(err));
1339 state(conn, SSH_SFTP_CLOSE);
1340 sshc->actualcode = CURLE_QUOTE_ERROR;
1343 state(conn, SSH_SFTP_NEXT_QUOTE);
1346 case SSH_SFTP_QUOTE_MKDIR:
1347 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
1348 (unsigned int)strlen(sshc->quote_path1),
1350 if(rc == LIBSSH2_ERROR_EAGAIN) {
1354 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1355 Curl_safefree(sshc->quote_path1);
1356 sshc->quote_path1 = NULL;
1357 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
1358 state(conn, SSH_SFTP_CLOSE);
1359 sshc->actualcode = CURLE_QUOTE_ERROR;
1362 state(conn, SSH_SFTP_NEXT_QUOTE);
1365 case SSH_SFTP_QUOTE_RENAME:
1366 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
1367 (unsigned int)strlen(sshc->quote_path1),
1369 (unsigned int)strlen(sshc->quote_path2),
1370 LIBSSH2_SFTP_RENAME_OVERWRITE |
1371 LIBSSH2_SFTP_RENAME_ATOMIC |
1372 LIBSSH2_SFTP_RENAME_NATIVE);
1373 if(rc == LIBSSH2_ERROR_EAGAIN) {
1377 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1378 Curl_safefree(sshc->quote_path1);
1379 sshc->quote_path1 = NULL;
1380 Curl_safefree(sshc->quote_path2);
1381 sshc->quote_path2 = NULL;
1382 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
1383 state(conn, SSH_SFTP_CLOSE);
1384 sshc->actualcode = CURLE_QUOTE_ERROR;
1387 state(conn, SSH_SFTP_NEXT_QUOTE);
1390 case SSH_SFTP_QUOTE_RMDIR:
1391 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
1392 (unsigned int)strlen(sshc->quote_path1));
1393 if(rc == LIBSSH2_ERROR_EAGAIN) {
1397 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1398 Curl_safefree(sshc->quote_path1);
1399 sshc->quote_path1 = NULL;
1400 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
1401 state(conn, SSH_SFTP_CLOSE);
1402 sshc->actualcode = CURLE_QUOTE_ERROR;
1405 state(conn, SSH_SFTP_NEXT_QUOTE);
1408 case SSH_SFTP_QUOTE_UNLINK:
1409 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
1410 (unsigned int)strlen(sshc->quote_path1));
1411 if(rc == LIBSSH2_ERROR_EAGAIN) {
1415 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1416 Curl_safefree(sshc->quote_path1);
1417 sshc->quote_path1 = NULL;
1418 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
1419 state(conn, SSH_SFTP_CLOSE);
1420 sshc->actualcode = CURLE_QUOTE_ERROR;
1423 state(conn, SSH_SFTP_NEXT_QUOTE);
1426 case SSH_SFTP_TRANS_INIT:
1427 if(data->set.upload)
1428 state(conn, SSH_SFTP_UPLOAD_INIT);
1430 if(data->set.opt_no_body)
1431 state(conn, SSH_STOP);
1432 else if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
1433 state(conn, SSH_SFTP_READDIR_INIT);
1435 state(conn, SSH_SFTP_DOWNLOAD_INIT);
1439 case SSH_SFTP_UPLOAD_INIT:
1441 unsigned long flags;
1443 * NOTE!!! libssh2 requires that the destination path is a full path
1444 * that includes the destination file and name OR ends in a "/"
1445 * If this is not done the destination file will be named the
1446 * same name as the last directory in the path.
1449 if(data->state.resume_from != 0) {
1450 LIBSSH2_SFTP_ATTRIBUTES attrs;
1451 if(data->state.resume_from < 0) {
1452 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
1453 (unsigned int)strlen(sftp_scp->path),
1454 LIBSSH2_SFTP_STAT, &attrs);
1455 if(rc == LIBSSH2_ERROR_EAGAIN) {
1459 data->state.resume_from = 0;
1462 curl_off_t size = attrs.filesize;
1464 failf(data, "Bad file size (%" FORMAT_OFF_T ")", size);
1465 return CURLE_BAD_DOWNLOAD_RESUME;
1467 data->state.resume_from = attrs.filesize;
1472 if(data->set.ftp_append)
1473 /* Try to open for append, but create if nonexisting */
1474 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
1475 else if (data->state.resume_from > 0)
1476 /* If we have restart position then open for append */
1477 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
1479 /* Clear file before writing (normal behaviour) */
1480 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
1483 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
1484 (unsigned int)strlen(sftp_scp->path),
1485 flags, data->set.new_file_perms,
1486 LIBSSH2_SFTP_OPENFILE);
1488 if(!sshc->sftp_handle) {
1489 rc = libssh2_session_last_errno(sshc->ssh_session);
1491 if(LIBSSH2_ERROR_EAGAIN == rc)
1494 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
1495 /* only when there was an SFTP protocol error can we extract
1497 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1499 err = -1; /* not an sftp error at all */
1501 if(sshc->secondCreateDirs) {
1502 state(conn, SSH_SFTP_CLOSE);
1503 sshc->actualcode = err>= LIBSSH2_FX_OK?
1504 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1505 failf(data, "Creating the dir/file failed: %s",
1506 sftp_libssh2_strerror(err));
1509 else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
1510 (err == LIBSSH2_FX_FAILURE) ||
1511 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
1512 (data->set.ftp_create_missing_dirs &&
1513 (strlen(sftp_scp->path) > 1))) {
1514 /* try to create the path remotely */
1515 sshc->secondCreateDirs = 1;
1516 state(conn, SSH_SFTP_CREATE_DIRS_INIT);
1519 state(conn, SSH_SFTP_CLOSE);
1520 sshc->actualcode = err>= LIBSSH2_FX_OK?
1521 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1522 if(!sshc->actualcode) {
1523 /* Sometimes, for some reason libssh2_sftp_last_error() returns
1524 zero even though libssh2_sftp_open() failed previously! We need
1525 to work around that! */
1526 sshc->actualcode = CURLE_SSH;
1529 failf(data, "Upload failed: %s (%d/%d)",
1530 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
1536 /* If we have restart point then we need to seek to the correct
1538 if(data->state.resume_from > 0) {
1539 /* Let's read off the proper amount of bytes from the input. */
1540 if(conn->seek_func) {
1541 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1545 if(seekerr != CURL_SEEKFUNC_OK){
1547 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1548 failf(data, "Could not seek stream");
1549 return CURLE_FTP_COULDNT_USE_REST;
1551 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
1553 curl_off_t passed=0;
1555 size_t readthisamountnow =
1556 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
1557 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
1559 size_t actuallyread =
1560 conn->fread_func(data->state.buffer, 1, readthisamountnow,
1563 passed += actuallyread;
1564 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1565 /* this checks for greater-than only to make sure that the
1566 CURL_READFUNC_ABORT return code still aborts */
1567 failf(data, "Failed to read data");
1568 return CURLE_FTP_COULDNT_USE_REST;
1570 } while(passed < data->state.resume_from);
1574 /* now, decrease the size of the read */
1575 if(data->set.infilesize > 0) {
1576 data->set.infilesize -= data->state.resume_from;
1577 data->req.size = data->set.infilesize;
1578 Curl_pgrsSetUploadSize(data, data->set.infilesize);
1581 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1583 if(data->set.infilesize > 0) {
1584 data->req.size = data->set.infilesize;
1585 Curl_pgrsSetUploadSize(data, data->set.infilesize);
1588 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
1590 /* not set by Curl_setup_transfer to preserve keepon bits */
1591 conn->sockfd = conn->writesockfd;
1594 state(conn, SSH_SFTP_CLOSE);
1595 sshc->actualcode = result;
1598 /* store this original bitmask setup to use later on if we can't
1599 figure out a "real" bitmask */
1600 sshc->orig_waitfor = data->req.keepon;
1602 state(conn, SSH_STOP);
1607 case SSH_SFTP_CREATE_DIRS_INIT:
1608 if(strlen(sftp_scp->path) > 1) {
1609 sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
1610 state(conn, SSH_SFTP_CREATE_DIRS);
1613 state(conn, SSH_SFTP_UPLOAD_INIT);
1617 case SSH_SFTP_CREATE_DIRS:
1618 if((sshc->slash_pos = strchr(sshc->slash_pos, '/')) != NULL) {
1619 *sshc->slash_pos = 0;
1621 infof(data, "Creating directory '%s'\n", sftp_scp->path);
1622 state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
1626 state(conn, SSH_SFTP_UPLOAD_INIT);
1630 case SSH_SFTP_CREATE_DIRS_MKDIR:
1631 /* 'mode' - parameter is preliminary - default to 0644 */
1632 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
1633 (unsigned int)strlen(sftp_scp->path),
1634 data->set.new_directory_perms);
1635 if(rc == LIBSSH2_ERROR_EAGAIN) {
1638 *sshc->slash_pos = '/';
1641 unsigned int sftp_err = 0;
1643 * Abort if failure wasn't that the dir already exists or the
1644 * permission was denied (creation might succeed further down the
1645 * path) - retry on unspecific FAILURE also
1647 sftp_err = (unsigned int)(libssh2_sftp_last_error(sshc->sftp_session));
1648 if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
1649 (sftp_err != LIBSSH2_FX_FAILURE) &&
1650 (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) {
1651 result = sftp_libssh2_error_to_CURLE(sftp_err);
1652 state(conn, SSH_SFTP_CLOSE);
1653 sshc->actualcode = result?result:CURLE_SSH;
1657 state(conn, SSH_SFTP_CREATE_DIRS);
1660 case SSH_SFTP_READDIR_INIT:
1662 * This is a directory that we are trying to get, so produce a directory
1665 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
1668 strlen(sftp_scp->path),
1669 0, 0, LIBSSH2_SFTP_OPENDIR);
1670 if(!sshc->sftp_handle) {
1671 if(libssh2_session_last_errno(sshc->ssh_session) ==
1672 LIBSSH2_ERROR_EAGAIN) {
1673 rc = LIBSSH2_ERROR_EAGAIN;
1677 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1678 failf(data, "Could not open directory for reading: %s",
1679 sftp_libssh2_strerror(err));
1680 state(conn, SSH_SFTP_CLOSE);
1681 result = sftp_libssh2_error_to_CURLE(err);
1682 sshc->actualcode = result?result:CURLE_SSH;
1686 if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
1687 state(conn, SSH_SFTP_CLOSE);
1688 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1691 if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
1692 Curl_safefree(sshc->readdir_filename);
1693 sshc->readdir_filename = NULL;
1694 state(conn, SSH_SFTP_CLOSE);
1695 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1698 state(conn, SSH_SFTP_READDIR);
1701 case SSH_SFTP_READDIR:
1702 sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
1703 sshc->readdir_filename,
1705 sshc->readdir_longentry,
1707 &sshc->readdir_attrs);
1708 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
1709 rc = LIBSSH2_ERROR_EAGAIN;
1712 if(sshc->readdir_len > 0) {
1713 sshc->readdir_filename[sshc->readdir_len] = '\0';
1715 if(data->set.ftp_list_only) {
1718 tmpLine = aprintf("%s\n", sshc->readdir_filename);
1719 if(tmpLine == NULL) {
1720 state(conn, SSH_SFTP_CLOSE);
1721 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1724 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1725 tmpLine, sshc->readdir_len+1);
1726 Curl_safefree(tmpLine);
1729 state(conn, SSH_STOP);
1732 /* since this counts what we send to the client, we include the
1733 newline in this counter */
1734 data->req.bytecount += sshc->readdir_len+1;
1736 /* output debug output if that is requested */
1737 if(data->set.verbose) {
1738 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
1739 sshc->readdir_len, conn);
1743 sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
1744 sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
1745 sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
1746 if(!sshc->readdir_line) {
1747 Curl_safefree(sshc->readdir_filename);
1748 sshc->readdir_filename = NULL;
1749 Curl_safefree(sshc->readdir_longentry);
1750 sshc->readdir_longentry = NULL;
1751 state(conn, SSH_SFTP_CLOSE);
1752 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1756 memcpy(sshc->readdir_line, sshc->readdir_longentry,
1757 sshc->readdir_currLen);
1758 if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
1759 ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
1760 LIBSSH2_SFTP_S_IFLNK)) {
1761 sshc->readdir_linkPath = malloc(PATH_MAX + 1);
1762 if(sshc->readdir_linkPath == NULL) {
1763 Curl_safefree(sshc->readdir_filename);
1764 sshc->readdir_filename = NULL;
1765 Curl_safefree(sshc->readdir_longentry);
1766 sshc->readdir_longentry = NULL;
1767 state(conn, SSH_SFTP_CLOSE);
1768 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1772 snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
1773 sshc->readdir_filename);
1774 state(conn, SSH_SFTP_READDIR_LINK);
1777 state(conn, SSH_SFTP_READDIR_BOTTOM);
1781 else if(sshc->readdir_len == 0) {
1782 Curl_safefree(sshc->readdir_filename);
1783 sshc->readdir_filename = NULL;
1784 Curl_safefree(sshc->readdir_longentry);
1785 sshc->readdir_longentry = NULL;
1786 state(conn, SSH_SFTP_READDIR_DONE);
1789 else if(sshc->readdir_len <= 0) {
1790 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1791 result = sftp_libssh2_error_to_CURLE(err);
1792 sshc->actualcode = result?result:CURLE_SSH;
1793 failf(data, "Could not open remote file for reading: %s :: %d",
1794 sftp_libssh2_strerror(err),
1795 libssh2_session_last_errno(sshc->ssh_session));
1796 Curl_safefree(sshc->readdir_filename);
1797 sshc->readdir_filename = NULL;
1798 Curl_safefree(sshc->readdir_longentry);
1799 sshc->readdir_longentry = NULL;
1800 state(conn, SSH_SFTP_CLOSE);
1805 case SSH_SFTP_READDIR_LINK:
1807 libssh2_sftp_symlink_ex(sshc->sftp_session,
1808 sshc->readdir_linkPath,
1809 (unsigned int) strlen(sshc->readdir_linkPath),
1810 sshc->readdir_filename,
1811 PATH_MAX, LIBSSH2_SFTP_READLINK);
1812 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
1813 rc = LIBSSH2_ERROR_EAGAIN;
1816 Curl_safefree(sshc->readdir_linkPath);
1817 sshc->readdir_linkPath = NULL;
1818 sshc->readdir_line = realloc(sshc->readdir_line,
1819 sshc->readdir_totalLen + 4 +
1821 if(!sshc->readdir_line) {
1822 Curl_safefree(sshc->readdir_filename);
1823 sshc->readdir_filename = NULL;
1824 Curl_safefree(sshc->readdir_longentry);
1825 sshc->readdir_longentry = NULL;
1826 state(conn, SSH_SFTP_CLOSE);
1827 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1831 sshc->readdir_currLen += snprintf(sshc->readdir_line +
1832 sshc->readdir_currLen,
1833 sshc->readdir_totalLen -
1834 sshc->readdir_currLen,
1836 sshc->readdir_filename);
1838 state(conn, SSH_SFTP_READDIR_BOTTOM);
1841 case SSH_SFTP_READDIR_BOTTOM:
1842 sshc->readdir_currLen += snprintf(sshc->readdir_line +
1843 sshc->readdir_currLen,
1844 sshc->readdir_totalLen -
1845 sshc->readdir_currLen, "\n");
1846 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1848 sshc->readdir_currLen);
1850 if(result == CURLE_OK) {
1852 /* output debug output if that is requested */
1853 if(data->set.verbose) {
1854 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
1855 sshc->readdir_currLen, conn);
1857 data->req.bytecount += sshc->readdir_currLen;
1859 Curl_safefree(sshc->readdir_line);
1860 sshc->readdir_line = NULL;
1862 state(conn, SSH_STOP);
1865 state(conn, SSH_SFTP_READDIR);
1868 case SSH_SFTP_READDIR_DONE:
1869 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
1870 LIBSSH2_ERROR_EAGAIN) {
1871 rc = LIBSSH2_ERROR_EAGAIN;
1874 sshc->sftp_handle = NULL;
1875 Curl_safefree(sshc->readdir_filename);
1876 sshc->readdir_filename = NULL;
1877 Curl_safefree(sshc->readdir_longentry);
1878 sshc->readdir_longentry = NULL;
1880 /* no data to transfer */
1881 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1882 state(conn, SSH_STOP);
1885 case SSH_SFTP_DOWNLOAD_INIT:
1887 * Work on getting the specified file
1890 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
1891 (unsigned int)strlen(sftp_scp->path),
1892 LIBSSH2_FXF_READ, data->set.new_file_perms,
1893 LIBSSH2_SFTP_OPENFILE);
1894 if(!sshc->sftp_handle) {
1895 if(libssh2_session_last_errno(sshc->ssh_session) ==
1896 LIBSSH2_ERROR_EAGAIN) {
1897 rc = LIBSSH2_ERROR_EAGAIN;
1901 err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
1902 failf(data, "Could not open remote file for reading: %s",
1903 sftp_libssh2_strerror(err));
1904 state(conn, SSH_SFTP_CLOSE);
1905 result = sftp_libssh2_error_to_CURLE(err);
1906 sshc->actualcode = result?result:CURLE_SSH;
1910 state(conn, SSH_SFTP_DOWNLOAD_STAT);
1913 case SSH_SFTP_DOWNLOAD_STAT:
1915 LIBSSH2_SFTP_ATTRIBUTES attrs;
1917 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
1918 (unsigned int)strlen(sftp_scp->path),
1919 LIBSSH2_SFTP_STAT, &attrs);
1920 if(rc == LIBSSH2_ERROR_EAGAIN) {
1925 * libssh2_sftp_open() didn't return an error, so maybe the server
1926 * just doesn't support stat()
1928 data->req.size = -1;
1929 data->req.maxdownload = -1;
1932 curl_off_t size = attrs.filesize;
1935 failf(data, "Bad file size (%" FORMAT_OFF_T ")", size);
1936 return CURLE_BAD_DOWNLOAD_RESUME;
1938 if(conn->data->state.use_range) {
1939 curl_off_t from, to;
1943 from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
1944 while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
1946 to=curlx_strtoofft(ptr, &ptr2, 0);
1947 if((ptr == ptr2) /* no "to" value given */
1952 /* from is relative to end of file */
1956 failf(data, "Offset (%"
1957 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")",
1958 from, attrs.filesize);
1959 return CURLE_BAD_DOWNLOAD_RESUME;
1966 size = to - from + 1;
1969 SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
1971 data->req.size = size;
1972 data->req.maxdownload = size;
1973 Curl_pgrsSetDownloadSize(data, size);
1976 /* We can resume if we can seek to the resume position */
1977 if(data->state.resume_from) {
1978 if(data->state.resume_from < 0) {
1979 /* We're supposed to download the last abs(from) bytes */
1980 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
1981 failf(data, "Offset (%"
1982 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")",
1983 data->state.resume_from, attrs.filesize);
1984 return CURLE_BAD_DOWNLOAD_RESUME;
1986 /* download from where? */
1987 data->state.resume_from += attrs.filesize;
1990 if((curl_off_t)attrs.filesize < data->state.resume_from) {
1991 failf(data, "Offset (%" FORMAT_OFF_T
1992 ") was beyond file size (%" FORMAT_OFF_T ")",
1993 data->state.resume_from, attrs.filesize);
1994 return CURLE_BAD_DOWNLOAD_RESUME;
1997 /* Does a completed file need to be seeked and started or closed ? */
1998 /* Now store the number of bytes we are expected to download */
1999 data->req.size = attrs.filesize - data->state.resume_from;
2000 data->req.maxdownload = attrs.filesize - data->state.resume_from;
2001 Curl_pgrsSetDownloadSize(data,
2002 attrs.filesize - data->state.resume_from);
2003 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2006 /* Setup the actual download */
2007 if(data->req.size == 0) {
2008 /* no data to transfer */
2009 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
2010 infof(data, "File already completely downloaded\n");
2011 state(conn, SSH_STOP);
2015 Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
2016 FALSE, NULL, -1, NULL);
2018 /* not set by Curl_setup_transfer to preserve keepon bits */
2019 conn->writesockfd = conn->sockfd;
2021 /* FIXME: here should be explained why we need it to start the
2023 conn->cselect_bits = CURL_CSELECT_IN;
2026 state(conn, SSH_SFTP_CLOSE);
2027 sshc->actualcode = result;
2030 state(conn, SSH_STOP);
2034 case SSH_SFTP_CLOSE:
2035 if(sshc->sftp_handle) {
2036 rc = libssh2_sftp_close(sshc->sftp_handle);
2037 if(rc == LIBSSH2_ERROR_EAGAIN) {
2041 infof(data, "Failed to close libssh2 file\n");
2043 sshc->sftp_handle = NULL;
2045 Curl_safefree(sftp_scp->path);
2046 sftp_scp->path = NULL;
2048 DEBUGF(infof(data, "SFTP DONE done\n"));
2050 state(conn, SSH_SFTP_SHUTDOWN);
2052 state(conn, SSH_STOP);
2053 result = sshc->actualcode;
2056 case SSH_SFTP_SHUTDOWN:
2057 /* during times we get here due to a broken transfer and then the
2058 sftp_handle might not have been taken down so make sure that is done
2059 before we proceed */
2061 if(sshc->sftp_handle) {
2062 rc = libssh2_sftp_close(sshc->sftp_handle);
2063 if(rc == LIBSSH2_ERROR_EAGAIN) {
2067 infof(data, "Failed to close libssh2 file\n");
2069 sshc->sftp_handle = NULL;
2071 if(sshc->sftp_session) {
2072 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2073 if(rc == LIBSSH2_ERROR_EAGAIN) {
2077 infof(data, "Failed to stop libssh2 sftp subsystem\n");
2079 sshc->sftp_session = NULL;
2082 Curl_safefree(sshc->homedir);
2083 sshc->homedir = NULL;
2084 conn->data->state.most_recent_ftp_entrypath = NULL;
2086 state(conn, SSH_SESSION_DISCONNECT);
2089 case SSH_SCP_TRANS_INIT:
2090 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
2092 sshc->actualcode = result;
2093 state(conn, SSH_STOP);
2097 if(data->set.upload) {
2098 if(data->set.infilesize < 0) {
2099 failf(data, "SCP requires a known file size for upload");
2100 sshc->actualcode = CURLE_UPLOAD_FAILED;
2101 state(conn, SSH_SCP_CHANNEL_FREE);
2104 state(conn, SSH_SCP_UPLOAD_INIT);
2107 state(conn, SSH_SCP_DOWNLOAD_INIT);
2111 case SSH_SCP_UPLOAD_INIT:
2113 * libssh2 requires that the destination path is a full path that
2114 * includes the destination file and name OR ends in a "/" . If this is
2115 * not done the destination file will be named the same name as the last
2116 * directory in the path.
2119 SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
2120 data->set.infilesize);
2121 if(!sshc->ssh_channel) {
2122 if(libssh2_session_last_errno(sshc->ssh_session) ==
2123 LIBSSH2_ERROR_EAGAIN) {
2124 rc = LIBSSH2_ERROR_EAGAIN;
2131 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2132 &err_msg, NULL, 0));
2133 failf(conn->data, "%s", err_msg);
2134 state(conn, SSH_SCP_CHANNEL_FREE);
2135 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2141 Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
2144 /* not set by Curl_setup_transfer to preserve keepon bits */
2145 conn->sockfd = conn->writesockfd;
2148 state(conn, SSH_SCP_CHANNEL_FREE);
2149 sshc->actualcode = result;
2152 state(conn, SSH_STOP);
2156 case SSH_SCP_DOWNLOAD_INIT:
2159 * We must check the remote file; if it is a directory no values will
2163 curl_off_t bytecount;
2165 /* clear the struct scp recv will fill in */
2166 memset(&sb, 0, sizeof(struct stat));
2168 /* get a fresh new channel from the ssh layer */
2169 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2170 sftp_scp->path, &sb);
2171 if(!sshc->ssh_channel) {
2172 if(libssh2_session_last_errno(sshc->ssh_session) ==
2173 LIBSSH2_ERROR_EAGAIN) {
2174 rc = LIBSSH2_ERROR_EAGAIN;
2181 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2182 &err_msg, NULL, 0));
2183 failf(conn->data, "%s", err_msg);
2184 state(conn, SSH_SCP_CHANNEL_FREE);
2185 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2191 bytecount = (curl_off_t)sb.st_size;
2192 data->req.maxdownload = (curl_off_t)sb.st_size;
2193 Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
2195 /* not set by Curl_setup_transfer to preserve keepon bits */
2196 conn->writesockfd = conn->sockfd;
2198 /* FIXME: here should be explained why we need it to start the
2200 conn->cselect_bits = CURL_CSELECT_IN;
2203 state(conn, SSH_SCP_CHANNEL_FREE);
2204 sshc->actualcode = result;
2207 state(conn, SSH_STOP);
2212 if(data->set.upload)
2213 state(conn, SSH_SCP_SEND_EOF);
2215 state(conn, SSH_SCP_CHANNEL_FREE);
2218 case SSH_SCP_SEND_EOF:
2219 if(sshc->ssh_channel) {
2220 rc = libssh2_channel_send_eof(sshc->ssh_channel);
2221 if(rc == LIBSSH2_ERROR_EAGAIN) {
2225 infof(data, "Failed to send libssh2 channel EOF\n");
2228 state(conn, SSH_SCP_WAIT_EOF);
2231 case SSH_SCP_WAIT_EOF:
2232 if(sshc->ssh_channel) {
2233 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2234 if(rc == LIBSSH2_ERROR_EAGAIN) {
2238 infof(data, "Failed to get channel EOF: %d\n", rc);
2241 state(conn, SSH_SCP_WAIT_CLOSE);
2244 case SSH_SCP_WAIT_CLOSE:
2245 if(sshc->ssh_channel) {
2246 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2247 if(rc == LIBSSH2_ERROR_EAGAIN) {
2251 infof(data, "Channel failed to close: %d\n", rc);
2254 state(conn, SSH_SCP_CHANNEL_FREE);
2257 case SSH_SCP_CHANNEL_FREE:
2258 if(sshc->ssh_channel) {
2259 rc = libssh2_channel_free(sshc->ssh_channel);
2260 if(rc == LIBSSH2_ERROR_EAGAIN) {
2264 infof(data, "Failed to free libssh2 scp subsystem\n");
2266 sshc->ssh_channel = NULL;
2268 DEBUGF(infof(data, "SCP DONE phase complete\n"));
2270 state(conn, SSH_SESSION_DISCONNECT);
2272 state(conn, SSH_STOP);
2273 result = sshc->actualcode;
2276 case SSH_SESSION_DISCONNECT:
2277 /* during weird times when we've been prematurely aborted, the channel
2278 is still alive when we reach this state and we MUST kill the channel
2280 if(sshc->ssh_channel) {
2281 rc = libssh2_channel_free(sshc->ssh_channel);
2282 if(rc == LIBSSH2_ERROR_EAGAIN) {
2286 infof(data, "Failed to free libssh2 scp subsystem\n");
2288 sshc->ssh_channel = NULL;
2291 if(sshc->ssh_session) {
2292 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2293 if(rc == LIBSSH2_ERROR_EAGAIN) {
2297 infof(data, "Failed to disconnect libssh2 session\n");
2301 Curl_safefree(sshc->homedir);
2302 sshc->homedir = NULL;
2303 conn->data->state.most_recent_ftp_entrypath = NULL;
2305 state(conn, SSH_SESSION_FREE);
2308 case SSH_SESSION_FREE:
2309 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2311 libssh2_knownhost_free(sshc->kh);
2316 if(sshc->ssh_session) {
2317 rc = libssh2_session_free(sshc->ssh_session);
2318 if(rc == LIBSSH2_ERROR_EAGAIN) {
2322 infof(data, "Failed to free libssh2 session\n");
2324 sshc->ssh_session = NULL;
2326 conn->bits.close = TRUE;
2327 sshc->nextstate = SSH_NO_STATE;
2328 state(conn, SSH_STOP);
2329 result = sshc->actualcode;
2333 /* fallthrough, just stop! */
2335 /* internal error */
2336 sshc->nextstate = SSH_NO_STATE;
2337 state(conn, SSH_STOP);
2341 } while(!rc && (sshc->state != SSH_STOP));
2343 if(rc == LIBSSH2_ERROR_EAGAIN) {
2344 /* we would block, we need to wait for the socket to be ready (in the
2345 right direction too)! */
2352 /* called by the multi interface to figure out what socket(s) to wait for and
2353 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
2354 static int ssh_perform_getsock(const struct connectdata *conn,
2355 curl_socket_t *sock, /* points to numsocks
2356 number of sockets */
2359 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2360 int bitmap = GETSOCK_BLANK;
2363 sock[0] = conn->sock[FIRSTSOCKET];
2365 if(conn->waitfor & KEEP_RECV)
2366 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
2368 if(conn->waitfor & KEEP_SEND)
2369 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
2373 /* if we don't know the direction we can use the generic *_getsock()
2374 function even for the protocol_connect and doing states */
2375 return Curl_single_getsock(conn, sock, numsocks);
2379 /* Generic function called by the multi interface to figure out what socket(s)
2380 to wait for and for what actions during the DOING and PROTOCONNECT states*/
2381 static int ssh_getsock(struct connectdata *conn,
2382 curl_socket_t *sock, /* points to numsocks number
2386 #ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2390 /* if we don't know any direction we can just play along as we used to and
2391 not provide any sensible info */
2392 return GETSOCK_BLANK;
2394 /* if we know the direction we can use the generic *_getsock() function even
2395 for the protocol_connect and doing states */
2396 return ssh_perform_getsock(conn, sock, numsocks);
2400 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2402 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
2403 * function is used to figure out in what direction and stores this info so
2404 * that the multi interface can take advantage of it. Make sure to call this
2405 * function in all cases so that when it _doesn't_ return EAGAIN we can
2406 * restore the default wait bits.
2408 static void ssh_block2waitfor(struct connectdata *conn, bool block)
2410 struct ssh_conn *sshc = &conn->proto.sshc;
2414 else if((dir = libssh2_session_block_directions(sshc->ssh_session))) {
2415 /* translate the libssh2 define bits into our own bit defines */
2416 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
2417 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
2420 /* It didn't block or libssh2 didn't reveal in which direction, put back
2422 conn->waitfor = sshc->orig_waitfor;
2425 /* no libssh2 directional support so we simply don't know */
2426 #define ssh_block2waitfor(x,y)
2429 /* called repeatedly until done from multi.c */
2430 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
2432 struct ssh_conn *sshc = &conn->proto.sshc;
2433 CURLcode result = CURLE_OK;
2434 bool block; /* we store the status and use that to provide a ssh_getsock()
2437 result = ssh_statemach_act(conn, &block);
2438 *done = (bool)(sshc->state == SSH_STOP);
2439 ssh_block2waitfor(conn, block);
2444 static CURLcode ssh_easy_statemach(struct connectdata *conn,
2447 struct ssh_conn *sshc = &conn->proto.sshc;
2448 CURLcode result = CURLE_OK;
2449 struct SessionHandle *data = conn->data;
2451 while((sshc->state != SSH_STOP) && !result) {
2455 result = ssh_statemach_act(conn, &block);
2459 if(Curl_pgrsUpdate(conn))
2460 return CURLE_ABORTED_BY_CALLBACK;
2462 struct timeval now = Curl_tvnow();
2463 result = Curl_speedcheck(data, now);
2468 left = Curl_timeleft(data, NULL, duringconnect);
2470 failf(data, "Operation timed out\n");
2471 return CURLE_OPERATION_TIMEDOUT;
2474 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2475 if((CURLE_OK == result) && block) {
2476 int dir = libssh2_session_block_directions(sshc->ssh_session);
2477 curl_socket_t sock = conn->sock[FIRSTSOCKET];
2478 curl_socket_t fd_read = CURL_SOCKET_BAD;
2479 curl_socket_t fd_write = CURL_SOCKET_BAD;
2480 if (LIBSSH2_SESSION_BLOCK_INBOUND & dir) {
2483 if (LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) {
2486 /* wait for the socket to become ready */
2487 Curl_socket_ready(fd_read, fd_write,
2488 (int)(left>1000?1000:left)); /* ignore result */
2498 * SSH setup and connection
2500 static CURLcode ssh_init(struct connectdata *conn)
2502 struct SessionHandle *data = conn->data;
2503 struct SSHPROTO *ssh;
2504 struct ssh_conn *sshc = &conn->proto.sshc;
2506 sshc->actualcode = CURLE_OK; /* reset error code */
2507 sshc->secondCreateDirs =0; /* reset the create dir attempt state
2510 if(data->state.proto.ssh)
2513 ssh = calloc(1, sizeof(struct SSHPROTO));
2515 return CURLE_OUT_OF_MEMORY;
2517 data->state.proto.ssh = ssh;
2522 static Curl_recv scp_recv, sftp_recv;
2523 static Curl_send scp_send, sftp_send;
2526 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
2527 * do protocol-specific actions at connect-time.
2529 static CURLcode ssh_connect(struct connectdata *conn, bool *done)
2531 #ifdef CURL_LIBSSH2_DEBUG
2534 struct ssh_conn *ssh;
2536 struct SessionHandle *data = conn->data;
2538 /* We default to persistent connections. We set this already in this connect
2539 function to make the re-use checks properly be able to check this bit. */
2540 conn->bits.close = FALSE;
2542 /* If there already is a protocol-specific struct allocated for this
2543 sessionhandle, deal with it */
2544 Curl_reset_reqproto(conn);
2546 result = ssh_init(conn);
2550 if(conn->protocol & PROT_SCP) {
2551 conn->recv[FIRSTSOCKET] = scp_recv;
2552 conn->send[FIRSTSOCKET] = scp_send;
2554 conn->recv[FIRSTSOCKET] = sftp_recv;
2555 conn->send[FIRSTSOCKET] = sftp_send;
2557 ssh = &conn->proto.sshc;
2559 #ifdef CURL_LIBSSH2_DEBUG
2561 infof(data, "User: %s\n", conn->user);
2564 infof(data, "Password: %s\n", conn->passwd);
2566 sock = conn->sock[FIRSTSOCKET];
2567 #endif /* CURL_LIBSSH2_DEBUG */
2569 ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
2571 my_libssh2_realloc, conn);
2572 if(ssh->ssh_session == NULL) {
2573 failf(data, "Failure initialising ssh session");
2574 return CURLE_FAILED_INIT;
2577 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2578 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
2580 ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
2582 /* eeek. TODO: free the ssh_session! */
2583 return CURLE_FAILED_INIT;
2586 /* read all known hosts from there */
2587 rc = libssh2_knownhost_readfile(ssh->kh,
2588 data->set.str[STRING_SSH_KNOWNHOSTS],
2589 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
2591 infof(data, "Failed to read known hosts from %s\n",
2592 data->set.str[STRING_SSH_KNOWNHOSTS]);
2595 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2597 #ifdef CURL_LIBSSH2_DEBUG
2598 libssh2_trace(ssh->ssh_session, ~0);
2599 infof(data, "SSH socket: %d\n", (int)sock);
2600 #endif /* CURL_LIBSSH2_DEBUG */
2602 state(conn, SSH_S_STARTUP);
2604 if(data->state.used_interface == Curl_if_multi)
2605 result = ssh_multi_statemach(conn, done);
2607 result = ssh_easy_statemach(conn, TRUE);
2616 ***********************************************************************
2620 * This is the actual DO function for SCP. Get a file according to
2621 * the options previously setup.
2625 CURLcode scp_perform(struct connectdata *conn,
2629 CURLcode result = CURLE_OK;
2631 DEBUGF(infof(conn->data, "DO phase starts\n"));
2633 *dophase_done = FALSE; /* not done yet */
2635 /* start the first command in the DO phase */
2636 state(conn, SSH_SCP_TRANS_INIT);
2638 /* run the state-machine */
2639 if(conn->data->state.used_interface == Curl_if_multi) {
2640 result = ssh_multi_statemach(conn, dophase_done);
2643 result = ssh_easy_statemach(conn, FALSE);
2644 *dophase_done = TRUE; /* with the easy interface we are done here */
2646 *connected = conn->bits.tcpconnect;
2649 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2655 /* called from multi.c while DOing */
2656 static CURLcode scp_doing(struct connectdata *conn,
2660 result = ssh_multi_statemach(conn, dophase_done);
2663 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2669 * The DO function is generic for both protocols. There was previously two
2670 * separate ones but this way means less duplicated code.
2673 static CURLcode ssh_do(struct connectdata *conn, bool *done)
2677 struct SessionHandle *data = conn->data;
2679 *done = FALSE; /* default to false */
2682 Since connections can be re-used between SessionHandles, this might be a
2683 connection already existing but on a fresh SessionHandle struct so we must
2684 make sure we have a good 'struct SSHPROTO' to play with. For new
2685 connections, the struct SSHPROTO is allocated and setup in the
2686 ssh_connect() function.
2688 Curl_reset_reqproto(conn);
2689 res = ssh_init(conn);
2693 data->req.size = -1; /* make sure this is unknown at this point */
2695 Curl_pgrsSetUploadCounter(data, 0);
2696 Curl_pgrsSetDownloadCounter(data, 0);
2697 Curl_pgrsSetUploadSize(data, 0);
2698 Curl_pgrsSetDownloadSize(data, 0);
2700 if(conn->protocol & PROT_SCP)
2701 res = scp_perform(conn, &connected, done);
2703 res = sftp_perform(conn, &connected, done);
2708 /* BLOCKING, but the function is using the state machine so the only reason
2709 this is still blocking is that the multi interface code has no support for
2710 disconnecting operations that takes a while */
2711 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
2713 CURLcode result = CURLE_OK;
2714 struct ssh_conn *ssh = &conn->proto.sshc;
2715 (void) dead_connection;
2717 Curl_safefree(conn->data->state.proto.ssh);
2718 conn->data->state.proto.ssh = NULL;
2720 if(ssh->ssh_session) {
2721 /* only if there's a session still around to use! */
2723 state(conn, SSH_SESSION_DISCONNECT);
2725 result = ssh_easy_statemach(conn, FALSE);
2731 /* generic done function for both SCP and SFTP called from their specific
2733 static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
2735 CURLcode result = CURLE_OK;
2736 struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh;
2738 if(status == CURLE_OK) {
2739 /* run the state-machine
2741 TODO: when the multi interface is used, this _really_ should be using
2742 the ssh_multi_statemach function but we have no general support for
2743 non-blocking DONE operations, not in the multi state machine and with
2744 Curl_done() invokes on several places in the code!
2746 result = ssh_easy_statemach(conn, FALSE);
2751 Curl_safefree(sftp_scp->path);
2752 sftp_scp->path = NULL;
2753 Curl_pgrsDone(conn);
2755 conn->data->req.keepon = 0; /* clear all bits */
2760 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
2763 (void)premature; /* not used */
2765 if(status == CURLE_OK)
2766 state(conn, SSH_SCP_DONE);
2768 return ssh_done(conn, status);
2772 /* return number of received (decrypted) bytes */
2773 static ssize_t scp_send(struct connectdata *conn, int sockindex,
2774 const void *mem, size_t len, CURLcode *err)
2777 (void)sockindex; /* we only support SCP on the fixed known primary socket */
2779 /* libssh2_channel_write() returns int! */
2781 libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
2783 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2785 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
2794 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
2795 * a regular CURLcode value.
2797 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
2798 char *mem, size_t len, CURLcode *err)
2801 (void)sockindex; /* we only support SCP on the fixed known primary socket */
2803 /* libssh2_channel_read() returns int */
2805 libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
2807 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2808 if (nread == LIBSSH2_ERROR_EAGAIN) {
2817 * =============== SFTP ===============
2821 ***********************************************************************
2825 * This is the actual DO function for SFTP. Get a file/directory according to
2826 * the options previously setup.
2830 CURLcode sftp_perform(struct connectdata *conn,
2834 CURLcode result = CURLE_OK;
2836 DEBUGF(infof(conn->data, "DO phase starts\n"));
2838 *dophase_done = FALSE; /* not done yet */
2840 /* start the first command in the DO phase */
2841 state(conn, SSH_SFTP_QUOTE_INIT);
2843 /* run the state-machine */
2844 if(conn->data->state.used_interface == Curl_if_multi) {
2845 result = ssh_multi_statemach(conn, dophase_done);
2848 result = ssh_easy_statemach(conn, FALSE);
2849 *dophase_done = TRUE; /* with the easy interface we are done here */
2851 *connected = conn->bits.tcpconnect;
2854 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2860 /* called from multi.c while DOing */
2861 static CURLcode sftp_doing(struct connectdata *conn,
2865 result = ssh_multi_statemach(conn, dophase_done);
2868 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2873 /* BLOCKING, but the function is using the state machine so the only reason
2874 this is still blocking is that the multi interface code has no support for
2875 disconnecting operations that takes a while */
2876 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
2878 CURLcode result = CURLE_OK;
2879 (void) dead_connection;
2881 DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
2883 Curl_safefree(conn->data->state.proto.ssh);
2884 conn->data->state.proto.ssh = NULL;
2886 if(conn->proto.sshc.ssh_session) {
2887 /* only if there's a session still around to use! */
2888 state(conn, SSH_SFTP_SHUTDOWN);
2889 result = ssh_easy_statemach(conn, FALSE);
2892 DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
2898 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
2901 struct ssh_conn *sshc = &conn->proto.sshc;
2903 if(status == CURLE_OK) {
2904 /* Before we shut down, see if there are any post-quote commands to
2906 if(!status && !premature && conn->data->set.postquote) {
2907 sshc->nextstate = SSH_SFTP_CLOSE;
2908 state(conn, SSH_SFTP_POSTQUOTE_INIT);
2911 state(conn, SSH_SFTP_CLOSE);
2913 return ssh_done(conn, status);
2916 /* return number of sent bytes */
2917 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
2918 const void *mem, size_t len, CURLcode *err)
2920 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
2921 but is changed to ssize_t in 0.15. These days we don't
2922 support libssh2 0.15*/
2925 nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
2927 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2929 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
2938 * Return number of received (decrypted) bytes
2940 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
2941 char *mem, size_t len, CURLcode *err)
2946 nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
2948 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2950 if(nread == LIBSSH2_ERROR_EAGAIN) {
2957 /* The get_pathname() function is being borrowed from OpenSSH sftp.c
2960 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
2962 * Permission to use, copy, modify, and distribute this software for any
2963 * purpose with or without fee is hereby granted, provided that the above
2964 * copyright notice and this permission notice appear in all copies.
2966 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
2967 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
2968 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
2969 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2970 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2971 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2972 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2975 get_pathname(const char **cpp, char **path)
2977 const char *cp = *cpp, *end;
2980 static const char WHITESPACE[] = " \t\r\n";
2982 cp += strspn(cp, WHITESPACE);
2986 return CURLE_QUOTE_ERROR;
2989 *path = malloc(strlen(cp) + 1);
2991 return CURLE_OUT_OF_MEMORY;
2993 /* Check for quoted filenames */
2994 if(*cp == '\"' || *cp == '\'') {
2997 /* Search for terminating quote, unescape some chars */
2998 for (i = j = 0; i <= strlen(cp); i++) {
2999 if(cp[i] == quot) { /* Found quote */
3004 if(cp[i] == '\0') { /* End of string */
3005 /*error("Unterminated quote");*/
3008 if(cp[i] == '\\') { /* Escaped characters */
3010 if(cp[i] != '\'' && cp[i] != '\"' &&
3012 /*error("Bad escaped character '\\%c'",
3017 (*path)[j++] = cp[i];
3021 /*error("Empty quotes");*/
3024 *cpp = cp + i + strspn(cp + i, WHITESPACE);
3027 /* Read to end of filename */
3028 end = strpbrk(cp, WHITESPACE);
3030 end = strchr(cp, '\0');
3031 *cpp = end + strspn(end, WHITESPACE);
3033 memcpy(*path, cp, end - cp);
3034 (*path)[end - cp] = '\0';
3039 Curl_safefree(*path);
3041 return CURLE_QUOTE_ERROR;
3045 static const char *sftp_libssh2_strerror(unsigned long err)
3048 case LIBSSH2_FX_NO_SUCH_FILE:
3049 return "No such file or directory";
3051 case LIBSSH2_FX_PERMISSION_DENIED:
3052 return "Permission denied";
3054 case LIBSSH2_FX_FAILURE:
3055 return "Operation failed";
3057 case LIBSSH2_FX_BAD_MESSAGE:
3058 return "Bad message from SFTP server";
3060 case LIBSSH2_FX_NO_CONNECTION:
3061 return "Not connected to SFTP server";
3063 case LIBSSH2_FX_CONNECTION_LOST:
3064 return "Connection to SFTP server lost";
3066 case LIBSSH2_FX_OP_UNSUPPORTED:
3067 return "Operation not supported by SFTP server";
3069 case LIBSSH2_FX_INVALID_HANDLE:
3070 return "Invalid handle";
3072 case LIBSSH2_FX_NO_SUCH_PATH:
3073 return "No such file or directory";
3075 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3076 return "File already exists";
3078 case LIBSSH2_FX_WRITE_PROTECT:
3079 return "File is write protected";
3081 case LIBSSH2_FX_NO_MEDIA:
3084 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3087 case LIBSSH2_FX_QUOTA_EXCEEDED:
3088 return "User quota exceeded";
3090 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3091 return "Unknown principle";
3093 case LIBSSH2_FX_LOCK_CONFlICT:
3094 return "File lock conflict";
3096 case LIBSSH2_FX_DIR_NOT_EMPTY:
3097 return "Directory not empty";
3099 case LIBSSH2_FX_NOT_A_DIRECTORY:
3100 return "Not a directory";
3102 case LIBSSH2_FX_INVALID_FILENAME:
3103 return "Invalid filename";
3105 case LIBSSH2_FX_LINK_LOOP:
3106 return "Link points to itself";
3108 return "Unknown error in libssh2";
3111 #endif /* USE_LIBSSH2 */