Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Utilities / cmcurl / lib / vssh / libssh.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2017 - 2022 Red Hat, Inc.
9  *
10  * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
11  *          Robert Kolcun, Andreas Schneider
12  *
13  * This software is licensed as described in the file COPYING, which
14  * you should have received as part of this distribution. The terms
15  * are also available at https://curl.se/docs/copyright.html.
16  *
17  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
18  * copies of the Software, and permit persons to whom the Software is
19  * furnished to do so, under the terms of the COPYING file.
20  *
21  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22  * KIND, either express or implied.
23  *
24  * SPDX-License-Identifier: curl
25  *
26  ***************************************************************************/
27
28 #include "curl_setup.h"
29
30 #ifdef USE_LIBSSH
31
32 #include <limits.h>
33
34 #include <libssh/libssh.h>
35 #include <libssh/sftp.h>
36
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43 #ifdef HAVE_UTSNAME_H
44 #include <sys/utsname.h>
45 #endif
46 #ifdef HAVE_NETDB_H
47 #include <netdb.h>
48 #endif
49 #ifdef __VMS
50 #include <in.h>
51 #include <inet.h>
52 #endif
53
54 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
55 #undef in_addr_t
56 #define in_addr_t unsigned long
57 #endif
58
59 #include <curl/curl.h>
60 #include "urldata.h"
61 #include "sendf.h"
62 #include "hostip.h"
63 #include "progress.h"
64 #include "transfer.h"
65 #include "escape.h"
66 #include "http.h"               /* for HTTP proxy tunnel stuff */
67 #include "ssh.h"
68 #include "url.h"
69 #include "speedcheck.h"
70 #include "getinfo.h"
71 #include "strdup.h"
72 #include "strcase.h"
73 #include "vtls/vtls.h"
74 #include "connect.h"
75 #include "inet_ntop.h"
76 #include "parsedate.h"          /* for the week day and month names */
77 #include "sockaddr.h"           /* required for Curl_sockaddr_storage */
78 #include "strtoofft.h"
79 #include "multiif.h"
80 #include "select.h"
81 #include "warnless.h"
82 #include "curl_path.h"
83
84 #ifdef HAVE_SYS_STAT_H
85 #include <sys/stat.h>
86 #endif
87 #ifdef HAVE_UNISTD_H
88 #include <unistd.h>
89 #endif
90 #ifdef HAVE_FCNTL_H
91 #include <fcntl.h>
92 #endif
93
94 /* The last 3 #include files should be in this order */
95 #include "curl_printf.h"
96 #include "curl_memory.h"
97 #include "memdebug.h"
98
99 /* in 0.10.0 or later, ignore deprecated warnings */
100 #if defined(__GNUC__) &&                        \
101   (LIBSSH_VERSION_MINOR >= 10) ||               \
102   (LIBSSH_VERSION_MAJOR > 0)
103 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
104 #endif
105
106 /* A recent macro provided by libssh. Or make our own. */
107 #ifndef SSH_STRING_FREE_CHAR
108 #define SSH_STRING_FREE_CHAR(x)                 \
109   do {                                          \
110     if(x) {                                     \
111       ssh_string_free_char(x);                  \
112       x = NULL;                                 \
113     }                                           \
114   } while(0)
115 #endif
116
117 /* These stat values may not be the same as the user's S_IFMT / S_IFLNK */
118 #ifndef SSH_S_IFMT
119 #define SSH_S_IFMT   00170000
120 #endif
121 #ifndef SSH_S_IFLNK
122 #define SSH_S_IFLNK  0120000
123 #endif
124
125 /* Local functions: */
126 static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
127 static CURLcode myssh_multi_statemach(struct Curl_easy *data,
128                                       bool *done);
129 static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);
130
131 static CURLcode scp_done(struct Curl_easy *data,
132                          CURLcode, bool premature);
133 static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
134 static CURLcode scp_disconnect(struct Curl_easy *data,
135                                struct connectdata *conn,
136                                bool dead_connection);
137
138 static CURLcode sftp_done(struct Curl_easy *data,
139                           CURLcode, bool premature);
140 static CURLcode sftp_doing(struct Curl_easy *data,
141                            bool *dophase_done);
142 static CURLcode sftp_disconnect(struct Curl_easy *data,
143                                 struct connectdata *conn,
144                                 bool dead);
145 static
146 CURLcode sftp_perform(struct Curl_easy *data,
147                       bool *connected,
148                       bool *dophase_done);
149
150 static void sftp_quote(struct Curl_easy *data);
151 static void sftp_quote_stat(struct Curl_easy *data);
152 static int myssh_getsock(struct Curl_easy *data,
153                          struct connectdata *conn, curl_socket_t *sock);
154
155 static CURLcode myssh_setup_connection(struct Curl_easy *data,
156                                        struct connectdata *conn);
157
158 /*
159  * SCP protocol handler.
160  */
161
162 const struct Curl_handler Curl_handler_scp = {
163   "SCP",                        /* scheme */
164   myssh_setup_connection,       /* setup_connection */
165   myssh_do_it,                  /* do_it */
166   scp_done,                     /* done */
167   ZERO_NULL,                    /* do_more */
168   myssh_connect,                /* connect_it */
169   myssh_multi_statemach,        /* connecting */
170   scp_doing,                    /* doing */
171   myssh_getsock,                /* proto_getsock */
172   myssh_getsock,                /* doing_getsock */
173   ZERO_NULL,                    /* domore_getsock */
174   myssh_getsock,                /* perform_getsock */
175   scp_disconnect,               /* disconnect */
176   ZERO_NULL,                    /* readwrite */
177   ZERO_NULL,                    /* connection_check */
178   ZERO_NULL,                    /* attach connection */
179   PORT_SSH,                     /* defport */
180   CURLPROTO_SCP,                /* protocol */
181   CURLPROTO_SCP,                /* family */
182   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */
183 };
184
185 /*
186  * SFTP protocol handler.
187  */
188
189 const struct Curl_handler Curl_handler_sftp = {
190   "SFTP",                               /* scheme */
191   myssh_setup_connection,               /* setup_connection */
192   myssh_do_it,                          /* do_it */
193   sftp_done,                            /* done */
194   ZERO_NULL,                            /* do_more */
195   myssh_connect,                        /* connect_it */
196   myssh_multi_statemach,                /* connecting */
197   sftp_doing,                           /* doing */
198   myssh_getsock,                        /* proto_getsock */
199   myssh_getsock,                        /* doing_getsock */
200   ZERO_NULL,                            /* domore_getsock */
201   myssh_getsock,                        /* perform_getsock */
202   sftp_disconnect,                      /* disconnect */
203   ZERO_NULL,                            /* readwrite */
204   ZERO_NULL,                            /* connection_check */
205   ZERO_NULL,                            /* attach connection */
206   PORT_SSH,                             /* defport */
207   CURLPROTO_SFTP,                       /* protocol */
208   CURLPROTO_SFTP,                       /* family */
209   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
210   | PROTOPT_NOURLQUERY                  /* flags */
211 };
212
213 static CURLcode sftp_error_to_CURLE(int err)
214 {
215   switch(err) {
216     case SSH_FX_OK:
217       return CURLE_OK;
218
219     case SSH_FX_NO_SUCH_FILE:
220     case SSH_FX_NO_SUCH_PATH:
221       return CURLE_REMOTE_FILE_NOT_FOUND;
222
223     case SSH_FX_PERMISSION_DENIED:
224     case SSH_FX_WRITE_PROTECT:
225       return CURLE_REMOTE_ACCESS_DENIED;
226
227     case SSH_FX_FILE_ALREADY_EXISTS:
228       return CURLE_REMOTE_FILE_EXISTS;
229
230     default:
231       break;
232   }
233
234   return CURLE_SSH;
235 }
236
237 #ifndef DEBUGBUILD
238 #define state(x,y) mystate(x,y)
239 #else
240 #define state(x,y) mystate(x,y, __LINE__)
241 #endif
242
243 /*
244  * SSH State machine related code
245  */
246 /* This is the ONLY way to change SSH state! */
247 static void mystate(struct Curl_easy *data, sshstate nowstate
248 #ifdef DEBUGBUILD
249                     , int lineno
250 #endif
251   )
252 {
253   struct connectdata *conn = data->conn;
254   struct ssh_conn *sshc = &conn->proto.sshc;
255 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
256   /* for debug purposes */
257   static const char *const names[] = {
258     "SSH_STOP",
259     "SSH_INIT",
260     "SSH_S_STARTUP",
261     "SSH_HOSTKEY",
262     "SSH_AUTHLIST",
263     "SSH_AUTH_PKEY_INIT",
264     "SSH_AUTH_PKEY",
265     "SSH_AUTH_PASS_INIT",
266     "SSH_AUTH_PASS",
267     "SSH_AUTH_AGENT_INIT",
268     "SSH_AUTH_AGENT_LIST",
269     "SSH_AUTH_AGENT",
270     "SSH_AUTH_HOST_INIT",
271     "SSH_AUTH_HOST",
272     "SSH_AUTH_KEY_INIT",
273     "SSH_AUTH_KEY",
274     "SSH_AUTH_GSSAPI",
275     "SSH_AUTH_DONE",
276     "SSH_SFTP_INIT",
277     "SSH_SFTP_REALPATH",
278     "SSH_SFTP_QUOTE_INIT",
279     "SSH_SFTP_POSTQUOTE_INIT",
280     "SSH_SFTP_QUOTE",
281     "SSH_SFTP_NEXT_QUOTE",
282     "SSH_SFTP_QUOTE_STAT",
283     "SSH_SFTP_QUOTE_SETSTAT",
284     "SSH_SFTP_QUOTE_SYMLINK",
285     "SSH_SFTP_QUOTE_MKDIR",
286     "SSH_SFTP_QUOTE_RENAME",
287     "SSH_SFTP_QUOTE_RMDIR",
288     "SSH_SFTP_QUOTE_UNLINK",
289     "SSH_SFTP_QUOTE_STATVFS",
290     "SSH_SFTP_GETINFO",
291     "SSH_SFTP_FILETIME",
292     "SSH_SFTP_TRANS_INIT",
293     "SSH_SFTP_UPLOAD_INIT",
294     "SSH_SFTP_CREATE_DIRS_INIT",
295     "SSH_SFTP_CREATE_DIRS",
296     "SSH_SFTP_CREATE_DIRS_MKDIR",
297     "SSH_SFTP_READDIR_INIT",
298     "SSH_SFTP_READDIR",
299     "SSH_SFTP_READDIR_LINK",
300     "SSH_SFTP_READDIR_BOTTOM",
301     "SSH_SFTP_READDIR_DONE",
302     "SSH_SFTP_DOWNLOAD_INIT",
303     "SSH_SFTP_DOWNLOAD_STAT",
304     "SSH_SFTP_CLOSE",
305     "SSH_SFTP_SHUTDOWN",
306     "SSH_SCP_TRANS_INIT",
307     "SSH_SCP_UPLOAD_INIT",
308     "SSH_SCP_DOWNLOAD_INIT",
309     "SSH_SCP_DOWNLOAD",
310     "SSH_SCP_DONE",
311     "SSH_SCP_SEND_EOF",
312     "SSH_SCP_WAIT_EOF",
313     "SSH_SCP_WAIT_CLOSE",
314     "SSH_SCP_CHANNEL_FREE",
315     "SSH_SESSION_DISCONNECT",
316     "SSH_SESSION_FREE",
317     "QUIT"
318   };
319
320
321   if(sshc->state != nowstate) {
322     infof(data, "SSH %p state change from %s to %s (line %d)",
323           (void *) sshc, names[sshc->state], names[nowstate],
324           lineno);
325   }
326 #endif
327
328   sshc->state = nowstate;
329 }
330
331 /* Multiple options:
332  * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
333  *    hash (90s style auth, not sure we should have it here)
334  * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
335  *    use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
336  *    is returned by it.
337  * 3. none of the above. We only accept if it is present on known hosts.
338  *
339  * Returns SSH_OK or SSH_ERROR.
340  */
341 static int myssh_is_known(struct Curl_easy *data)
342 {
343   int rc;
344   struct connectdata *conn = data->conn;
345   struct ssh_conn *sshc = &conn->proto.sshc;
346   ssh_key pubkey;
347   size_t hlen;
348   unsigned char *hash = NULL;
349   char *found_base64 = NULL;
350   char *known_base64 = NULL;
351   int vstate;
352   enum curl_khmatch keymatch;
353   struct curl_khkey foundkey;
354   struct curl_khkey *knownkeyp = NULL;
355   curl_sshkeycallback func =
356     data->set.ssh_keyfunc;
357
358 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
359   struct ssh_knownhosts_entry *knownhostsentry = NULL;
360   struct curl_khkey knownkey;
361 #endif
362
363 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
364   rc = ssh_get_server_publickey(sshc->ssh_session, &pubkey);
365 #else
366   rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
367 #endif
368   if(rc != SSH_OK)
369     return rc;
370
371   if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
372     int i;
373     char md5buffer[33];
374     const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
375
376     rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
377                                 &hash, &hlen);
378     if(rc != SSH_OK || hlen != 16) {
379       failf(data,
380             "Denied establishing ssh session: md5 fingerprint not available");
381       goto cleanup;
382     }
383
384     for(i = 0; i < 16; i++)
385       msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]);
386
387     infof(data, "SSH MD5 fingerprint: %s", md5buffer);
388
389     if(!strcasecompare(md5buffer, pubkey_md5)) {
390       failf(data,
391             "Denied establishing ssh session: mismatch md5 fingerprint. "
392             "Remote %s is not equal to %s", md5buffer, pubkey_md5);
393       rc = SSH_ERROR;
394       goto cleanup;
395     }
396
397     rc = SSH_OK;
398     goto cleanup;
399   }
400
401   if(data->set.ssl.primary.verifyhost != TRUE) {
402     rc = SSH_OK;
403     goto cleanup;
404   }
405
406 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
407   /* Get the known_key from the known hosts file */
408   vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session,
409                                              &knownhostsentry);
410
411   /* Case an entry was found in a known hosts file */
412   if(knownhostsentry) {
413     if(knownhostsentry->publickey) {
414       rc = ssh_pki_export_pubkey_base64(knownhostsentry->publickey,
415                                         &known_base64);
416       if(rc != SSH_OK) {
417         goto cleanup;
418       }
419       knownkey.key = known_base64;
420       knownkey.len = strlen(known_base64);
421
422       switch(ssh_key_type(knownhostsentry->publickey)) {
423         case SSH_KEYTYPE_RSA:
424           knownkey.keytype = CURLKHTYPE_RSA;
425           break;
426         case SSH_KEYTYPE_RSA1:
427           knownkey.keytype = CURLKHTYPE_RSA1;
428           break;
429         case SSH_KEYTYPE_ECDSA:
430         case SSH_KEYTYPE_ECDSA_P256:
431         case SSH_KEYTYPE_ECDSA_P384:
432         case SSH_KEYTYPE_ECDSA_P521:
433           knownkey.keytype = CURLKHTYPE_ECDSA;
434           break;
435         case SSH_KEYTYPE_ED25519:
436           knownkey.keytype = CURLKHTYPE_ED25519;
437           break;
438         case SSH_KEYTYPE_DSS:
439           knownkey.keytype = CURLKHTYPE_DSS;
440           break;
441         default:
442           rc = SSH_ERROR;
443           goto cleanup;
444       }
445       knownkeyp = &knownkey;
446     }
447   }
448
449   switch(vstate) {
450     case SSH_KNOWN_HOSTS_OK:
451       keymatch = CURLKHMATCH_OK;
452       break;
453     case SSH_KNOWN_HOSTS_OTHER:
454       /* fallthrough */
455     case SSH_KNOWN_HOSTS_NOT_FOUND:
456       /* fallthrough */
457     case SSH_KNOWN_HOSTS_UNKNOWN:
458       /* fallthrough */
459     case SSH_KNOWN_HOSTS_ERROR:
460       keymatch = CURLKHMATCH_MISSING;
461       break;
462   default:
463       keymatch = CURLKHMATCH_MISMATCH;
464       break;
465   }
466
467 #else
468   vstate = ssh_is_server_known(sshc->ssh_session);
469   switch(vstate) {
470     case SSH_SERVER_KNOWN_OK:
471       keymatch = CURLKHMATCH_OK;
472       break;
473     case SSH_SERVER_FILE_NOT_FOUND:
474       /* fallthrough */
475     case SSH_SERVER_NOT_KNOWN:
476       keymatch = CURLKHMATCH_MISSING;
477       break;
478   default:
479       keymatch = CURLKHMATCH_MISMATCH;
480       break;
481   }
482 #endif
483
484   if(func) { /* use callback to determine action */
485     rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64);
486     if(rc != SSH_OK)
487       goto cleanup;
488
489     foundkey.key = found_base64;
490     foundkey.len = strlen(found_base64);
491
492     switch(ssh_key_type(pubkey)) {
493       case SSH_KEYTYPE_RSA:
494         foundkey.keytype = CURLKHTYPE_RSA;
495         break;
496       case SSH_KEYTYPE_RSA1:
497         foundkey.keytype = CURLKHTYPE_RSA1;
498         break;
499       case SSH_KEYTYPE_ECDSA:
500 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
501       case SSH_KEYTYPE_ECDSA_P256:
502       case SSH_KEYTYPE_ECDSA_P384:
503       case SSH_KEYTYPE_ECDSA_P521:
504 #endif
505         foundkey.keytype = CURLKHTYPE_ECDSA;
506         break;
507 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
508       case SSH_KEYTYPE_ED25519:
509         foundkey.keytype = CURLKHTYPE_ED25519;
510         break;
511 #endif
512       case SSH_KEYTYPE_DSS:
513         foundkey.keytype = CURLKHTYPE_DSS;
514         break;
515       default:
516         rc = SSH_ERROR;
517         goto cleanup;
518     }
519
520     Curl_set_in_callback(data, true);
521     rc = func(data, knownkeyp, /* from the knownhosts file */
522               &foundkey, /* from the remote host */
523               keymatch, data->set.ssh_keyfunc_userp);
524     Curl_set_in_callback(data, false);
525
526     switch(rc) {
527       case CURLKHSTAT_FINE_ADD_TO_FILE:
528 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
529         rc = ssh_session_update_known_hosts(sshc->ssh_session);
530 #else
531         rc = ssh_write_knownhost(sshc->ssh_session);
532 #endif
533         if(rc != SSH_OK) {
534           goto cleanup;
535         }
536         break;
537       case CURLKHSTAT_FINE:
538         break;
539       default: /* REJECT/DEFER */
540         rc = SSH_ERROR;
541         goto cleanup;
542     }
543   }
544   else {
545     if(keymatch != CURLKHMATCH_OK) {
546       rc = SSH_ERROR;
547       goto cleanup;
548     }
549   }
550   rc = SSH_OK;
551
552 cleanup:
553   if(found_base64) {
554     (free)(found_base64);
555   }
556   if(known_base64) {
557     (free)(known_base64);
558   }
559   if(hash)
560     ssh_clean_pubkey_hash(&hash);
561   ssh_key_free(pubkey);
562 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
563   if(knownhostsentry) {
564     ssh_knownhosts_entry_free(knownhostsentry);
565   }
566 #endif
567   return rc;
568 }
569
570 #define MOVE_TO_ERROR_STATE(_r) do {            \
571     state(data, SSH_SESSION_DISCONNECT);        \
572     sshc->actualcode = _r;                      \
573     rc = SSH_ERROR;                             \
574   } while(0)
575
576 #define MOVE_TO_SFTP_CLOSE_STATE() do {                         \
577     state(data, SSH_SFTP_CLOSE);                                \
578     sshc->actualcode =                                          \
579       sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session));  \
580     rc = SSH_ERROR;                                             \
581   } while(0)
582
583 #define MOVE_TO_LAST_AUTH do {                          \
584     if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
585       rc = SSH_OK;                                      \
586       state(data, SSH_AUTH_PASS_INIT);                  \
587     }                                                   \
588     else {                                              \
589       MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);          \
590     }                                                   \
591   } while(0)
592
593 #define MOVE_TO_TERTIARY_AUTH do {                              \
594     if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {      \
595       rc = SSH_OK;                                              \
596       state(data, SSH_AUTH_KEY_INIT);                           \
597     }                                                           \
598     else {                                                      \
599       MOVE_TO_LAST_AUTH;                                        \
600     }                                                           \
601   } while(0)
602
603 #define MOVE_TO_SECONDARY_AUTH do {                             \
604     if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {       \
605       rc = SSH_OK;                                              \
606       state(data, SSH_AUTH_GSSAPI);                             \
607     }                                                           \
608     else {                                                      \
609       MOVE_TO_TERTIARY_AUTH;                                    \
610     }                                                           \
611   } while(0)
612
613 static
614 int myssh_auth_interactive(struct connectdata *conn)
615 {
616   int rc;
617   struct ssh_conn *sshc = &conn->proto.sshc;
618   int nprompts;
619
620 restart:
621   switch(sshc->kbd_state) {
622     case 0:
623       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
624       if(rc == SSH_AUTH_AGAIN)
625         return SSH_AGAIN;
626
627       if(rc != SSH_AUTH_INFO)
628         return SSH_ERROR;
629
630       nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
631       if(nprompts != 1)
632         return SSH_ERROR;
633
634       rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd);
635       if(rc < 0)
636         return SSH_ERROR;
637
638     /* FALLTHROUGH */
639     case 1:
640       sshc->kbd_state = 1;
641
642       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
643       if(rc == SSH_AUTH_AGAIN)
644         return SSH_AGAIN;
645       else if(rc == SSH_AUTH_SUCCESS)
646         rc = SSH_OK;
647       else if(rc == SSH_AUTH_INFO) {
648         nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
649         if(nprompts)
650           return SSH_ERROR;
651
652         sshc->kbd_state = 2;
653         goto restart;
654       }
655       else
656         rc = SSH_ERROR;
657       break;
658     case 2:
659       sshc->kbd_state = 2;
660
661       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
662       if(rc == SSH_AUTH_AGAIN)
663         return SSH_AGAIN;
664       else if(rc == SSH_AUTH_SUCCESS)
665         rc = SSH_OK;
666       else
667         rc = SSH_ERROR;
668
669       break;
670     default:
671       return SSH_ERROR;
672   }
673
674   sshc->kbd_state = 0;
675   return rc;
676 }
677
678 /*
679  * ssh_statemach_act() runs the SSH state machine as far as it can without
680  * blocking and without reaching the end.  The data the pointer 'block' points
681  * to will be set to TRUE if the libssh function returns SSH_AGAIN
682  * meaning it wants to be called again when the socket is ready
683  */
684 static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
685 {
686   CURLcode result = CURLE_OK;
687   struct connectdata *conn = data->conn;
688   struct SSHPROTO *protop = data->req.p.ssh;
689   struct ssh_conn *sshc = &conn->proto.sshc;
690   curl_socket_t sock = conn->sock[FIRSTSOCKET];
691   int rc = SSH_NO_ERROR, err;
692   char *new_readdir_line;
693   int seekerr = CURL_SEEKFUNC_OK;
694   const char *err_msg;
695   *block = 0;                   /* we're not blocking by default */
696
697   do {
698
699     switch(sshc->state) {
700     case SSH_INIT:
701       sshc->secondCreateDirs = 0;
702       sshc->nextstate = SSH_NO_STATE;
703       sshc->actualcode = CURLE_OK;
704
705 #if 0
706       ssh_set_log_level(SSH_LOG_PROTOCOL);
707 #endif
708
709       /* Set libssh to non-blocking, since everything internally is
710          non-blocking */
711       ssh_set_blocking(sshc->ssh_session, 0);
712
713       state(data, SSH_S_STARTUP);
714       /* FALLTHROUGH */
715
716     case SSH_S_STARTUP:
717       rc = ssh_connect(sshc->ssh_session);
718       if(rc == SSH_AGAIN)
719         break;
720
721       if(rc != SSH_OK) {
722         failf(data, "Failure establishing ssh session");
723         MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
724         break;
725       }
726
727       state(data, SSH_HOSTKEY);
728
729       /* FALLTHROUGH */
730     case SSH_HOSTKEY:
731
732       rc = myssh_is_known(data);
733       if(rc != SSH_OK) {
734         MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
735         break;
736       }
737
738       state(data, SSH_AUTHLIST);
739       /* FALLTHROUGH */
740     case SSH_AUTHLIST:{
741         sshc->authed = FALSE;
742
743         rc = ssh_userauth_none(sshc->ssh_session, NULL);
744         if(rc == SSH_AUTH_AGAIN) {
745           rc = SSH_AGAIN;
746           break;
747         }
748
749         if(rc == SSH_AUTH_SUCCESS) {
750           sshc->authed = TRUE;
751           infof(data, "Authenticated with none");
752           state(data, SSH_AUTH_DONE);
753           break;
754         }
755         else if(rc == SSH_AUTH_ERROR) {
756           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
757           break;
758         }
759
760         sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
761         if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
762           state(data, SSH_AUTH_PKEY_INIT);
763           infof(data, "Authentication using SSH public key file");
764         }
765         else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
766           state(data, SSH_AUTH_GSSAPI);
767         }
768         else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
769           state(data, SSH_AUTH_KEY_INIT);
770         }
771         else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
772           state(data, SSH_AUTH_PASS_INIT);
773         }
774         else {                  /* unsupported authentication method */
775           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
776           break;
777         }
778
779         break;
780       }
781     case SSH_AUTH_PKEY_INIT:
782       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
783         MOVE_TO_SECONDARY_AUTH;
784         break;
785       }
786
787       /* Two choices, (1) private key was given on CMD,
788        * (2) use the "default" keys. */
789       if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
790         if(sshc->pubkey && !data->set.ssl.key_passwd) {
791           rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
792                                           sshc->pubkey);
793           if(rc == SSH_AUTH_AGAIN) {
794             rc = SSH_AGAIN;
795             break;
796           }
797
798           if(rc != SSH_OK) {
799             MOVE_TO_SECONDARY_AUTH;
800             break;
801           }
802         }
803
804         rc = ssh_pki_import_privkey_file(data->
805                                          set.str[STRING_SSH_PRIVATE_KEY],
806                                          data->set.ssl.key_passwd, NULL,
807                                          NULL, &sshc->privkey);
808         if(rc != SSH_OK) {
809           failf(data, "Could not load private key file %s",
810                 data->set.str[STRING_SSH_PRIVATE_KEY]);
811           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
812           break;
813         }
814
815         state(data, SSH_AUTH_PKEY);
816         break;
817
818       }
819       else {
820         rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
821                                          data->set.ssl.key_passwd);
822         if(rc == SSH_AUTH_AGAIN) {
823           rc = SSH_AGAIN;
824           break;
825         }
826         if(rc == SSH_AUTH_SUCCESS) {
827           rc = SSH_OK;
828           sshc->authed = TRUE;
829           infof(data, "Completed public key authentication");
830           state(data, SSH_AUTH_DONE);
831           break;
832         }
833
834         MOVE_TO_SECONDARY_AUTH;
835       }
836       break;
837     case SSH_AUTH_PKEY:
838       rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
839       if(rc == SSH_AUTH_AGAIN) {
840         rc = SSH_AGAIN;
841         break;
842       }
843
844       if(rc == SSH_AUTH_SUCCESS) {
845         sshc->authed = TRUE;
846         infof(data, "Completed public key authentication");
847         state(data, SSH_AUTH_DONE);
848         break;
849       }
850       else {
851         infof(data, "Failed public key authentication (rc: %d)", rc);
852         MOVE_TO_SECONDARY_AUTH;
853       }
854       break;
855
856     case SSH_AUTH_GSSAPI:
857       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
858         MOVE_TO_TERTIARY_AUTH;
859         break;
860       }
861
862       rc = ssh_userauth_gssapi(sshc->ssh_session);
863       if(rc == SSH_AUTH_AGAIN) {
864         rc = SSH_AGAIN;
865         break;
866       }
867
868       if(rc == SSH_AUTH_SUCCESS) {
869         rc = SSH_OK;
870         sshc->authed = TRUE;
871         infof(data, "Completed gssapi authentication");
872         state(data, SSH_AUTH_DONE);
873         break;
874       }
875
876       MOVE_TO_TERTIARY_AUTH;
877       break;
878
879     case SSH_AUTH_KEY_INIT:
880       if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
881         state(data, SSH_AUTH_KEY);
882       }
883       else {
884         MOVE_TO_LAST_AUTH;
885       }
886       break;
887
888     case SSH_AUTH_KEY:
889
890       /* Authentication failed. Continue with keyboard-interactive now. */
891       rc = myssh_auth_interactive(conn);
892       if(rc == SSH_AGAIN) {
893         break;
894       }
895       if(rc == SSH_OK) {
896         sshc->authed = TRUE;
897         infof(data, "completed keyboard interactive authentication");
898       }
899       state(data, SSH_AUTH_DONE);
900       break;
901
902     case SSH_AUTH_PASS_INIT:
903       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
904         /* Host key authentication is intentionally not implemented */
905         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
906         break;
907       }
908       state(data, SSH_AUTH_PASS);
909       /* FALLTHROUGH */
910
911     case SSH_AUTH_PASS:
912       rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
913       if(rc == SSH_AUTH_AGAIN) {
914         rc = SSH_AGAIN;
915         break;
916       }
917
918       if(rc == SSH_AUTH_SUCCESS) {
919         sshc->authed = TRUE;
920         infof(data, "Completed password authentication");
921         state(data, SSH_AUTH_DONE);
922       }
923       else {
924         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
925       }
926       break;
927
928     case SSH_AUTH_DONE:
929       if(!sshc->authed) {
930         failf(data, "Authentication failure");
931         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
932         break;
933       }
934
935       /*
936        * At this point we have an authenticated ssh session.
937        */
938       infof(data, "Authentication complete");
939
940       Curl_pgrsTime(data, TIMER_APPCONNECT);      /* SSH is connected */
941
942       conn->sockfd = sock;
943       conn->writesockfd = CURL_SOCKET_BAD;
944
945       if(conn->handler->protocol == CURLPROTO_SFTP) {
946         state(data, SSH_SFTP_INIT);
947         break;
948       }
949       infof(data, "SSH CONNECT phase done");
950       state(data, SSH_STOP);
951       break;
952
953     case SSH_SFTP_INIT:
954       ssh_set_blocking(sshc->ssh_session, 1);
955
956       sshc->sftp_session = sftp_new(sshc->ssh_session);
957       if(!sshc->sftp_session) {
958         failf(data, "Failure initializing sftp session: %s",
959               ssh_get_error(sshc->ssh_session));
960         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
961         break;
962       }
963
964       rc = sftp_init(sshc->sftp_session);
965       if(rc != SSH_OK) {
966         failf(data, "Failure initializing sftp session: %s",
967               ssh_get_error(sshc->ssh_session));
968         MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(SSH_FX_FAILURE));
969         break;
970       }
971       state(data, SSH_SFTP_REALPATH);
972       /* FALLTHROUGH */
973     case SSH_SFTP_REALPATH:
974       /*
975        * Get the "home" directory
976        */
977       sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
978       if(!sshc->homedir) {
979         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
980         break;
981       }
982       data->state.most_recent_ftp_entrypath = sshc->homedir;
983
984       /* This is the last step in the SFTP connect phase. Do note that while
985          we get the homedir here, we get the "workingpath" in the DO action
986          since the homedir will remain the same between request but the
987          working path will not. */
988       DEBUGF(infof(data, "SSH CONNECT phase done"));
989       state(data, SSH_STOP);
990       break;
991
992     case SSH_SFTP_QUOTE_INIT:
993       result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
994       if(result) {
995         sshc->actualcode = result;
996         state(data, SSH_STOP);
997         break;
998       }
999
1000       if(data->set.quote) {
1001         infof(data, "Sending quote commands");
1002         sshc->quote_item = data->set.quote;
1003         state(data, SSH_SFTP_QUOTE);
1004       }
1005       else {
1006         state(data, SSH_SFTP_GETINFO);
1007       }
1008       break;
1009
1010     case SSH_SFTP_POSTQUOTE_INIT:
1011       if(data->set.postquote) {
1012         infof(data, "Sending quote commands");
1013         sshc->quote_item = data->set.postquote;
1014         state(data, SSH_SFTP_QUOTE);
1015       }
1016       else {
1017         state(data, SSH_STOP);
1018       }
1019       break;
1020
1021     case SSH_SFTP_QUOTE:
1022       /* Send any quote commands */
1023       sftp_quote(data);
1024       break;
1025
1026     case SSH_SFTP_NEXT_QUOTE:
1027       Curl_safefree(sshc->quote_path1);
1028       Curl_safefree(sshc->quote_path2);
1029
1030       sshc->quote_item = sshc->quote_item->next;
1031
1032       if(sshc->quote_item) {
1033         state(data, SSH_SFTP_QUOTE);
1034       }
1035       else {
1036         if(sshc->nextstate != SSH_NO_STATE) {
1037           state(data, sshc->nextstate);
1038           sshc->nextstate = SSH_NO_STATE;
1039         }
1040         else {
1041           state(data, SSH_SFTP_GETINFO);
1042         }
1043       }
1044       break;
1045
1046     case SSH_SFTP_QUOTE_STAT:
1047       sftp_quote_stat(data);
1048       break;
1049
1050     case SSH_SFTP_QUOTE_SETSTAT:
1051       rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
1052                         sshc->quote_attrs);
1053       if(rc && !sshc->acceptfail) {
1054         Curl_safefree(sshc->quote_path1);
1055         Curl_safefree(sshc->quote_path2);
1056         failf(data, "Attempt to set SFTP stats failed: %s",
1057               ssh_get_error(sshc->ssh_session));
1058         state(data, SSH_SFTP_CLOSE);
1059         sshc->nextstate = SSH_NO_STATE;
1060         sshc->actualcode = CURLE_QUOTE_ERROR;
1061         /* sshc->actualcode = sftp_error_to_CURLE(err);
1062          * we do not send the actual error; we return
1063          * the error the libssh2 backend is returning */
1064         break;
1065       }
1066       state(data, SSH_SFTP_NEXT_QUOTE);
1067       break;
1068
1069     case SSH_SFTP_QUOTE_SYMLINK:
1070       rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
1071                         sshc->quote_path1);
1072       if(rc && !sshc->acceptfail) {
1073         Curl_safefree(sshc->quote_path1);
1074         Curl_safefree(sshc->quote_path2);
1075         failf(data, "symlink command failed: %s",
1076               ssh_get_error(sshc->ssh_session));
1077         state(data, SSH_SFTP_CLOSE);
1078         sshc->nextstate = SSH_NO_STATE;
1079         sshc->actualcode = CURLE_QUOTE_ERROR;
1080         break;
1081       }
1082       state(data, SSH_SFTP_NEXT_QUOTE);
1083       break;
1084
1085     case SSH_SFTP_QUOTE_MKDIR:
1086       rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
1087                       (mode_t)data->set.new_directory_perms);
1088       if(rc && !sshc->acceptfail) {
1089         Curl_safefree(sshc->quote_path1);
1090         failf(data, "mkdir command failed: %s",
1091               ssh_get_error(sshc->ssh_session));
1092         state(data, SSH_SFTP_CLOSE);
1093         sshc->nextstate = SSH_NO_STATE;
1094         sshc->actualcode = CURLE_QUOTE_ERROR;
1095         break;
1096       }
1097       state(data, SSH_SFTP_NEXT_QUOTE);
1098       break;
1099
1100     case SSH_SFTP_QUOTE_RENAME:
1101       rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
1102                        sshc->quote_path2);
1103       if(rc && !sshc->acceptfail) {
1104         Curl_safefree(sshc->quote_path1);
1105         Curl_safefree(sshc->quote_path2);
1106         failf(data, "rename command failed: %s",
1107               ssh_get_error(sshc->ssh_session));
1108         state(data, SSH_SFTP_CLOSE);
1109         sshc->nextstate = SSH_NO_STATE;
1110         sshc->actualcode = CURLE_QUOTE_ERROR;
1111         break;
1112       }
1113       state(data, SSH_SFTP_NEXT_QUOTE);
1114       break;
1115
1116     case SSH_SFTP_QUOTE_RMDIR:
1117       rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
1118       if(rc && !sshc->acceptfail) {
1119         Curl_safefree(sshc->quote_path1);
1120         failf(data, "rmdir command failed: %s",
1121               ssh_get_error(sshc->ssh_session));
1122         state(data, SSH_SFTP_CLOSE);
1123         sshc->nextstate = SSH_NO_STATE;
1124         sshc->actualcode = CURLE_QUOTE_ERROR;
1125         break;
1126       }
1127       state(data, SSH_SFTP_NEXT_QUOTE);
1128       break;
1129
1130     case SSH_SFTP_QUOTE_UNLINK:
1131       rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
1132       if(rc && !sshc->acceptfail) {
1133         Curl_safefree(sshc->quote_path1);
1134         failf(data, "rm command failed: %s",
1135               ssh_get_error(sshc->ssh_session));
1136         state(data, SSH_SFTP_CLOSE);
1137         sshc->nextstate = SSH_NO_STATE;
1138         sshc->actualcode = CURLE_QUOTE_ERROR;
1139         break;
1140       }
1141       state(data, SSH_SFTP_NEXT_QUOTE);
1142       break;
1143
1144     case SSH_SFTP_QUOTE_STATVFS:
1145     {
1146       sftp_statvfs_t statvfs;
1147
1148       statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
1149       if(!statvfs && !sshc->acceptfail) {
1150         Curl_safefree(sshc->quote_path1);
1151         failf(data, "statvfs command failed: %s",
1152               ssh_get_error(sshc->ssh_session));
1153         state(data, SSH_SFTP_CLOSE);
1154         sshc->nextstate = SSH_NO_STATE;
1155         sshc->actualcode = CURLE_QUOTE_ERROR;
1156         break;
1157       }
1158       else if(statvfs) {
1159         char *tmp = aprintf("statvfs:\n"
1160                             "f_bsize: %llu\n" "f_frsize: %llu\n"
1161                             "f_blocks: %llu\n" "f_bfree: %llu\n"
1162                             "f_bavail: %llu\n" "f_files: %llu\n"
1163                             "f_ffree: %llu\n" "f_favail: %llu\n"
1164                             "f_fsid: %llu\n" "f_flag: %llu\n"
1165                             "f_namemax: %llu\n",
1166                             statvfs->f_bsize, statvfs->f_frsize,
1167                             statvfs->f_blocks, statvfs->f_bfree,
1168                             statvfs->f_bavail, statvfs->f_files,
1169                             statvfs->f_ffree, statvfs->f_favail,
1170                             statvfs->f_fsid, statvfs->f_flag,
1171                             statvfs->f_namemax);
1172         sftp_statvfs_free(statvfs);
1173
1174         if(!tmp) {
1175           result = CURLE_OUT_OF_MEMORY;
1176           state(data, SSH_SFTP_CLOSE);
1177           sshc->nextstate = SSH_NO_STATE;
1178           break;
1179         }
1180
1181         result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1182         free(tmp);
1183         if(result) {
1184           state(data, SSH_SFTP_CLOSE);
1185           sshc->nextstate = SSH_NO_STATE;
1186           sshc->actualcode = result;
1187         }
1188       }
1189       state(data, SSH_SFTP_NEXT_QUOTE);
1190       break;
1191     }
1192
1193     case SSH_SFTP_GETINFO:
1194       if(data->set.get_filetime) {
1195         state(data, SSH_SFTP_FILETIME);
1196       }
1197       else {
1198         state(data, SSH_SFTP_TRANS_INIT);
1199       }
1200       break;
1201
1202     case SSH_SFTP_FILETIME:
1203     {
1204       sftp_attributes attrs;
1205
1206       attrs = sftp_stat(sshc->sftp_session, protop->path);
1207       if(attrs) {
1208         data->info.filetime = attrs->mtime;
1209         sftp_attributes_free(attrs);
1210       }
1211
1212       state(data, SSH_SFTP_TRANS_INIT);
1213       break;
1214     }
1215
1216     case SSH_SFTP_TRANS_INIT:
1217       if(data->set.upload)
1218         state(data, SSH_SFTP_UPLOAD_INIT);
1219       else {
1220         if(protop->path[strlen(protop->path)-1] == '/')
1221           state(data, SSH_SFTP_READDIR_INIT);
1222         else
1223           state(data, SSH_SFTP_DOWNLOAD_INIT);
1224       }
1225       break;
1226
1227     case SSH_SFTP_UPLOAD_INIT:
1228     {
1229       int flags;
1230
1231       if(data->state.resume_from) {
1232         sftp_attributes attrs;
1233
1234         if(data->state.resume_from < 0) {
1235           attrs = sftp_stat(sshc->sftp_session, protop->path);
1236           if(attrs) {
1237             curl_off_t size = attrs->size;
1238             if(size < 0) {
1239               failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
1240               MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
1241               break;
1242             }
1243             data->state.resume_from = attrs->size;
1244
1245             sftp_attributes_free(attrs);
1246           }
1247           else {
1248             data->state.resume_from = 0;
1249           }
1250         }
1251       }
1252
1253       if(data->set.remote_append)
1254         /* Try to open for append, but create if nonexisting */
1255         flags = O_WRONLY|O_CREAT|O_APPEND;
1256       else if(data->state.resume_from > 0)
1257         /* If we have restart position then open for append */
1258         flags = O_WRONLY|O_APPEND;
1259       else
1260         /* Clear file before writing (normal behavior) */
1261         flags = O_WRONLY|O_CREAT|O_TRUNC;
1262
1263       if(sshc->sftp_file)
1264         sftp_close(sshc->sftp_file);
1265       sshc->sftp_file =
1266         sftp_open(sshc->sftp_session, protop->path,
1267                   flags, (mode_t)data->set.new_file_perms);
1268       if(!sshc->sftp_file) {
1269         err = sftp_get_error(sshc->sftp_session);
1270
1271         if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
1272              err == SSH_FX_NO_SUCH_PATH)) &&
1273              (data->set.ftp_create_missing_dirs &&
1274              (strlen(protop->path) > 1))) {
1275                /* try to create the path remotely */
1276                rc = 0;
1277                sshc->secondCreateDirs = 1;
1278                state(data, SSH_SFTP_CREATE_DIRS_INIT);
1279                break;
1280         }
1281         else {
1282           MOVE_TO_SFTP_CLOSE_STATE();
1283           break;
1284         }
1285       }
1286
1287       /* If we have a restart point then we need to seek to the correct
1288          position. */
1289       if(data->state.resume_from > 0) {
1290         /* Let's read off the proper amount of bytes from the input. */
1291         if(conn->seek_func) {
1292           Curl_set_in_callback(data, true);
1293           seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1294                                     SEEK_SET);
1295           Curl_set_in_callback(data, false);
1296         }
1297
1298         if(seekerr != CURL_SEEKFUNC_OK) {
1299           curl_off_t passed = 0;
1300
1301           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1302             failf(data, "Could not seek stream");
1303             return CURLE_FTP_COULDNT_USE_REST;
1304           }
1305           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
1306           do {
1307             size_t readthisamountnow =
1308               (data->state.resume_from - passed > data->set.buffer_size) ?
1309               (size_t)data->set.buffer_size :
1310               curlx_sotouz(data->state.resume_from - passed);
1311
1312             size_t actuallyread =
1313               data->state.fread_func(data->state.buffer, 1,
1314                                      readthisamountnow, data->state.in);
1315
1316             passed += actuallyread;
1317             if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1318               /* this checks for greater-than only to make sure that the
1319                  CURL_READFUNC_ABORT return code still aborts */
1320               failf(data, "Failed to read data");
1321               MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
1322               break;
1323             }
1324           } while(passed < data->state.resume_from);
1325           if(rc)
1326             break;
1327         }
1328
1329         /* now, decrease the size of the read */
1330         if(data->state.infilesize > 0) {
1331           data->state.infilesize -= data->state.resume_from;
1332           data->req.size = data->state.infilesize;
1333           Curl_pgrsSetUploadSize(data, data->state.infilesize);
1334         }
1335
1336         rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
1337         if(rc) {
1338           MOVE_TO_SFTP_CLOSE_STATE();
1339           break;
1340         }
1341       }
1342       if(data->state.infilesize > 0) {
1343         data->req.size = data->state.infilesize;
1344         Curl_pgrsSetUploadSize(data, data->state.infilesize);
1345       }
1346       /* upload data */
1347       Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
1348
1349       /* not set by Curl_setup_transfer to preserve keepon bits */
1350       conn->sockfd = conn->writesockfd;
1351
1352       /* store this original bitmask setup to use later on if we can't
1353          figure out a "real" bitmask */
1354       sshc->orig_waitfor = data->req.keepon;
1355
1356       /* we want to use the _sending_ function even when the socket turns
1357          out readable as the underlying libssh sftp send function will deal
1358          with both accordingly */
1359       conn->cselect_bits = CURL_CSELECT_OUT;
1360
1361       /* since we don't really wait for anything at this point, we want the
1362          state machine to move on as soon as possible so we set a very short
1363          timeout here */
1364       Curl_expire(data, 0, EXPIRE_RUN_NOW);
1365
1366       state(data, SSH_STOP);
1367       break;
1368     }
1369
1370     case SSH_SFTP_CREATE_DIRS_INIT:
1371       if(strlen(protop->path) > 1) {
1372         sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
1373         state(data, SSH_SFTP_CREATE_DIRS);
1374       }
1375       else {
1376         state(data, SSH_SFTP_UPLOAD_INIT);
1377       }
1378       break;
1379
1380     case SSH_SFTP_CREATE_DIRS:
1381       sshc->slash_pos = strchr(sshc->slash_pos, '/');
1382       if(sshc->slash_pos) {
1383         *sshc->slash_pos = 0;
1384
1385         infof(data, "Creating directory '%s'", protop->path);
1386         state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
1387         break;
1388       }
1389       state(data, SSH_SFTP_UPLOAD_INIT);
1390       break;
1391
1392     case SSH_SFTP_CREATE_DIRS_MKDIR:
1393       /* 'mode' - parameter is preliminary - default to 0644 */
1394       rc = sftp_mkdir(sshc->sftp_session, protop->path,
1395                       (mode_t)data->set.new_directory_perms);
1396       *sshc->slash_pos = '/';
1397       ++sshc->slash_pos;
1398       if(rc < 0) {
1399         /*
1400          * Abort if failure wasn't that the dir already exists or the
1401          * permission was denied (creation might succeed further down the
1402          * path) - retry on unspecific FAILURE also
1403          */
1404         err = sftp_get_error(sshc->sftp_session);
1405         if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
1406            (err != SSH_FX_FAILURE) &&
1407            (err != SSH_FX_PERMISSION_DENIED)) {
1408           MOVE_TO_SFTP_CLOSE_STATE();
1409           break;
1410         }
1411         rc = 0; /* clear rc and continue */
1412       }
1413       state(data, SSH_SFTP_CREATE_DIRS);
1414       break;
1415
1416     case SSH_SFTP_READDIR_INIT:
1417       Curl_pgrsSetDownloadSize(data, -1);
1418       if(data->set.opt_no_body) {
1419         state(data, SSH_STOP);
1420         break;
1421       }
1422
1423       /*
1424        * This is a directory that we are trying to get, so produce a directory
1425        * listing
1426        */
1427       sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
1428                                     protop->path);
1429       if(!sshc->sftp_dir) {
1430         failf(data, "Could not open directory for reading: %s",
1431               ssh_get_error(sshc->ssh_session));
1432         MOVE_TO_SFTP_CLOSE_STATE();
1433         break;
1434       }
1435       state(data, SSH_SFTP_READDIR);
1436       break;
1437
1438     case SSH_SFTP_READDIR:
1439
1440       if(sshc->readdir_attrs)
1441         sftp_attributes_free(sshc->readdir_attrs);
1442
1443       sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
1444       if(sshc->readdir_attrs) {
1445         sshc->readdir_filename = sshc->readdir_attrs->name;
1446         sshc->readdir_longentry = sshc->readdir_attrs->longname;
1447         sshc->readdir_len = strlen(sshc->readdir_filename);
1448
1449         if(data->set.list_only) {
1450           char *tmpLine;
1451
1452           tmpLine = aprintf("%s\n", sshc->readdir_filename);
1453           if(!tmpLine) {
1454             state(data, SSH_SFTP_CLOSE);
1455             sshc->actualcode = CURLE_OUT_OF_MEMORY;
1456             break;
1457           }
1458           result = Curl_client_write(data, CLIENTWRITE_BODY,
1459                                      tmpLine, sshc->readdir_len + 1);
1460           free(tmpLine);
1461
1462           if(result) {
1463             state(data, SSH_STOP);
1464             break;
1465           }
1466           /* since this counts what we send to the client, we include the
1467              newline in this counter */
1468           data->req.bytecount += sshc->readdir_len + 1;
1469
1470           /* output debug output if that is requested */
1471           Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
1472                      sshc->readdir_len);
1473         }
1474         else {
1475           sshc->readdir_currLen = strlen(sshc->readdir_longentry);
1476           sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
1477           sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
1478           if(!sshc->readdir_line) {
1479             state(data, SSH_SFTP_CLOSE);
1480             sshc->actualcode = CURLE_OUT_OF_MEMORY;
1481             break;
1482           }
1483
1484           memcpy(sshc->readdir_line, sshc->readdir_longentry,
1485                  sshc->readdir_currLen);
1486           if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
1487              ((sshc->readdir_attrs->permissions & SSH_S_IFMT) ==
1488               SSH_S_IFLNK)) {
1489             sshc->readdir_linkPath = aprintf("%s%s", protop->path,
1490                                              sshc->readdir_filename);
1491
1492             if(!sshc->readdir_linkPath) {
1493               state(data, SSH_SFTP_CLOSE);
1494               sshc->actualcode = CURLE_OUT_OF_MEMORY;
1495               break;
1496             }
1497
1498             state(data, SSH_SFTP_READDIR_LINK);
1499             break;
1500           }
1501           state(data, SSH_SFTP_READDIR_BOTTOM);
1502           break;
1503         }
1504       }
1505       else if(sftp_dir_eof(sshc->sftp_dir)) {
1506         state(data, SSH_SFTP_READDIR_DONE);
1507         break;
1508       }
1509       else {
1510         failf(data, "Could not open remote file for reading: %s",
1511               ssh_get_error(sshc->ssh_session));
1512         MOVE_TO_SFTP_CLOSE_STATE();
1513         break;
1514       }
1515       break;
1516
1517     case SSH_SFTP_READDIR_LINK:
1518       if(sshc->readdir_link_attrs)
1519         sftp_attributes_free(sshc->readdir_link_attrs);
1520
1521       sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session,
1522                                             sshc->readdir_linkPath);
1523       if(sshc->readdir_link_attrs == 0) {
1524         failf(data, "Could not read symlink for reading: %s",
1525               ssh_get_error(sshc->ssh_session));
1526         MOVE_TO_SFTP_CLOSE_STATE();
1527         break;
1528       }
1529
1530       if(!sshc->readdir_link_attrs->name) {
1531         sshc->readdir_tmp = sftp_readlink(sshc->sftp_session,
1532                                           sshc->readdir_linkPath);
1533         if(!sshc->readdir_filename)
1534           sshc->readdir_len = 0;
1535         else
1536           sshc->readdir_len = strlen(sshc->readdir_tmp);
1537         sshc->readdir_longentry = NULL;
1538         sshc->readdir_filename = sshc->readdir_tmp;
1539       }
1540       else {
1541         sshc->readdir_len = strlen(sshc->readdir_link_attrs->name);
1542         sshc->readdir_filename = sshc->readdir_link_attrs->name;
1543         sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
1544       }
1545
1546       Curl_safefree(sshc->readdir_linkPath);
1547
1548       /* get room for the filename and extra output */
1549       sshc->readdir_totalLen += 4 + sshc->readdir_len;
1550       new_readdir_line = Curl_saferealloc(sshc->readdir_line,
1551                                           sshc->readdir_totalLen);
1552       if(!new_readdir_line) {
1553         sshc->readdir_line = NULL;
1554         state(data, SSH_SFTP_CLOSE);
1555         sshc->actualcode = CURLE_OUT_OF_MEMORY;
1556         break;
1557       }
1558       sshc->readdir_line = new_readdir_line;
1559
1560       sshc->readdir_currLen += msnprintf(sshc->readdir_line +
1561                                          sshc->readdir_currLen,
1562                                          sshc->readdir_totalLen -
1563                                          sshc->readdir_currLen,
1564                                          " -> %s",
1565                                          sshc->readdir_filename);
1566
1567       sftp_attributes_free(sshc->readdir_link_attrs);
1568       sshc->readdir_link_attrs = NULL;
1569       sshc->readdir_filename = NULL;
1570       sshc->readdir_longentry = NULL;
1571
1572       state(data, SSH_SFTP_READDIR_BOTTOM);
1573       /* FALLTHROUGH */
1574     case SSH_SFTP_READDIR_BOTTOM:
1575       sshc->readdir_currLen += msnprintf(sshc->readdir_line +
1576                                          sshc->readdir_currLen,
1577                                          sshc->readdir_totalLen -
1578                                          sshc->readdir_currLen, "\n");
1579       result = Curl_client_write(data, CLIENTWRITE_BODY,
1580                                  sshc->readdir_line,
1581                                  sshc->readdir_currLen);
1582
1583       if(!result) {
1584         /* output debug output if that is requested */
1585         Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
1586                    sshc->readdir_currLen);
1587         data->req.bytecount += sshc->readdir_currLen;
1588       }
1589       Curl_safefree(sshc->readdir_line);
1590       ssh_string_free_char(sshc->readdir_tmp);
1591       sshc->readdir_tmp = NULL;
1592
1593       if(result) {
1594         state(data, SSH_STOP);
1595       }
1596       else
1597         state(data, SSH_SFTP_READDIR);
1598       break;
1599
1600     case SSH_SFTP_READDIR_DONE:
1601       sftp_closedir(sshc->sftp_dir);
1602       sshc->sftp_dir = NULL;
1603
1604       /* no data to transfer */
1605       Curl_setup_transfer(data, -1, -1, FALSE, -1);
1606       state(data, SSH_STOP);
1607       break;
1608
1609     case SSH_SFTP_DOWNLOAD_INIT:
1610       /*
1611        * Work on getting the specified file
1612        */
1613       if(sshc->sftp_file)
1614         sftp_close(sshc->sftp_file);
1615
1616       sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
1617                                   O_RDONLY, (mode_t)data->set.new_file_perms);
1618       if(!sshc->sftp_file) {
1619         failf(data, "Could not open remote file for reading: %s",
1620               ssh_get_error(sshc->ssh_session));
1621
1622         MOVE_TO_SFTP_CLOSE_STATE();
1623         break;
1624       }
1625
1626       state(data, SSH_SFTP_DOWNLOAD_STAT);
1627       break;
1628
1629     case SSH_SFTP_DOWNLOAD_STAT:
1630     {
1631       sftp_attributes attrs;
1632       curl_off_t size;
1633
1634       attrs = sftp_fstat(sshc->sftp_file);
1635       if(!attrs ||
1636               !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
1637               (attrs->size == 0)) {
1638         /*
1639          * sftp_fstat didn't return an error, so maybe the server
1640          * just doesn't support stat()
1641          * OR the server doesn't return a file size with a stat()
1642          * OR file size is 0
1643          */
1644         data->req.size = -1;
1645         data->req.maxdownload = -1;
1646         Curl_pgrsSetDownloadSize(data, -1);
1647         size = 0;
1648       }
1649       else {
1650         size = attrs->size;
1651
1652         sftp_attributes_free(attrs);
1653
1654         if(size < 0) {
1655           failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
1656           return CURLE_BAD_DOWNLOAD_RESUME;
1657         }
1658         if(data->state.use_range) {
1659           curl_off_t from, to;
1660           char *ptr;
1661           char *ptr2;
1662           CURLofft to_t;
1663           CURLofft from_t;
1664
1665           from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
1666           if(from_t == CURL_OFFT_FLOW) {
1667             return CURLE_RANGE_ERROR;
1668           }
1669           while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
1670             ptr++;
1671           to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
1672           if(to_t == CURL_OFFT_FLOW) {
1673             return CURLE_RANGE_ERROR;
1674           }
1675           if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
1676              || (to >= size)) {
1677             to = size - 1;
1678           }
1679           if(from_t) {
1680             /* from is relative to end of file */
1681             from = size - to;
1682             to = size - 1;
1683           }
1684           if(from > size) {
1685             failf(data, "Offset (%"
1686                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
1687                   CURL_FORMAT_CURL_OFF_T ")", from, size);
1688             return CURLE_BAD_DOWNLOAD_RESUME;
1689           }
1690           if(from > to) {
1691             from = to;
1692             size = 0;
1693           }
1694           else {
1695             size = to - from + 1;
1696           }
1697
1698           rc = sftp_seek64(sshc->sftp_file, from);
1699           if(rc) {
1700             MOVE_TO_SFTP_CLOSE_STATE();
1701             break;
1702           }
1703         }
1704         data->req.size = size;
1705         data->req.maxdownload = size;
1706         Curl_pgrsSetDownloadSize(data, size);
1707       }
1708
1709       /* We can resume if we can seek to the resume position */
1710       if(data->state.resume_from) {
1711         if(data->state.resume_from < 0) {
1712           /* We're supposed to download the last abs(from) bytes */
1713           if((curl_off_t)size < -data->state.resume_from) {
1714             failf(data, "Offset (%"
1715                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
1716                   CURL_FORMAT_CURL_OFF_T ")",
1717                   data->state.resume_from, size);
1718             return CURLE_BAD_DOWNLOAD_RESUME;
1719           }
1720           /* download from where? */
1721           data->state.resume_from += size;
1722         }
1723         else {
1724           if((curl_off_t)size < data->state.resume_from) {
1725             failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
1726                   ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
1727                   data->state.resume_from, size);
1728             return CURLE_BAD_DOWNLOAD_RESUME;
1729           }
1730         }
1731         /* Now store the number of bytes we are expected to download */
1732         data->req.size = size - data->state.resume_from;
1733         data->req.maxdownload = size - data->state.resume_from;
1734         Curl_pgrsSetDownloadSize(data,
1735                                  size - data->state.resume_from);
1736
1737         rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
1738         if(rc) {
1739           MOVE_TO_SFTP_CLOSE_STATE();
1740           break;
1741         }
1742       }
1743     }
1744
1745     /* Setup the actual download */
1746     if(data->req.size == 0) {
1747       /* no data to transfer */
1748       Curl_setup_transfer(data, -1, -1, FALSE, -1);
1749       infof(data, "File already completely downloaded");
1750       state(data, SSH_STOP);
1751       break;
1752     }
1753     Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
1754
1755     /* not set by Curl_setup_transfer to preserve keepon bits */
1756     conn->writesockfd = conn->sockfd;
1757
1758     /* we want to use the _receiving_ function even when the socket turns
1759        out writableable as the underlying libssh recv function will deal
1760        with both accordingly */
1761     conn->cselect_bits = CURL_CSELECT_IN;
1762
1763     if(result) {
1764       /* this should never occur; the close state should be entered
1765          at the time the error occurs */
1766       state(data, SSH_SFTP_CLOSE);
1767       sshc->actualcode = result;
1768     }
1769     else {
1770       sshc->sftp_recv_state = 0;
1771       state(data, SSH_STOP);
1772     }
1773     break;
1774
1775     case SSH_SFTP_CLOSE:
1776       if(sshc->sftp_file) {
1777         sftp_close(sshc->sftp_file);
1778         sshc->sftp_file = NULL;
1779       }
1780       Curl_safefree(protop->path);
1781
1782       DEBUGF(infof(data, "SFTP DONE done"));
1783
1784       /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
1785          After nextstate is executed, the control should come back to
1786          SSH_SFTP_CLOSE to pass the correct result back  */
1787       if(sshc->nextstate != SSH_NO_STATE &&
1788          sshc->nextstate != SSH_SFTP_CLOSE) {
1789         state(data, sshc->nextstate);
1790         sshc->nextstate = SSH_SFTP_CLOSE;
1791       }
1792       else {
1793         state(data, SSH_STOP);
1794         result = sshc->actualcode;
1795       }
1796       break;
1797
1798     case SSH_SFTP_SHUTDOWN:
1799       /* during times we get here due to a broken transfer and then the
1800          sftp_handle might not have been taken down so make sure that is done
1801          before we proceed */
1802
1803       if(sshc->sftp_file) {
1804         sftp_close(sshc->sftp_file);
1805         sshc->sftp_file = NULL;
1806       }
1807
1808       if(sshc->sftp_session) {
1809         sftp_free(sshc->sftp_session);
1810         sshc->sftp_session = NULL;
1811       }
1812
1813       SSH_STRING_FREE_CHAR(sshc->homedir);
1814       data->state.most_recent_ftp_entrypath = NULL;
1815
1816       state(data, SSH_SESSION_DISCONNECT);
1817       break;
1818
1819     case SSH_SCP_TRANS_INIT:
1820       result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
1821       if(result) {
1822         sshc->actualcode = result;
1823         state(data, SSH_STOP);
1824         break;
1825       }
1826
1827       /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
1828       ssh_set_blocking(sshc->ssh_session, 1);
1829
1830       if(data->set.upload) {
1831         if(data->state.infilesize < 0) {
1832           failf(data, "SCP requires a known file size for upload");
1833           sshc->actualcode = CURLE_UPLOAD_FAILED;
1834           MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1835           break;
1836         }
1837
1838         sshc->scp_session =
1839           ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
1840         state(data, SSH_SCP_UPLOAD_INIT);
1841       }
1842       else {
1843         sshc->scp_session =
1844           ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
1845         state(data, SSH_SCP_DOWNLOAD_INIT);
1846       }
1847
1848       if(!sshc->scp_session) {
1849         err_msg = ssh_get_error(sshc->ssh_session);
1850         failf(data, "%s", err_msg);
1851         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1852       }
1853
1854       break;
1855
1856     case SSH_SCP_UPLOAD_INIT:
1857
1858       rc = ssh_scp_init(sshc->scp_session);
1859       if(rc != SSH_OK) {
1860         err_msg = ssh_get_error(sshc->ssh_session);
1861         failf(data, "%s", err_msg);
1862         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1863         break;
1864       }
1865
1866       rc = ssh_scp_push_file(sshc->scp_session, protop->path,
1867                              data->state.infilesize,
1868                              (int)data->set.new_file_perms);
1869       if(rc != SSH_OK) {
1870         err_msg = ssh_get_error(sshc->ssh_session);
1871         failf(data, "%s", err_msg);
1872         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1873         break;
1874       }
1875
1876       /* upload data */
1877       Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
1878
1879       /* not set by Curl_setup_transfer to preserve keepon bits */
1880       conn->sockfd = conn->writesockfd;
1881
1882       /* store this original bitmask setup to use later on if we can't
1883          figure out a "real" bitmask */
1884       sshc->orig_waitfor = data->req.keepon;
1885
1886       /* we want to use the _sending_ function even when the socket turns
1887          out readable as the underlying libssh scp send function will deal
1888          with both accordingly */
1889       conn->cselect_bits = CURL_CSELECT_OUT;
1890
1891       state(data, SSH_STOP);
1892
1893       break;
1894
1895     case SSH_SCP_DOWNLOAD_INIT:
1896
1897       rc = ssh_scp_init(sshc->scp_session);
1898       if(rc != SSH_OK) {
1899         err_msg = ssh_get_error(sshc->ssh_session);
1900         failf(data, "%s", err_msg);
1901         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
1902         break;
1903       }
1904       state(data, SSH_SCP_DOWNLOAD);
1905       /* FALLTHROUGH */
1906
1907     case SSH_SCP_DOWNLOAD:{
1908         curl_off_t bytecount;
1909
1910         rc = ssh_scp_pull_request(sshc->scp_session);
1911         if(rc != SSH_SCP_REQUEST_NEWFILE) {
1912           err_msg = ssh_get_error(sshc->ssh_session);
1913           failf(data, "%s", err_msg);
1914           MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
1915           break;
1916         }
1917
1918         /* download data */
1919         bytecount = ssh_scp_request_get_size(sshc->scp_session);
1920         data->req.maxdownload = (curl_off_t) bytecount;
1921         Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
1922
1923         /* not set by Curl_setup_transfer to preserve keepon bits */
1924         conn->writesockfd = conn->sockfd;
1925
1926         /* we want to use the _receiving_ function even when the socket turns
1927            out writableable as the underlying libssh recv function will deal
1928            with both accordingly */
1929         conn->cselect_bits = CURL_CSELECT_IN;
1930
1931         state(data, SSH_STOP);
1932         break;
1933       }
1934     case SSH_SCP_DONE:
1935       if(data->set.upload)
1936         state(data, SSH_SCP_SEND_EOF);
1937       else
1938         state(data, SSH_SCP_CHANNEL_FREE);
1939       break;
1940
1941     case SSH_SCP_SEND_EOF:
1942       if(sshc->scp_session) {
1943         rc = ssh_scp_close(sshc->scp_session);
1944         if(rc == SSH_AGAIN) {
1945           /* Currently the ssh_scp_close handles waiting for EOF in
1946            * blocking way.
1947            */
1948           break;
1949         }
1950         if(rc != SSH_OK) {
1951           infof(data, "Failed to close libssh scp channel: %s",
1952                 ssh_get_error(sshc->ssh_session));
1953         }
1954       }
1955
1956       state(data, SSH_SCP_CHANNEL_FREE);
1957       break;
1958
1959     case SSH_SCP_CHANNEL_FREE:
1960       if(sshc->scp_session) {
1961         ssh_scp_free(sshc->scp_session);
1962         sshc->scp_session = NULL;
1963       }
1964       DEBUGF(infof(data, "SCP DONE phase complete"));
1965
1966       ssh_set_blocking(sshc->ssh_session, 0);
1967
1968       state(data, SSH_SESSION_DISCONNECT);
1969       /* FALLTHROUGH */
1970
1971     case SSH_SESSION_DISCONNECT:
1972       /* during weird times when we've been prematurely aborted, the channel
1973          is still alive when we reach this state and we MUST kill the channel
1974          properly first */
1975       if(sshc->scp_session) {
1976         ssh_scp_free(sshc->scp_session);
1977         sshc->scp_session = NULL;
1978       }
1979
1980       ssh_disconnect(sshc->ssh_session);
1981       if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
1982         /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
1983            explicitly mark it as closed with the memdebug macro. This libssh
1984            bug is fixed in 0.10.0. */
1985         fake_sclose(conn->sock[FIRSTSOCKET]);
1986         conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
1987       }
1988
1989       SSH_STRING_FREE_CHAR(sshc->homedir);
1990       data->state.most_recent_ftp_entrypath = NULL;
1991
1992       state(data, SSH_SESSION_FREE);
1993       /* FALLTHROUGH */
1994     case SSH_SESSION_FREE:
1995       if(sshc->ssh_session) {
1996         ssh_free(sshc->ssh_session);
1997         sshc->ssh_session = NULL;
1998       }
1999
2000       /* worst-case scenario cleanup */
2001
2002       DEBUGASSERT(sshc->ssh_session == NULL);
2003       DEBUGASSERT(sshc->scp_session == NULL);
2004
2005       if(sshc->readdir_tmp) {
2006         ssh_string_free_char(sshc->readdir_tmp);
2007         sshc->readdir_tmp = NULL;
2008       }
2009
2010       if(sshc->quote_attrs)
2011         sftp_attributes_free(sshc->quote_attrs);
2012
2013       if(sshc->readdir_attrs)
2014         sftp_attributes_free(sshc->readdir_attrs);
2015
2016       if(sshc->readdir_link_attrs)
2017         sftp_attributes_free(sshc->readdir_link_attrs);
2018
2019       if(sshc->privkey)
2020         ssh_key_free(sshc->privkey);
2021       if(sshc->pubkey)
2022         ssh_key_free(sshc->pubkey);
2023
2024       Curl_safefree(sshc->rsa_pub);
2025       Curl_safefree(sshc->rsa);
2026       Curl_safefree(sshc->quote_path1);
2027       Curl_safefree(sshc->quote_path2);
2028       Curl_safefree(sshc->readdir_line);
2029       Curl_safefree(sshc->readdir_linkPath);
2030       SSH_STRING_FREE_CHAR(sshc->homedir);
2031
2032       /* the code we are about to return */
2033       result = sshc->actualcode;
2034
2035       memset(sshc, 0, sizeof(struct ssh_conn));
2036
2037       connclose(conn, "SSH session free");
2038       sshc->state = SSH_SESSION_FREE;   /* current */
2039       sshc->nextstate = SSH_NO_STATE;
2040       state(data, SSH_STOP);
2041       break;
2042
2043     case SSH_QUIT:
2044       /* fallthrough, just stop! */
2045     default:
2046       /* internal error */
2047       sshc->nextstate = SSH_NO_STATE;
2048       state(data, SSH_STOP);
2049       break;
2050
2051     }
2052   } while(!rc && (sshc->state != SSH_STOP));
2053
2054
2055   if(rc == SSH_AGAIN) {
2056     /* we would block, we need to wait for the socket to be ready (in the
2057        right direction too)! */
2058     *block = TRUE;
2059   }
2060
2061   return result;
2062 }
2063
2064
2065 /* called by the multi interface to figure out what socket(s) to wait for and
2066    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
2067 static int myssh_getsock(struct Curl_easy *data,
2068                          struct connectdata *conn,
2069                          curl_socket_t *sock)
2070 {
2071   int bitmap = GETSOCK_BLANK;
2072   (void)data;
2073   sock[0] = conn->sock[FIRSTSOCKET];
2074
2075   if(conn->waitfor & KEEP_RECV)
2076     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
2077
2078   if(conn->waitfor & KEEP_SEND)
2079     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
2080
2081   if(!conn->waitfor)
2082     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
2083
2084   return bitmap;
2085 }
2086
2087 static void myssh_block2waitfor(struct connectdata *conn, bool block)
2088 {
2089   struct ssh_conn *sshc = &conn->proto.sshc;
2090
2091   /* If it didn't block, or nothing was returned by ssh_get_poll_flags
2092    * have the original set */
2093   conn->waitfor = sshc->orig_waitfor;
2094
2095   if(block) {
2096     int dir = ssh_get_poll_flags(sshc->ssh_session);
2097     if(dir & SSH_READ_PENDING) {
2098       /* translate the libssh define bits into our own bit defines */
2099       conn->waitfor = KEEP_RECV;
2100     }
2101     else if(dir & SSH_WRITE_PENDING) {
2102       conn->waitfor = KEEP_SEND;
2103     }
2104   }
2105 }
2106
2107 /* called repeatedly until done from multi.c */
2108 static CURLcode myssh_multi_statemach(struct Curl_easy *data,
2109                                       bool *done)
2110 {
2111   struct connectdata *conn = data->conn;
2112   struct ssh_conn *sshc = &conn->proto.sshc;
2113   bool block;    /* we store the status and use that to provide a ssh_getsock()
2114                     implementation */
2115   CURLcode result = myssh_statemach_act(data, &block);
2116
2117   *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
2118   myssh_block2waitfor(conn, block);
2119
2120   return result;
2121 }
2122
2123 static CURLcode myssh_block_statemach(struct Curl_easy *data,
2124                                       bool disconnect)
2125 {
2126   struct connectdata *conn = data->conn;
2127   struct ssh_conn *sshc = &conn->proto.sshc;
2128   CURLcode result = CURLE_OK;
2129
2130   while((sshc->state != SSH_STOP) && !result) {
2131     bool block;
2132     timediff_t left = 1000;
2133     struct curltime now = Curl_now();
2134
2135     result = myssh_statemach_act(data, &block);
2136     if(result)
2137       break;
2138
2139     if(!disconnect) {
2140       if(Curl_pgrsUpdate(data))
2141         return CURLE_ABORTED_BY_CALLBACK;
2142
2143       result = Curl_speedcheck(data, now);
2144       if(result)
2145         break;
2146
2147       left = Curl_timeleft(data, NULL, FALSE);
2148       if(left < 0) {
2149         failf(data, "Operation timed out");
2150         return CURLE_OPERATION_TIMEDOUT;
2151       }
2152     }
2153
2154     if(block) {
2155       curl_socket_t fd_read = conn->sock[FIRSTSOCKET];
2156       /* wait for the socket to become ready */
2157       (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD,
2158                                CURL_SOCKET_BAD, left > 1000 ? 1000 : left);
2159     }
2160
2161   }
2162
2163   return result;
2164 }
2165
2166 /*
2167  * SSH setup connection
2168  */
2169 static CURLcode myssh_setup_connection(struct Curl_easy *data,
2170                                        struct connectdata *conn)
2171 {
2172   struct SSHPROTO *ssh;
2173   (void)conn;
2174
2175   data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
2176   if(!ssh)
2177     return CURLE_OUT_OF_MEMORY;
2178
2179   return CURLE_OK;
2180 }
2181
2182 static Curl_recv scp_recv, sftp_recv;
2183 static Curl_send scp_send, sftp_send;
2184
2185 /*
2186  * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
2187  * do protocol-specific actions at connect-time.
2188  */
2189 static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
2190 {
2191   struct ssh_conn *ssh;
2192   CURLcode result;
2193   struct connectdata *conn = data->conn;
2194   curl_socket_t sock = conn->sock[FIRSTSOCKET];
2195   int rc;
2196
2197   /* initialize per-handle data if not already */
2198   if(!data->req.p.ssh)
2199     myssh_setup_connection(data, conn);
2200
2201   /* We default to persistent connections. We set this already in this connect
2202      function to make the re-use checks properly be able to check this bit. */
2203   connkeep(conn, "SSH default");
2204
2205   if(conn->handler->protocol & CURLPROTO_SCP) {
2206     conn->recv[FIRSTSOCKET] = scp_recv;
2207     conn->send[FIRSTSOCKET] = scp_send;
2208   }
2209   else {
2210     conn->recv[FIRSTSOCKET] = sftp_recv;
2211     conn->send[FIRSTSOCKET] = sftp_send;
2212   }
2213
2214   ssh = &conn->proto.sshc;
2215
2216   ssh->ssh_session = ssh_new();
2217   if(!ssh->ssh_session) {
2218     failf(data, "Failure initialising ssh session");
2219     return CURLE_FAILED_INIT;
2220   }
2221
2222   rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
2223   if(rc != SSH_OK) {
2224     failf(data, "Could not set remote host");
2225     return CURLE_FAILED_INIT;
2226   }
2227
2228   rc = ssh_options_parse_config(ssh->ssh_session, NULL);
2229   if(rc != SSH_OK) {
2230     infof(data, "Could not parse SSH configuration files");
2231     /* ignore */
2232   }
2233
2234   rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_FD, &sock);
2235   if(rc != SSH_OK) {
2236     failf(data, "Could not set socket");
2237     return CURLE_FAILED_INIT;
2238   }
2239
2240   if(conn->user && conn->user[0] != '\0') {
2241     infof(data, "User: %s", conn->user);
2242     rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
2243     if(rc != SSH_OK) {
2244       failf(data, "Could not set user");
2245       return CURLE_FAILED_INIT;
2246     }
2247   }
2248
2249   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
2250     infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]);
2251     rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
2252                          data->set.str[STRING_SSH_KNOWNHOSTS]);
2253     if(rc != SSH_OK) {
2254       failf(data, "Could not set known hosts file path");
2255       return CURLE_FAILED_INIT;
2256     }
2257   }
2258
2259   if(conn->remote_port) {
2260     rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT,
2261                          &conn->remote_port);
2262     if(rc != SSH_OK) {
2263       failf(data, "Could not set remote port");
2264       return CURLE_FAILED_INIT;
2265     }
2266   }
2267
2268   if(data->set.ssh_compression) {
2269     rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION,
2270                          "zlib,zlib@openssh.com,none");
2271     if(rc != SSH_OK) {
2272       failf(data, "Could not set compression");
2273       return CURLE_FAILED_INIT;
2274     }
2275   }
2276
2277   ssh->privkey = NULL;
2278   ssh->pubkey = NULL;
2279
2280   if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
2281     rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
2282                                     &ssh->pubkey);
2283     if(rc != SSH_OK) {
2284       failf(data, "Could not load public key file");
2285       return CURLE_FAILED_INIT;
2286     }
2287   }
2288
2289   /* we do not verify here, we do it at the state machine,
2290    * after connection */
2291
2292   state(data, SSH_INIT);
2293
2294   result = myssh_multi_statemach(data, done);
2295
2296   return result;
2297 }
2298
2299 /* called from multi.c while DOing */
2300 static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
2301 {
2302   CURLcode result;
2303
2304   result = myssh_multi_statemach(data, dophase_done);
2305
2306   if(*dophase_done) {
2307     DEBUGF(infof(data, "DO phase is complete"));
2308   }
2309   return result;
2310 }
2311
2312 /*
2313  ***********************************************************************
2314  *
2315  * scp_perform()
2316  *
2317  * This is the actual DO function for SCP. Get a file according to
2318  * the options previously setup.
2319  */
2320
2321 static
2322 CURLcode scp_perform(struct Curl_easy *data,
2323                      bool *connected, bool *dophase_done)
2324 {
2325   CURLcode result = CURLE_OK;
2326   struct connectdata *conn = data->conn;
2327
2328   DEBUGF(infof(data, "DO phase starts"));
2329
2330   *dophase_done = FALSE;        /* not done yet */
2331
2332   /* start the first command in the DO phase */
2333   state(data, SSH_SCP_TRANS_INIT);
2334
2335   result = myssh_multi_statemach(data, dophase_done);
2336
2337   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
2338
2339   if(*dophase_done) {
2340     DEBUGF(infof(data, "DO phase is complete"));
2341   }
2342
2343   return result;
2344 }
2345
2346 static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
2347 {
2348   CURLcode result;
2349   bool connected = 0;
2350   struct connectdata *conn = data->conn;
2351   struct ssh_conn *sshc = &conn->proto.sshc;
2352
2353   *done = FALSE;                /* default to false */
2354
2355   data->req.size = -1;          /* make sure this is unknown at this point */
2356
2357   sshc->actualcode = CURLE_OK;  /* reset error code */
2358   sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
2359                                    variable */
2360
2361   Curl_pgrsSetUploadCounter(data, 0);
2362   Curl_pgrsSetDownloadCounter(data, 0);
2363   Curl_pgrsSetUploadSize(data, -1);
2364   Curl_pgrsSetDownloadSize(data, -1);
2365
2366   if(conn->handler->protocol & CURLPROTO_SCP)
2367     result = scp_perform(data, &connected, done);
2368   else
2369     result = sftp_perform(data, &connected, done);
2370
2371   return result;
2372 }
2373
2374 /* BLOCKING, but the function is using the state machine so the only reason
2375    this is still blocking is that the multi interface code has no support for
2376    disconnecting operations that takes a while */
2377 static CURLcode scp_disconnect(struct Curl_easy *data,
2378                                struct connectdata *conn,
2379                                bool dead_connection)
2380 {
2381   CURLcode result = CURLE_OK;
2382   struct ssh_conn *ssh = &conn->proto.sshc;
2383   (void) dead_connection;
2384
2385   if(ssh->ssh_session) {
2386     /* only if there's a session still around to use! */
2387
2388     state(data, SSH_SESSION_DISCONNECT);
2389
2390     result = myssh_block_statemach(data, TRUE);
2391   }
2392
2393   return result;
2394 }
2395
2396 /* generic done function for both SCP and SFTP called from their specific
2397    done functions */
2398 static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
2399 {
2400   CURLcode result = CURLE_OK;
2401   struct SSHPROTO *protop = data->req.p.ssh;
2402
2403   if(!status) {
2404     /* run the state-machine */
2405     result = myssh_block_statemach(data, FALSE);
2406   }
2407   else
2408     result = status;
2409
2410   if(protop)
2411     Curl_safefree(protop->path);
2412   if(Curl_pgrsDone(data))
2413     return CURLE_ABORTED_BY_CALLBACK;
2414
2415   data->req.keepon = 0;   /* clear all bits */
2416   return result;
2417 }
2418
2419
2420 static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
2421                          bool premature)
2422 {
2423   (void) premature;             /* not used */
2424
2425   if(!status)
2426     state(data, SSH_SCP_DONE);
2427
2428   return myssh_done(data, status);
2429
2430 }
2431
2432 static ssize_t scp_send(struct Curl_easy *data, int sockindex,
2433                         const void *mem, size_t len, CURLcode *err)
2434 {
2435   int rc;
2436   struct connectdata *conn = data->conn;
2437   (void) sockindex; /* we only support SCP on the fixed known primary socket */
2438   (void) err;
2439
2440   rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);
2441
2442 #if 0
2443   /* The following code is misleading, mostly added as wishful thinking
2444    * that libssh at some point will implement non-blocking ssh_scp_write/read.
2445    * Currently rc can only be number of bytes read or SSH_ERROR. */
2446   myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE);
2447
2448   if(rc == SSH_AGAIN) {
2449     *err = CURLE_AGAIN;
2450     return 0;
2451   }
2452   else
2453 #endif
2454   if(rc != SSH_OK) {
2455     *err = CURLE_SSH;
2456     return -1;
2457   }
2458
2459   return len;
2460 }
2461
2462 static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
2463                         char *mem, size_t len, CURLcode *err)
2464 {
2465   ssize_t nread;
2466   struct connectdata *conn = data->conn;
2467   (void) err;
2468   (void) sockindex; /* we only support SCP on the fixed known primary socket */
2469
2470   /* libssh returns int */
2471   nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);
2472
2473 #if 0
2474   /* The following code is misleading, mostly added as wishful thinking
2475    * that libssh at some point will implement non-blocking ssh_scp_write/read.
2476    * Currently rc can only be SSH_OK or SSH_ERROR. */
2477
2478   myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE);
2479   if(nread == SSH_AGAIN) {
2480     *err = CURLE_AGAIN;
2481     nread = -1;
2482   }
2483 #endif
2484
2485   return nread;
2486 }
2487
2488 /*
2489  * =============== SFTP ===============
2490  */
2491
2492 /*
2493  ***********************************************************************
2494  *
2495  * sftp_perform()
2496  *
2497  * This is the actual DO function for SFTP. Get a file/directory according to
2498  * the options previously setup.
2499  */
2500
2501 static
2502 CURLcode sftp_perform(struct Curl_easy *data,
2503                       bool *connected,
2504                       bool *dophase_done)
2505 {
2506   CURLcode result = CURLE_OK;
2507   struct connectdata *conn = data->conn;
2508
2509   DEBUGF(infof(data, "DO phase starts"));
2510
2511   *dophase_done = FALSE; /* not done yet */
2512
2513   /* start the first command in the DO phase */
2514   state(data, SSH_SFTP_QUOTE_INIT);
2515
2516   /* run the state-machine */
2517   result = myssh_multi_statemach(data, dophase_done);
2518
2519   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
2520
2521   if(*dophase_done) {
2522     DEBUGF(infof(data, "DO phase is complete"));
2523   }
2524
2525   return result;
2526 }
2527
2528 /* called from multi.c while DOing */
2529 static CURLcode sftp_doing(struct Curl_easy *data,
2530                            bool *dophase_done)
2531 {
2532   CURLcode result = myssh_multi_statemach(data, dophase_done);
2533   if(*dophase_done) {
2534     DEBUGF(infof(data, "DO phase is complete"));
2535   }
2536   return result;
2537 }
2538
2539 /* BLOCKING, but the function is using the state machine so the only reason
2540    this is still blocking is that the multi interface code has no support for
2541    disconnecting operations that takes a while */
2542 static CURLcode sftp_disconnect(struct Curl_easy *data,
2543                                 struct connectdata *conn,
2544                                 bool dead_connection)
2545 {
2546   CURLcode result = CURLE_OK;
2547   (void) dead_connection;
2548
2549   DEBUGF(infof(data, "SSH DISCONNECT starts now"));
2550
2551   if(conn->proto.sshc.ssh_session) {
2552     /* only if there's a session still around to use! */
2553     state(data, SSH_SFTP_SHUTDOWN);
2554     result = myssh_block_statemach(data, TRUE);
2555   }
2556
2557   DEBUGF(infof(data, "SSH DISCONNECT is done"));
2558
2559   return result;
2560
2561 }
2562
2563 static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
2564                           bool premature)
2565 {
2566   struct connectdata *conn = data->conn;
2567   struct ssh_conn *sshc = &conn->proto.sshc;
2568
2569   if(!status) {
2570     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
2571        errors that could happen due to open file handles during POSTQUOTE
2572        operation */
2573     if(!premature && data->set.postquote && !conn->bits.retry)
2574       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
2575     state(data, SSH_SFTP_CLOSE);
2576   }
2577   return myssh_done(data, status);
2578 }
2579
2580 /* return number of sent bytes */
2581 static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
2582                          const void *mem, size_t len, CURLcode *err)
2583 {
2584   ssize_t nwrite;
2585   struct connectdata *conn = data->conn;
2586   (void)sockindex;
2587
2588   nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
2589
2590   myssh_block2waitfor(conn, FALSE);
2591
2592 #if 0 /* not returned by libssh on write */
2593   if(nwrite == SSH_AGAIN) {
2594     *err = CURLE_AGAIN;
2595     nwrite = 0;
2596   }
2597   else
2598 #endif
2599   if(nwrite < 0) {
2600     *err = CURLE_SSH;
2601     nwrite = -1;
2602   }
2603
2604   return nwrite;
2605 }
2606
2607 /*
2608  * Return number of received (decrypted) bytes
2609  * or <0 on error
2610  */
2611 static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
2612                          char *mem, size_t len, CURLcode *err)
2613 {
2614   ssize_t nread;
2615   struct connectdata *conn = data->conn;
2616   (void)sockindex;
2617
2618   DEBUGASSERT(len < CURL_MAX_READ_SIZE);
2619
2620   switch(conn->proto.sshc.sftp_recv_state) {
2621     case 0:
2622       conn->proto.sshc.sftp_file_index =
2623         sftp_async_read_begin(conn->proto.sshc.sftp_file,
2624                               (uint32_t)len);
2625       if(conn->proto.sshc.sftp_file_index < 0) {
2626         *err = CURLE_RECV_ERROR;
2627         return -1;
2628       }
2629
2630       /* FALLTHROUGH */
2631     case 1:
2632       conn->proto.sshc.sftp_recv_state = 1;
2633
2634       nread = sftp_async_read(conn->proto.sshc.sftp_file,
2635                               mem, (uint32_t)len,
2636                               conn->proto.sshc.sftp_file_index);
2637
2638       myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE);
2639
2640       if(nread == SSH_AGAIN) {
2641         *err = CURLE_AGAIN;
2642         return -1;
2643       }
2644       else if(nread < 0) {
2645         *err = CURLE_RECV_ERROR;
2646         return -1;
2647       }
2648
2649       conn->proto.sshc.sftp_recv_state = 0;
2650       return nread;
2651
2652     default:
2653       /* we never reach here */
2654       return -1;
2655   }
2656 }
2657
2658 static void sftp_quote(struct Curl_easy *data)
2659 {
2660   const char *cp;
2661   struct connectdata *conn = data->conn;
2662   struct SSHPROTO *protop = data->req.p.ssh;
2663   struct ssh_conn *sshc = &conn->proto.sshc;
2664   CURLcode result;
2665
2666   /*
2667    * Support some of the "FTP" commands
2668    */
2669   char *cmd = sshc->quote_item->data;
2670   sshc->acceptfail = FALSE;
2671
2672   /* if a command starts with an asterisk, which a legal SFTP command never
2673      can, the command will be allowed to fail without it causing any
2674      aborts or cancels etc. It will cause libcurl to act as if the command
2675      is successful, whatever the server reponds. */
2676
2677   if(cmd[0] == '*') {
2678     cmd++;
2679     sshc->acceptfail = TRUE;
2680   }
2681
2682   if(strcasecompare("pwd", cmd)) {
2683     /* output debug output if that is requested */
2684     char *tmp = aprintf("257 \"%s\" is current directory.\n",
2685                         protop->path);
2686     if(!tmp) {
2687       sshc->actualcode = CURLE_OUT_OF_MEMORY;
2688       state(data, SSH_SFTP_CLOSE);
2689       sshc->nextstate = SSH_NO_STATE;
2690       return;
2691     }
2692     Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
2693     Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
2694
2695     /* this sends an FTP-like "header" to the header callback so that the
2696        current directory can be read very similar to how it is read when
2697        using ordinary FTP. */
2698     result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
2699     free(tmp);
2700     if(result) {
2701       state(data, SSH_SFTP_CLOSE);
2702       sshc->nextstate = SSH_NO_STATE;
2703       sshc->actualcode = result;
2704     }
2705     else
2706       state(data, SSH_SFTP_NEXT_QUOTE);
2707     return;
2708   }
2709
2710   /*
2711    * the arguments following the command must be separated from the
2712    * command with a space so we can check for it unconditionally
2713    */
2714   cp = strchr(cmd, ' ');
2715   if(!cp) {
2716     failf(data, "Syntax error in SFTP command. Supply parameter(s)");
2717     state(data, SSH_SFTP_CLOSE);
2718     sshc->nextstate = SSH_NO_STATE;
2719     sshc->actualcode = CURLE_QUOTE_ERROR;
2720     return;
2721   }
2722
2723   /*
2724    * also, every command takes at least one argument so we get that
2725    * first argument right now
2726    */
2727   result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
2728   if(result) {
2729     if(result == CURLE_OUT_OF_MEMORY)
2730       failf(data, "Out of memory");
2731     else
2732       failf(data, "Syntax error: Bad first parameter");
2733     state(data, SSH_SFTP_CLOSE);
2734     sshc->nextstate = SSH_NO_STATE;
2735     sshc->actualcode = result;
2736     return;
2737   }
2738
2739   /*
2740    * SFTP is a binary protocol, so we don't send text commands
2741    * to the server. Instead, we scan for commands used by
2742    * OpenSSH's sftp program and call the appropriate libssh
2743    * functions.
2744    */
2745   if(strncasecompare(cmd, "chgrp ", 6) ||
2746      strncasecompare(cmd, "chmod ", 6) ||
2747      strncasecompare(cmd, "chown ", 6) ||
2748      strncasecompare(cmd, "atime ", 6) ||
2749      strncasecompare(cmd, "mtime ", 6)) {
2750     /* attribute change */
2751
2752     /* sshc->quote_path1 contains the mode to set */
2753     /* get the destination */
2754     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
2755     if(result) {
2756       if(result == CURLE_OUT_OF_MEMORY)
2757         failf(data, "Out of memory");
2758       else
2759         failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
2760               "Bad second parameter");
2761       Curl_safefree(sshc->quote_path1);
2762       state(data, SSH_SFTP_CLOSE);
2763       sshc->nextstate = SSH_NO_STATE;
2764       sshc->actualcode = result;
2765       return;
2766     }
2767     sshc->quote_attrs = NULL;
2768     state(data, SSH_SFTP_QUOTE_STAT);
2769     return;
2770   }
2771   if(strncasecompare(cmd, "ln ", 3) ||
2772      strncasecompare(cmd, "symlink ", 8)) {
2773     /* symbolic linking */
2774     /* sshc->quote_path1 is the source */
2775     /* get the destination */
2776     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
2777     if(result) {
2778       if(result == CURLE_OUT_OF_MEMORY)
2779         failf(data, "Out of memory");
2780       else
2781         failf(data, "Syntax error in ln/symlink: Bad second parameter");
2782       Curl_safefree(sshc->quote_path1);
2783       state(data, SSH_SFTP_CLOSE);
2784       sshc->nextstate = SSH_NO_STATE;
2785       sshc->actualcode = result;
2786       return;
2787     }
2788     state(data, SSH_SFTP_QUOTE_SYMLINK);
2789     return;
2790   }
2791   else if(strncasecompare(cmd, "mkdir ", 6)) {
2792     /* create dir */
2793     state(data, SSH_SFTP_QUOTE_MKDIR);
2794     return;
2795   }
2796   else if(strncasecompare(cmd, "rename ", 7)) {
2797     /* rename file */
2798     /* first param is the source path */
2799     /* second param is the dest. path */
2800     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
2801     if(result) {
2802       if(result == CURLE_OUT_OF_MEMORY)
2803         failf(data, "Out of memory");
2804       else
2805         failf(data, "Syntax error in rename: Bad second parameter");
2806       Curl_safefree(sshc->quote_path1);
2807       state(data, SSH_SFTP_CLOSE);
2808       sshc->nextstate = SSH_NO_STATE;
2809       sshc->actualcode = result;
2810       return;
2811     }
2812     state(data, SSH_SFTP_QUOTE_RENAME);
2813     return;
2814   }
2815   else if(strncasecompare(cmd, "rmdir ", 6)) {
2816     /* delete dir */
2817     state(data, SSH_SFTP_QUOTE_RMDIR);
2818     return;
2819   }
2820   else if(strncasecompare(cmd, "rm ", 3)) {
2821     state(data, SSH_SFTP_QUOTE_UNLINK);
2822     return;
2823   }
2824 #ifdef HAS_STATVFS_SUPPORT
2825   else if(strncasecompare(cmd, "statvfs ", 8)) {
2826     state(data, SSH_SFTP_QUOTE_STATVFS);
2827     return;
2828   }
2829 #endif
2830
2831   failf(data, "Unknown SFTP command");
2832   Curl_safefree(sshc->quote_path1);
2833   Curl_safefree(sshc->quote_path2);
2834   state(data, SSH_SFTP_CLOSE);
2835   sshc->nextstate = SSH_NO_STATE;
2836   sshc->actualcode = CURLE_QUOTE_ERROR;
2837 }
2838
2839 static void sftp_quote_stat(struct Curl_easy *data)
2840 {
2841   struct connectdata *conn = data->conn;
2842   struct ssh_conn *sshc = &conn->proto.sshc;
2843   char *cmd = sshc->quote_item->data;
2844   sshc->acceptfail = FALSE;
2845
2846   /* if a command starts with an asterisk, which a legal SFTP command never
2847      can, the command will be allowed to fail without it causing any
2848      aborts or cancels etc. It will cause libcurl to act as if the command
2849      is successful, whatever the server reponds. */
2850
2851   if(cmd[0] == '*') {
2852     cmd++;
2853     sshc->acceptfail = TRUE;
2854   }
2855
2856   /* We read the file attributes, store them in sshc->quote_attrs
2857    * and modify them accordingly to command. Then we switch to
2858    * QUOTE_SETSTAT state to write new ones.
2859    */
2860
2861   if(sshc->quote_attrs)
2862     sftp_attributes_free(sshc->quote_attrs);
2863   sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
2864   if(!sshc->quote_attrs) {
2865     Curl_safefree(sshc->quote_path1);
2866     Curl_safefree(sshc->quote_path2);
2867     failf(data, "Attempt to get SFTP stats failed: %d",
2868           sftp_get_error(sshc->sftp_session));
2869     state(data, SSH_SFTP_CLOSE);
2870     sshc->nextstate = SSH_NO_STATE;
2871     sshc->actualcode = CURLE_QUOTE_ERROR;
2872     return;
2873   }
2874
2875   /* Now set the new attributes... */
2876   if(strncasecompare(cmd, "chgrp", 5)) {
2877     sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
2878     if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
2879         !sshc->acceptfail) {
2880       Curl_safefree(sshc->quote_path1);
2881       Curl_safefree(sshc->quote_path2);
2882       failf(data, "Syntax error: chgrp gid not a number");
2883       state(data, SSH_SFTP_CLOSE);
2884       sshc->nextstate = SSH_NO_STATE;
2885       sshc->actualcode = CURLE_QUOTE_ERROR;
2886       return;
2887     }
2888     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
2889   }
2890   else if(strncasecompare(cmd, "chmod", 5)) {
2891     mode_t perms;
2892     perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
2893     /* permissions are octal */
2894     if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
2895       Curl_safefree(sshc->quote_path1);
2896       Curl_safefree(sshc->quote_path2);
2897       failf(data, "Syntax error: chmod permissions not a number");
2898       state(data, SSH_SFTP_CLOSE);
2899       sshc->nextstate = SSH_NO_STATE;
2900       sshc->actualcode = CURLE_QUOTE_ERROR;
2901       return;
2902     }
2903     sshc->quote_attrs->permissions = perms;
2904     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
2905   }
2906   else if(strncasecompare(cmd, "chown", 5)) {
2907     sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
2908     if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
2909         !sshc->acceptfail) {
2910       Curl_safefree(sshc->quote_path1);
2911       Curl_safefree(sshc->quote_path2);
2912       failf(data, "Syntax error: chown uid not a number");
2913       state(data, SSH_SFTP_CLOSE);
2914       sshc->nextstate = SSH_NO_STATE;
2915       sshc->actualcode = CURLE_QUOTE_ERROR;
2916       return;
2917     }
2918     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
2919   }
2920   else if(strncasecompare(cmd, "atime", 5) ||
2921           strncasecompare(cmd, "mtime", 5)) {
2922     time_t date = Curl_getdate_capped(sshc->quote_path1);
2923     bool fail = FALSE;
2924     if(date == -1) {
2925       failf(data, "incorrect date format for %.*s", 5, cmd);
2926       fail = TRUE;
2927     }
2928 #if SIZEOF_TIME_T > 4
2929     else if(date > 0xffffffff) {
2930       failf(data, "date overflow");
2931       fail = TRUE; /* avoid setting a capped time */
2932     }
2933 #endif
2934     if(fail) {
2935       Curl_safefree(sshc->quote_path1);
2936       Curl_safefree(sshc->quote_path2);
2937       state(data, SSH_SFTP_CLOSE);
2938       sshc->nextstate = SSH_NO_STATE;
2939       sshc->actualcode = CURLE_QUOTE_ERROR;
2940       return;
2941     }
2942     if(strncasecompare(cmd, "atime", 5))
2943       sshc->quote_attrs->atime = (uint32_t)date;
2944     else /* mtime */
2945       sshc->quote_attrs->mtime = (uint32_t)date;
2946
2947     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
2948   }
2949
2950   /* Now send the completed structure... */
2951   state(data, SSH_SFTP_QUOTE_SETSTAT);
2952   return;
2953 }
2954
2955 CURLcode Curl_ssh_init(void)
2956 {
2957   if(ssh_init()) {
2958     DEBUGF(fprintf(stderr, "Error: libssh_init failed\n"));
2959     return CURLE_FAILED_INIT;
2960   }
2961   return CURLE_OK;
2962 }
2963
2964 void Curl_ssh_cleanup(void)
2965 {
2966   (void)ssh_finalize();
2967 }
2968
2969 void Curl_ssh_version(char *buffer, size_t buflen)
2970 {
2971   (void)msnprintf(buffer, buflen, "libssh/%s", ssh_version(0));
2972 }
2973
2974 #endif                          /* USE_LIBSSH */