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