1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2013, 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 */
25 #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"
79 #include "inet_ntop.h"
80 #include "parsedate.h" /* for the week day and month names */
81 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
82 #include "strtoofft.h"
87 #define _MPRINTF_REPLACE /* use our functions only */
88 #include <curl/mprintf.h>
90 #include "curl_memory.h"
91 /* The last #include file should be: */
96 # define PATH_MAX MAX_PATH
100 #define PATH_MAX 1024 /* just an extra precaution since there are systems that
101 have their definition hidden well */
104 #define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
106 #define sftp_libssh2_realpath(s,p,t,m) \
107 libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
108 (t), (m), LIBSSH2_SFTP_REALPATH)
110 /* Local functions: */
111 static const char *sftp_libssh2_strerror(int err);
112 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
113 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
114 static LIBSSH2_FREE_FUNC(my_libssh2_free);
116 static CURLcode get_pathname(const char **cpp, char **path);
118 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
119 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
120 static CURLcode ssh_do(struct connectdata *conn, bool *done);
122 static CURLcode ssh_getworkingpath(struct connectdata *conn,
123 char *homedir, /* when SFTP is used */
126 static CURLcode scp_done(struct connectdata *conn,
127 CURLcode, bool premature);
128 static CURLcode scp_doing(struct connectdata *conn,
130 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
132 static CURLcode sftp_done(struct connectdata *conn,
133 CURLcode, bool premature);
134 static CURLcode sftp_doing(struct connectdata *conn,
136 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
138 CURLcode sftp_perform(struct connectdata *conn,
142 static int ssh_getsock(struct connectdata *conn,
143 curl_socket_t *sock, /* points to numsocks number
147 static int ssh_perform_getsock(const struct connectdata *conn,
148 curl_socket_t *sock, /* points to numsocks
152 static CURLcode ssh_setup_connection(struct connectdata *conn);
155 * SCP protocol handler.
158 const struct Curl_handler Curl_handler_scp = {
160 ssh_setup_connection, /* setup_connection */
163 ZERO_NULL, /* do_more */
164 ssh_connect, /* connect_it */
165 ssh_multi_statemach, /* connecting */
166 scp_doing, /* doing */
167 ssh_getsock, /* proto_getsock */
168 ssh_getsock, /* doing_getsock */
169 ZERO_NULL, /* domore_getsock */
170 ssh_perform_getsock, /* perform_getsock */
171 scp_disconnect, /* disconnect */
172 ZERO_NULL, /* readwrite */
173 PORT_SSH, /* defport */
174 CURLPROTO_SCP, /* protocol */
175 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
176 | PROTOPT_NOURLQUERY /* flags */
181 * SFTP protocol handler.
184 const struct Curl_handler Curl_handler_sftp = {
186 ssh_setup_connection, /* setup_connection */
188 sftp_done, /* done */
189 ZERO_NULL, /* do_more */
190 ssh_connect, /* connect_it */
191 ssh_multi_statemach, /* connecting */
192 sftp_doing, /* doing */
193 ssh_getsock, /* proto_getsock */
194 ssh_getsock, /* doing_getsock */
195 ZERO_NULL, /* domore_getsock */
196 ssh_perform_getsock, /* perform_getsock */
197 sftp_disconnect, /* disconnect */
198 ZERO_NULL, /* readwrite */
199 PORT_SSH, /* defport */
200 CURLPROTO_SFTP, /* protocol */
201 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
202 | PROTOPT_NOURLQUERY /* flags */
206 kbd_callback(const char *name, int name_len, const char *instruction,
207 int instruction_len, int num_prompts,
208 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
209 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
212 struct connectdata *conn = (struct connectdata *)*abstract;
214 #ifdef CURL_LIBSSH2_DEBUG
215 fprintf(stderr, "name=%s\n", name);
216 fprintf(stderr, "name_len=%d\n", name_len);
217 fprintf(stderr, "instruction=%s\n", instruction);
218 fprintf(stderr, "instruction_len=%d\n", instruction_len);
219 fprintf(stderr, "num_prompts=%d\n", num_prompts);
224 (void)instruction_len;
225 #endif /* CURL_LIBSSH2_DEBUG */
226 if(num_prompts == 1) {
227 responses[0].text = strdup(conn->passwd);
228 responses[0].length = curlx_uztoui(strlen(conn->passwd));
234 static CURLcode sftp_libssh2_error_to_CURLE(int err)
240 case LIBSSH2_FX_NO_SUCH_FILE:
241 case LIBSSH2_FX_NO_SUCH_PATH:
242 return CURLE_REMOTE_FILE_NOT_FOUND;
244 case LIBSSH2_FX_PERMISSION_DENIED:
245 case LIBSSH2_FX_WRITE_PROTECT:
246 case LIBSSH2_FX_LOCK_CONFlICT:
247 return CURLE_REMOTE_ACCESS_DENIED;
249 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
250 case LIBSSH2_FX_QUOTA_EXCEEDED:
251 return CURLE_REMOTE_DISK_FULL;
253 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
254 return CURLE_REMOTE_FILE_EXISTS;
256 case LIBSSH2_FX_DIR_NOT_EMPTY:
257 return CURLE_QUOTE_ERROR;
266 static CURLcode libssh2_session_error_to_CURLE(int err)
269 /* Ordered by order of appearance in libssh2.h */
270 case LIBSSH2_ERROR_NONE:
273 case LIBSSH2_ERROR_SOCKET_NONE:
274 return CURLE_COULDNT_CONNECT;
276 case LIBSSH2_ERROR_ALLOC:
277 return CURLE_OUT_OF_MEMORY;
279 case LIBSSH2_ERROR_SOCKET_SEND:
280 return CURLE_SEND_ERROR;
282 case LIBSSH2_ERROR_HOSTKEY_INIT:
283 case LIBSSH2_ERROR_HOSTKEY_SIGN:
284 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
285 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
286 return CURLE_PEER_FAILED_VERIFICATION;
288 case LIBSSH2_ERROR_PASSWORD_EXPIRED:
289 return CURLE_LOGIN_DENIED;
291 case LIBSSH2_ERROR_SOCKET_TIMEOUT:
292 case LIBSSH2_ERROR_TIMEOUT:
293 return CURLE_OPERATION_TIMEDOUT;
295 case LIBSSH2_ERROR_EAGAIN:
299 /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
300 error code, and possibly add a few new SSH-related one. We must however
301 not return or even depend on libssh2 errors in the public libcurl API */
306 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
308 (void)abstract; /* arg not used */
309 return malloc(count);
312 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
314 (void)abstract; /* arg not used */
315 return realloc(ptr, count);
318 static LIBSSH2_FREE_FUNC(my_libssh2_free)
320 (void)abstract; /* arg not used */
321 if(ptr) /* ssh2 agent sometimes call free with null ptr */
326 * SSH State machine related code
328 /* This is the ONLY way to change SSH state! */
329 static void state(struct connectdata *conn, sshstate nowstate)
331 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
332 /* for debug purposes */
333 static const char * const names[] = {
339 "SSH_AUTH_PKEY_INIT",
341 "SSH_AUTH_PASS_INIT",
343 "SSH_AUTH_AGENT_INIT",
344 "SSH_AUTH_AGENT_LIST",
346 "SSH_AUTH_HOST_INIT",
353 "SSH_SFTP_QUOTE_INIT",
354 "SSH_SFTP_POSTQUOTE_INIT",
356 "SSH_SFTP_NEXT_QUOTE",
357 "SSH_SFTP_QUOTE_STAT",
358 "SSH_SFTP_QUOTE_SETSTAT",
359 "SSH_SFTP_QUOTE_SYMLINK",
360 "SSH_SFTP_QUOTE_MKDIR",
361 "SSH_SFTP_QUOTE_RENAME",
362 "SSH_SFTP_QUOTE_RMDIR",
363 "SSH_SFTP_QUOTE_UNLINK",
364 "SSH_SFTP_TRANS_INIT",
365 "SSH_SFTP_UPLOAD_INIT",
366 "SSH_SFTP_CREATE_DIRS_INIT",
367 "SSH_SFTP_CREATE_DIRS",
368 "SSH_SFTP_CREATE_DIRS_MKDIR",
369 "SSH_SFTP_READDIR_INIT",
371 "SSH_SFTP_READDIR_LINK",
372 "SSH_SFTP_READDIR_BOTTOM",
373 "SSH_SFTP_READDIR_DONE",
374 "SSH_SFTP_DOWNLOAD_INIT",
375 "SSH_SFTP_DOWNLOAD_STAT",
378 "SSH_SCP_TRANS_INIT",
379 "SSH_SCP_UPLOAD_INIT",
380 "SSH_SCP_DOWNLOAD_INIT",
384 "SSH_SCP_WAIT_CLOSE",
385 "SSH_SCP_CHANNEL_FREE",
386 "SSH_SESSION_DISCONNECT",
391 struct ssh_conn *sshc = &conn->proto.sshc;
393 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
394 if(sshc->state != nowstate) {
395 infof(conn->data, "SFTP %p state change from %s to %s\n",
396 (void *)sshc, names[sshc->state], names[nowstate]);
400 sshc->state = nowstate;
403 /* figure out the path to work with in this particular request */
404 static CURLcode ssh_getworkingpath(struct connectdata *conn,
405 char *homedir, /* when SFTP is used */
406 char **path) /* returns the allocated
407 real path to work with */
409 struct SessionHandle *data = conn->data;
410 char *real_path = NULL;
412 int working_path_len;
414 working_path = curl_easy_unescape(data, data->state.path, 0,
417 return CURLE_OUT_OF_MEMORY;
419 /* Check for /~/ , indicating relative to the user's home directory */
420 if(conn->handler->protocol & CURLPROTO_SCP) {
421 real_path = malloc(working_path_len+1);
422 if(real_path == NULL) {
424 return CURLE_OUT_OF_MEMORY;
426 if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
427 /* It is referenced to the home directory, so strip the leading '/~/' */
428 memcpy(real_path, working_path+3, 4 + working_path_len-3);
430 memcpy(real_path, working_path, 1 + working_path_len);
432 else if(conn->handler->protocol & CURLPROTO_SFTP) {
433 if((working_path_len > 1) && (working_path[1] == '~')) {
434 size_t homelen = strlen(homedir);
435 real_path = malloc(homelen + working_path_len + 1);
436 if(real_path == NULL) {
438 return CURLE_OUT_OF_MEMORY;
440 /* It is referenced to the home directory, so strip the
442 memcpy(real_path, homedir, homelen);
443 real_path[homelen] = '/';
444 real_path[homelen+1] = '\0';
445 if(working_path_len > 3) {
446 memcpy(real_path+homelen+1, working_path + 3,
447 1 + working_path_len -3);
451 real_path = malloc(working_path_len+1);
452 if(real_path == NULL) {
454 return CURLE_OUT_OF_MEMORY;
456 memcpy(real_path, working_path, 1+working_path_len);
462 /* store the pointer for the caller to receive */
468 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
469 static int sshkeycallback(CURL *easy,
470 const struct curl_khkey *knownkey, /* known */
471 const struct curl_khkey *foundkey, /* found */
472 enum curl_khmatch match,
480 /* we only allow perfect matches, and we reject everything else */
481 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
486 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
489 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
490 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
492 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
496 * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
497 * architectures so we check of the necessary function is present.
499 #ifndef HAVE_LIBSSH2_SCP_SEND64
500 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
502 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
503 (libssh2_uint64_t)d, 0, 0)
507 * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
509 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
510 #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
513 static CURLcode ssh_knownhost(struct connectdata *conn)
515 CURLcode result = CURLE_OK;
517 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
518 struct SessionHandle *data = conn->data;
520 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
521 /* we're asked to verify the host against a file */
522 struct ssh_conn *sshc = &conn->proto.sshc;
526 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
528 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
533 * A subject to figure out is what host name we need to pass in here.
534 * What host name does OpenSSH store in its file if an IDN name is
537 struct libssh2_knownhost *host;
538 enum curl_khmatch keymatch;
539 curl_sshkeycallback func =
540 data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
541 struct curl_khkey knownkey;
542 struct curl_khkey *knownkeyp = NULL;
543 struct curl_khkey foundkey;
545 keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
546 LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
548 keycheck = libssh2_knownhost_check(sshc->kh,
551 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
552 LIBSSH2_KNOWNHOST_KEYENC_RAW|
556 infof(data, "SSH host check: %d, key: %s\n", keycheck,
557 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
560 /* setup 'knownkey' */
561 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
562 knownkey.key = host->key;
564 knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
565 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
566 knownkeyp = &knownkey;
569 /* setup 'foundkey' */
570 foundkey.key = remotekey;
571 foundkey.len = keylen;
572 foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
573 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
576 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
577 * curl_khmatch enum are ever modified, we need to introduce a
578 * translation table here!
580 keymatch = (enum curl_khmatch)keycheck;
582 /* Ask the callback how to behave */
583 rc = func(data, knownkeyp, /* from the knownhosts file */
584 &foundkey, /* from the remote host */
585 keymatch, data->set.ssh_keyfunc_userp);
588 /* no remotekey means failure! */
589 rc = CURLKHSTAT_REJECT;
592 default: /* unknown return codes will equal reject */
593 case CURLKHSTAT_REJECT:
594 state(conn, SSH_SESSION_FREE);
595 case CURLKHSTAT_DEFER:
596 /* DEFER means bail out but keep the SSH_HOSTKEY state */
597 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
599 case CURLKHSTAT_FINE:
600 case CURLKHSTAT_FINE_ADD_TO_FILE:
602 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
603 /* the found host+key didn't match but has been told to be fine
604 anyway so we add it in memory */
605 int addrc = libssh2_knownhost_add(sshc->kh,
606 conn->host.name, NULL,
608 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
609 LIBSSH2_KNOWNHOST_KEYENC_RAW|
612 infof(data, "Warning adding the known host %s failed!\n",
614 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
615 /* now we write the entire in-memory list of known hosts to the
618 libssh2_knownhost_writefile(sshc->kh,
619 data->set.str[STRING_SSH_KNOWNHOSTS],
620 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
622 infof(data, "Warning, writing %s failed!\n",
623 data->set.str[STRING_SSH_KNOWNHOSTS]);
630 #else /* HAVE_LIBSSH2_KNOWNHOST_API */
636 static CURLcode ssh_check_fingerprint(struct connectdata *conn)
638 struct ssh_conn *sshc = &conn->proto.sshc;
639 struct SessionHandle *data = conn->data;
640 const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
644 const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
645 LIBSSH2_HOSTKEY_HASH_MD5);
648 /* The fingerprint points to static storage (!), don't free() it. */
649 for(i = 0; i < 16; i++)
650 snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
651 infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
654 /* Before we authenticate we check the hostkey's MD5 fingerprint
655 * against a known fingerprint, if available.
657 if(pubkey_md5 && strlen(pubkey_md5) == 32) {
658 if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
661 "Denied establishing ssh session: mismatch md5 fingerprint. "
662 "Remote %s is not equal to %s", md5buffer, pubkey_md5);
665 "Denied establishing ssh session: md5 fingerprint not available");
666 state(conn, SSH_SESSION_FREE);
667 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
668 return sshc->actualcode;
671 infof(data, "MD5 checksum match!\n");
672 /* as we already matched, we skip the check for known hosts */
677 return ssh_knownhost(conn);
681 * ssh_statemach_act() runs the SSH state machine as far as it can without
682 * blocking and without reaching the end. The data the pointer 'block' points
683 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
684 * meaning it wants to be called again when the socket is ready
687 static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
689 CURLcode result = CURLE_OK;
690 struct SessionHandle *data = conn->data;
691 struct SSHPROTO *sftp_scp = data->req.protop;
692 struct ssh_conn *sshc = &conn->proto.sshc;
693 curl_socket_t sock = conn->sock[FIRSTSOCKET];
694 char *new_readdir_line;
695 int rc = LIBSSH2_ERROR_NONE;
697 int seekerr = CURL_SEEKFUNC_OK;
698 *block = 0; /* we're not blocking by default */
702 switch(sshc->state) {
704 sshc->secondCreateDirs = 0;
705 sshc->nextstate = SSH_NO_STATE;
706 sshc->actualcode = CURLE_OK;
708 /* Set libssh2 to non-blocking, since everything internally is
710 libssh2_session_set_blocking(sshc->ssh_session, 0);
712 state(conn, SSH_S_STARTUP);
716 rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
717 if(rc == LIBSSH2_ERROR_EAGAIN) {
721 failf(data, "Failure establishing ssh session");
722 state(conn, SSH_SESSION_FREE);
723 sshc->actualcode = CURLE_FAILED_INIT;
727 state(conn, SSH_HOSTKEY);
732 * Before we authenticate we should check the hostkey's fingerprint
733 * against our known hosts. How that is handled (reading from file,
734 * whatever) is up to us.
736 result = ssh_check_fingerprint(conn);
737 if(result == CURLE_OK)
738 state(conn, SSH_AUTHLIST);
743 * Figure out authentication methods
744 * NB: As soon as we have provided a username to an openssh server we
745 * must never change it later. Thus, always specify the correct username
746 * here, even though the libssh2 docs kind of indicate that it should be
747 * possible to get a 'generic' list (not user-specific) of authentication
748 * methods, presumably with a blank username. That won't work in my
750 * So always specify it here.
752 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
754 curlx_uztoui(strlen(conn->user)));
756 if(!sshc->authlist) {
757 if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
758 LIBSSH2_ERROR_EAGAIN) {
759 rc = LIBSSH2_ERROR_EAGAIN;
763 state(conn, SSH_SESSION_FREE);
764 sshc->actualcode = libssh2_session_error_to_CURLE(err);
768 infof(data, "SSH authentication methods available: %s\n",
771 state(conn, SSH_AUTH_PKEY_INIT);
774 case SSH_AUTH_PKEY_INIT:
776 * Check the supported auth types in the order I feel is most secure
777 * with the requested type of authentication
779 sshc->authed = FALSE;
781 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
782 (strstr(sshc->authlist, "publickey") != NULL)) {
784 bool rsa_pub_empty_but_ok = FALSE;
786 sshc->rsa_pub = sshc->rsa = NULL;
788 /* To ponder about: should really the lib be messing about with the
789 HOME environment variable etc? */
790 home = curl_getenv("HOME");
792 if(data->set.str[STRING_SSH_PUBLIC_KEY] &&
793 !*data->set.str[STRING_SSH_PUBLIC_KEY])
794 rsa_pub_empty_but_ok = true;
795 else if(data->set.str[STRING_SSH_PUBLIC_KEY])
796 sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]);
798 sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
800 /* as a final resort, try current dir! */
801 sshc->rsa_pub = strdup("id_dsa.pub");
803 if(!rsa_pub_empty_but_ok && (sshc->rsa_pub == NULL)) {
805 state(conn, SSH_SESSION_FREE);
806 sshc->actualcode = CURLE_OUT_OF_MEMORY;
810 if(data->set.str[STRING_SSH_PRIVATE_KEY])
811 sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]);
813 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
815 /* as a final resort, try current dir! */
816 sshc->rsa = strdup("id_dsa");
818 if(sshc->rsa == NULL) {
820 Curl_safefree(sshc->rsa_pub);
821 state(conn, SSH_SESSION_FREE);
822 sshc->actualcode = CURLE_OUT_OF_MEMORY;
826 sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
827 if(!sshc->passphrase)
828 sshc->passphrase = "";
832 infof(data, "Using ssh public key file %s\n", sshc->rsa_pub);
833 infof(data, "Using ssh private key file %s\n", sshc->rsa);
835 state(conn, SSH_AUTH_PKEY);
838 state(conn, SSH_AUTH_PASS_INIT);
843 /* The function below checks if the files exists, no need to stat() here.
845 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
850 sshc->rsa, sshc->passphrase);
851 if(rc == LIBSSH2_ERROR_EAGAIN) {
855 Curl_safefree(sshc->rsa_pub);
856 Curl_safefree(sshc->rsa);
860 infof(data, "Initialized SSH public key authentication\n");
861 state(conn, SSH_AUTH_DONE);
865 (void)libssh2_session_last_error(sshc->ssh_session,
867 infof(data, "SSH public key authentication failed: %s\n", err_msg);
868 state(conn, SSH_AUTH_PASS_INIT);
872 case SSH_AUTH_PASS_INIT:
873 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
874 (strstr(sshc->authlist, "password") != NULL)) {
875 state(conn, SSH_AUTH_PASS);
878 state(conn, SSH_AUTH_HOST_INIT);
883 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
884 curlx_uztoui(strlen(conn->user)),
886 curlx_uztoui(strlen(conn->passwd)),
888 if(rc == LIBSSH2_ERROR_EAGAIN) {
893 infof(data, "Initialized password authentication\n");
894 state(conn, SSH_AUTH_DONE);
897 state(conn, SSH_AUTH_HOST_INIT);
901 case SSH_AUTH_HOST_INIT:
902 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
903 (strstr(sshc->authlist, "hostbased") != NULL)) {
904 state(conn, SSH_AUTH_HOST);
907 state(conn, SSH_AUTH_AGENT_INIT);
912 state(conn, SSH_AUTH_AGENT_INIT);
915 case SSH_AUTH_AGENT_INIT:
916 #ifdef HAVE_LIBSSH2_AGENT_API
917 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
918 && (strstr(sshc->authlist, "publickey") != NULL)) {
920 /* Connect to the ssh-agent */
921 /* The agent could be shared by a curl thread i believe
922 but nothing obvious as keys can be added/removed at any time */
923 if(!sshc->ssh_agent) {
924 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
925 if(!sshc->ssh_agent) {
926 infof(data, "Could not create agent object\n");
928 state(conn, SSH_AUTH_KEY_INIT);
932 rc = libssh2_agent_connect(sshc->ssh_agent);
933 if(rc == LIBSSH2_ERROR_EAGAIN)
936 infof(data, "Failure connecting to agent\n");
937 state(conn, SSH_AUTH_KEY_INIT);
940 state(conn, SSH_AUTH_AGENT_LIST);
944 #endif /* HAVE_LIBSSH2_AGENT_API */
945 state(conn, SSH_AUTH_KEY_INIT);
948 case SSH_AUTH_AGENT_LIST:
949 #ifdef HAVE_LIBSSH2_AGENT_API
950 rc = libssh2_agent_list_identities(sshc->ssh_agent);
952 if(rc == LIBSSH2_ERROR_EAGAIN)
955 infof(data, "Failure requesting identities to agent\n");
956 state(conn, SSH_AUTH_KEY_INIT);
959 state(conn, SSH_AUTH_AGENT);
960 sshc->sshagent_prev_identity = NULL;
966 #ifdef HAVE_LIBSSH2_AGENT_API
967 /* as prev_identity evolves only after an identity user auth finished we
968 can safely request it again as long as EAGAIN is returned here or by
969 libssh2_agent_userauth */
970 rc = libssh2_agent_get_identity(sshc->ssh_agent,
971 &sshc->sshagent_identity,
972 sshc->sshagent_prev_identity);
973 if(rc == LIBSSH2_ERROR_EAGAIN)
977 rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
978 sshc->sshagent_identity);
981 if(rc != LIBSSH2_ERROR_EAGAIN) {
982 /* tried and failed? go to next identity */
983 sshc->sshagent_prev_identity = sshc->sshagent_identity;
990 infof(data, "Failure requesting identities to agent\n");
992 infof(data, "No identity would match\n");
994 if(rc == LIBSSH2_ERROR_NONE) {
996 infof(data, "Agent based authentication successful\n");
997 state(conn, SSH_AUTH_DONE);
1000 state(conn, SSH_AUTH_KEY_INIT);
1004 case SSH_AUTH_KEY_INIT:
1005 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
1006 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
1007 state(conn, SSH_AUTH_KEY);
1010 state(conn, SSH_AUTH_DONE);
1015 /* Authentication failed. Continue with keyboard-interactive now. */
1016 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
1019 strlen(conn->user)),
1021 if(rc == LIBSSH2_ERROR_EAGAIN) {
1025 sshc->authed = TRUE;
1026 infof(data, "Initialized keyboard interactive authentication\n");
1028 state(conn, SSH_AUTH_DONE);
1033 failf(data, "Authentication failure");
1034 state(conn, SSH_SESSION_FREE);
1035 sshc->actualcode = CURLE_LOGIN_DENIED;
1040 * At this point we have an authenticated ssh session.
1042 infof(data, "Authentication complete\n");
1044 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
1046 conn->sockfd = sock;
1047 conn->writesockfd = CURL_SOCKET_BAD;
1049 if(conn->handler->protocol == CURLPROTO_SFTP) {
1050 state(conn, SSH_SFTP_INIT);
1053 infof(data, "SSH CONNECT phase done\n");
1054 state(conn, SSH_STOP);
1059 * Start the libssh2 sftp session
1061 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
1062 if(!sshc->sftp_session) {
1063 if(libssh2_session_last_errno(sshc->ssh_session) ==
1064 LIBSSH2_ERROR_EAGAIN) {
1065 rc = LIBSSH2_ERROR_EAGAIN;
1071 (void)libssh2_session_last_error(sshc->ssh_session,
1073 failf(data, "Failure initializing sftp session: %s", err_msg);
1074 state(conn, SSH_SESSION_FREE);
1075 sshc->actualcode = CURLE_FAILED_INIT;
1079 state(conn, SSH_SFTP_REALPATH);
1082 case SSH_SFTP_REALPATH:
1084 char tempHome[PATH_MAX];
1087 * Get the "home" directory
1089 rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
1090 tempHome, PATH_MAX-1);
1091 if(rc == LIBSSH2_ERROR_EAGAIN) {
1095 /* It seems that this string is not always NULL terminated */
1096 tempHome[rc] = '\0';
1097 sshc->homedir = strdup(tempHome);
1098 if(!sshc->homedir) {
1099 state(conn, SSH_SFTP_CLOSE);
1100 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1103 conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
1106 /* Return the error type */
1107 err = sftp_libssh2_last_error(sshc->sftp_session);
1108 result = sftp_libssh2_error_to_CURLE(err);
1109 sshc->actualcode = result?result:CURLE_SSH;
1110 DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
1112 state(conn, SSH_STOP);
1116 /* This is the last step in the SFTP connect phase. Do note that while
1117 we get the homedir here, we get the "workingpath" in the DO action
1118 since the homedir will remain the same between request but the
1119 working path will not. */
1120 DEBUGF(infof(data, "SSH CONNECT phase done\n"));
1121 state(conn, SSH_STOP);
1124 case SSH_SFTP_QUOTE_INIT:
1126 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
1128 sshc->actualcode = result;
1129 state(conn, SSH_STOP);
1133 if(data->set.quote) {
1134 infof(data, "Sending quote commands\n");
1135 sshc->quote_item = data->set.quote;
1136 state(conn, SSH_SFTP_QUOTE);
1139 state(conn, SSH_SFTP_TRANS_INIT);
1143 case SSH_SFTP_POSTQUOTE_INIT:
1144 if(data->set.postquote) {
1145 infof(data, "Sending quote commands\n");
1146 sshc->quote_item = data->set.postquote;
1147 state(conn, SSH_SFTP_QUOTE);
1150 state(conn, SSH_STOP);
1154 case SSH_SFTP_QUOTE:
1155 /* Send any quote commands */
1160 * Support some of the "FTP" commands
1162 char *cmd = sshc->quote_item->data;
1163 sshc->acceptfail = FALSE;
1165 /* if a command starts with an asterisk, which a legal SFTP command never
1166 can, the command will be allowed to fail without it causing any
1167 aborts or cancels etc. It will cause libcurl to act as if the command
1168 is successful, whatever the server reponds. */
1172 sshc->acceptfail = TRUE;
1175 if(curl_strequal("pwd", cmd)) {
1176 /* output debug output if that is requested */
1177 char *tmp = aprintf("257 \"%s\" is current directory.\n",
1180 result = CURLE_OUT_OF_MEMORY;
1181 state(conn, SSH_SFTP_CLOSE);
1182 sshc->nextstate = SSH_NO_STATE;
1185 if(data->set.verbose) {
1186 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
1187 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
1189 /* this sends an FTP-like "header" to the header callback so that the
1190 current directory can be read very similar to how it is read when
1191 using ordinary FTP. */
1192 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1194 state(conn, SSH_SFTP_NEXT_QUOTE);
1199 * the arguments following the command must be separated from the
1200 * command with a space so we can check for it unconditionally
1202 cp = strchr(cmd, ' ');
1204 failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
1205 state(conn, SSH_SFTP_CLOSE);
1206 sshc->nextstate = SSH_NO_STATE;
1207 sshc->actualcode = CURLE_QUOTE_ERROR;
1212 * also, every command takes at least one argument so we get that
1213 * first argument right now
1215 result = get_pathname(&cp, &sshc->quote_path1);
1217 if(result == CURLE_OUT_OF_MEMORY)
1218 failf(data, "Out of memory");
1220 failf(data, "Syntax error: Bad first parameter");
1221 state(conn, SSH_SFTP_CLOSE);
1222 sshc->nextstate = SSH_NO_STATE;
1223 sshc->actualcode = result;
1228 * SFTP is a binary protocol, so we don't send text commands to
1229 * the server. Instead, we scan for commands for commands used by
1230 * OpenSSH's sftp program and call the appropriate libssh2
1233 if(curl_strnequal(cmd, "chgrp ", 6) ||
1234 curl_strnequal(cmd, "chmod ", 6) ||
1235 curl_strnequal(cmd, "chown ", 6) ) {
1236 /* attribute change */
1238 /* sshc->quote_path1 contains the mode to set */
1239 /* get the destination */
1240 result = get_pathname(&cp, &sshc->quote_path2);
1242 if(result == CURLE_OUT_OF_MEMORY)
1243 failf(data, "Out of memory");
1245 failf(data, "Syntax error in chgrp/chmod/chown: "
1246 "Bad second parameter");
1247 Curl_safefree(sshc->quote_path1);
1248 state(conn, SSH_SFTP_CLOSE);
1249 sshc->nextstate = SSH_NO_STATE;
1250 sshc->actualcode = result;
1253 memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1254 state(conn, SSH_SFTP_QUOTE_STAT);
1257 else if(curl_strnequal(cmd, "ln ", 3) ||
1258 curl_strnequal(cmd, "symlink ", 8)) {
1259 /* symbolic linking */
1260 /* sshc->quote_path1 is the source */
1261 /* get the destination */
1262 result = get_pathname(&cp, &sshc->quote_path2);
1264 if(result == CURLE_OUT_OF_MEMORY)
1265 failf(data, "Out of memory");
1268 "Syntax error in ln/symlink: Bad second parameter");
1269 Curl_safefree(sshc->quote_path1);
1270 state(conn, SSH_SFTP_CLOSE);
1271 sshc->nextstate = SSH_NO_STATE;
1272 sshc->actualcode = result;
1275 state(conn, SSH_SFTP_QUOTE_SYMLINK);
1278 else if(curl_strnequal(cmd, "mkdir ", 6)) {
1280 state(conn, SSH_SFTP_QUOTE_MKDIR);
1283 else if(curl_strnequal(cmd, "rename ", 7)) {
1285 /* first param is the source path */
1286 /* second param is the dest. path */
1287 result = get_pathname(&cp, &sshc->quote_path2);
1289 if(result == CURLE_OUT_OF_MEMORY)
1290 failf(data, "Out of memory");
1292 failf(data, "Syntax error in rename: Bad second parameter");
1293 Curl_safefree(sshc->quote_path1);
1294 state(conn, SSH_SFTP_CLOSE);
1295 sshc->nextstate = SSH_NO_STATE;
1296 sshc->actualcode = result;
1299 state(conn, SSH_SFTP_QUOTE_RENAME);
1302 else if(curl_strnequal(cmd, "rmdir ", 6)) {
1304 state(conn, SSH_SFTP_QUOTE_RMDIR);
1307 else if(curl_strnequal(cmd, "rm ", 3)) {
1308 state(conn, SSH_SFTP_QUOTE_UNLINK);
1312 failf(data, "Unknown SFTP command");
1313 Curl_safefree(sshc->quote_path1);
1314 Curl_safefree(sshc->quote_path2);
1315 state(conn, SSH_SFTP_CLOSE);
1316 sshc->nextstate = SSH_NO_STATE;
1317 sshc->actualcode = CURLE_QUOTE_ERROR;
1321 if(!sshc->quote_item) {
1322 state(conn, SSH_SFTP_TRANS_INIT);
1326 case SSH_SFTP_NEXT_QUOTE:
1327 Curl_safefree(sshc->quote_path1);
1328 Curl_safefree(sshc->quote_path2);
1330 sshc->quote_item = sshc->quote_item->next;
1332 if(sshc->quote_item) {
1333 state(conn, SSH_SFTP_QUOTE);
1336 if(sshc->nextstate != SSH_NO_STATE) {
1337 state(conn, sshc->nextstate);
1338 sshc->nextstate = SSH_NO_STATE;
1341 state(conn, SSH_SFTP_TRANS_INIT);
1346 case SSH_SFTP_QUOTE_STAT:
1348 char *cmd = sshc->quote_item->data;
1349 sshc->acceptfail = FALSE;
1351 /* if a command starts with an asterisk, which a legal SFTP command never
1352 can, the command will be allowed to fail without it causing any
1353 aborts or cancels etc. It will cause libcurl to act as if the command
1354 is successful, whatever the server reponds. */
1358 sshc->acceptfail = TRUE;
1361 if(!curl_strnequal(cmd, "chmod", 5)) {
1362 /* Since chown and chgrp only set owner OR group but libssh2 wants to
1363 * set them both at once, we need to obtain the current ownership
1364 * first. This takes an extra protocol round trip.
1366 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1367 curlx_uztoui(strlen(sshc->quote_path2)),
1369 &sshc->quote_attrs);
1370 if(rc == LIBSSH2_ERROR_EAGAIN) {
1373 else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
1374 err = sftp_libssh2_last_error(sshc->sftp_session);
1375 Curl_safefree(sshc->quote_path1);
1376 Curl_safefree(sshc->quote_path2);
1377 failf(data, "Attempt to get SFTP stats failed: %s",
1378 sftp_libssh2_strerror(err));
1379 state(conn, SSH_SFTP_CLOSE);
1380 sshc->nextstate = SSH_NO_STATE;
1381 sshc->actualcode = CURLE_QUOTE_ERROR;
1386 /* Now set the new attributes... */
1387 if(curl_strnequal(cmd, "chgrp", 5)) {
1388 sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
1389 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1390 if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1391 !sshc->acceptfail) {
1392 Curl_safefree(sshc->quote_path1);
1393 Curl_safefree(sshc->quote_path2);
1394 failf(data, "Syntax error: chgrp gid not a number");
1395 state(conn, SSH_SFTP_CLOSE);
1396 sshc->nextstate = SSH_NO_STATE;
1397 sshc->actualcode = CURLE_QUOTE_ERROR;
1401 else if(curl_strnequal(cmd, "chmod", 5)) {
1402 sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
1403 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1404 /* permissions are octal */
1405 if(sshc->quote_attrs.permissions == 0 &&
1406 !ISDIGIT(sshc->quote_path1[0])) {
1407 Curl_safefree(sshc->quote_path1);
1408 Curl_safefree(sshc->quote_path2);
1409 failf(data, "Syntax error: chmod permissions not a number");
1410 state(conn, SSH_SFTP_CLOSE);
1411 sshc->nextstate = SSH_NO_STATE;
1412 sshc->actualcode = CURLE_QUOTE_ERROR;
1416 else if(curl_strnequal(cmd, "chown", 5)) {
1417 sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
1418 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1419 if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1420 !sshc->acceptfail) {
1421 Curl_safefree(sshc->quote_path1);
1422 Curl_safefree(sshc->quote_path2);
1423 failf(data, "Syntax error: chown uid not a number");
1424 state(conn, SSH_SFTP_CLOSE);
1425 sshc->nextstate = SSH_NO_STATE;
1426 sshc->actualcode = CURLE_QUOTE_ERROR;
1431 /* Now send the completed structure... */
1432 state(conn, SSH_SFTP_QUOTE_SETSTAT);
1436 case SSH_SFTP_QUOTE_SETSTAT:
1437 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1438 curlx_uztoui(strlen(sshc->quote_path2)),
1439 LIBSSH2_SFTP_SETSTAT,
1440 &sshc->quote_attrs);
1441 if(rc == LIBSSH2_ERROR_EAGAIN) {
1444 else if(rc != 0 && !sshc->acceptfail) {
1445 err = sftp_libssh2_last_error(sshc->sftp_session);
1446 Curl_safefree(sshc->quote_path1);
1447 Curl_safefree(sshc->quote_path2);
1448 failf(data, "Attempt to set SFTP stats failed: %s",
1449 sftp_libssh2_strerror(err));
1450 state(conn, SSH_SFTP_CLOSE);
1451 sshc->nextstate = SSH_NO_STATE;
1452 sshc->actualcode = CURLE_QUOTE_ERROR;
1455 state(conn, SSH_SFTP_NEXT_QUOTE);
1458 case SSH_SFTP_QUOTE_SYMLINK:
1459 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
1460 curlx_uztoui(strlen(sshc->quote_path1)),
1462 curlx_uztoui(strlen(sshc->quote_path2)),
1463 LIBSSH2_SFTP_SYMLINK);
1464 if(rc == LIBSSH2_ERROR_EAGAIN) {
1467 else if(rc != 0 && !sshc->acceptfail) {
1468 err = sftp_libssh2_last_error(sshc->sftp_session);
1469 Curl_safefree(sshc->quote_path1);
1470 Curl_safefree(sshc->quote_path2);
1471 failf(data, "symlink command failed: %s",
1472 sftp_libssh2_strerror(err));
1473 state(conn, SSH_SFTP_CLOSE);
1474 sshc->nextstate = SSH_NO_STATE;
1475 sshc->actualcode = CURLE_QUOTE_ERROR;
1478 state(conn, SSH_SFTP_NEXT_QUOTE);
1481 case SSH_SFTP_QUOTE_MKDIR:
1482 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
1483 curlx_uztoui(strlen(sshc->quote_path1)),
1484 data->set.new_directory_perms);
1485 if(rc == LIBSSH2_ERROR_EAGAIN) {
1488 else if(rc != 0 && !sshc->acceptfail) {
1489 err = sftp_libssh2_last_error(sshc->sftp_session);
1490 Curl_safefree(sshc->quote_path1);
1491 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
1492 state(conn, SSH_SFTP_CLOSE);
1493 sshc->nextstate = SSH_NO_STATE;
1494 sshc->actualcode = CURLE_QUOTE_ERROR;
1497 state(conn, SSH_SFTP_NEXT_QUOTE);
1500 case SSH_SFTP_QUOTE_RENAME:
1501 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
1502 curlx_uztoui(strlen(sshc->quote_path1)),
1504 curlx_uztoui(strlen(sshc->quote_path2)),
1505 LIBSSH2_SFTP_RENAME_OVERWRITE |
1506 LIBSSH2_SFTP_RENAME_ATOMIC |
1507 LIBSSH2_SFTP_RENAME_NATIVE);
1509 if(rc == LIBSSH2_ERROR_EAGAIN) {
1512 else if(rc != 0 && !sshc->acceptfail) {
1513 err = sftp_libssh2_last_error(sshc->sftp_session);
1514 Curl_safefree(sshc->quote_path1);
1515 Curl_safefree(sshc->quote_path2);
1516 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
1517 state(conn, SSH_SFTP_CLOSE);
1518 sshc->nextstate = SSH_NO_STATE;
1519 sshc->actualcode = CURLE_QUOTE_ERROR;
1522 state(conn, SSH_SFTP_NEXT_QUOTE);
1525 case SSH_SFTP_QUOTE_RMDIR:
1526 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
1527 curlx_uztoui(strlen(sshc->quote_path1)));
1528 if(rc == LIBSSH2_ERROR_EAGAIN) {
1531 else if(rc != 0 && !sshc->acceptfail) {
1532 err = sftp_libssh2_last_error(sshc->sftp_session);
1533 Curl_safefree(sshc->quote_path1);
1534 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
1535 state(conn, SSH_SFTP_CLOSE);
1536 sshc->nextstate = SSH_NO_STATE;
1537 sshc->actualcode = CURLE_QUOTE_ERROR;
1540 state(conn, SSH_SFTP_NEXT_QUOTE);
1543 case SSH_SFTP_QUOTE_UNLINK:
1544 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
1545 curlx_uztoui(strlen(sshc->quote_path1)));
1546 if(rc == LIBSSH2_ERROR_EAGAIN) {
1549 else if(rc != 0 && !sshc->acceptfail) {
1550 err = sftp_libssh2_last_error(sshc->sftp_session);
1551 Curl_safefree(sshc->quote_path1);
1552 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
1553 state(conn, SSH_SFTP_CLOSE);
1554 sshc->nextstate = SSH_NO_STATE;
1555 sshc->actualcode = CURLE_QUOTE_ERROR;
1558 state(conn, SSH_SFTP_NEXT_QUOTE);
1561 case SSH_SFTP_TRANS_INIT:
1562 if(data->set.upload)
1563 state(conn, SSH_SFTP_UPLOAD_INIT);
1565 if(data->set.opt_no_body)
1566 state(conn, SSH_STOP);
1567 else if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
1568 state(conn, SSH_SFTP_READDIR_INIT);
1570 state(conn, SSH_SFTP_DOWNLOAD_INIT);
1574 case SSH_SFTP_UPLOAD_INIT:
1576 unsigned long flags;
1578 * NOTE!!! libssh2 requires that the destination path is a full path
1579 * that includes the destination file and name OR ends in a "/"
1580 * If this is not done the destination file will be named the
1581 * same name as the last directory in the path.
1584 if(data->state.resume_from != 0) {
1585 LIBSSH2_SFTP_ATTRIBUTES attrs;
1586 if(data->state.resume_from < 0) {
1587 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
1588 curlx_uztoui(strlen(sftp_scp->path)),
1589 LIBSSH2_SFTP_STAT, &attrs);
1590 if(rc == LIBSSH2_ERROR_EAGAIN) {
1594 data->state.resume_from = 0;
1597 curl_off_t size = attrs.filesize;
1599 failf(data, "Bad file size (%" FORMAT_OFF_T ")", size);
1600 return CURLE_BAD_DOWNLOAD_RESUME;
1602 data->state.resume_from = attrs.filesize;
1607 if(data->set.ftp_append)
1608 /* Try to open for append, but create if nonexisting */
1609 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
1610 else if(data->state.resume_from > 0)
1611 /* If we have restart position then open for append */
1612 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
1614 /* Clear file before writing (normal behaviour) */
1615 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
1618 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
1619 curlx_uztoui(strlen(sftp_scp->path)),
1620 flags, data->set.new_file_perms,
1621 LIBSSH2_SFTP_OPENFILE);
1623 if(!sshc->sftp_handle) {
1624 rc = libssh2_session_last_errno(sshc->ssh_session);
1626 if(LIBSSH2_ERROR_EAGAIN == rc)
1629 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
1630 /* only when there was an SFTP protocol error can we extract
1632 err = sftp_libssh2_last_error(sshc->sftp_session);
1634 err = -1; /* not an sftp error at all */
1636 if(sshc->secondCreateDirs) {
1637 state(conn, SSH_SFTP_CLOSE);
1638 sshc->actualcode = err>= LIBSSH2_FX_OK?
1639 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1640 failf(data, "Creating the dir/file failed: %s",
1641 sftp_libssh2_strerror(err));
1644 else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
1645 (err == LIBSSH2_FX_FAILURE) ||
1646 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
1647 (data->set.ftp_create_missing_dirs &&
1648 (strlen(sftp_scp->path) > 1))) {
1649 /* try to create the path remotely */
1650 sshc->secondCreateDirs = 1;
1651 state(conn, SSH_SFTP_CREATE_DIRS_INIT);
1654 state(conn, SSH_SFTP_CLOSE);
1655 sshc->actualcode = err>= LIBSSH2_FX_OK?
1656 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1657 if(!sshc->actualcode) {
1658 /* Sometimes, for some reason libssh2_sftp_last_error() returns
1659 zero even though libssh2_sftp_open() failed previously! We need
1660 to work around that! */
1661 sshc->actualcode = CURLE_SSH;
1664 failf(data, "Upload failed: %s (%d/%d)",
1665 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
1671 /* If we have restart point then we need to seek to the correct
1673 if(data->state.resume_from > 0) {
1674 /* Let's read off the proper amount of bytes from the input. */
1675 if(conn->seek_func) {
1676 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1680 if(seekerr != CURL_SEEKFUNC_OK) {
1682 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1683 failf(data, "Could not seek stream");
1684 return CURLE_FTP_COULDNT_USE_REST;
1686 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
1688 curl_off_t passed=0;
1690 size_t readthisamountnow =
1691 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
1692 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
1694 size_t actuallyread =
1695 conn->fread_func(data->state.buffer, 1, readthisamountnow,
1698 passed += actuallyread;
1699 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1700 /* this checks for greater-than only to make sure that the
1701 CURL_READFUNC_ABORT return code still aborts */
1702 failf(data, "Failed to read data");
1703 return CURLE_FTP_COULDNT_USE_REST;
1705 } while(passed < data->state.resume_from);
1709 /* now, decrease the size of the read */
1710 if(data->set.infilesize > 0) {
1711 data->set.infilesize -= data->state.resume_from;
1712 data->req.size = data->set.infilesize;
1713 Curl_pgrsSetUploadSize(data, data->set.infilesize);
1716 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1718 if(data->set.infilesize > 0) {
1719 data->req.size = data->set.infilesize;
1720 Curl_pgrsSetUploadSize(data, data->set.infilesize);
1723 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
1725 /* not set by Curl_setup_transfer to preserve keepon bits */
1726 conn->sockfd = conn->writesockfd;
1729 state(conn, SSH_SFTP_CLOSE);
1730 sshc->actualcode = result;
1733 /* store this original bitmask setup to use later on if we can't
1734 figure out a "real" bitmask */
1735 sshc->orig_waitfor = data->req.keepon;
1737 /* we want to use the _sending_ function even when the socket turns
1738 out readable as the underlying libssh2 sftp send function will deal
1739 with both accordingly */
1740 conn->cselect_bits = CURL_CSELECT_OUT;
1742 /* since we don't really wait for anything at this point, we want the
1743 state machine to move on as soon as possible so we set a very short
1745 Curl_expire(data, 1);
1747 state(conn, SSH_STOP);
1752 case SSH_SFTP_CREATE_DIRS_INIT:
1753 if(strlen(sftp_scp->path) > 1) {
1754 sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
1755 state(conn, SSH_SFTP_CREATE_DIRS);
1758 state(conn, SSH_SFTP_UPLOAD_INIT);
1762 case SSH_SFTP_CREATE_DIRS:
1763 if((sshc->slash_pos = strchr(sshc->slash_pos, '/')) != NULL) {
1764 *sshc->slash_pos = 0;
1766 infof(data, "Creating directory '%s'\n", sftp_scp->path);
1767 state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
1771 state(conn, SSH_SFTP_UPLOAD_INIT);
1775 case SSH_SFTP_CREATE_DIRS_MKDIR:
1776 /* 'mode' - parameter is preliminary - default to 0644 */
1777 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
1778 curlx_uztoui(strlen(sftp_scp->path)),
1779 data->set.new_directory_perms);
1780 if(rc == LIBSSH2_ERROR_EAGAIN) {
1783 *sshc->slash_pos = '/';
1787 * Abort if failure wasn't that the dir already exists or the
1788 * permission was denied (creation might succeed further down the
1789 * path) - retry on unspecific FAILURE also
1791 err = sftp_libssh2_last_error(sshc->sftp_session);
1792 if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
1793 (err != LIBSSH2_FX_FAILURE) &&
1794 (err != LIBSSH2_FX_PERMISSION_DENIED)) {
1795 result = sftp_libssh2_error_to_CURLE(err);
1796 state(conn, SSH_SFTP_CLOSE);
1797 sshc->actualcode = result?result:CURLE_SSH;
1801 state(conn, SSH_SFTP_CREATE_DIRS);
1804 case SSH_SFTP_READDIR_INIT:
1806 * This is a directory that we are trying to get, so produce a directory
1809 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
1812 strlen(sftp_scp->path)),
1813 0, 0, LIBSSH2_SFTP_OPENDIR);
1814 if(!sshc->sftp_handle) {
1815 if(libssh2_session_last_errno(sshc->ssh_session) ==
1816 LIBSSH2_ERROR_EAGAIN) {
1817 rc = LIBSSH2_ERROR_EAGAIN;
1821 err = sftp_libssh2_last_error(sshc->sftp_session);
1822 failf(data, "Could not open directory for reading: %s",
1823 sftp_libssh2_strerror(err));
1824 state(conn, SSH_SFTP_CLOSE);
1825 result = sftp_libssh2_error_to_CURLE(err);
1826 sshc->actualcode = result?result:CURLE_SSH;
1830 if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
1831 state(conn, SSH_SFTP_CLOSE);
1832 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1835 if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
1836 Curl_safefree(sshc->readdir_filename);
1837 state(conn, SSH_SFTP_CLOSE);
1838 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1841 state(conn, SSH_SFTP_READDIR);
1844 case SSH_SFTP_READDIR:
1845 sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
1846 sshc->readdir_filename,
1848 sshc->readdir_longentry,
1850 &sshc->readdir_attrs);
1851 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
1852 rc = LIBSSH2_ERROR_EAGAIN;
1855 if(sshc->readdir_len > 0) {
1856 sshc->readdir_filename[sshc->readdir_len] = '\0';
1858 if(data->set.ftp_list_only) {
1861 tmpLine = aprintf("%s\n", sshc->readdir_filename);
1862 if(tmpLine == NULL) {
1863 state(conn, SSH_SFTP_CLOSE);
1864 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1867 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1868 tmpLine, sshc->readdir_len+1);
1869 Curl_safefree(tmpLine);
1872 state(conn, SSH_STOP);
1875 /* since this counts what we send to the client, we include the
1876 newline in this counter */
1877 data->req.bytecount += sshc->readdir_len+1;
1879 /* output debug output if that is requested */
1880 if(data->set.verbose) {
1881 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
1882 sshc->readdir_len, conn);
1886 sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
1887 sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
1888 sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
1889 if(!sshc->readdir_line) {
1890 Curl_safefree(sshc->readdir_filename);
1891 Curl_safefree(sshc->readdir_longentry);
1892 state(conn, SSH_SFTP_CLOSE);
1893 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1897 memcpy(sshc->readdir_line, sshc->readdir_longentry,
1898 sshc->readdir_currLen);
1899 if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
1900 ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
1901 LIBSSH2_SFTP_S_IFLNK)) {
1902 sshc->readdir_linkPath = malloc(PATH_MAX + 1);
1903 if(sshc->readdir_linkPath == NULL) {
1904 Curl_safefree(sshc->readdir_filename);
1905 Curl_safefree(sshc->readdir_longentry);
1906 state(conn, SSH_SFTP_CLOSE);
1907 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1911 snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
1912 sshc->readdir_filename);
1913 state(conn, SSH_SFTP_READDIR_LINK);
1916 state(conn, SSH_SFTP_READDIR_BOTTOM);
1920 else if(sshc->readdir_len == 0) {
1921 Curl_safefree(sshc->readdir_filename);
1922 Curl_safefree(sshc->readdir_longentry);
1923 state(conn, SSH_SFTP_READDIR_DONE);
1926 else if(sshc->readdir_len <= 0) {
1927 err = sftp_libssh2_last_error(sshc->sftp_session);
1928 result = sftp_libssh2_error_to_CURLE(err);
1929 sshc->actualcode = result?result:CURLE_SSH;
1930 failf(data, "Could not open remote file for reading: %s :: %d",
1931 sftp_libssh2_strerror(err),
1932 libssh2_session_last_errno(sshc->ssh_session));
1933 Curl_safefree(sshc->readdir_filename);
1934 Curl_safefree(sshc->readdir_longentry);
1935 state(conn, SSH_SFTP_CLOSE);
1940 case SSH_SFTP_READDIR_LINK:
1942 libssh2_sftp_symlink_ex(sshc->sftp_session,
1943 sshc->readdir_linkPath,
1944 curlx_uztoui(strlen(sshc->readdir_linkPath)),
1945 sshc->readdir_filename,
1946 PATH_MAX, LIBSSH2_SFTP_READLINK);
1947 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
1948 rc = LIBSSH2_ERROR_EAGAIN;
1951 Curl_safefree(sshc->readdir_linkPath);
1953 /* get room for the filename and extra output */
1954 sshc->readdir_totalLen += 4 + sshc->readdir_len;
1955 new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
1956 if(!new_readdir_line) {
1957 Curl_safefree(sshc->readdir_line);
1958 Curl_safefree(sshc->readdir_filename);
1959 Curl_safefree(sshc->readdir_longentry);
1960 state(conn, SSH_SFTP_CLOSE);
1961 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1964 sshc->readdir_line = new_readdir_line;
1966 sshc->readdir_currLen += snprintf(sshc->readdir_line +
1967 sshc->readdir_currLen,
1968 sshc->readdir_totalLen -
1969 sshc->readdir_currLen,
1971 sshc->readdir_filename);
1973 state(conn, SSH_SFTP_READDIR_BOTTOM);
1976 case SSH_SFTP_READDIR_BOTTOM:
1977 sshc->readdir_currLen += snprintf(sshc->readdir_line +
1978 sshc->readdir_currLen,
1979 sshc->readdir_totalLen -
1980 sshc->readdir_currLen, "\n");
1981 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1983 sshc->readdir_currLen);
1985 if(result == CURLE_OK) {
1987 /* output debug output if that is requested */
1988 if(data->set.verbose) {
1989 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
1990 sshc->readdir_currLen, conn);
1992 data->req.bytecount += sshc->readdir_currLen;
1994 Curl_safefree(sshc->readdir_line);
1996 state(conn, SSH_STOP);
1999 state(conn, SSH_SFTP_READDIR);
2002 case SSH_SFTP_READDIR_DONE:
2003 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2004 LIBSSH2_ERROR_EAGAIN) {
2005 rc = LIBSSH2_ERROR_EAGAIN;
2008 sshc->sftp_handle = NULL;
2009 Curl_safefree(sshc->readdir_filename);
2010 Curl_safefree(sshc->readdir_longentry);
2012 /* no data to transfer */
2013 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
2014 state(conn, SSH_STOP);
2017 case SSH_SFTP_DOWNLOAD_INIT:
2019 * Work on getting the specified file
2022 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
2023 curlx_uztoui(strlen(sftp_scp->path)),
2024 LIBSSH2_FXF_READ, data->set.new_file_perms,
2025 LIBSSH2_SFTP_OPENFILE);
2026 if(!sshc->sftp_handle) {
2027 if(libssh2_session_last_errno(sshc->ssh_session) ==
2028 LIBSSH2_ERROR_EAGAIN) {
2029 rc = LIBSSH2_ERROR_EAGAIN;
2033 err = sftp_libssh2_last_error(sshc->sftp_session);
2034 failf(data, "Could not open remote file for reading: %s",
2035 sftp_libssh2_strerror(err));
2036 state(conn, SSH_SFTP_CLOSE);
2037 result = sftp_libssh2_error_to_CURLE(err);
2038 sshc->actualcode = result?result:CURLE_SSH;
2042 state(conn, SSH_SFTP_DOWNLOAD_STAT);
2045 case SSH_SFTP_DOWNLOAD_STAT:
2047 LIBSSH2_SFTP_ATTRIBUTES attrs;
2049 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
2050 curlx_uztoui(strlen(sftp_scp->path)),
2051 LIBSSH2_SFTP_STAT, &attrs);
2052 if(rc == LIBSSH2_ERROR_EAGAIN) {
2057 * libssh2_sftp_open() didn't return an error, so maybe the server
2058 * just doesn't support stat()
2060 data->req.size = -1;
2061 data->req.maxdownload = -1;
2064 curl_off_t size = attrs.filesize;
2067 failf(data, "Bad file size (%" FORMAT_OFF_T ")", size);
2068 return CURLE_BAD_DOWNLOAD_RESUME;
2070 if(conn->data->state.use_range) {
2071 curl_off_t from, to;
2075 from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
2076 while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
2078 to=curlx_strtoofft(ptr, &ptr2, 0);
2079 if((ptr == ptr2) /* no "to" value given */
2084 /* from is relative to end of file */
2088 failf(data, "Offset (%"
2089 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")",
2090 from, attrs.filesize);
2091 return CURLE_BAD_DOWNLOAD_RESUME;
2098 size = to - from + 1;
2101 SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
2103 data->req.size = size;
2104 data->req.maxdownload = size;
2105 Curl_pgrsSetDownloadSize(data, size);
2108 /* We can resume if we can seek to the resume position */
2109 if(data->state.resume_from) {
2110 if(data->state.resume_from < 0) {
2111 /* We're supposed to download the last abs(from) bytes */
2112 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
2113 failf(data, "Offset (%"
2114 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")",
2115 data->state.resume_from, attrs.filesize);
2116 return CURLE_BAD_DOWNLOAD_RESUME;
2118 /* download from where? */
2119 data->state.resume_from += attrs.filesize;
2122 if((curl_off_t)attrs.filesize < data->state.resume_from) {
2123 failf(data, "Offset (%" FORMAT_OFF_T
2124 ") was beyond file size (%" FORMAT_OFF_T ")",
2125 data->state.resume_from, attrs.filesize);
2126 return CURLE_BAD_DOWNLOAD_RESUME;
2129 /* Does a completed file need to be seeked and started or closed ? */
2130 /* Now store the number of bytes we are expected to download */
2131 data->req.size = attrs.filesize - data->state.resume_from;
2132 data->req.maxdownload = attrs.filesize - data->state.resume_from;
2133 Curl_pgrsSetDownloadSize(data,
2134 attrs.filesize - data->state.resume_from);
2135 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2138 /* Setup the actual download */
2139 if(data->req.size == 0) {
2140 /* no data to transfer */
2141 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
2142 infof(data, "File already completely downloaded\n");
2143 state(conn, SSH_STOP);
2147 Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
2148 FALSE, NULL, -1, NULL);
2150 /* not set by Curl_setup_transfer to preserve keepon bits */
2151 conn->writesockfd = conn->sockfd;
2153 /* we want to use the _receiving_ function even when the socket turns
2154 out writableable as the underlying libssh2 recv function will deal
2155 with both accordingly */
2156 conn->cselect_bits = CURL_CSELECT_IN;
2159 state(conn, SSH_SFTP_CLOSE);
2160 sshc->actualcode = result;
2163 state(conn, SSH_STOP);
2167 case SSH_SFTP_CLOSE:
2168 if(sshc->sftp_handle) {
2169 rc = libssh2_sftp_close(sshc->sftp_handle);
2170 if(rc == LIBSSH2_ERROR_EAGAIN) {
2174 infof(data, "Failed to close libssh2 file\n");
2176 sshc->sftp_handle = NULL;
2179 Curl_safefree(sftp_scp->path);
2181 DEBUGF(infof(data, "SFTP DONE done\n"));
2183 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2184 After nextstate is executed,the control should come back to
2185 SSH_SFTP_CLOSE to pass the correct result back */
2186 if(sshc->nextstate != SSH_NO_STATE) {
2187 state(conn, sshc->nextstate);
2188 sshc->nextstate = SSH_SFTP_CLOSE;
2191 state(conn, SSH_STOP);
2192 result = sshc->actualcode;
2196 case SSH_SFTP_SHUTDOWN:
2197 /* during times we get here due to a broken transfer and then the
2198 sftp_handle might not have been taken down so make sure that is done
2199 before we proceed */
2201 if(sshc->sftp_handle) {
2202 rc = libssh2_sftp_close(sshc->sftp_handle);
2203 if(rc == LIBSSH2_ERROR_EAGAIN) {
2207 infof(data, "Failed to close libssh2 file\n");
2209 sshc->sftp_handle = NULL;
2211 if(sshc->sftp_session) {
2212 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2213 if(rc == LIBSSH2_ERROR_EAGAIN) {
2217 infof(data, "Failed to stop libssh2 sftp subsystem\n");
2219 sshc->sftp_session = NULL;
2222 Curl_safefree(sshc->homedir);
2223 conn->data->state.most_recent_ftp_entrypath = NULL;
2225 state(conn, SSH_SESSION_DISCONNECT);
2228 case SSH_SCP_TRANS_INIT:
2229 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
2231 sshc->actualcode = result;
2232 state(conn, SSH_STOP);
2236 if(data->set.upload) {
2237 if(data->set.infilesize < 0) {
2238 failf(data, "SCP requires a known file size for upload");
2239 sshc->actualcode = CURLE_UPLOAD_FAILED;
2240 state(conn, SSH_SCP_CHANNEL_FREE);
2243 state(conn, SSH_SCP_UPLOAD_INIT);
2246 state(conn, SSH_SCP_DOWNLOAD_INIT);
2250 case SSH_SCP_UPLOAD_INIT:
2252 * libssh2 requires that the destination path is a full path that
2253 * includes the destination file and name OR ends in a "/" . If this is
2254 * not done the destination file will be named the same name as the last
2255 * directory in the path.
2258 SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
2259 data->set.infilesize);
2260 if(!sshc->ssh_channel) {
2261 if(libssh2_session_last_errno(sshc->ssh_session) ==
2262 LIBSSH2_ERROR_EAGAIN) {
2263 rc = LIBSSH2_ERROR_EAGAIN;
2270 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2271 &err_msg, NULL, 0));
2272 failf(conn->data, "%s", err_msg);
2273 state(conn, SSH_SCP_CHANNEL_FREE);
2274 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2280 Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
2283 /* not set by Curl_setup_transfer to preserve keepon bits */
2284 conn->sockfd = conn->writesockfd;
2287 state(conn, SSH_SCP_CHANNEL_FREE);
2288 sshc->actualcode = result;
2291 /* store this original bitmask setup to use later on if we can't
2292 figure out a "real" bitmask */
2293 sshc->orig_waitfor = data->req.keepon;
2295 /* we want to use the _sending_ function even when the socket turns
2296 out readable as the underlying libssh2 scp send function will deal
2297 with both accordingly */
2298 conn->cselect_bits = CURL_CSELECT_OUT;
2300 state(conn, SSH_STOP);
2304 case SSH_SCP_DOWNLOAD_INIT:
2307 * We must check the remote file; if it is a directory no values will
2311 curl_off_t bytecount;
2313 /* clear the struct scp recv will fill in */
2314 memset(&sb, 0, sizeof(struct stat));
2316 /* get a fresh new channel from the ssh layer */
2317 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2318 sftp_scp->path, &sb);
2319 if(!sshc->ssh_channel) {
2320 if(libssh2_session_last_errno(sshc->ssh_session) ==
2321 LIBSSH2_ERROR_EAGAIN) {
2322 rc = LIBSSH2_ERROR_EAGAIN;
2329 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2330 &err_msg, NULL, 0));
2331 failf(conn->data, "%s", err_msg);
2332 state(conn, SSH_SCP_CHANNEL_FREE);
2333 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2339 bytecount = (curl_off_t)sb.st_size;
2340 data->req.maxdownload = (curl_off_t)sb.st_size;
2341 Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
2343 /* not set by Curl_setup_transfer to preserve keepon bits */
2344 conn->writesockfd = conn->sockfd;
2346 /* we want to use the _receiving_ function even when the socket turns
2347 out writableable as the underlying libssh2 recv function will deal
2348 with both accordingly */
2349 conn->cselect_bits = CURL_CSELECT_IN;
2352 state(conn, SSH_SCP_CHANNEL_FREE);
2353 sshc->actualcode = result;
2356 state(conn, SSH_STOP);
2361 if(data->set.upload)
2362 state(conn, SSH_SCP_SEND_EOF);
2364 state(conn, SSH_SCP_CHANNEL_FREE);
2367 case SSH_SCP_SEND_EOF:
2368 if(sshc->ssh_channel) {
2369 rc = libssh2_channel_send_eof(sshc->ssh_channel);
2370 if(rc == LIBSSH2_ERROR_EAGAIN) {
2374 infof(data, "Failed to send libssh2 channel EOF\n");
2377 state(conn, SSH_SCP_WAIT_EOF);
2380 case SSH_SCP_WAIT_EOF:
2381 if(sshc->ssh_channel) {
2382 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2383 if(rc == LIBSSH2_ERROR_EAGAIN) {
2387 infof(data, "Failed to get channel EOF: %d\n", rc);
2390 state(conn, SSH_SCP_WAIT_CLOSE);
2393 case SSH_SCP_WAIT_CLOSE:
2394 if(sshc->ssh_channel) {
2395 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2396 if(rc == LIBSSH2_ERROR_EAGAIN) {
2400 infof(data, "Channel failed to close: %d\n", rc);
2403 state(conn, SSH_SCP_CHANNEL_FREE);
2406 case SSH_SCP_CHANNEL_FREE:
2407 if(sshc->ssh_channel) {
2408 rc = libssh2_channel_free(sshc->ssh_channel);
2409 if(rc == LIBSSH2_ERROR_EAGAIN) {
2413 infof(data, "Failed to free libssh2 scp subsystem\n");
2415 sshc->ssh_channel = NULL;
2417 DEBUGF(infof(data, "SCP DONE phase complete\n"));
2419 state(conn, SSH_SESSION_DISCONNECT);
2421 state(conn, SSH_STOP);
2422 result = sshc->actualcode;
2425 case SSH_SESSION_DISCONNECT:
2426 /* during weird times when we've been prematurely aborted, the channel
2427 is still alive when we reach this state and we MUST kill the channel
2429 if(sshc->ssh_channel) {
2430 rc = libssh2_channel_free(sshc->ssh_channel);
2431 if(rc == LIBSSH2_ERROR_EAGAIN) {
2435 infof(data, "Failed to free libssh2 scp subsystem\n");
2437 sshc->ssh_channel = NULL;
2440 if(sshc->ssh_session) {
2441 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2442 if(rc == LIBSSH2_ERROR_EAGAIN) {
2446 infof(data, "Failed to disconnect libssh2 session\n");
2450 Curl_safefree(sshc->homedir);
2451 conn->data->state.most_recent_ftp_entrypath = NULL;
2453 state(conn, SSH_SESSION_FREE);
2456 case SSH_SESSION_FREE:
2457 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2459 libssh2_knownhost_free(sshc->kh);
2464 #ifdef HAVE_LIBSSH2_AGENT_API
2465 if(sshc->ssh_agent) {
2466 rc = libssh2_agent_disconnect(sshc->ssh_agent);
2467 if(rc == LIBSSH2_ERROR_EAGAIN) {
2471 infof(data, "Failed to disconnect from libssh2 agent\n");
2473 libssh2_agent_free (sshc->ssh_agent);
2474 sshc->ssh_agent = NULL;
2476 /* NB: there is no need to free identities, they are part of internal
2478 sshc->sshagent_identity = NULL;
2479 sshc->sshagent_prev_identity = NULL;
2483 if(sshc->ssh_session) {
2484 rc = libssh2_session_free(sshc->ssh_session);
2485 if(rc == LIBSSH2_ERROR_EAGAIN) {
2489 infof(data, "Failed to free libssh2 session\n");
2491 sshc->ssh_session = NULL;
2494 /* worst-case scenario cleanup */
2496 DEBUGASSERT(sshc->ssh_session == NULL);
2497 DEBUGASSERT(sshc->ssh_channel == NULL);
2498 DEBUGASSERT(sshc->sftp_session == NULL);
2499 DEBUGASSERT(sshc->sftp_handle == NULL);
2500 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2501 DEBUGASSERT(sshc->kh == NULL);
2503 #ifdef HAVE_LIBSSH2_AGENT_API
2504 DEBUGASSERT(sshc->ssh_agent == NULL);
2507 Curl_safefree(sshc->rsa_pub);
2508 Curl_safefree(sshc->rsa);
2510 Curl_safefree(sshc->quote_path1);
2511 Curl_safefree(sshc->quote_path2);
2513 Curl_safefree(sshc->homedir);
2515 Curl_safefree(sshc->readdir_filename);
2516 Curl_safefree(sshc->readdir_longentry);
2517 Curl_safefree(sshc->readdir_line);
2518 Curl_safefree(sshc->readdir_linkPath);
2520 /* the code we are about to return */
2521 result = sshc->actualcode;
2523 memset(sshc, 0, sizeof(struct ssh_conn));
2525 conn->bits.close = TRUE;
2526 sshc->state = SSH_SESSION_FREE; /* current */
2527 sshc->nextstate = SSH_NO_STATE;
2528 state(conn, SSH_STOP);
2532 /* fallthrough, just stop! */
2534 /* internal error */
2535 sshc->nextstate = SSH_NO_STATE;
2536 state(conn, SSH_STOP);
2540 } while(!rc && (sshc->state != SSH_STOP));
2542 if(rc == LIBSSH2_ERROR_EAGAIN) {
2543 /* we would block, we need to wait for the socket to be ready (in the
2544 right direction too)! */
2551 /* called by the multi interface to figure out what socket(s) to wait for and
2552 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
2553 static int ssh_perform_getsock(const struct connectdata *conn,
2554 curl_socket_t *sock, /* points to numsocks
2555 number of sockets */
2558 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2559 int bitmap = GETSOCK_BLANK;
2562 sock[0] = conn->sock[FIRSTSOCKET];
2564 if(conn->waitfor & KEEP_RECV)
2565 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
2567 if(conn->waitfor & KEEP_SEND)
2568 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
2572 /* if we don't know the direction we can use the generic *_getsock()
2573 function even for the protocol_connect and doing states */
2574 return Curl_single_getsock(conn, sock, numsocks);
2578 /* Generic function called by the multi interface to figure out what socket(s)
2579 to wait for and for what actions during the DOING and PROTOCONNECT states*/
2580 static int ssh_getsock(struct connectdata *conn,
2581 curl_socket_t *sock, /* points to numsocks number
2585 #ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2589 /* if we don't know any direction we can just play along as we used to and
2590 not provide any sensible info */
2591 return GETSOCK_BLANK;
2593 /* if we know the direction we can use the generic *_getsock() function even
2594 for the protocol_connect and doing states */
2595 return ssh_perform_getsock(conn, sock, numsocks);
2599 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2601 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
2602 * function is used to figure out in what direction and stores this info so
2603 * that the multi interface can take advantage of it. Make sure to call this
2604 * function in all cases so that when it _doesn't_ return EAGAIN we can
2605 * restore the default wait bits.
2607 static void ssh_block2waitfor(struct connectdata *conn, bool block)
2609 struct ssh_conn *sshc = &conn->proto.sshc;
2611 if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
2612 /* translate the libssh2 define bits into our own bit defines */
2613 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
2614 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
2617 /* It didn't block or libssh2 didn't reveal in which direction, put back
2619 conn->waitfor = sshc->orig_waitfor;
2622 /* no libssh2 directional support so we simply don't know */
2623 #define ssh_block2waitfor(x,y) Curl_nop_stmt
2626 /* called repeatedly until done from multi.c */
2627 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
2629 struct ssh_conn *sshc = &conn->proto.sshc;
2630 CURLcode result = CURLE_OK;
2631 bool block; /* we store the status and use that to provide a ssh_getsock()
2634 result = ssh_statemach_act(conn, &block);
2635 *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
2636 ssh_block2waitfor(conn, block);
2641 static CURLcode ssh_block_statemach(struct connectdata *conn,
2644 struct ssh_conn *sshc = &conn->proto.sshc;
2645 CURLcode result = CURLE_OK;
2646 struct SessionHandle *data = conn->data;
2648 while((sshc->state != SSH_STOP) && !result) {
2652 result = ssh_statemach_act(conn, &block);
2656 if(Curl_pgrsUpdate(conn))
2657 return CURLE_ABORTED_BY_CALLBACK;
2659 struct timeval now = Curl_tvnow();
2660 result = Curl_speedcheck(data, now);
2665 left = Curl_timeleft(data, NULL, duringconnect);
2667 failf(data, "Operation timed out");
2668 return CURLE_OPERATION_TIMEDOUT;
2671 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2672 if((CURLE_OK == result) && block) {
2673 int dir = libssh2_session_block_directions(sshc->ssh_session);
2674 curl_socket_t sock = conn->sock[FIRSTSOCKET];
2675 curl_socket_t fd_read = CURL_SOCKET_BAD;
2676 curl_socket_t fd_write = CURL_SOCKET_BAD;
2677 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
2679 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
2681 /* wait for the socket to become ready */
2682 Curl_socket_ready(fd_read, fd_write,
2683 left>1000?1000:left); /* ignore result */
2693 * SSH setup and connection
2695 static CURLcode ssh_setup_connection(struct connectdata *conn)
2697 struct SSHPROTO *ssh;
2699 conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
2701 return CURLE_OUT_OF_MEMORY;
2706 static Curl_recv scp_recv, sftp_recv;
2707 static Curl_send scp_send, sftp_send;
2710 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
2711 * do protocol-specific actions at connect-time.
2713 static CURLcode ssh_connect(struct connectdata *conn, bool *done)
2715 #ifdef CURL_LIBSSH2_DEBUG
2718 struct ssh_conn *ssh;
2720 struct SessionHandle *data = conn->data;
2722 /* We default to persistent connections. We set this already in this connect
2723 function to make the re-use checks properly be able to check this bit. */
2724 conn->bits.close = FALSE;
2726 if(conn->handler->protocol & CURLPROTO_SCP) {
2727 conn->recv[FIRSTSOCKET] = scp_recv;
2728 conn->send[FIRSTSOCKET] = scp_send;
2731 conn->recv[FIRSTSOCKET] = sftp_recv;
2732 conn->send[FIRSTSOCKET] = sftp_send;
2734 ssh = &conn->proto.sshc;
2736 #ifdef CURL_LIBSSH2_DEBUG
2738 infof(data, "User: %s\n", conn->user);
2741 infof(data, "Password: %s\n", conn->passwd);
2743 sock = conn->sock[FIRSTSOCKET];
2744 #endif /* CURL_LIBSSH2_DEBUG */
2746 ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
2748 my_libssh2_realloc, conn);
2749 if(ssh->ssh_session == NULL) {
2750 failf(data, "Failure initialising ssh session");
2751 return CURLE_FAILED_INIT;
2754 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2755 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
2757 ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
2759 /* eeek. TODO: free the ssh_session! */
2760 return CURLE_FAILED_INIT;
2763 /* read all known hosts from there */
2764 rc = libssh2_knownhost_readfile(ssh->kh,
2765 data->set.str[STRING_SSH_KNOWNHOSTS],
2766 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
2768 infof(data, "Failed to read known hosts from %s\n",
2769 data->set.str[STRING_SSH_KNOWNHOSTS]);
2771 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2773 #ifdef CURL_LIBSSH2_DEBUG
2774 libssh2_trace(ssh->ssh_session, ~0);
2775 infof(data, "SSH socket: %d\n", (int)sock);
2776 #endif /* CURL_LIBSSH2_DEBUG */
2778 state(conn, SSH_INIT);
2780 result = ssh_multi_statemach(conn, done);
2786 ***********************************************************************
2790 * This is the actual DO function for SCP. Get a file according to
2791 * the options previously setup.
2795 CURLcode scp_perform(struct connectdata *conn,
2799 CURLcode result = CURLE_OK;
2801 DEBUGF(infof(conn->data, "DO phase starts\n"));
2803 *dophase_done = FALSE; /* not done yet */
2805 /* start the first command in the DO phase */
2806 state(conn, SSH_SCP_TRANS_INIT);
2808 /* run the state-machine */
2809 result = ssh_multi_statemach(conn, dophase_done);
2811 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
2814 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2820 /* called from multi.c while DOing */
2821 static CURLcode scp_doing(struct connectdata *conn,
2825 result = ssh_multi_statemach(conn, dophase_done);
2828 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2834 * The DO function is generic for both protocols. There was previously two
2835 * separate ones but this way means less duplicated code.
2838 static CURLcode ssh_do(struct connectdata *conn, bool *done)
2842 struct SessionHandle *data = conn->data;
2843 struct ssh_conn *sshc = &conn->proto.sshc;
2845 *done = FALSE; /* default to false */
2847 data->req.size = -1; /* make sure this is unknown at this point */
2849 sshc->actualcode = CURLE_OK; /* reset error code */
2850 sshc->secondCreateDirs =0; /* reset the create dir attempt state
2853 Curl_pgrsSetUploadCounter(data, 0);
2854 Curl_pgrsSetDownloadCounter(data, 0);
2855 Curl_pgrsSetUploadSize(data, 0);
2856 Curl_pgrsSetDownloadSize(data, 0);
2858 if(conn->handler->protocol & CURLPROTO_SCP)
2859 res = scp_perform(conn, &connected, done);
2861 res = sftp_perform(conn, &connected, done);
2866 /* BLOCKING, but the function is using the state machine so the only reason
2867 this is still blocking is that the multi interface code has no support for
2868 disconnecting operations that takes a while */
2869 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
2871 CURLcode result = CURLE_OK;
2872 struct ssh_conn *ssh = &conn->proto.sshc;
2873 (void) dead_connection;
2875 Curl_safefree(conn->data->req.protop);
2877 if(ssh->ssh_session) {
2878 /* only if there's a session still around to use! */
2880 state(conn, SSH_SESSION_DISCONNECT);
2882 result = ssh_block_statemach(conn, FALSE);
2888 /* generic done function for both SCP and SFTP called from their specific
2890 static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
2892 CURLcode result = CURLE_OK;
2893 struct SSHPROTO *sftp_scp = conn->data->req.protop;
2895 if(status == CURLE_OK) {
2896 /* run the state-machine
2898 TODO: when the multi interface is used, this _really_ should be using
2899 the ssh_multi_statemach function but we have no general support for
2900 non-blocking DONE operations, not in the multi state machine and with
2901 Curl_done() invokes on several places in the code!
2903 result = ssh_block_statemach(conn, FALSE);
2909 Curl_safefree(sftp_scp->path);
2910 if(Curl_pgrsDone(conn))
2911 return CURLE_ABORTED_BY_CALLBACK;
2913 conn->data->req.keepon = 0; /* clear all bits */
2918 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
2921 (void)premature; /* not used */
2923 if(status == CURLE_OK)
2924 state(conn, SSH_SCP_DONE);
2926 return ssh_done(conn, status);
2930 /* return number of received (decrypted) bytes */
2931 static ssize_t scp_send(struct connectdata *conn, int sockindex,
2932 const void *mem, size_t len, CURLcode *err)
2935 (void)sockindex; /* we only support SCP on the fixed known primary socket */
2937 /* libssh2_channel_write() returns int! */
2939 libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
2941 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2943 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
2947 else if(nwrite < LIBSSH2_ERROR_NONE) {
2948 *err = libssh2_session_error_to_CURLE((int)nwrite);
2956 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
2957 * a regular CURLcode value.
2959 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
2960 char *mem, size_t len, CURLcode *err)
2963 (void)sockindex; /* we only support SCP on the fixed known primary socket */
2965 /* libssh2_channel_read() returns int */
2967 libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
2969 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2970 if(nread == LIBSSH2_ERROR_EAGAIN) {
2979 * =============== SFTP ===============
2983 ***********************************************************************
2987 * This is the actual DO function for SFTP. Get a file/directory according to
2988 * the options previously setup.
2992 CURLcode sftp_perform(struct connectdata *conn,
2996 CURLcode result = CURLE_OK;
2998 DEBUGF(infof(conn->data, "DO phase starts\n"));
3000 *dophase_done = FALSE; /* not done yet */
3002 /* start the first command in the DO phase */
3003 state(conn, SSH_SFTP_QUOTE_INIT);
3005 /* run the state-machine */
3006 result = ssh_multi_statemach(conn, dophase_done);
3008 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
3011 DEBUGF(infof(conn->data, "DO phase is complete\n"));
3017 /* called from multi.c while DOing */
3018 static CURLcode sftp_doing(struct connectdata *conn,
3022 result = ssh_multi_statemach(conn, dophase_done);
3025 DEBUGF(infof(conn->data, "DO phase is complete\n"));
3030 /* BLOCKING, but the function is using the state machine so the only reason
3031 this is still blocking is that the multi interface code has no support for
3032 disconnecting operations that takes a while */
3033 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
3035 CURLcode result = CURLE_OK;
3036 (void) dead_connection;
3038 DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
3040 Curl_safefree(conn->data->req.protop);
3042 if(conn->proto.sshc.ssh_session) {
3043 /* only if there's a session still around to use! */
3044 state(conn, SSH_SFTP_SHUTDOWN);
3045 result = ssh_block_statemach(conn, FALSE);
3048 DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
3054 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
3057 struct ssh_conn *sshc = &conn->proto.sshc;
3059 if(status == CURLE_OK) {
3060 /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3061 errors that could happen due to open file handles during POSTQUOTE
3063 if(!status && !premature && conn->data->set.postquote) {
3064 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3065 state(conn, SSH_SFTP_CLOSE);
3068 state(conn, SSH_SFTP_CLOSE);
3070 return ssh_done(conn, status);
3073 /* return number of sent bytes */
3074 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
3075 const void *mem, size_t len, CURLcode *err)
3077 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
3078 but is changed to ssize_t in 0.15. These days we don't
3079 support libssh2 0.15*/
3082 nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
3084 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3086 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3090 else if(nwrite < LIBSSH2_ERROR_NONE) {
3091 *err = libssh2_session_error_to_CURLE((int)nwrite);
3099 * Return number of received (decrypted) bytes
3101 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
3102 char *mem, size_t len, CURLcode *err)
3107 nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
3109 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3111 if(nread == LIBSSH2_ERROR_EAGAIN) {
3118 /* The get_pathname() function is being borrowed from OpenSSH sftp.c
3121 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
3123 * Permission to use, copy, modify, and distribute this software for any
3124 * purpose with or without fee is hereby granted, provided that the above
3125 * copyright notice and this permission notice appear in all copies.
3127 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3128 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3129 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3130 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3131 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3132 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3133 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3136 get_pathname(const char **cpp, char **path)
3138 const char *cp = *cpp, *end;
3141 static const char WHITESPACE[] = " \t\r\n";
3143 cp += strspn(cp, WHITESPACE);
3147 return CURLE_QUOTE_ERROR;
3150 *path = malloc(strlen(cp) + 1);
3152 return CURLE_OUT_OF_MEMORY;
3154 /* Check for quoted filenames */
3155 if(*cp == '\"' || *cp == '\'') {
3158 /* Search for terminating quote, unescape some chars */
3159 for(i = j = 0; i <= strlen(cp); i++) {
3160 if(cp[i] == quot) { /* Found quote */
3165 if(cp[i] == '\0') { /* End of string */
3166 /*error("Unterminated quote");*/
3169 if(cp[i] == '\\') { /* Escaped characters */
3171 if(cp[i] != '\'' && cp[i] != '\"' &&
3173 /*error("Bad escaped character '\\%c'",
3178 (*path)[j++] = cp[i];
3182 /*error("Empty quotes");*/
3185 *cpp = cp + i + strspn(cp + i, WHITESPACE);
3188 /* Read to end of filename */
3189 end = strpbrk(cp, WHITESPACE);
3191 end = strchr(cp, '\0');
3192 *cpp = end + strspn(end, WHITESPACE);
3194 memcpy(*path, cp, end - cp);
3195 (*path)[end - cp] = '\0';
3200 Curl_safefree(*path);
3201 return CURLE_QUOTE_ERROR;
3205 static const char *sftp_libssh2_strerror(int err)
3208 case LIBSSH2_FX_NO_SUCH_FILE:
3209 return "No such file or directory";
3211 case LIBSSH2_FX_PERMISSION_DENIED:
3212 return "Permission denied";
3214 case LIBSSH2_FX_FAILURE:
3215 return "Operation failed";
3217 case LIBSSH2_FX_BAD_MESSAGE:
3218 return "Bad message from SFTP server";
3220 case LIBSSH2_FX_NO_CONNECTION:
3221 return "Not connected to SFTP server";
3223 case LIBSSH2_FX_CONNECTION_LOST:
3224 return "Connection to SFTP server lost";
3226 case LIBSSH2_FX_OP_UNSUPPORTED:
3227 return "Operation not supported by SFTP server";
3229 case LIBSSH2_FX_INVALID_HANDLE:
3230 return "Invalid handle";
3232 case LIBSSH2_FX_NO_SUCH_PATH:
3233 return "No such file or directory";
3235 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3236 return "File already exists";
3238 case LIBSSH2_FX_WRITE_PROTECT:
3239 return "File is write protected";
3241 case LIBSSH2_FX_NO_MEDIA:
3244 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3247 case LIBSSH2_FX_QUOTA_EXCEEDED:
3248 return "User quota exceeded";
3250 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3251 return "Unknown principle";
3253 case LIBSSH2_FX_LOCK_CONFlICT:
3254 return "File lock conflict";
3256 case LIBSSH2_FX_DIR_NOT_EMPTY:
3257 return "Directory not empty";
3259 case LIBSSH2_FX_NOT_A_DIRECTORY:
3260 return "Not a directory";
3262 case LIBSSH2_FX_INVALID_FILENAME:
3263 return "Invalid filename";
3265 case LIBSSH2_FX_LINK_LOOP:
3266 return "Link points to itself";
3268 return "Unknown error in libssh2";
3271 #endif /* USE_LIBSSH2 */