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