xref: /curl/lib/vssh/libssh2.c (revision 876047d1)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 
25 /* #define CURL_LIBSSH2_DEBUG */
26 
27 #include "curl_setup.h"
28 
29 #ifdef USE_LIBSSH2
30 
31 #include <limits.h>
32 
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36 
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43 #ifdef HAVE_NETDB_H
44 #include <netdb.h>
45 #endif
46 #ifdef __VMS
47 #include <in.h>
48 #include <inet.h>
49 #endif
50 
51 #include <curl/curl.h>
52 #include "urldata.h"
53 #include "sendf.h"
54 #include "hostip.h"
55 #include "progress.h"
56 #include "transfer.h"
57 #include "escape.h"
58 #include "http.h" /* for HTTP proxy tunnel stuff */
59 #include "ssh.h"
60 #include "url.h"
61 #include "speedcheck.h"
62 #include "getinfo.h"
63 #include "strdup.h"
64 #include "strcase.h"
65 #include "vtls/vtls.h"
66 #include "cfilters.h"
67 #include "connect.h"
68 #include "inet_ntop.h"
69 #include "parsedate.h" /* for the week day and month names */
70 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
71 #include "strtoofft.h"
72 #include "multiif.h"
73 #include "select.h"
74 #include "warnless.h"
75 #include "curl_path.h"
76 
77 #include <curl_base64.h> /* for base64 encoding/decoding */
78 #include <curl_sha256.h>
79 
80 
81 /* The last 3 #include files should be in this order */
82 #include "curl_printf.h"
83 #include "curl_memory.h"
84 #include "memdebug.h"
85 
86 #if LIBSSH2_VERSION_NUM >= 0x010206
87 /* libssh2_sftp_statvfs and friends were added in 1.2.6 */
88 #define HAS_STATVFS_SUPPORT 1
89 #endif
90 
91 #define sftp_libssh2_realpath(s,p,t,m)                          \
92   libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)),    \
93                           (t), (m), LIBSSH2_SFTP_REALPATH)
94 
95 /* Local functions: */
96 static const char *sftp_libssh2_strerror(unsigned long err);
97 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
98 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
99 static LIBSSH2_FREE_FUNC(my_libssh2_free);
100 static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
101 static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
102 static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
103 static CURLcode ssh_do(struct Curl_easy *data, bool *done);
104 static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);
105 static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
106 static CURLcode scp_disconnect(struct Curl_easy *data,
107                                struct connectdata *conn, bool dead_connection);
108 static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);
109 static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);
110 static CURLcode sftp_disconnect(struct Curl_easy *data,
111                                 struct connectdata *conn, bool dead);
112 static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
113                              bool *dophase_done);
114 static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
115                        curl_socket_t *sock);
116 static CURLcode ssh_setup_connection(struct Curl_easy *data,
117                                      struct connectdata *conn);
118 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn);
119 
120 /*
121  * SCP protocol handler.
122  */
123 
124 const struct Curl_handler Curl_handler_scp = {
125   "SCP",                                /* scheme */
126   ssh_setup_connection,                 /* setup_connection */
127   ssh_do,                               /* do_it */
128   scp_done,                             /* done */
129   ZERO_NULL,                            /* do_more */
130   ssh_connect,                          /* connect_it */
131   ssh_multi_statemach,                  /* connecting */
132   scp_doing,                            /* doing */
133   ssh_getsock,                          /* proto_getsock */
134   ssh_getsock,                          /* doing_getsock */
135   ZERO_NULL,                            /* domore_getsock */
136   ssh_getsock,                          /* perform_getsock */
137   scp_disconnect,                       /* disconnect */
138   ZERO_NULL,                            /* write_resp */
139   ZERO_NULL,                            /* write_resp_hd */
140   ZERO_NULL,                            /* connection_check */
141   ssh_attach,                           /* attach */
142   PORT_SSH,                             /* defport */
143   CURLPROTO_SCP,                        /* protocol */
144   CURLPROTO_SCP,                        /* family */
145   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
146   | PROTOPT_NOURLQUERY                  /* flags */
147 };
148 
149 
150 /*
151  * SFTP protocol handler.
152  */
153 
154 const struct Curl_handler Curl_handler_sftp = {
155   "SFTP",                               /* scheme */
156   ssh_setup_connection,                 /* setup_connection */
157   ssh_do,                               /* do_it */
158   sftp_done,                            /* done */
159   ZERO_NULL,                            /* do_more */
160   ssh_connect,                          /* connect_it */
161   ssh_multi_statemach,                  /* connecting */
162   sftp_doing,                           /* doing */
163   ssh_getsock,                          /* proto_getsock */
164   ssh_getsock,                          /* doing_getsock */
165   ZERO_NULL,                            /* domore_getsock */
166   ssh_getsock,                          /* perform_getsock */
167   sftp_disconnect,                      /* disconnect */
168   ZERO_NULL,                            /* write_resp */
169   ZERO_NULL,                            /* write_resp_hd */
170   ZERO_NULL,                            /* connection_check */
171   ssh_attach,                           /* attach */
172   PORT_SSH,                             /* defport */
173   CURLPROTO_SFTP,                       /* protocol */
174   CURLPROTO_SFTP,                       /* family */
175   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
176   | PROTOPT_NOURLQUERY                  /* flags */
177 };
178 
179 static void
kbd_callback(const char * name,int name_len,const char * instruction,int instruction_len,int num_prompts,const LIBSSH2_USERAUTH_KBDINT_PROMPT * prompts,LIBSSH2_USERAUTH_KBDINT_RESPONSE * responses,void ** abstract)180 kbd_callback(const char *name, int name_len, const char *instruction,
181              int instruction_len, int num_prompts,
182              const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
183              LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
184              void **abstract)
185 {
186   struct Curl_easy *data = (struct Curl_easy *)*abstract;
187 
188 #ifdef CURL_LIBSSH2_DEBUG
189   fprintf(stderr, "name=%s\n", name);
190   fprintf(stderr, "name_len=%d\n", name_len);
191   fprintf(stderr, "instruction=%s\n", instruction);
192   fprintf(stderr, "instruction_len=%d\n", instruction_len);
193   fprintf(stderr, "num_prompts=%d\n", num_prompts);
194 #else
195   (void)name;
196   (void)name_len;
197   (void)instruction;
198   (void)instruction_len;
199 #endif  /* CURL_LIBSSH2_DEBUG */
200   if(num_prompts == 1) {
201     struct connectdata *conn = data->conn;
202     responses[0].text = strdup(conn->passwd);
203     responses[0].length =
204       responses[0].text == NULL ? 0 : curlx_uztoui(strlen(conn->passwd));
205   }
206   (void)prompts;
207 } /* kbd_callback */
208 
sftp_libssh2_error_to_CURLE(unsigned long err)209 static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
210 {
211   switch(err) {
212     case LIBSSH2_FX_OK:
213       return CURLE_OK;
214 
215     case LIBSSH2_FX_NO_SUCH_FILE:
216     case LIBSSH2_FX_NO_SUCH_PATH:
217       return CURLE_REMOTE_FILE_NOT_FOUND;
218 
219     case LIBSSH2_FX_PERMISSION_DENIED:
220     case LIBSSH2_FX_WRITE_PROTECT:
221     case LIBSSH2_FX_LOCK_CONFlICT:
222       return CURLE_REMOTE_ACCESS_DENIED;
223 
224     case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
225     case LIBSSH2_FX_QUOTA_EXCEEDED:
226       return CURLE_REMOTE_DISK_FULL;
227 
228     case LIBSSH2_FX_FILE_ALREADY_EXISTS:
229       return CURLE_REMOTE_FILE_EXISTS;
230 
231     case LIBSSH2_FX_DIR_NOT_EMPTY:
232       return CURLE_QUOTE_ERROR;
233 
234     default:
235       break;
236   }
237 
238   return CURLE_SSH;
239 }
240 
libssh2_session_error_to_CURLE(int err)241 static CURLcode libssh2_session_error_to_CURLE(int err)
242 {
243   switch(err) {
244     /* Ordered by order of appearance in libssh2.h */
245     case LIBSSH2_ERROR_NONE:
246       return CURLE_OK;
247 
248     /* This is the error returned by libssh2_scp_recv2
249      * on unknown file */
250     case LIBSSH2_ERROR_SCP_PROTOCOL:
251       return CURLE_REMOTE_FILE_NOT_FOUND;
252 
253     case LIBSSH2_ERROR_SOCKET_NONE:
254       return CURLE_COULDNT_CONNECT;
255 
256     case LIBSSH2_ERROR_ALLOC:
257       return CURLE_OUT_OF_MEMORY;
258 
259     case LIBSSH2_ERROR_SOCKET_SEND:
260       return CURLE_SEND_ERROR;
261 
262     case LIBSSH2_ERROR_HOSTKEY_INIT:
263     case LIBSSH2_ERROR_HOSTKEY_SIGN:
264     case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
265     case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
266       return CURLE_PEER_FAILED_VERIFICATION;
267 
268     case LIBSSH2_ERROR_PASSWORD_EXPIRED:
269       return CURLE_LOGIN_DENIED;
270 
271     case LIBSSH2_ERROR_SOCKET_TIMEOUT:
272     case LIBSSH2_ERROR_TIMEOUT:
273       return CURLE_OPERATION_TIMEDOUT;
274 
275     case LIBSSH2_ERROR_EAGAIN:
276       return CURLE_AGAIN;
277   }
278 
279   return CURLE_SSH;
280 }
281 
282 /* These functions are made to use the libcurl memory functions - NOT the
283    debugmem functions, as that leads us to trigger on libssh2 memory leaks
284    that are not ours to care for */
285 
LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)286 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
287 {
288   (void)abstract; /* arg not used */
289   return Curl_cmalloc(count);
290 }
291 
LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)292 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
293 {
294   (void)abstract; /* arg not used */
295   return Curl_crealloc(ptr, count);
296 }
297 
LIBSSH2_FREE_FUNC(my_libssh2_free)298 static LIBSSH2_FREE_FUNC(my_libssh2_free)
299 {
300   (void)abstract; /* arg not used */
301   if(ptr) /* ssh2 agent sometimes call free with null ptr */
302     Curl_cfree(ptr);
303 }
304 
305 /*
306  * SSH State machine related code
307  */
308 /* This is the ONLY way to change SSH state! */
state(struct Curl_easy * data,sshstate nowstate)309 static void state(struct Curl_easy *data, sshstate nowstate)
310 {
311   struct connectdata *conn = data->conn;
312   struct ssh_conn *sshc = &conn->proto.sshc;
313 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
314   /* for debug purposes */
315   static const char * const names[] = {
316     "SSH_STOP",
317     "SSH_INIT",
318     "SSH_S_STARTUP",
319     "SSH_HOSTKEY",
320     "SSH_AUTHLIST",
321     "SSH_AUTH_PKEY_INIT",
322     "SSH_AUTH_PKEY",
323     "SSH_AUTH_PASS_INIT",
324     "SSH_AUTH_PASS",
325     "SSH_AUTH_AGENT_INIT",
326     "SSH_AUTH_AGENT_LIST",
327     "SSH_AUTH_AGENT",
328     "SSH_AUTH_HOST_INIT",
329     "SSH_AUTH_HOST",
330     "SSH_AUTH_KEY_INIT",
331     "SSH_AUTH_KEY",
332     "SSH_AUTH_GSSAPI",
333     "SSH_AUTH_DONE",
334     "SSH_SFTP_INIT",
335     "SSH_SFTP_REALPATH",
336     "SSH_SFTP_QUOTE_INIT",
337     "SSH_SFTP_POSTQUOTE_INIT",
338     "SSH_SFTP_QUOTE",
339     "SSH_SFTP_NEXT_QUOTE",
340     "SSH_SFTP_QUOTE_STAT",
341     "SSH_SFTP_QUOTE_SETSTAT",
342     "SSH_SFTP_QUOTE_SYMLINK",
343     "SSH_SFTP_QUOTE_MKDIR",
344     "SSH_SFTP_QUOTE_RENAME",
345     "SSH_SFTP_QUOTE_RMDIR",
346     "SSH_SFTP_QUOTE_UNLINK",
347     "SSH_SFTP_QUOTE_STATVFS",
348     "SSH_SFTP_GETINFO",
349     "SSH_SFTP_FILETIME",
350     "SSH_SFTP_TRANS_INIT",
351     "SSH_SFTP_UPLOAD_INIT",
352     "SSH_SFTP_CREATE_DIRS_INIT",
353     "SSH_SFTP_CREATE_DIRS",
354     "SSH_SFTP_CREATE_DIRS_MKDIR",
355     "SSH_SFTP_READDIR_INIT",
356     "SSH_SFTP_READDIR",
357     "SSH_SFTP_READDIR_LINK",
358     "SSH_SFTP_READDIR_BOTTOM",
359     "SSH_SFTP_READDIR_DONE",
360     "SSH_SFTP_DOWNLOAD_INIT",
361     "SSH_SFTP_DOWNLOAD_STAT",
362     "SSH_SFTP_CLOSE",
363     "SSH_SFTP_SHUTDOWN",
364     "SSH_SCP_TRANS_INIT",
365     "SSH_SCP_UPLOAD_INIT",
366     "SSH_SCP_DOWNLOAD_INIT",
367     "SSH_SCP_DOWNLOAD",
368     "SSH_SCP_DONE",
369     "SSH_SCP_SEND_EOF",
370     "SSH_SCP_WAIT_EOF",
371     "SSH_SCP_WAIT_CLOSE",
372     "SSH_SCP_CHANNEL_FREE",
373     "SSH_SESSION_DISCONNECT",
374     "SSH_SESSION_FREE",
375     "QUIT"
376   };
377 
378   /* a precaution to make sure the lists are in sync */
379   DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
380 
381   if(sshc->state != nowstate) {
382     infof(data, "SFTP %p state change from %s to %s",
383           (void *)sshc, names[sshc->state], names[nowstate]);
384   }
385 #endif
386 
387   sshc->state = nowstate;
388 }
389 
390 
391 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
sshkeycallback(struct Curl_easy * easy,const struct curl_khkey * knownkey,const struct curl_khkey * foundkey,enum curl_khmatch match,void * clientp)392 static int sshkeycallback(struct Curl_easy *easy,
393                           const struct curl_khkey *knownkey, /* known */
394                           const struct curl_khkey *foundkey, /* found */
395                           enum curl_khmatch match,
396                           void *clientp)
397 {
398   (void)easy;
399   (void)knownkey;
400   (void)foundkey;
401   (void)clientp;
402 
403   /* we only allow perfect matches, and we reject everything else */
404   return (match != CURLKHMATCH_OK) ? CURLKHSTAT_REJECT : CURLKHSTAT_FINE;
405 }
406 #endif
407 
408 /*
409  * Earlier libssh2 versions did not have the ability to seek to 64-bit
410  * positions with 32-bit size_t.
411  */
412 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
413 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
414 #else
415 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
416 #endif
417 
418 /*
419  * Earlier libssh2 versions did not do SCP properly beyond 32-bit sizes on
420  * 32-bit architectures so we check of the necessary function is present.
421  */
422 #ifndef HAVE_LIBSSH2_SCP_SEND64
423 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
424 #else
425 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c),            \
426                                              (libssh2_int64_t)d, 0, 0)
427 #endif
428 
429 /*
430  * libssh2 1.2.8 fixed the problem with 32-bit ints used for sockets on win64.
431  */
432 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
433 #define session_startup(x,y) libssh2_session_handshake(x, y)
434 #else
435 #define session_startup(x,y) libssh2_session_startup(x, (int)y)
436 #endif
convert_ssh2_keytype(int sshkeytype)437 static enum curl_khtype convert_ssh2_keytype(int sshkeytype)
438 {
439   enum curl_khtype keytype = CURLKHTYPE_UNKNOWN;
440   switch(sshkeytype) {
441   case LIBSSH2_HOSTKEY_TYPE_RSA:
442     keytype = CURLKHTYPE_RSA;
443     break;
444   case LIBSSH2_HOSTKEY_TYPE_DSS:
445     keytype = CURLKHTYPE_DSS;
446     break;
447 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
448   case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
449     keytype = CURLKHTYPE_ECDSA;
450     break;
451 #endif
452 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
453   case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
454     keytype = CURLKHTYPE_ECDSA;
455     break;
456 #endif
457 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
458   case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
459     keytype = CURLKHTYPE_ECDSA;
460     break;
461 #endif
462 #ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
463   case LIBSSH2_HOSTKEY_TYPE_ED25519:
464     keytype = CURLKHTYPE_ED25519;
465     break;
466 #endif
467   }
468   return keytype;
469 }
470 
ssh_knownhost(struct Curl_easy * data)471 static CURLcode ssh_knownhost(struct Curl_easy *data)
472 {
473   int sshkeytype = 0;
474   size_t keylen = 0;
475   int rc = 0;
476   CURLcode result = CURLE_OK;
477 
478 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
479   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
480     /* we are asked to verify the host against a file */
481     struct connectdata *conn = data->conn;
482     struct ssh_conn *sshc = &conn->proto.sshc;
483     struct libssh2_knownhost *host = NULL;
484     const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
485                                                     &keylen, &sshkeytype);
486     int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
487     int keybit = 0;
488 
489     if(remotekey) {
490       /*
491        * A subject to figure out is what hostname we need to pass in here.
492        * What hostname does OpenSSH store in its file if an IDN name is
493        * used?
494        */
495       enum curl_khmatch keymatch;
496       curl_sshkeycallback func =
497         data->set.ssh_keyfunc ? data->set.ssh_keyfunc : sshkeycallback;
498       struct curl_khkey knownkey;
499       struct curl_khkey *knownkeyp = NULL;
500       struct curl_khkey foundkey;
501 
502       switch(sshkeytype) {
503       case LIBSSH2_HOSTKEY_TYPE_RSA:
504         keybit = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
505         break;
506       case LIBSSH2_HOSTKEY_TYPE_DSS:
507         keybit = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
508         break;
509 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
510       case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
511         keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_256;
512         break;
513 #endif
514 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
515       case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
516         keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_384;
517         break;
518 #endif
519 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
520       case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
521         keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_521;
522         break;
523 #endif
524 #ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
525       case LIBSSH2_HOSTKEY_TYPE_ED25519:
526         keybit = LIBSSH2_KNOWNHOST_KEY_ED25519;
527         break;
528 #endif
529       default:
530         infof(data, "unsupported key type, cannot check knownhosts");
531         keybit = 0;
532         break;
533       }
534       if(!keybit)
535         /* no check means failure! */
536         rc = CURLKHSTAT_REJECT;
537       else {
538 #ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
539         keycheck = libssh2_knownhost_checkp(sshc->kh,
540                                             conn->host.name,
541                                             (conn->remote_port != PORT_SSH) ?
542                                             conn->remote_port : -1,
543                                             remotekey, keylen,
544                                             LIBSSH2_KNOWNHOST_TYPE_PLAIN|
545                                             LIBSSH2_KNOWNHOST_KEYENC_RAW|
546                                             keybit,
547                                             &host);
548 #else
549         keycheck = libssh2_knownhost_check(sshc->kh,
550                                            conn->host.name,
551                                            remotekey, keylen,
552                                            LIBSSH2_KNOWNHOST_TYPE_PLAIN|
553                                            LIBSSH2_KNOWNHOST_KEYENC_RAW|
554                                            keybit,
555                                            &host);
556 #endif
557 
558         infof(data, "SSH host check: %d, key: %s", keycheck,
559               (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) ?
560               host->key : "<none>");
561 
562         /* setup 'knownkey' */
563         if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
564           knownkey.key = host->key;
565           knownkey.len = 0;
566           knownkey.keytype = convert_ssh2_keytype(sshkeytype);
567           knownkeyp = &knownkey;
568         }
569 
570         /* setup 'foundkey' */
571         foundkey.key = remotekey;
572         foundkey.len = keylen;
573         foundkey.keytype = convert_ssh2_keytype(sshkeytype);
574 
575         /*
576          * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
577          * curl_khmatch enum are ever modified, we need to introduce a
578          * translation table here!
579          */
580         keymatch = (enum curl_khmatch)keycheck;
581 
582         /* Ask the callback how to behave */
583         Curl_set_in_callback(data, true);
584         rc = func(data, knownkeyp, /* from the knownhosts file */
585                   &foundkey, /* from the remote host */
586                   keymatch, data->set.ssh_keyfunc_userp);
587         Curl_set_in_callback(data, false);
588       }
589     }
590     else
591       /* no remotekey means failure! */
592       rc = CURLKHSTAT_REJECT;
593 
594     switch(rc) {
595     default: /* unknown return codes will equal reject */
596     case CURLKHSTAT_REJECT:
597       state(data, SSH_SESSION_FREE);
598       FALLTHROUGH();
599     case CURLKHSTAT_DEFER:
600       /* DEFER means bail out but keep the SSH_HOSTKEY state */
601       result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
602       break;
603     case CURLKHSTAT_FINE_REPLACE:
604       /* remove old host+key that does not match */
605       if(host)
606         libssh2_knownhost_del(sshc->kh, host);
607       FALLTHROUGH();
608     case CURLKHSTAT_FINE:
609     case CURLKHSTAT_FINE_ADD_TO_FILE:
610       /* proceed */
611       if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
612         /* the found host+key did not match but has been told to be fine
613            anyway so we add it in memory */
614         int addrc = libssh2_knownhost_add(sshc->kh,
615                                           conn->host.name, NULL,
616                                           remotekey, keylen,
617                                           LIBSSH2_KNOWNHOST_TYPE_PLAIN|
618                                           LIBSSH2_KNOWNHOST_KEYENC_RAW|
619                                           keybit, NULL);
620         if(addrc)
621           infof(data, "WARNING: adding the known host %s failed",
622                 conn->host.name);
623         else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
624                 rc == CURLKHSTAT_FINE_REPLACE) {
625           /* now we write the entire in-memory list of known hosts to the
626              known_hosts file */
627           int wrc =
628             libssh2_knownhost_writefile(sshc->kh,
629                                         data->set.str[STRING_SSH_KNOWNHOSTS],
630                                         LIBSSH2_KNOWNHOST_FILE_OPENSSH);
631           if(wrc) {
632             infof(data, "WARNING: writing %s failed",
633                   data->set.str[STRING_SSH_KNOWNHOSTS]);
634           }
635         }
636       }
637       break;
638     }
639   }
640 #else /* HAVE_LIBSSH2_KNOWNHOST_API */
641   (void)data;
642 #endif
643   return result;
644 }
645 
ssh_check_fingerprint(struct Curl_easy * data)646 static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
647 {
648   struct connectdata *conn = data->conn;
649   struct ssh_conn *sshc = &conn->proto.sshc;
650   const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
651   const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
652 
653   infof(data, "SSH MD5 public key: %s",
654     pubkey_md5 != NULL ? pubkey_md5 : "NULL");
655   infof(data, "SSH SHA256 public key: %s",
656       pubkey_sha256 != NULL ? pubkey_sha256 : "NULL");
657 
658   if(pubkey_sha256) {
659     const char *fingerprint = NULL;
660     char *fingerprint_b64 = NULL;
661     size_t fingerprint_b64_len;
662     size_t pub_pos = 0;
663     size_t b64_pos = 0;
664 
665 #ifdef LIBSSH2_HOSTKEY_HASH_SHA256
666     /* The fingerprint points to static storage (!), do not free() it. */
667     fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
668                                        LIBSSH2_HOSTKEY_HASH_SHA256);
669 #else
670     const char *hostkey;
671     size_t len = 0;
672     unsigned char hash[32];
673 
674     hostkey = libssh2_session_hostkey(sshc->ssh_session, &len, NULL);
675     if(hostkey) {
676       if(!Curl_sha256it(hash, (const unsigned char *) hostkey, len))
677         fingerprint = (char *) hash;
678     }
679 #endif
680 
681     if(!fingerprint) {
682       failf(data,
683             "Denied establishing ssh session: sha256 fingerprint "
684             "not available");
685       state(data, SSH_SESSION_FREE);
686       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
687       return sshc->actualcode;
688     }
689 
690     /* The length of fingerprint is 32 bytes for SHA256.
691      * See libssh2_hostkey_hash documentation. */
692     if(Curl_base64_encode(fingerprint, 32, &fingerprint_b64,
693                           &fingerprint_b64_len) != CURLE_OK) {
694       state(data, SSH_SESSION_FREE);
695       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
696       return sshc->actualcode;
697     }
698 
699     if(!fingerprint_b64) {
700       failf(data, "sha256 fingerprint could not be encoded");
701       state(data, SSH_SESSION_FREE);
702       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
703       return sshc->actualcode;
704     }
705 
706     infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64);
707 
708     /* Find the position of any = padding characters in the public key */
709     while((pubkey_sha256[pub_pos] != '=') && pubkey_sha256[pub_pos]) {
710       pub_pos++;
711     }
712 
713     /* Find the position of any = padding characters in the base64 coded
714      * hostkey fingerprint */
715     while((fingerprint_b64[b64_pos] != '=') && fingerprint_b64[b64_pos]) {
716       b64_pos++;
717     }
718 
719     /* Before we authenticate we check the hostkey's sha256 fingerprint
720      * against a known fingerprint, if available.
721      */
722     if((pub_pos != b64_pos) ||
723        strncmp(fingerprint_b64, pubkey_sha256, pub_pos)) {
724       failf(data,
725             "Denied establishing ssh session: mismatch sha256 fingerprint. "
726             "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
727       free(fingerprint_b64);
728       state(data, SSH_SESSION_FREE);
729       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
730       return sshc->actualcode;
731     }
732 
733     free(fingerprint_b64);
734 
735     infof(data, "SHA256 checksum match");
736   }
737 
738   if(pubkey_md5) {
739     char md5buffer[33];
740     const char *fingerprint = NULL;
741 
742     fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
743                                        LIBSSH2_HOSTKEY_HASH_MD5);
744 
745     if(fingerprint) {
746       /* The fingerprint points to static storage (!), do not free() it. */
747       int i;
748       for(i = 0; i < 16; i++) {
749         msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
750       }
751 
752       infof(data, "SSH MD5 fingerprint: %s", md5buffer);
753     }
754 
755     /* This does NOT verify the length of 'pubkey_md5' separately, which will
756        make the comparison below fail unless it is exactly 32 characters */
757     if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
758       if(fingerprint) {
759         failf(data,
760               "Denied establishing ssh session: mismatch md5 fingerprint. "
761               "Remote %s is not equal to %s", md5buffer, pubkey_md5);
762       }
763       else {
764         failf(data,
765               "Denied establishing ssh session: md5 fingerprint "
766               "not available");
767       }
768       state(data, SSH_SESSION_FREE);
769       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
770       return sshc->actualcode;
771     }
772     infof(data, "MD5 checksum match");
773   }
774 
775   if(!pubkey_md5 && !pubkey_sha256) {
776     if(data->set.ssh_hostkeyfunc) {
777       size_t keylen = 0;
778       int sshkeytype = 0;
779       int rc = 0;
780       /* we handle the process to the callback */
781       const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
782                                                       &keylen, &sshkeytype);
783       if(remotekey) {
784         enum curl_khtype keytype = convert_ssh2_keytype(sshkeytype);
785         Curl_set_in_callback(data, true);
786         rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp,
787                                        (int)keytype, remotekey, keylen);
788         Curl_set_in_callback(data, false);
789         if(rc!= CURLKHMATCH_OK) {
790           state(data, SSH_SESSION_FREE);
791           sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
792           return sshc->actualcode;
793         }
794       }
795       else {
796         state(data, SSH_SESSION_FREE);
797         sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
798         return sshc->actualcode;
799       }
800       return CURLE_OK;
801     }
802     else {
803       return ssh_knownhost(data);
804     }
805   }
806   else {
807     /* as we already matched, we skip the check for known hosts */
808     return CURLE_OK;
809   }
810 }
811 
812 /*
813  * ssh_force_knownhost_key_type() will check the known hosts file and try to
814  * force a specific public key type from the server if an entry is found.
815  */
ssh_force_knownhost_key_type(struct Curl_easy * data)816 static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
817 {
818   CURLcode result = CURLE_OK;
819 
820 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
821 
822 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
823   static const char * const hostkey_method_ssh_ed25519
824     = "ssh-ed25519";
825 #endif
826 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
827   static const char * const hostkey_method_ssh_ecdsa_521
828     = "ecdsa-sha2-nistp521";
829 #endif
830 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
831   static const char * const hostkey_method_ssh_ecdsa_384
832     = "ecdsa-sha2-nistp384";
833 #endif
834 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
835   static const char * const hostkey_method_ssh_ecdsa_256
836     = "ecdsa-sha2-nistp256";
837 #endif
838   static const char * const hostkey_method_ssh_rsa
839     = "ssh-rsa";
840   static const char * const hostkey_method_ssh_rsa_all
841     = "rsa-sha2-256,rsa-sha2-512,ssh-rsa";
842   static const char * const hostkey_method_ssh_dss
843     = "ssh-dss";
844 
845   const char *hostkey_method = NULL;
846   struct connectdata *conn = data->conn;
847   struct ssh_conn *sshc = &conn->proto.sshc;
848   struct libssh2_knownhost* store = NULL;
849   const char *kh_name_end = NULL;
850   size_t kh_name_size = 0;
851   int port = 0;
852   bool found = false;
853 
854   if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
855     /* lets try to find our host in the known hosts file */
856     while(!libssh2_knownhost_get(sshc->kh, &store, store)) {
857       /* For non-standard ports, the name will be enclosed in */
858       /* square brackets, followed by a colon and the port */
859       if(store) {
860         if(store->name) {
861           if(store->name[0] == '[') {
862             kh_name_end = strstr(store->name, "]:");
863             if(!kh_name_end) {
864               infof(data, "Invalid host pattern %s in %s",
865                     store->name, data->set.str[STRING_SSH_KNOWNHOSTS]);
866               continue;
867             }
868             port = atoi(kh_name_end + 2);
869             if(kh_name_end && (port == conn->remote_port)) {
870               kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end);
871               if(strncmp(store->name + 1,
872                  conn->host.name, kh_name_size) == 0) {
873                 found = true;
874                 break;
875               }
876             }
877           }
878           else if(strcmp(store->name, conn->host.name) == 0) {
879             found = true;
880             break;
881           }
882         }
883         else {
884           found = true;
885           break;
886         }
887       }
888     }
889 
890     if(found) {
891       int rc;
892       infof(data, "Found host %s in %s",
893             conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
894 
895       switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
896 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
897       case LIBSSH2_KNOWNHOST_KEY_ED25519:
898         hostkey_method = hostkey_method_ssh_ed25519;
899         break;
900 #endif
901 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
902       case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
903         hostkey_method = hostkey_method_ssh_ecdsa_521;
904         break;
905 #endif
906 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
907       case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
908         hostkey_method = hostkey_method_ssh_ecdsa_384;
909         break;
910 #endif
911 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
912       case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
913         hostkey_method = hostkey_method_ssh_ecdsa_256;
914         break;
915 #endif
916       case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
917 #ifdef HAVE_LIBSSH2_VERSION
918         if(libssh2_version(0x010900))
919           /* since 1.9.0 libssh2_session_method_pref() works as expected */
920           hostkey_method = hostkey_method_ssh_rsa_all;
921         else
922 #endif
923           /* old libssh2 which cannot correctly remove unsupported methods due
924            * to bug in src/kex.c or does not support the new methods anyways.
925            */
926           hostkey_method = hostkey_method_ssh_rsa;
927         break;
928       case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
929         hostkey_method = hostkey_method_ssh_dss;
930         break;
931       case LIBSSH2_KNOWNHOST_KEY_RSA1:
932         failf(data, "Found host key type RSA1 which is not supported");
933         return CURLE_SSH;
934       default:
935         failf(data, "Unknown host key type: %i",
936               (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
937         return CURLE_SSH;
938       }
939 
940       infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method);
941       rc = libssh2_session_method_pref(sshc->ssh_session,
942                                        LIBSSH2_METHOD_HOSTKEY, hostkey_method);
943       if(rc) {
944         char *errmsg = NULL;
945         int errlen;
946         libssh2_session_last_error(sshc->ssh_session, &errmsg, &errlen, 0);
947         failf(data, "libssh2: %s", errmsg);
948         result = libssh2_session_error_to_CURLE(rc);
949       }
950     }
951     else {
952       infof(data, "Did not find host %s in %s",
953             conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
954     }
955   }
956 
957 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
958 
959   return result;
960 }
961 
962 /*
963  * ssh_statemach_act() runs the SSH state machine as far as it can without
964  * blocking and without reaching the end. The data the pointer 'block' points
965  * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
966  * meaning it wants to be called again when the socket is ready
967  */
968 
ssh_statemach_act(struct Curl_easy * data,bool * block)969 static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
970 {
971   CURLcode result = CURLE_OK;
972   struct connectdata *conn = data->conn;
973   struct SSHPROTO *sshp = data->req.p.ssh;
974   struct ssh_conn *sshc = &conn->proto.sshc;
975   curl_socket_t sock = conn->sock[FIRSTSOCKET];
976   int rc = LIBSSH2_ERROR_NONE;
977   int ssherr;
978   unsigned long sftperr;
979   int seekerr = CURL_SEEKFUNC_OK;
980   size_t readdir_len;
981   *block = 0; /* we are not blocking by default */
982 
983   do {
984     switch(sshc->state) {
985     case SSH_INIT:
986       sshc->secondCreateDirs = 0;
987       sshc->nextstate = SSH_NO_STATE;
988       sshc->actualcode = CURLE_OK;
989 
990       /* Set libssh2 to non-blocking, since everything internally is
991          non-blocking */
992       libssh2_session_set_blocking(sshc->ssh_session, 0);
993 
994       result = ssh_force_knownhost_key_type(data);
995       if(result) {
996         state(data, SSH_SESSION_FREE);
997         sshc->actualcode = result;
998         break;
999       }
1000 
1001       state(data, SSH_S_STARTUP);
1002       FALLTHROUGH();
1003 
1004     case SSH_S_STARTUP:
1005       rc = session_startup(sshc->ssh_session, sock);
1006       if(rc == LIBSSH2_ERROR_EAGAIN) {
1007         break;
1008       }
1009       if(rc) {
1010         char *err_msg = NULL;
1011         (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
1012         failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
1013 
1014         state(data, SSH_SESSION_FREE);
1015         sshc->actualcode = CURLE_FAILED_INIT;
1016         break;
1017       }
1018 
1019       state(data, SSH_HOSTKEY);
1020 
1021       FALLTHROUGH();
1022     case SSH_HOSTKEY:
1023       /*
1024        * Before we authenticate we should check the hostkey's fingerprint
1025        * against our known hosts. How that is handled (reading from file,
1026        * whatever) is up to us.
1027        */
1028       result = ssh_check_fingerprint(data);
1029       if(!result)
1030         state(data, SSH_AUTHLIST);
1031       /* ssh_check_fingerprint sets state appropriately on error */
1032       break;
1033 
1034     case SSH_AUTHLIST:
1035       /*
1036        * Figure out authentication methods
1037        * NB: As soon as we have provided a username to an openssh server we
1038        * must never change it later. Thus, always specify the correct username
1039        * here, even though the libssh2 docs kind of indicate that it should be
1040        * possible to get a 'generic' list (not user-specific) of authentication
1041        * methods, presumably with a blank username. That will not work in my
1042        * experience.
1043        * So always specify it here.
1044        */
1045       sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
1046                                              conn->user,
1047                                              curlx_uztoui(strlen(conn->user)));
1048 
1049       if(!sshc->authlist) {
1050         if(libssh2_userauth_authenticated(sshc->ssh_session)) {
1051           sshc->authed = TRUE;
1052           infof(data, "SSH user accepted with no authentication");
1053           state(data, SSH_AUTH_DONE);
1054           break;
1055         }
1056         ssherr = libssh2_session_last_errno(sshc->ssh_session);
1057         if(ssherr == LIBSSH2_ERROR_EAGAIN)
1058           rc = LIBSSH2_ERROR_EAGAIN;
1059         else {
1060           state(data, SSH_SESSION_FREE);
1061           sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
1062         }
1063         break;
1064       }
1065       infof(data, "SSH authentication methods available: %s",
1066             sshc->authlist);
1067 
1068       state(data, SSH_AUTH_PKEY_INIT);
1069       break;
1070 
1071     case SSH_AUTH_PKEY_INIT:
1072       /*
1073        * Check the supported auth types in the order I feel is most secure
1074        * with the requested type of authentication
1075        */
1076       sshc->authed = FALSE;
1077 
1078       if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
1079          (strstr(sshc->authlist, "publickey") != NULL)) {
1080         bool out_of_memory = FALSE;
1081 
1082         sshc->rsa_pub = sshc->rsa = NULL;
1083 
1084         if(data->set.str[STRING_SSH_PRIVATE_KEY])
1085           sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
1086         else {
1087           /* To ponder about: should really the lib be messing about with the
1088              HOME environment variable etc? */
1089           char *home = curl_getenv("HOME");
1090           struct_stat sbuf;
1091 
1092           /* If no private key file is specified, try some common paths. */
1093           if(home) {
1094             /* Try ~/.ssh first. */
1095             sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
1096             if(!sshc->rsa)
1097               out_of_memory = TRUE;
1098             else if(stat(sshc->rsa, &sbuf)) {
1099               Curl_safefree(sshc->rsa);
1100               sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
1101               if(!sshc->rsa)
1102                 out_of_memory = TRUE;
1103               else if(stat(sshc->rsa, &sbuf)) {
1104                 Curl_safefree(sshc->rsa);
1105               }
1106             }
1107             free(home);
1108           }
1109           if(!out_of_memory && !sshc->rsa) {
1110             /* Nothing found; try the current dir. */
1111             sshc->rsa = strdup("id_rsa");
1112             if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
1113               Curl_safefree(sshc->rsa);
1114               sshc->rsa = strdup("id_dsa");
1115               if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
1116                 Curl_safefree(sshc->rsa);
1117                 /* Out of guesses. Set to the empty string to avoid
1118                  * surprising info messages. */
1119                 sshc->rsa = strdup("");
1120               }
1121             }
1122           }
1123         }
1124 
1125         /*
1126          * Unless the user explicitly specifies a public key file, let
1127          * libssh2 extract the public key from the private key file.
1128          * This is done by simply passing sshc->rsa_pub = NULL.
1129          */
1130         if(data->set.str[STRING_SSH_PUBLIC_KEY]
1131            /* treat empty string the same way as NULL */
1132            && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
1133           sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
1134           if(!sshc->rsa_pub)
1135             out_of_memory = TRUE;
1136         }
1137 
1138         if(out_of_memory || !sshc->rsa) {
1139           Curl_safefree(sshc->rsa);
1140           Curl_safefree(sshc->rsa_pub);
1141           state(data, SSH_SESSION_FREE);
1142           sshc->actualcode = CURLE_OUT_OF_MEMORY;
1143           break;
1144         }
1145 
1146         sshc->passphrase = data->set.ssl.key_passwd;
1147         if(!sshc->passphrase)
1148           sshc->passphrase = "";
1149 
1150         if(sshc->rsa_pub)
1151           infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
1152         infof(data, "Using SSH private key file '%s'", sshc->rsa);
1153 
1154         state(data, SSH_AUTH_PKEY);
1155       }
1156       else {
1157         state(data, SSH_AUTH_PASS_INIT);
1158       }
1159       break;
1160 
1161     case SSH_AUTH_PKEY:
1162       /* The function below checks if the files exists, no need to stat() here.
1163        */
1164       rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
1165                                                   conn->user,
1166                                                   curlx_uztoui(
1167                                                     strlen(conn->user)),
1168                                                   sshc->rsa_pub,
1169                                                   sshc->rsa, sshc->passphrase);
1170       if(rc == LIBSSH2_ERROR_EAGAIN) {
1171         break;
1172       }
1173 
1174       Curl_safefree(sshc->rsa_pub);
1175       Curl_safefree(sshc->rsa);
1176 
1177       if(rc == 0) {
1178         sshc->authed = TRUE;
1179         infof(data, "Initialized SSH public key authentication");
1180         state(data, SSH_AUTH_DONE);
1181       }
1182       else {
1183         char *err_msg = NULL;
1184         char unknown[] = "Reason unknown (-1)";
1185         if(rc == -1) {
1186           /* No error message has been set and the last set error message, if
1187              any, is from a previous error so ignore it. #11837 */
1188           err_msg = unknown;
1189         }
1190         else {
1191           (void)libssh2_session_last_error(sshc->ssh_session,
1192                                            &err_msg, NULL, 0);
1193         }
1194         infof(data, "SSH public key authentication failed: %s", err_msg);
1195         state(data, SSH_AUTH_PASS_INIT);
1196         rc = 0; /* clear rc and continue */
1197       }
1198       break;
1199 
1200     case SSH_AUTH_PASS_INIT:
1201       if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
1202          (strstr(sshc->authlist, "password") != NULL)) {
1203         state(data, SSH_AUTH_PASS);
1204       }
1205       else {
1206         state(data, SSH_AUTH_HOST_INIT);
1207         rc = 0; /* clear rc and continue */
1208       }
1209       break;
1210 
1211     case SSH_AUTH_PASS:
1212       rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
1213                                         curlx_uztoui(strlen(conn->user)),
1214                                         conn->passwd,
1215                                         curlx_uztoui(strlen(conn->passwd)),
1216                                         NULL);
1217       if(rc == LIBSSH2_ERROR_EAGAIN) {
1218         break;
1219       }
1220       if(rc == 0) {
1221         sshc->authed = TRUE;
1222         infof(data, "Initialized password authentication");
1223         state(data, SSH_AUTH_DONE);
1224       }
1225       else {
1226         state(data, SSH_AUTH_HOST_INIT);
1227         rc = 0; /* clear rc and continue */
1228       }
1229       break;
1230 
1231     case SSH_AUTH_HOST_INIT:
1232       if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
1233          (strstr(sshc->authlist, "hostbased") != NULL)) {
1234         state(data, SSH_AUTH_HOST);
1235       }
1236       else {
1237         state(data, SSH_AUTH_AGENT_INIT);
1238       }
1239       break;
1240 
1241     case SSH_AUTH_HOST:
1242       state(data, SSH_AUTH_AGENT_INIT);
1243       break;
1244 
1245     case SSH_AUTH_AGENT_INIT:
1246 #ifdef HAVE_LIBSSH2_AGENT_API
1247       if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
1248          && (strstr(sshc->authlist, "publickey") != NULL)) {
1249 
1250         /* Connect to the ssh-agent */
1251         /* The agent could be shared by a curl thread i believe
1252            but nothing obvious as keys can be added/removed at any time */
1253         if(!sshc->ssh_agent) {
1254           sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
1255           if(!sshc->ssh_agent) {
1256             infof(data, "Could not create agent object");
1257 
1258             state(data, SSH_AUTH_KEY_INIT);
1259             break;
1260           }
1261         }
1262 
1263         rc = libssh2_agent_connect(sshc->ssh_agent);
1264         if(rc == LIBSSH2_ERROR_EAGAIN)
1265           break;
1266         if(rc < 0) {
1267           infof(data, "Failure connecting to agent");
1268           state(data, SSH_AUTH_KEY_INIT);
1269           rc = 0; /* clear rc and continue */
1270         }
1271         else {
1272           state(data, SSH_AUTH_AGENT_LIST);
1273         }
1274       }
1275       else
1276 #endif /* HAVE_LIBSSH2_AGENT_API */
1277         state(data, SSH_AUTH_KEY_INIT);
1278       break;
1279 
1280     case SSH_AUTH_AGENT_LIST:
1281 #ifdef HAVE_LIBSSH2_AGENT_API
1282       rc = libssh2_agent_list_identities(sshc->ssh_agent);
1283 
1284       if(rc == LIBSSH2_ERROR_EAGAIN)
1285         break;
1286       if(rc < 0) {
1287         infof(data, "Failure requesting identities to agent");
1288         state(data, SSH_AUTH_KEY_INIT);
1289         rc = 0; /* clear rc and continue */
1290       }
1291       else {
1292         state(data, SSH_AUTH_AGENT);
1293         sshc->sshagent_prev_identity = NULL;
1294       }
1295 #endif
1296       break;
1297 
1298     case SSH_AUTH_AGENT:
1299 #ifdef HAVE_LIBSSH2_AGENT_API
1300       /* as prev_identity evolves only after an identity user auth finished we
1301          can safely request it again as long as EAGAIN is returned here or by
1302          libssh2_agent_userauth */
1303       rc = libssh2_agent_get_identity(sshc->ssh_agent,
1304                                       &sshc->sshagent_identity,
1305                                       sshc->sshagent_prev_identity);
1306       if(rc == LIBSSH2_ERROR_EAGAIN)
1307         break;
1308 
1309       if(rc == 0) {
1310         rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
1311                                     sshc->sshagent_identity);
1312 
1313         if(rc < 0) {
1314           if(rc != LIBSSH2_ERROR_EAGAIN) {
1315             /* tried and failed? go to next identity */
1316             sshc->sshagent_prev_identity = sshc->sshagent_identity;
1317           }
1318           break;
1319         }
1320       }
1321 
1322       if(rc < 0)
1323         infof(data, "Failure requesting identities to agent");
1324       else if(rc == 1)
1325         infof(data, "No identity would match");
1326 
1327       if(rc == LIBSSH2_ERROR_NONE) {
1328         sshc->authed = TRUE;
1329         infof(data, "Agent based authentication successful");
1330         state(data, SSH_AUTH_DONE);
1331       }
1332       else {
1333         state(data, SSH_AUTH_KEY_INIT);
1334         rc = 0; /* clear rc and continue */
1335       }
1336 #endif
1337       break;
1338 
1339     case SSH_AUTH_KEY_INIT:
1340       if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
1341          && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
1342         state(data, SSH_AUTH_KEY);
1343       }
1344       else {
1345         state(data, SSH_AUTH_DONE);
1346       }
1347       break;
1348 
1349     case SSH_AUTH_KEY:
1350       /* Authentication failed. Continue with keyboard-interactive now. */
1351       rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
1352                                                     conn->user,
1353                                                     curlx_uztoui(
1354                                                       strlen(conn->user)),
1355                                                     &kbd_callback);
1356       if(rc == LIBSSH2_ERROR_EAGAIN) {
1357         break;
1358       }
1359       if(rc == 0) {
1360         sshc->authed = TRUE;
1361         infof(data, "Initialized keyboard interactive authentication");
1362       }
1363       state(data, SSH_AUTH_DONE);
1364       break;
1365 
1366     case SSH_AUTH_DONE:
1367       if(!sshc->authed) {
1368         failf(data, "Authentication failure");
1369         state(data, SSH_SESSION_FREE);
1370         sshc->actualcode = CURLE_LOGIN_DENIED;
1371         break;
1372       }
1373 
1374       /*
1375        * At this point we have an authenticated ssh session.
1376        */
1377       infof(data, "Authentication complete");
1378 
1379       Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
1380 
1381       conn->sockfd = sock;
1382       conn->writesockfd = CURL_SOCKET_BAD;
1383 
1384       if(conn->handler->protocol == CURLPROTO_SFTP) {
1385         state(data, SSH_SFTP_INIT);
1386         break;
1387       }
1388       infof(data, "SSH CONNECT phase done");
1389       state(data, SSH_STOP);
1390       break;
1391 
1392     case SSH_SFTP_INIT:
1393       /*
1394        * Start the libssh2 sftp session
1395        */
1396       sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
1397       if(!sshc->sftp_session) {
1398         char *err_msg = NULL;
1399         if(libssh2_session_last_errno(sshc->ssh_session) ==
1400            LIBSSH2_ERROR_EAGAIN) {
1401           rc = LIBSSH2_ERROR_EAGAIN;
1402           break;
1403         }
1404 
1405         (void)libssh2_session_last_error(sshc->ssh_session,
1406                                          &err_msg, NULL, 0);
1407         failf(data, "Failure initializing sftp session: %s", err_msg);
1408         state(data, SSH_SESSION_FREE);
1409         sshc->actualcode = CURLE_FAILED_INIT;
1410         break;
1411       }
1412       state(data, SSH_SFTP_REALPATH);
1413       break;
1414 
1415     case SSH_SFTP_REALPATH:
1416     {
1417       char tempHome[PATH_MAX];
1418 
1419       /*
1420        * Get the "home" directory
1421        */
1422       rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
1423                                  tempHome, PATH_MAX-1);
1424       if(rc == LIBSSH2_ERROR_EAGAIN) {
1425         break;
1426       }
1427       if(rc > 0) {
1428         /* It seems that this string is not always NULL terminated */
1429         tempHome[rc] = '\0';
1430         sshc->homedir = strdup(tempHome);
1431         if(!sshc->homedir) {
1432           state(data, SSH_SFTP_CLOSE);
1433           sshc->actualcode = CURLE_OUT_OF_MEMORY;
1434           break;
1435         }
1436         data->state.most_recent_ftp_entrypath = sshc->homedir;
1437       }
1438       else {
1439         /* Return the error type */
1440         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1441         if(sftperr)
1442           result = sftp_libssh2_error_to_CURLE(sftperr);
1443         else
1444           /* in this case, the error was not in the SFTP level but for example
1445              a time-out or similar */
1446           result = CURLE_SSH;
1447         sshc->actualcode = result;
1448         DEBUGF(infof(data, "error = %lu makes libcurl = %d",
1449                      sftperr, (int)result));
1450         state(data, SSH_STOP);
1451         break;
1452       }
1453     }
1454     /* This is the last step in the SFTP connect phase. Do note that while
1455        we get the homedir here, we get the "workingpath" in the DO action
1456        since the homedir will remain the same between request but the
1457        working path will not. */
1458     DEBUGF(infof(data, "SSH CONNECT phase done"));
1459     state(data, SSH_STOP);
1460     break;
1461 
1462     case SSH_SFTP_QUOTE_INIT:
1463 
1464       result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
1465       if(result) {
1466         sshc->actualcode = result;
1467         state(data, SSH_STOP);
1468         break;
1469       }
1470 
1471       if(data->set.quote) {
1472         infof(data, "Sending quote commands");
1473         sshc->quote_item = data->set.quote;
1474         state(data, SSH_SFTP_QUOTE);
1475       }
1476       else {
1477         state(data, SSH_SFTP_GETINFO);
1478       }
1479       break;
1480 
1481     case SSH_SFTP_POSTQUOTE_INIT:
1482       if(data->set.postquote) {
1483         infof(data, "Sending quote commands");
1484         sshc->quote_item = data->set.postquote;
1485         state(data, SSH_SFTP_QUOTE);
1486       }
1487       else {
1488         state(data, SSH_STOP);
1489       }
1490       break;
1491 
1492     case SSH_SFTP_QUOTE:
1493       /* Send any quote commands */
1494     {
1495       const char *cp;
1496 
1497       /*
1498        * Support some of the "FTP" commands
1499        *
1500        * 'sshc->quote_item' is already verified to be non-NULL before it
1501        * switched to this state.
1502        */
1503       char *cmd = sshc->quote_item->data;
1504       sshc->acceptfail = FALSE;
1505 
1506       /* if a command starts with an asterisk, which a legal SFTP command never
1507          can, the command will be allowed to fail without it causing any
1508          aborts or cancels etc. It will cause libcurl to act as if the command
1509          is successful, whatever the server responds. */
1510 
1511       if(cmd[0] == '*') {
1512         cmd++;
1513         sshc->acceptfail = TRUE;
1514       }
1515 
1516       if(strcasecompare("pwd", cmd)) {
1517         /* output debug output if that is requested */
1518         char *tmp = aprintf("257 \"%s\" is current directory.\n",
1519                             sshp->path);
1520         if(!tmp) {
1521           result = CURLE_OUT_OF_MEMORY;
1522           state(data, SSH_SFTP_CLOSE);
1523           sshc->nextstate = SSH_NO_STATE;
1524           break;
1525         }
1526         Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
1527         Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
1528 
1529         /* this sends an FTP-like "header" to the header callback so that the
1530            current directory can be read very similar to how it is read when
1531            using ordinary FTP. */
1532         result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1533         free(tmp);
1534         if(result) {
1535           state(data, SSH_SFTP_CLOSE);
1536           sshc->nextstate = SSH_NO_STATE;
1537           sshc->actualcode = result;
1538         }
1539         else
1540           state(data, SSH_SFTP_NEXT_QUOTE);
1541         break;
1542       }
1543 
1544       /*
1545        * the arguments following the command must be separated from the
1546        * command with a space so we can check for it unconditionally
1547        */
1548       cp = strchr(cmd, ' ');
1549       if(!cp) {
1550         failf(data, "Syntax error command '%s', missing parameter",
1551               cmd);
1552         state(data, SSH_SFTP_CLOSE);
1553         sshc->nextstate = SSH_NO_STATE;
1554         sshc->actualcode = CURLE_QUOTE_ERROR;
1555         break;
1556       }
1557 
1558       /*
1559        * also, every command takes at least one argument so we get that
1560        * first argument right now
1561        */
1562       result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
1563       if(result) {
1564         if(result == CURLE_OUT_OF_MEMORY)
1565           failf(data, "Out of memory");
1566         else
1567           failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
1568         state(data, SSH_SFTP_CLOSE);
1569         sshc->nextstate = SSH_NO_STATE;
1570         sshc->actualcode = result;
1571         break;
1572       }
1573 
1574       /*
1575        * SFTP is a binary protocol, so we do not send text commands
1576        * to the server. Instead, we scan for commands used by
1577        * OpenSSH's sftp program and call the appropriate libssh2
1578        * functions.
1579        */
1580       if(strncasecompare(cmd, "chgrp ", 6) ||
1581          strncasecompare(cmd, "chmod ", 6) ||
1582          strncasecompare(cmd, "chown ", 6) ||
1583          strncasecompare(cmd, "atime ", 6) ||
1584          strncasecompare(cmd, "mtime ", 6)) {
1585         /* attribute change */
1586 
1587         /* sshc->quote_path1 contains the mode to set */
1588         /* get the destination */
1589         result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1590         if(result) {
1591           if(result == CURLE_OUT_OF_MEMORY)
1592             failf(data, "Out of memory");
1593           else
1594             failf(data, "Syntax error in %s: Bad second parameter", cmd);
1595           Curl_safefree(sshc->quote_path1);
1596           state(data, SSH_SFTP_CLOSE);
1597           sshc->nextstate = SSH_NO_STATE;
1598           sshc->actualcode = result;
1599           break;
1600         }
1601         memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1602         state(data, SSH_SFTP_QUOTE_STAT);
1603         break;
1604       }
1605       if(strncasecompare(cmd, "ln ", 3) ||
1606          strncasecompare(cmd, "symlink ", 8)) {
1607         /* symbolic linking */
1608         /* sshc->quote_path1 is the source */
1609         /* get the destination */
1610         result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1611         if(result) {
1612           if(result == CURLE_OUT_OF_MEMORY)
1613             failf(data, "Out of memory");
1614           else
1615             failf(data,
1616                   "Syntax error in ln/symlink: Bad second parameter");
1617           Curl_safefree(sshc->quote_path1);
1618           state(data, SSH_SFTP_CLOSE);
1619           sshc->nextstate = SSH_NO_STATE;
1620           sshc->actualcode = result;
1621           break;
1622         }
1623         state(data, SSH_SFTP_QUOTE_SYMLINK);
1624         break;
1625       }
1626       else if(strncasecompare(cmd, "mkdir ", 6)) {
1627         /* create dir */
1628         state(data, SSH_SFTP_QUOTE_MKDIR);
1629         break;
1630       }
1631       else if(strncasecompare(cmd, "rename ", 7)) {
1632         /* rename file */
1633         /* first param is the source path */
1634         /* second param is the dest. path */
1635         result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1636         if(result) {
1637           if(result == CURLE_OUT_OF_MEMORY)
1638             failf(data, "Out of memory");
1639           else
1640             failf(data, "Syntax error in rename: Bad second parameter");
1641           Curl_safefree(sshc->quote_path1);
1642           state(data, SSH_SFTP_CLOSE);
1643           sshc->nextstate = SSH_NO_STATE;
1644           sshc->actualcode = result;
1645           break;
1646         }
1647         state(data, SSH_SFTP_QUOTE_RENAME);
1648         break;
1649       }
1650       else if(strncasecompare(cmd, "rmdir ", 6)) {
1651         /* delete dir */
1652         state(data, SSH_SFTP_QUOTE_RMDIR);
1653         break;
1654       }
1655       else if(strncasecompare(cmd, "rm ", 3)) {
1656         state(data, SSH_SFTP_QUOTE_UNLINK);
1657         break;
1658       }
1659 #ifdef HAS_STATVFS_SUPPORT
1660       else if(strncasecompare(cmd, "statvfs ", 8)) {
1661         state(data, SSH_SFTP_QUOTE_STATVFS);
1662         break;
1663       }
1664 #endif
1665 
1666       failf(data, "Unknown SFTP command");
1667       Curl_safefree(sshc->quote_path1);
1668       Curl_safefree(sshc->quote_path2);
1669       state(data, SSH_SFTP_CLOSE);
1670       sshc->nextstate = SSH_NO_STATE;
1671       sshc->actualcode = CURLE_QUOTE_ERROR;
1672       break;
1673     }
1674 
1675     case SSH_SFTP_NEXT_QUOTE:
1676       Curl_safefree(sshc->quote_path1);
1677       Curl_safefree(sshc->quote_path2);
1678 
1679       sshc->quote_item = sshc->quote_item->next;
1680 
1681       if(sshc->quote_item) {
1682         state(data, SSH_SFTP_QUOTE);
1683       }
1684       else {
1685         if(sshc->nextstate != SSH_NO_STATE) {
1686           state(data, sshc->nextstate);
1687           sshc->nextstate = SSH_NO_STATE;
1688         }
1689         else {
1690           state(data, SSH_SFTP_GETINFO);
1691         }
1692       }
1693       break;
1694 
1695     case SSH_SFTP_QUOTE_STAT:
1696     {
1697       char *cmd = sshc->quote_item->data;
1698       sshc->acceptfail = FALSE;
1699 
1700       /* if a command starts with an asterisk, which a legal SFTP command never
1701          can, the command will be allowed to fail without it causing any
1702          aborts or cancels etc. It will cause libcurl to act as if the command
1703          is successful, whatever the server responds. */
1704 
1705       if(cmd[0] == '*') {
1706         cmd++;
1707         sshc->acceptfail = TRUE;
1708       }
1709 
1710       if(!strncasecompare(cmd, "chmod", 5)) {
1711         /* Since chown and chgrp only set owner OR group but libssh2 wants to
1712          * set them both at once, we need to obtain the current ownership
1713          * first. This takes an extra protocol round trip.
1714          */
1715         rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1716                                   curlx_uztoui(strlen(sshc->quote_path2)),
1717                                   LIBSSH2_SFTP_STAT,
1718                                   &sshp->quote_attrs);
1719         if(rc == LIBSSH2_ERROR_EAGAIN) {
1720           break;
1721         }
1722         if(rc && !sshc->acceptfail) { /* get those attributes */
1723           sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1724           Curl_safefree(sshc->quote_path1);
1725           Curl_safefree(sshc->quote_path2);
1726           failf(data, "Attempt to get SFTP stats failed: %s",
1727                 sftp_libssh2_strerror(sftperr));
1728           state(data, SSH_SFTP_CLOSE);
1729           sshc->nextstate = SSH_NO_STATE;
1730           sshc->actualcode = CURLE_QUOTE_ERROR;
1731           break;
1732         }
1733       }
1734 
1735       /* Now set the new attributes... */
1736       if(strncasecompare(cmd, "chgrp", 5)) {
1737         sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
1738         sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1739         if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1740            !sshc->acceptfail) {
1741           Curl_safefree(sshc->quote_path1);
1742           Curl_safefree(sshc->quote_path2);
1743           failf(data, "Syntax error: chgrp gid not a number");
1744           state(data, SSH_SFTP_CLOSE);
1745           sshc->nextstate = SSH_NO_STATE;
1746           sshc->actualcode = CURLE_QUOTE_ERROR;
1747           break;
1748         }
1749       }
1750       else if(strncasecompare(cmd, "chmod", 5)) {
1751         sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
1752         sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1753         /* permissions are octal */
1754         if(sshp->quote_attrs.permissions == 0 &&
1755            !ISDIGIT(sshc->quote_path1[0])) {
1756           Curl_safefree(sshc->quote_path1);
1757           Curl_safefree(sshc->quote_path2);
1758           failf(data, "Syntax error: chmod permissions not a number");
1759           state(data, SSH_SFTP_CLOSE);
1760           sshc->nextstate = SSH_NO_STATE;
1761           sshc->actualcode = CURLE_QUOTE_ERROR;
1762           break;
1763         }
1764       }
1765       else if(strncasecompare(cmd, "chown", 5)) {
1766         sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
1767         sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1768         if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1769            !sshc->acceptfail) {
1770           Curl_safefree(sshc->quote_path1);
1771           Curl_safefree(sshc->quote_path2);
1772           failf(data, "Syntax error: chown uid not a number");
1773           state(data, SSH_SFTP_CLOSE);
1774           sshc->nextstate = SSH_NO_STATE;
1775           sshc->actualcode = CURLE_QUOTE_ERROR;
1776           break;
1777         }
1778       }
1779       else if(strncasecompare(cmd, "atime", 5) ||
1780               strncasecompare(cmd, "mtime", 5)) {
1781         time_t date = Curl_getdate_capped(sshc->quote_path1);
1782         bool fail = FALSE;
1783 
1784         if(date == -1) {
1785           failf(data, "incorrect date format for %.*s", 5, cmd);
1786           fail = TRUE;
1787         }
1788 #if SIZEOF_TIME_T > SIZEOF_LONG
1789         if(date > 0xffffffff) {
1790           /* if 'long' cannot old >32-bit, this date cannot be sent */
1791           failf(data, "date overflow");
1792           fail = TRUE;
1793         }
1794 #endif
1795         if(fail) {
1796           Curl_safefree(sshc->quote_path1);
1797           Curl_safefree(sshc->quote_path2);
1798           state(data, SSH_SFTP_CLOSE);
1799           sshc->nextstate = SSH_NO_STATE;
1800           sshc->actualcode = CURLE_QUOTE_ERROR;
1801           break;
1802         }
1803         if(strncasecompare(cmd, "atime", 5))
1804           sshp->quote_attrs.atime = (unsigned long)date;
1805         else /* mtime */
1806           sshp->quote_attrs.mtime = (unsigned long)date;
1807 
1808         sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
1809       }
1810 
1811       /* Now send the completed structure... */
1812       state(data, SSH_SFTP_QUOTE_SETSTAT);
1813       break;
1814     }
1815 
1816     case SSH_SFTP_QUOTE_SETSTAT:
1817       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1818                                 curlx_uztoui(strlen(sshc->quote_path2)),
1819                                 LIBSSH2_SFTP_SETSTAT,
1820                                 &sshp->quote_attrs);
1821       if(rc == LIBSSH2_ERROR_EAGAIN) {
1822         break;
1823       }
1824       if(rc && !sshc->acceptfail) {
1825         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1826         Curl_safefree(sshc->quote_path1);
1827         Curl_safefree(sshc->quote_path2);
1828         failf(data, "Attempt to set SFTP stats failed: %s",
1829               sftp_libssh2_strerror(sftperr));
1830         state(data, SSH_SFTP_CLOSE);
1831         sshc->nextstate = SSH_NO_STATE;
1832         sshc->actualcode = CURLE_QUOTE_ERROR;
1833         break;
1834       }
1835       state(data, SSH_SFTP_NEXT_QUOTE);
1836       break;
1837 
1838     case SSH_SFTP_QUOTE_SYMLINK:
1839       rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
1840                                    curlx_uztoui(strlen(sshc->quote_path1)),
1841                                    sshc->quote_path2,
1842                                    curlx_uztoui(strlen(sshc->quote_path2)),
1843                                    LIBSSH2_SFTP_SYMLINK);
1844       if(rc == LIBSSH2_ERROR_EAGAIN) {
1845         break;
1846       }
1847       if(rc && !sshc->acceptfail) {
1848         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1849         Curl_safefree(sshc->quote_path1);
1850         Curl_safefree(sshc->quote_path2);
1851         failf(data, "symlink command failed: %s",
1852               sftp_libssh2_strerror(sftperr));
1853         state(data, SSH_SFTP_CLOSE);
1854         sshc->nextstate = SSH_NO_STATE;
1855         sshc->actualcode = CURLE_QUOTE_ERROR;
1856         break;
1857       }
1858       state(data, SSH_SFTP_NEXT_QUOTE);
1859       break;
1860 
1861     case SSH_SFTP_QUOTE_MKDIR:
1862       rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
1863                                  curlx_uztoui(strlen(sshc->quote_path1)),
1864                                  (long)data->set.new_directory_perms);
1865       if(rc == LIBSSH2_ERROR_EAGAIN) {
1866         break;
1867       }
1868       if(rc && !sshc->acceptfail) {
1869         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1870         Curl_safefree(sshc->quote_path1);
1871         failf(data, "mkdir command failed: %s",
1872               sftp_libssh2_strerror(sftperr));
1873         state(data, SSH_SFTP_CLOSE);
1874         sshc->nextstate = SSH_NO_STATE;
1875         sshc->actualcode = CURLE_QUOTE_ERROR;
1876         break;
1877       }
1878       state(data, SSH_SFTP_NEXT_QUOTE);
1879       break;
1880 
1881     case SSH_SFTP_QUOTE_RENAME:
1882       rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
1883                                   curlx_uztoui(strlen(sshc->quote_path1)),
1884                                   sshc->quote_path2,
1885                                   curlx_uztoui(strlen(sshc->quote_path2)),
1886                                   LIBSSH2_SFTP_RENAME_OVERWRITE |
1887                                   LIBSSH2_SFTP_RENAME_ATOMIC |
1888                                   LIBSSH2_SFTP_RENAME_NATIVE);
1889 
1890       if(rc == LIBSSH2_ERROR_EAGAIN) {
1891         break;
1892       }
1893       if(rc && !sshc->acceptfail) {
1894         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1895         Curl_safefree(sshc->quote_path1);
1896         Curl_safefree(sshc->quote_path2);
1897         failf(data, "rename command failed: %s",
1898               sftp_libssh2_strerror(sftperr));
1899         state(data, SSH_SFTP_CLOSE);
1900         sshc->nextstate = SSH_NO_STATE;
1901         sshc->actualcode = CURLE_QUOTE_ERROR;
1902         break;
1903       }
1904       state(data, SSH_SFTP_NEXT_QUOTE);
1905       break;
1906 
1907     case SSH_SFTP_QUOTE_RMDIR:
1908       rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
1909                                  curlx_uztoui(strlen(sshc->quote_path1)));
1910       if(rc == LIBSSH2_ERROR_EAGAIN) {
1911         break;
1912       }
1913       if(rc && !sshc->acceptfail) {
1914         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1915         Curl_safefree(sshc->quote_path1);
1916         failf(data, "rmdir command failed: %s",
1917               sftp_libssh2_strerror(sftperr));
1918         state(data, SSH_SFTP_CLOSE);
1919         sshc->nextstate = SSH_NO_STATE;
1920         sshc->actualcode = CURLE_QUOTE_ERROR;
1921         break;
1922       }
1923       state(data, SSH_SFTP_NEXT_QUOTE);
1924       break;
1925 
1926     case SSH_SFTP_QUOTE_UNLINK:
1927       rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
1928                                   curlx_uztoui(strlen(sshc->quote_path1)));
1929       if(rc == LIBSSH2_ERROR_EAGAIN) {
1930         break;
1931       }
1932       if(rc && !sshc->acceptfail) {
1933         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1934         Curl_safefree(sshc->quote_path1);
1935         failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
1936         state(data, SSH_SFTP_CLOSE);
1937         sshc->nextstate = SSH_NO_STATE;
1938         sshc->actualcode = CURLE_QUOTE_ERROR;
1939         break;
1940       }
1941       state(data, SSH_SFTP_NEXT_QUOTE);
1942       break;
1943 
1944 #ifdef HAS_STATVFS_SUPPORT
1945     case SSH_SFTP_QUOTE_STATVFS:
1946     {
1947       LIBSSH2_SFTP_STATVFS statvfs;
1948       rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
1949                                 curlx_uztoui(strlen(sshc->quote_path1)),
1950                                 &statvfs);
1951 
1952       if(rc == LIBSSH2_ERROR_EAGAIN) {
1953         break;
1954       }
1955       if(rc && !sshc->acceptfail) {
1956         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1957         Curl_safefree(sshc->quote_path1);
1958         failf(data, "statvfs command failed: %s",
1959               sftp_libssh2_strerror(sftperr));
1960         state(data, SSH_SFTP_CLOSE);
1961         sshc->nextstate = SSH_NO_STATE;
1962         sshc->actualcode = CURLE_QUOTE_ERROR;
1963         break;
1964       }
1965       else if(rc == 0) {
1966         #ifdef _MSC_VER
1967         #define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
1968         #else
1969         #define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
1970         #endif
1971         char *tmp = aprintf("statvfs:\n"
1972                             "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1973                             "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1974                             "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1975                             "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1976                             "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1977                             "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1978                             "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1979                             "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1980                             "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1981                             "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
1982                             "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
1983                             statvfs.f_bsize, statvfs.f_frsize,
1984                             statvfs.f_blocks, statvfs.f_bfree,
1985                             statvfs.f_bavail, statvfs.f_files,
1986                             statvfs.f_ffree, statvfs.f_favail,
1987                             statvfs.f_fsid, statvfs.f_flag,
1988                             statvfs.f_namemax);
1989         if(!tmp) {
1990           result = CURLE_OUT_OF_MEMORY;
1991           state(data, SSH_SFTP_CLOSE);
1992           sshc->nextstate = SSH_NO_STATE;
1993           break;
1994         }
1995 
1996         result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1997         free(tmp);
1998         if(result) {
1999           state(data, SSH_SFTP_CLOSE);
2000           sshc->nextstate = SSH_NO_STATE;
2001           sshc->actualcode = result;
2002         }
2003       }
2004       state(data, SSH_SFTP_NEXT_QUOTE);
2005       break;
2006     }
2007 #endif
2008     case SSH_SFTP_GETINFO:
2009     {
2010       if(data->set.get_filetime) {
2011         state(data, SSH_SFTP_FILETIME);
2012       }
2013       else {
2014         state(data, SSH_SFTP_TRANS_INIT);
2015       }
2016       break;
2017     }
2018 
2019     case SSH_SFTP_FILETIME:
2020     {
2021       LIBSSH2_SFTP_ATTRIBUTES attrs;
2022 
2023       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2024                                 curlx_uztoui(strlen(sshp->path)),
2025                                 LIBSSH2_SFTP_STAT, &attrs);
2026       if(rc == LIBSSH2_ERROR_EAGAIN) {
2027         break;
2028       }
2029       if(rc == 0) {
2030         data->info.filetime = (time_t)attrs.mtime;
2031       }
2032 
2033       state(data, SSH_SFTP_TRANS_INIT);
2034       break;
2035     }
2036 
2037     case SSH_SFTP_TRANS_INIT:
2038       if(data->state.upload)
2039         state(data, SSH_SFTP_UPLOAD_INIT);
2040       else {
2041         if(sshp->path[strlen(sshp->path)-1] == '/')
2042           state(data, SSH_SFTP_READDIR_INIT);
2043         else
2044           state(data, SSH_SFTP_DOWNLOAD_INIT);
2045       }
2046       break;
2047 
2048     case SSH_SFTP_UPLOAD_INIT:
2049     {
2050       unsigned long flags;
2051       /*
2052        * NOTE!!!  libssh2 requires that the destination path is a full path
2053        *          that includes the destination file and name OR ends in a "/"
2054        *          If this is not done the destination file will be named the
2055        *          same name as the last directory in the path.
2056        */
2057 
2058       if(data->state.resume_from) {
2059         LIBSSH2_SFTP_ATTRIBUTES attrs;
2060         if(data->state.resume_from < 0) {
2061           rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2062                                     curlx_uztoui(strlen(sshp->path)),
2063                                     LIBSSH2_SFTP_STAT, &attrs);
2064           if(rc == LIBSSH2_ERROR_EAGAIN) {
2065             break;
2066           }
2067           if(rc) {
2068             data->state.resume_from = 0;
2069           }
2070           else {
2071             curl_off_t size = attrs.filesize;
2072             if(size < 0) {
2073               failf(data, "Bad file size (%" FMT_OFF_T ")", size);
2074               return CURLE_BAD_DOWNLOAD_RESUME;
2075             }
2076             data->state.resume_from = attrs.filesize;
2077           }
2078         }
2079       }
2080 
2081       if(data->set.remote_append)
2082         /* Try to open for append, but create if nonexisting */
2083         flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
2084       else if(data->state.resume_from > 0)
2085         /* If we have restart position then open for append */
2086         flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
2087       else
2088         /* Clear file before writing (normal behavior) */
2089         flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
2090 
2091       sshc->sftp_handle =
2092         libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2093                              curlx_uztoui(strlen(sshp->path)),
2094                              flags, (long)data->set.new_file_perms,
2095                              LIBSSH2_SFTP_OPENFILE);
2096 
2097       if(!sshc->sftp_handle) {
2098         rc = libssh2_session_last_errno(sshc->ssh_session);
2099 
2100         if(LIBSSH2_ERROR_EAGAIN == rc)
2101           break;
2102 
2103         if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
2104           /* only when there was an SFTP protocol error can we extract
2105              the sftp error! */
2106           sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2107         else
2108           sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
2109 
2110         if(sshc->secondCreateDirs) {
2111           state(data, SSH_SFTP_CLOSE);
2112           sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
2113             sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
2114           failf(data, "Creating the dir/file failed: %s",
2115                 sftp_libssh2_strerror(sftperr));
2116           break;
2117         }
2118         if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
2119             (sftperr == LIBSSH2_FX_FAILURE) ||
2120             (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
2121            (data->set.ftp_create_missing_dirs &&
2122             (strlen(sshp->path) > 1))) {
2123           /* try to create the path remotely */
2124           rc = 0; /* clear rc and continue */
2125           sshc->secondCreateDirs = 1;
2126           state(data, SSH_SFTP_CREATE_DIRS_INIT);
2127           break;
2128         }
2129         state(data, SSH_SFTP_CLOSE);
2130         sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
2131           sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
2132         if(!sshc->actualcode) {
2133           /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
2134              even though libssh2_sftp_open() failed previously! We need to
2135              work around that! */
2136           sshc->actualcode = CURLE_SSH;
2137           sftperr = LIBSSH2_FX_OK;
2138         }
2139         failf(data, "Upload failed: %s (%lu/%d)",
2140               sftperr != LIBSSH2_FX_OK ?
2141               sftp_libssh2_strerror(sftperr) : "ssh error",
2142               sftperr, rc);
2143         break;
2144       }
2145 
2146       /* If we have a restart point then we need to seek to the correct
2147          position. */
2148       if(data->state.resume_from > 0) {
2149         /* Let's read off the proper amount of bytes from the input. */
2150         if(data->set.seek_func) {
2151           Curl_set_in_callback(data, true);
2152           seekerr = data->set.seek_func(data->set.seek_client,
2153                                         data->state.resume_from, SEEK_SET);
2154           Curl_set_in_callback(data, false);
2155         }
2156 
2157         if(seekerr != CURL_SEEKFUNC_OK) {
2158           curl_off_t passed = 0;
2159 
2160           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2161             failf(data, "Could not seek stream");
2162             return CURLE_FTP_COULDNT_USE_REST;
2163           }
2164           /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
2165           do {
2166             char scratch[4*1024];
2167             size_t readthisamountnow =
2168               (data->state.resume_from - passed >
2169                 (curl_off_t)sizeof(scratch)) ?
2170               sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
2171 
2172             size_t actuallyread;
2173             Curl_set_in_callback(data, true);
2174             actuallyread = data->state.fread_func(scratch, 1,
2175                                                   readthisamountnow,
2176                                                   data->state.in);
2177             Curl_set_in_callback(data, false);
2178 
2179             passed += actuallyread;
2180             if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2181               /* this checks for greater-than only to make sure that the
2182                  CURL_READFUNC_ABORT return code still aborts */
2183               failf(data, "Failed to read data");
2184               return CURLE_FTP_COULDNT_USE_REST;
2185             }
2186           } while(passed < data->state.resume_from);
2187         }
2188 
2189         /* now, decrease the size of the read */
2190         if(data->state.infilesize > 0) {
2191           data->state.infilesize -= data->state.resume_from;
2192           data->req.size = data->state.infilesize;
2193           Curl_pgrsSetUploadSize(data, data->state.infilesize);
2194         }
2195 
2196         SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2197       }
2198       if(data->state.infilesize > 0) {
2199         data->req.size = data->state.infilesize;
2200         Curl_pgrsSetUploadSize(data, data->state.infilesize);
2201       }
2202       /* upload data */
2203       Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
2204 
2205       /* not set by Curl_xfer_setup to preserve keepon bits */
2206       conn->sockfd = conn->writesockfd;
2207 
2208       if(result) {
2209         state(data, SSH_SFTP_CLOSE);
2210         sshc->actualcode = result;
2211       }
2212       else {
2213         /* store this original bitmask setup to use later on if we cannot
2214            figure out a "real" bitmask */
2215         sshc->orig_waitfor = data->req.keepon;
2216 
2217         /* we want to use the _sending_ function even when the socket turns
2218            out readable as the underlying libssh2 sftp send function will deal
2219            with both accordingly */
2220         data->state.select_bits = CURL_CSELECT_OUT;
2221 
2222         /* since we do not really wait for anything at this point, we want the
2223            state machine to move on as soon as possible so we set a very short
2224            timeout here */
2225         Curl_expire(data, 0, EXPIRE_RUN_NOW);
2226 
2227         state(data, SSH_STOP);
2228       }
2229       break;
2230     }
2231 
2232     case SSH_SFTP_CREATE_DIRS_INIT:
2233       if(strlen(sshp->path) > 1) {
2234         sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
2235         state(data, SSH_SFTP_CREATE_DIRS);
2236       }
2237       else {
2238         state(data, SSH_SFTP_UPLOAD_INIT);
2239       }
2240       break;
2241 
2242     case SSH_SFTP_CREATE_DIRS:
2243       sshc->slash_pos = strchr(sshc->slash_pos, '/');
2244       if(sshc->slash_pos) {
2245         *sshc->slash_pos = 0;
2246 
2247         infof(data, "Creating directory '%s'", sshp->path);
2248         state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
2249         break;
2250       }
2251       state(data, SSH_SFTP_UPLOAD_INIT);
2252       break;
2253 
2254     case SSH_SFTP_CREATE_DIRS_MKDIR:
2255       /* 'mode' - parameter is preliminary - default to 0644 */
2256       rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
2257                                  curlx_uztoui(strlen(sshp->path)),
2258                                  (long)data->set.new_directory_perms);
2259       if(rc == LIBSSH2_ERROR_EAGAIN) {
2260         break;
2261       }
2262       *sshc->slash_pos = '/';
2263       ++sshc->slash_pos;
2264       if(rc < 0) {
2265         /*
2266          * Abort if failure was not that the dir already exists or the
2267          * permission was denied (creation might succeed further down the
2268          * path) - retry on unspecific FAILURE also
2269          */
2270         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2271         if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
2272            (sftperr != LIBSSH2_FX_FAILURE) &&
2273            (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
2274           result = sftp_libssh2_error_to_CURLE(sftperr);
2275           state(data, SSH_SFTP_CLOSE);
2276           sshc->actualcode = result ? result : CURLE_SSH;
2277           break;
2278         }
2279         rc = 0; /* clear rc and continue */
2280       }
2281       state(data, SSH_SFTP_CREATE_DIRS);
2282       break;
2283 
2284     case SSH_SFTP_READDIR_INIT:
2285       Curl_pgrsSetDownloadSize(data, -1);
2286       if(data->req.no_body) {
2287         state(data, SSH_STOP);
2288         break;
2289       }
2290 
2291       /*
2292        * This is a directory that we are trying to get, so produce a directory
2293        * listing
2294        */
2295       sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
2296                                                sshp->path,
2297                                                curlx_uztoui(
2298                                                  strlen(sshp->path)),
2299                                                0, 0, LIBSSH2_SFTP_OPENDIR);
2300       if(!sshc->sftp_handle) {
2301         if(libssh2_session_last_errno(sshc->ssh_session) ==
2302            LIBSSH2_ERROR_EAGAIN) {
2303           rc = LIBSSH2_ERROR_EAGAIN;
2304           break;
2305         }
2306         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2307         failf(data, "Could not open directory for reading: %s",
2308               sftp_libssh2_strerror(sftperr));
2309         state(data, SSH_SFTP_CLOSE);
2310         result = sftp_libssh2_error_to_CURLE(sftperr);
2311         sshc->actualcode = result ? result : CURLE_SSH;
2312         break;
2313       }
2314       sshp->readdir_filename = malloc(PATH_MAX + 1);
2315       if(!sshp->readdir_filename) {
2316         state(data, SSH_SFTP_CLOSE);
2317         sshc->actualcode = CURLE_OUT_OF_MEMORY;
2318         break;
2319       }
2320       sshp->readdir_longentry = malloc(PATH_MAX + 1);
2321       if(!sshp->readdir_longentry) {
2322         Curl_safefree(sshp->readdir_filename);
2323         state(data, SSH_SFTP_CLOSE);
2324         sshc->actualcode = CURLE_OUT_OF_MEMORY;
2325         break;
2326       }
2327       Curl_dyn_init(&sshp->readdir, PATH_MAX * 2);
2328       state(data, SSH_SFTP_READDIR);
2329       break;
2330 
2331     case SSH_SFTP_READDIR:
2332       rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
2333                                    sshp->readdir_filename,
2334                                    PATH_MAX,
2335                                    sshp->readdir_longentry,
2336                                    PATH_MAX,
2337                                    &sshp->readdir_attrs);
2338       if(rc == LIBSSH2_ERROR_EAGAIN) {
2339         break;
2340       }
2341       if(rc > 0) {
2342         readdir_len = (size_t) rc;
2343         sshp->readdir_filename[readdir_len] = '\0';
2344 
2345         if(data->set.list_only) {
2346           result = Curl_client_write(data, CLIENTWRITE_BODY,
2347                                      sshp->readdir_filename,
2348                                      readdir_len);
2349           if(!result)
2350             result = Curl_client_write(data, CLIENTWRITE_BODY,
2351                                        (char *)"\n", 1);
2352           if(result) {
2353             state(data, SSH_STOP);
2354             break;
2355           }
2356 
2357         }
2358         else {
2359           result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
2360 
2361           if(!result) {
2362             if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
2363                ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
2364                 LIBSSH2_SFTP_S_IFLNK)) {
2365               Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
2366               result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
2367                                      sshp->readdir_filename);
2368               state(data, SSH_SFTP_READDIR_LINK);
2369               if(!result)
2370                 break;
2371             }
2372             else {
2373               state(data, SSH_SFTP_READDIR_BOTTOM);
2374               break;
2375             }
2376           }
2377           sshc->actualcode = result;
2378           state(data, SSH_SFTP_CLOSE);
2379           break;
2380         }
2381       }
2382       else if(rc == 0) {
2383         Curl_safefree(sshp->readdir_filename);
2384         Curl_safefree(sshp->readdir_longentry);
2385         state(data, SSH_SFTP_READDIR_DONE);
2386         break;
2387       }
2388       else if(rc < 0) {
2389         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2390         result = sftp_libssh2_error_to_CURLE(sftperr);
2391         sshc->actualcode = result ? result : CURLE_SSH;
2392         failf(data, "Could not open remote file for reading: %s :: %d",
2393               sftp_libssh2_strerror(sftperr),
2394               libssh2_session_last_errno(sshc->ssh_session));
2395         Curl_safefree(sshp->readdir_filename);
2396         Curl_safefree(sshp->readdir_longentry);
2397         state(data, SSH_SFTP_CLOSE);
2398         break;
2399       }
2400       break;
2401 
2402     case SSH_SFTP_READDIR_LINK:
2403       rc =
2404         libssh2_sftp_symlink_ex(sshc->sftp_session,
2405                                 Curl_dyn_ptr(&sshp->readdir_link),
2406                                 (unsigned int)
2407                                   Curl_dyn_len(&sshp->readdir_link),
2408                                 sshp->readdir_filename,
2409                                 PATH_MAX, LIBSSH2_SFTP_READLINK);
2410       if(rc == LIBSSH2_ERROR_EAGAIN) {
2411         break;
2412       }
2413       Curl_dyn_free(&sshp->readdir_link);
2414 
2415       /* append filename and extra output */
2416       result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
2417 
2418       if(result) {
2419         Curl_safefree(sshp->readdir_filename);
2420         Curl_safefree(sshp->readdir_longentry);
2421         state(data, SSH_SFTP_CLOSE);
2422         sshc->actualcode = result;
2423         break;
2424       }
2425 
2426       state(data, SSH_SFTP_READDIR_BOTTOM);
2427       break;
2428 
2429     case SSH_SFTP_READDIR_BOTTOM:
2430       result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
2431       if(!result)
2432         result = Curl_client_write(data, CLIENTWRITE_BODY,
2433                                    Curl_dyn_ptr(&sshp->readdir),
2434                                    Curl_dyn_len(&sshp->readdir));
2435 
2436       if(result) {
2437         Curl_dyn_free(&sshp->readdir);
2438         state(data, SSH_STOP);
2439       }
2440       else {
2441         Curl_dyn_reset(&sshp->readdir);
2442         state(data, SSH_SFTP_READDIR);
2443       }
2444       break;
2445 
2446     case SSH_SFTP_READDIR_DONE:
2447       if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2448          LIBSSH2_ERROR_EAGAIN) {
2449         rc = LIBSSH2_ERROR_EAGAIN;
2450         break;
2451       }
2452       sshc->sftp_handle = NULL;
2453       Curl_safefree(sshp->readdir_filename);
2454       Curl_safefree(sshp->readdir_longentry);
2455 
2456       /* no data to transfer */
2457       Curl_xfer_setup_nop(data);
2458       state(data, SSH_STOP);
2459       break;
2460 
2461     case SSH_SFTP_DOWNLOAD_INIT:
2462       /*
2463        * Work on getting the specified file
2464        */
2465       sshc->sftp_handle =
2466         libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2467                              curlx_uztoui(strlen(sshp->path)),
2468                              LIBSSH2_FXF_READ, (long)data->set.new_file_perms,
2469                              LIBSSH2_SFTP_OPENFILE);
2470       if(!sshc->sftp_handle) {
2471         if(libssh2_session_last_errno(sshc->ssh_session) ==
2472            LIBSSH2_ERROR_EAGAIN) {
2473           rc = LIBSSH2_ERROR_EAGAIN;
2474           break;
2475         }
2476         sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2477         failf(data, "Could not open remote file for reading: %s",
2478               sftp_libssh2_strerror(sftperr));
2479         state(data, SSH_SFTP_CLOSE);
2480         result = sftp_libssh2_error_to_CURLE(sftperr);
2481         sshc->actualcode = result ? result : CURLE_SSH;
2482         break;
2483       }
2484       state(data, SSH_SFTP_DOWNLOAD_STAT);
2485       break;
2486 
2487     case SSH_SFTP_DOWNLOAD_STAT:
2488     {
2489       LIBSSH2_SFTP_ATTRIBUTES attrs;
2490 
2491       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2492                                 curlx_uztoui(strlen(sshp->path)),
2493                                 LIBSSH2_SFTP_STAT, &attrs);
2494       if(rc == LIBSSH2_ERROR_EAGAIN) {
2495         break;
2496       }
2497       if(rc ||
2498          !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
2499          (attrs.filesize == 0)) {
2500         /*
2501          * libssh2_sftp_open() did not return an error, so maybe the server
2502          * just does not support stat()
2503          * OR the server does not return a file size with a stat()
2504          * OR file size is 0
2505          */
2506         data->req.size = -1;
2507         data->req.maxdownload = -1;
2508         Curl_pgrsSetDownloadSize(data, -1);
2509       }
2510       else {
2511         curl_off_t size = attrs.filesize;
2512 
2513         if(size < 0) {
2514           failf(data, "Bad file size (%" FMT_OFF_T ")", size);
2515           return CURLE_BAD_DOWNLOAD_RESUME;
2516         }
2517         if(data->state.use_range) {
2518           curl_off_t from, to;
2519           char *ptr;
2520           char *ptr2;
2521           CURLofft to_t;
2522           CURLofft from_t;
2523 
2524           from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
2525           if(from_t == CURL_OFFT_FLOW)
2526             return CURLE_RANGE_ERROR;
2527           while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
2528             ptr++;
2529           to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
2530           if(to_t == CURL_OFFT_FLOW)
2531             return CURLE_RANGE_ERROR;
2532           if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
2533              || (to >= size)) {
2534             to = size - 1;
2535           }
2536           if(from_t) {
2537             /* from is relative to end of file */
2538             from = size - to;
2539             to = size - 1;
2540           }
2541           if(from > size) {
2542             failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
2543                   FMT_OFF_T ")", from, (curl_off_t)attrs.filesize);
2544             return CURLE_BAD_DOWNLOAD_RESUME;
2545           }
2546           if(from > to) {
2547             from = to;
2548             size = 0;
2549           }
2550           else {
2551             if((to - from) == CURL_OFF_T_MAX)
2552               return CURLE_RANGE_ERROR;
2553             size = to - from + 1;
2554           }
2555 
2556           SFTP_SEEK(sshc->sftp_handle, from);
2557         }
2558         data->req.size = size;
2559         data->req.maxdownload = size;
2560         Curl_pgrsSetDownloadSize(data, size);
2561       }
2562 
2563       /* We can resume if we can seek to the resume position */
2564       if(data->state.resume_from) {
2565         if(data->state.resume_from < 0) {
2566           /* We are supposed to download the last abs(from) bytes */
2567           if((curl_off_t)attrs.filesize < -data->state.resume_from) {
2568             failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
2569                   FMT_OFF_T ")",
2570                   data->state.resume_from, (curl_off_t)attrs.filesize);
2571             return CURLE_BAD_DOWNLOAD_RESUME;
2572           }
2573           /* download from where? */
2574           data->state.resume_from += attrs.filesize;
2575         }
2576         else {
2577           if((curl_off_t)attrs.filesize < data->state.resume_from) {
2578             failf(data, "Offset (%" FMT_OFF_T
2579                   ") was beyond file size (%" FMT_OFF_T ")",
2580                   data->state.resume_from, (curl_off_t)attrs.filesize);
2581             return CURLE_BAD_DOWNLOAD_RESUME;
2582           }
2583         }
2584         /* Now store the number of bytes we are expected to download */
2585         data->req.size = attrs.filesize - data->state.resume_from;
2586         data->req.maxdownload = attrs.filesize - data->state.resume_from;
2587         Curl_pgrsSetDownloadSize(data,
2588                                  attrs.filesize - data->state.resume_from);
2589         SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2590       }
2591     }
2592 
2593     /* Setup the actual download */
2594     if(data->req.size == 0) {
2595       /* no data to transfer */
2596       Curl_xfer_setup_nop(data);
2597       infof(data, "File already completely downloaded");
2598       state(data, SSH_STOP);
2599       break;
2600     }
2601     Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
2602 
2603     /* not set by Curl_xfer_setup to preserve keepon bits */
2604     conn->writesockfd = conn->sockfd;
2605 
2606     /* we want to use the _receiving_ function even when the socket turns
2607        out writableable as the underlying libssh2 recv function will deal
2608        with both accordingly */
2609     data->state.select_bits = CURL_CSELECT_IN;
2610 
2611     if(result) {
2612       /* this should never occur; the close state should be entered
2613          at the time the error occurs */
2614       state(data, SSH_SFTP_CLOSE);
2615       sshc->actualcode = result;
2616     }
2617     else {
2618       state(data, SSH_STOP);
2619     }
2620     break;
2621 
2622     case SSH_SFTP_CLOSE:
2623       if(sshc->sftp_handle) {
2624         rc = libssh2_sftp_close(sshc->sftp_handle);
2625         if(rc == LIBSSH2_ERROR_EAGAIN) {
2626           break;
2627         }
2628         if(rc < 0) {
2629           char *err_msg = NULL;
2630           (void)libssh2_session_last_error(sshc->ssh_session,
2631                                            &err_msg, NULL, 0);
2632           infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2633         }
2634         sshc->sftp_handle = NULL;
2635       }
2636 
2637       Curl_safefree(sshp->path);
2638 
2639       DEBUGF(infof(data, "SFTP DONE done"));
2640 
2641       /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2642          After nextstate is executed, the control should come back to
2643          SSH_SFTP_CLOSE to pass the correct result back  */
2644       if(sshc->nextstate != SSH_NO_STATE &&
2645          sshc->nextstate != SSH_SFTP_CLOSE) {
2646         state(data, sshc->nextstate);
2647         sshc->nextstate = SSH_SFTP_CLOSE;
2648       }
2649       else {
2650         state(data, SSH_STOP);
2651         result = sshc->actualcode;
2652       }
2653       break;
2654 
2655     case SSH_SFTP_SHUTDOWN:
2656       /* during times we get here due to a broken transfer and then the
2657          sftp_handle might not have been taken down so make sure that is done
2658          before we proceed */
2659 
2660       if(sshc->sftp_handle) {
2661         rc = libssh2_sftp_close(sshc->sftp_handle);
2662         if(rc == LIBSSH2_ERROR_EAGAIN) {
2663           break;
2664         }
2665         if(rc < 0) {
2666           char *err_msg = NULL;
2667           (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
2668                                            NULL, 0);
2669           infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2670         }
2671         sshc->sftp_handle = NULL;
2672       }
2673       if(sshc->sftp_session) {
2674         rc = libssh2_sftp_shutdown(sshc->sftp_session);
2675         if(rc == LIBSSH2_ERROR_EAGAIN) {
2676           break;
2677         }
2678         if(rc < 0) {
2679           infof(data, "Failed to stop libssh2 sftp subsystem");
2680         }
2681         sshc->sftp_session = NULL;
2682       }
2683 
2684       Curl_safefree(sshc->homedir);
2685       data->state.most_recent_ftp_entrypath = NULL;
2686 
2687       state(data, SSH_SESSION_DISCONNECT);
2688       break;
2689 
2690     case SSH_SCP_TRANS_INIT:
2691       result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
2692       if(result) {
2693         sshc->actualcode = result;
2694         state(data, SSH_STOP);
2695         break;
2696       }
2697 
2698       if(data->state.upload) {
2699         if(data->state.infilesize < 0) {
2700           failf(data, "SCP requires a known file size for upload");
2701           sshc->actualcode = CURLE_UPLOAD_FAILED;
2702           state(data, SSH_SCP_CHANNEL_FREE);
2703           break;
2704         }
2705         state(data, SSH_SCP_UPLOAD_INIT);
2706       }
2707       else {
2708         state(data, SSH_SCP_DOWNLOAD_INIT);
2709       }
2710       break;
2711 
2712     case SSH_SCP_UPLOAD_INIT:
2713       /*
2714        * libssh2 requires that the destination path is a full path that
2715        * includes the destination file and name OR ends in a "/" . If this is
2716        * not done the destination file will be named the same name as the last
2717        * directory in the path.
2718        */
2719       sshc->ssh_channel =
2720         SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
2721                  data->state.infilesize);
2722       if(!sshc->ssh_channel) {
2723         int ssh_err;
2724         char *err_msg = NULL;
2725 
2726         if(libssh2_session_last_errno(sshc->ssh_session) ==
2727            LIBSSH2_ERROR_EAGAIN) {
2728           rc = LIBSSH2_ERROR_EAGAIN;
2729           break;
2730         }
2731 
2732         ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2733                                                    &err_msg, NULL, 0));
2734         failf(data, "%s", err_msg);
2735         state(data, SSH_SCP_CHANNEL_FREE);
2736         sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2737         /* Map generic errors to upload failed */
2738         if(sshc->actualcode == CURLE_SSH ||
2739            sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
2740           sshc->actualcode = CURLE_UPLOAD_FAILED;
2741         break;
2742       }
2743 
2744       /* upload data */
2745       data->req.size = data->state.infilesize;
2746       Curl_pgrsSetUploadSize(data, data->state.infilesize);
2747       Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
2748 
2749       /* not set by Curl_xfer_setup to preserve keepon bits */
2750       conn->sockfd = conn->writesockfd;
2751 
2752       if(result) {
2753         state(data, SSH_SCP_CHANNEL_FREE);
2754         sshc->actualcode = result;
2755       }
2756       else {
2757         /* store this original bitmask setup to use later on if we cannot
2758            figure out a "real" bitmask */
2759         sshc->orig_waitfor = data->req.keepon;
2760 
2761         /* we want to use the _sending_ function even when the socket turns
2762            out readable as the underlying libssh2 scp send function will deal
2763            with both accordingly */
2764         data->state.select_bits = CURL_CSELECT_OUT;
2765 
2766         state(data, SSH_STOP);
2767       }
2768       break;
2769 
2770     case SSH_SCP_DOWNLOAD_INIT:
2771     {
2772       curl_off_t bytecount;
2773 
2774       /*
2775        * We must check the remote file; if it is a directory no values will
2776        * be set in sb
2777        */
2778 
2779       /*
2780        * If support for >2GB files exists, use it.
2781        */
2782 
2783       /* get a fresh new channel from the ssh layer */
2784 #if LIBSSH2_VERSION_NUM < 0x010700
2785       struct stat sb;
2786       memset(&sb, 0, sizeof(struct stat));
2787       sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2788                                            sshp->path, &sb);
2789 #else
2790       libssh2_struct_stat sb;
2791       memset(&sb, 0, sizeof(libssh2_struct_stat));
2792       sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
2793                                             sshp->path, &sb);
2794 #endif
2795 
2796       if(!sshc->ssh_channel) {
2797         int ssh_err;
2798         char *err_msg = NULL;
2799 
2800         if(libssh2_session_last_errno(sshc->ssh_session) ==
2801            LIBSSH2_ERROR_EAGAIN) {
2802           rc = LIBSSH2_ERROR_EAGAIN;
2803           break;
2804         }
2805 
2806 
2807         ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2808                                                    &err_msg, NULL, 0));
2809         failf(data, "%s", err_msg);
2810         state(data, SSH_SCP_CHANNEL_FREE);
2811         sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2812         break;
2813       }
2814 
2815       /* download data */
2816       bytecount = (curl_off_t)sb.st_size;
2817       data->req.maxdownload = (curl_off_t)sb.st_size;
2818       Curl_xfer_setup1(data, CURL_XFER_RECV, bytecount, FALSE);
2819 
2820       /* not set by Curl_xfer_setup to preserve keepon bits */
2821       conn->writesockfd = conn->sockfd;
2822 
2823       /* we want to use the _receiving_ function even when the socket turns
2824          out writableable as the underlying libssh2 recv function will deal
2825          with both accordingly */
2826       data->state.select_bits = CURL_CSELECT_IN;
2827 
2828       if(result) {
2829         state(data, SSH_SCP_CHANNEL_FREE);
2830         sshc->actualcode = result;
2831       }
2832       else
2833         state(data, SSH_STOP);
2834     }
2835     break;
2836 
2837     case SSH_SCP_DONE:
2838       if(data->state.upload)
2839         state(data, SSH_SCP_SEND_EOF);
2840       else
2841         state(data, SSH_SCP_CHANNEL_FREE);
2842       break;
2843 
2844     case SSH_SCP_SEND_EOF:
2845       if(sshc->ssh_channel) {
2846         rc = libssh2_channel_send_eof(sshc->ssh_channel);
2847         if(rc == LIBSSH2_ERROR_EAGAIN) {
2848           break;
2849         }
2850         if(rc) {
2851           char *err_msg = NULL;
2852           (void)libssh2_session_last_error(sshc->ssh_session,
2853                                            &err_msg, NULL, 0);
2854           infof(data, "Failed to send libssh2 channel EOF: %d %s",
2855                 rc, err_msg);
2856         }
2857       }
2858       state(data, SSH_SCP_WAIT_EOF);
2859       break;
2860 
2861     case SSH_SCP_WAIT_EOF:
2862       if(sshc->ssh_channel) {
2863         rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2864         if(rc == LIBSSH2_ERROR_EAGAIN) {
2865           break;
2866         }
2867         if(rc) {
2868           char *err_msg = NULL;
2869           (void)libssh2_session_last_error(sshc->ssh_session,
2870                                            &err_msg, NULL, 0);
2871           infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
2872         }
2873       }
2874       state(data, SSH_SCP_WAIT_CLOSE);
2875       break;
2876 
2877     case SSH_SCP_WAIT_CLOSE:
2878       if(sshc->ssh_channel) {
2879         rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2880         if(rc == LIBSSH2_ERROR_EAGAIN) {
2881           break;
2882         }
2883         if(rc) {
2884           char *err_msg = NULL;
2885           (void)libssh2_session_last_error(sshc->ssh_session,
2886                                            &err_msg, NULL, 0);
2887           infof(data, "Channel failed to close: %d %s", rc, err_msg);
2888         }
2889       }
2890       state(data, SSH_SCP_CHANNEL_FREE);
2891       break;
2892 
2893     case SSH_SCP_CHANNEL_FREE:
2894       if(sshc->ssh_channel) {
2895         rc = libssh2_channel_free(sshc->ssh_channel);
2896         if(rc == LIBSSH2_ERROR_EAGAIN) {
2897           break;
2898         }
2899         if(rc < 0) {
2900           char *err_msg = NULL;
2901           (void)libssh2_session_last_error(sshc->ssh_session,
2902                                            &err_msg, NULL, 0);
2903           infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2904                 rc, err_msg);
2905         }
2906         sshc->ssh_channel = NULL;
2907       }
2908       DEBUGF(infof(data, "SCP DONE phase complete"));
2909 #if 0 /* PREV */
2910       state(data, SSH_SESSION_DISCONNECT);
2911 #endif
2912       state(data, SSH_STOP);
2913       result = sshc->actualcode;
2914       break;
2915 
2916     case SSH_SESSION_DISCONNECT:
2917       /* during weird times when we have been prematurely aborted, the channel
2918          is still alive when we reach this state and we MUST kill the channel
2919          properly first */
2920       if(sshc->ssh_channel) {
2921         rc = libssh2_channel_free(sshc->ssh_channel);
2922         if(rc == LIBSSH2_ERROR_EAGAIN) {
2923           break;
2924         }
2925         if(rc < 0) {
2926           char *err_msg = NULL;
2927           (void)libssh2_session_last_error(sshc->ssh_session,
2928                                            &err_msg, NULL, 0);
2929           infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2930                 rc, err_msg);
2931         }
2932         sshc->ssh_channel = NULL;
2933       }
2934 
2935       if(sshc->ssh_session) {
2936         rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2937         if(rc == LIBSSH2_ERROR_EAGAIN) {
2938           break;
2939         }
2940         if(rc < 0) {
2941           char *err_msg = NULL;
2942           (void)libssh2_session_last_error(sshc->ssh_session,
2943                                            &err_msg, NULL, 0);
2944           infof(data, "Failed to disconnect libssh2 session: %d %s",
2945                 rc, err_msg);
2946         }
2947       }
2948 
2949       Curl_safefree(sshc->homedir);
2950       data->state.most_recent_ftp_entrypath = NULL;
2951 
2952       state(data, SSH_SESSION_FREE);
2953       break;
2954 
2955     case SSH_SESSION_FREE:
2956 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2957       if(sshc->kh) {
2958         libssh2_knownhost_free(sshc->kh);
2959         sshc->kh = NULL;
2960       }
2961 #endif
2962 
2963 #ifdef HAVE_LIBSSH2_AGENT_API
2964       if(sshc->ssh_agent) {
2965         rc = libssh2_agent_disconnect(sshc->ssh_agent);
2966         if(rc == LIBSSH2_ERROR_EAGAIN) {
2967           break;
2968         }
2969         if(rc < 0) {
2970           char *err_msg = NULL;
2971           (void)libssh2_session_last_error(sshc->ssh_session,
2972                                            &err_msg, NULL, 0);
2973           infof(data, "Failed to disconnect from libssh2 agent: %d %s",
2974                 rc, err_msg);
2975         }
2976         libssh2_agent_free(sshc->ssh_agent);
2977         sshc->ssh_agent = NULL;
2978 
2979         /* NB: there is no need to free identities, they are part of internal
2980            agent stuff */
2981         sshc->sshagent_identity = NULL;
2982         sshc->sshagent_prev_identity = NULL;
2983       }
2984 #endif
2985 
2986       if(sshc->ssh_session) {
2987         rc = libssh2_session_free(sshc->ssh_session);
2988         if(rc == LIBSSH2_ERROR_EAGAIN) {
2989           break;
2990         }
2991         if(rc < 0) {
2992           char *err_msg = NULL;
2993           (void)libssh2_session_last_error(sshc->ssh_session,
2994                                            &err_msg, NULL, 0);
2995           infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
2996         }
2997         sshc->ssh_session = NULL;
2998       }
2999 
3000       /* worst-case scenario cleanup */
3001 
3002       DEBUGASSERT(sshc->ssh_session == NULL);
3003       DEBUGASSERT(sshc->ssh_channel == NULL);
3004       DEBUGASSERT(sshc->sftp_session == NULL);
3005       DEBUGASSERT(sshc->sftp_handle == NULL);
3006 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
3007       DEBUGASSERT(sshc->kh == NULL);
3008 #endif
3009 #ifdef HAVE_LIBSSH2_AGENT_API
3010       DEBUGASSERT(sshc->ssh_agent == NULL);
3011 #endif
3012 
3013       Curl_safefree(sshc->rsa_pub);
3014       Curl_safefree(sshc->rsa);
3015       Curl_safefree(sshc->quote_path1);
3016       Curl_safefree(sshc->quote_path2);
3017       Curl_safefree(sshc->homedir);
3018 
3019       /* the code we are about to return */
3020       result = sshc->actualcode;
3021 
3022       memset(sshc, 0, sizeof(struct ssh_conn));
3023 
3024       connclose(conn, "SSH session free");
3025       sshc->state = SSH_SESSION_FREE; /* current */
3026       sshc->nextstate = SSH_NO_STATE;
3027       state(data, SSH_STOP);
3028       break;
3029 
3030     case SSH_QUIT:
3031     default:
3032       /* internal error */
3033       sshc->nextstate = SSH_NO_STATE;
3034       state(data, SSH_STOP);
3035       break;
3036     }
3037 
3038   } while(!rc && (sshc->state != SSH_STOP));
3039 
3040   if(rc == LIBSSH2_ERROR_EAGAIN) {
3041     /* we would block, we need to wait for the socket to be ready (in the
3042        right direction too)! */
3043     *block = TRUE;
3044   }
3045 
3046   return result;
3047 }
3048 
3049 /* called by the multi interface to figure out what socket(s) to wait for and
3050    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
ssh_getsock(struct Curl_easy * data,struct connectdata * conn,curl_socket_t * sock)3051 static int ssh_getsock(struct Curl_easy *data,
3052                        struct connectdata *conn,
3053                        curl_socket_t *sock)
3054 {
3055   int bitmap = GETSOCK_BLANK;
3056   (void)data;
3057 
3058   sock[0] = conn->sock[FIRSTSOCKET];
3059 
3060   if(conn->waitfor & KEEP_RECV)
3061     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
3062 
3063   if(conn->waitfor & KEEP_SEND)
3064     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
3065 
3066   return bitmap;
3067 }
3068 
3069 /*
3070  * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
3071  * function is used to figure out in what direction and stores this info so
3072  * that the multi interface can take advantage of it. Make sure to call this
3073  * function in all cases so that when it _does not_ return EAGAIN we can
3074  * restore the default wait bits.
3075  */
ssh_block2waitfor(struct Curl_easy * data,bool block)3076 static void ssh_block2waitfor(struct Curl_easy *data, bool block)
3077 {
3078   struct connectdata *conn = data->conn;
3079   struct ssh_conn *sshc = &conn->proto.sshc;
3080   int dir = 0;
3081   if(block) {
3082     dir = libssh2_session_block_directions(sshc->ssh_session);
3083     if(dir) {
3084       /* translate the libssh2 define bits into our own bit defines */
3085       conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND) ? KEEP_RECV : 0) |
3086         ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND) ? KEEP_SEND : 0);
3087     }
3088   }
3089   if(!dir)
3090     /* It did not block or libssh2 did not reveal in which direction, put back
3091        the original set */
3092     conn->waitfor = sshc->orig_waitfor;
3093 }
3094 
3095 /* called repeatedly until done from multi.c */
ssh_multi_statemach(struct Curl_easy * data,bool * done)3096 static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
3097 {
3098   struct connectdata *conn = data->conn;
3099   struct ssh_conn *sshc = &conn->proto.sshc;
3100   CURLcode result = CURLE_OK;
3101   bool block; /* we store the status and use that to provide a ssh_getsock()
3102                  implementation */
3103   do {
3104     result = ssh_statemach_act(data, &block);
3105     *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
3106     /* if there is no error, it is not done and it did not EWOULDBLOCK, then
3107        try again */
3108   } while(!result && !*done && !block);
3109   ssh_block2waitfor(data, block);
3110 
3111   return result;
3112 }
3113 
ssh_block_statemach(struct Curl_easy * data,struct connectdata * conn,bool disconnect)3114 static CURLcode ssh_block_statemach(struct Curl_easy *data,
3115                                     struct connectdata *conn,
3116                                     bool disconnect)
3117 {
3118   struct ssh_conn *sshc = &conn->proto.sshc;
3119   CURLcode result = CURLE_OK;
3120   struct curltime dis = Curl_now();
3121 
3122   while((sshc->state != SSH_STOP) && !result) {
3123     bool block;
3124     timediff_t left = 1000;
3125     struct curltime now = Curl_now();
3126 
3127     result = ssh_statemach_act(data, &block);
3128     if(result)
3129       break;
3130 
3131     if(!disconnect) {
3132       if(Curl_pgrsUpdate(data))
3133         return CURLE_ABORTED_BY_CALLBACK;
3134 
3135       result = Curl_speedcheck(data, now);
3136       if(result)
3137         break;
3138 
3139       left = Curl_timeleft(data, NULL, FALSE);
3140       if(left < 0) {
3141         failf(data, "Operation timed out");
3142         return CURLE_OPERATION_TIMEDOUT;
3143       }
3144     }
3145     else if(Curl_timediff(now, dis) > 1000) {
3146       /* disconnect timeout */
3147       failf(data, "Disconnect timed out");
3148       result = CURLE_OK;
3149       break;
3150     }
3151 
3152     if(block) {
3153       int dir = libssh2_session_block_directions(sshc->ssh_session);
3154       curl_socket_t sock = conn->sock[FIRSTSOCKET];
3155       curl_socket_t fd_read = CURL_SOCKET_BAD;
3156       curl_socket_t fd_write = CURL_SOCKET_BAD;
3157       if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
3158         fd_read = sock;
3159       if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
3160         fd_write = sock;
3161       /* wait for the socket to become ready */
3162       (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
3163                               left > 1000 ? 1000 : left);
3164     }
3165   }
3166 
3167   return result;
3168 }
3169 
3170 /*
3171  * SSH setup and connection
3172  */
ssh_setup_connection(struct Curl_easy * data,struct connectdata * conn)3173 static CURLcode ssh_setup_connection(struct Curl_easy *data,
3174                                      struct connectdata *conn)
3175 {
3176   struct SSHPROTO *ssh;
3177   (void)conn;
3178 
3179   data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
3180   if(!ssh)
3181     return CURLE_OUT_OF_MEMORY;
3182 
3183   return CURLE_OK;
3184 }
3185 
3186 static Curl_recv scp_recv, sftp_recv;
3187 static Curl_send scp_send, sftp_send;
3188 
3189 #ifndef CURL_DISABLE_PROXY
ssh_tls_recv(libssh2_socket_t sock,void * buffer,size_t length,int flags,void ** abstract)3190 static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
3191                             size_t length, int flags, void **abstract)
3192 {
3193   struct Curl_easy *data = (struct Curl_easy *)*abstract;
3194   ssize_t nread;
3195   CURLcode result;
3196   struct connectdata *conn = data->conn;
3197   Curl_recv *backup = conn->recv[0];
3198   struct ssh_conn *ssh = &conn->proto.sshc;
3199   int socknum = Curl_conn_sockindex(data, sock);
3200   (void)flags;
3201 
3202   /* swap in the TLS reader function for this call only, and then swap back
3203      the SSH one again */
3204   conn->recv[0] = ssh->tls_recv;
3205   result = Curl_conn_recv(data, socknum, buffer, length, &nread);
3206   conn->recv[0] = backup;
3207   if(result == CURLE_AGAIN)
3208     return -EAGAIN; /* magic return code for libssh2 */
3209   else if(result)
3210     return -1; /* generic error */
3211   Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
3212   return nread;
3213 }
3214 
ssh_tls_send(libssh2_socket_t sock,const void * buffer,size_t length,int flags,void ** abstract)3215 static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
3216                             size_t length, int flags, void **abstract)
3217 {
3218   struct Curl_easy *data = (struct Curl_easy *)*abstract;
3219   size_t nwrite;
3220   CURLcode result;
3221   struct connectdata *conn = data->conn;
3222   Curl_send *backup = conn->send[0];
3223   struct ssh_conn *ssh = &conn->proto.sshc;
3224   int socknum = Curl_conn_sockindex(data, sock);
3225   (void)flags;
3226 
3227   /* swap in the TLS writer function for this call only, and then swap back
3228      the SSH one again */
3229   conn->send[0] = ssh->tls_send;
3230   result = Curl_conn_send(data, socknum, buffer, length, FALSE, &nwrite);
3231   conn->send[0] = backup;
3232   if(result == CURLE_AGAIN)
3233     return -EAGAIN; /* magic return code for libssh2 */
3234   else if(result)
3235     return -1; /* error */
3236   Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, nwrite);
3237   return (ssize_t)nwrite;
3238 }
3239 #endif
3240 
3241 /*
3242  * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
3243  * do protocol-specific actions at connect-time.
3244  */
ssh_connect(struct Curl_easy * data,bool * done)3245 static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
3246 {
3247 #ifdef CURL_LIBSSH2_DEBUG
3248   curl_socket_t sock;
3249 #endif
3250   struct ssh_conn *sshc;
3251   CURLcode result;
3252   struct connectdata *conn = data->conn;
3253 
3254   /* initialize per-handle data if not already */
3255   if(!data->req.p.ssh) {
3256     result = ssh_setup_connection(data, conn);
3257     if(result)
3258       return result;
3259   }
3260 
3261   /* We default to persistent connections. We set this already in this connect
3262      function to make the reuse checks properly be able to check this bit. */
3263   connkeep(conn, "SSH default");
3264 
3265   sshc = &conn->proto.sshc;
3266 
3267 #ifdef CURL_LIBSSH2_DEBUG
3268   if(conn->user) {
3269     infof(data, "User: %s", conn->user);
3270   }
3271   if(conn->passwd) {
3272     infof(data, "Password: %s", conn->passwd);
3273   }
3274   sock = conn->sock[FIRSTSOCKET];
3275 #endif /* CURL_LIBSSH2_DEBUG */
3276 
3277   /* libcurl MUST to set custom memory functions so that the kbd_callback
3278      function's memory allocations can be properly freed */
3279   sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
3280                                               my_libssh2_free,
3281                                               my_libssh2_realloc, data);
3282 
3283   if(!sshc->ssh_session) {
3284     failf(data, "Failure initialising ssh session");
3285     return CURLE_FAILED_INIT;
3286   }
3287 
3288   /* Set the packet read timeout if the libssh2 version supports it */
3289 #if LIBSSH2_VERSION_NUM >= 0x010B00
3290   if(data->set.server_response_timeout > 0) {
3291     libssh2_session_set_read_timeout(sshc->ssh_session,
3292                              (long)(data->set.server_response_timeout / 1000));
3293   }
3294 #endif
3295 
3296 #ifndef CURL_DISABLE_PROXY
3297   if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
3298     /*
3299       Setup libssh2 callbacks to make it read/write TLS from the socket.
3300 
3301       ssize_t
3302       recvcb(libssh2_socket_t sock, void *buffer, size_t length,
3303       int flags, void **abstract);
3304 
3305       ssize_t
3306       sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
3307       int flags, void **abstract);
3308 
3309     */
3310 #if LIBSSH2_VERSION_NUM >= 0x010b01
3311     infof(data, "Uses HTTPS proxy");
3312     libssh2_session_callback_set2(sshc->ssh_session,
3313                                   LIBSSH2_CALLBACK_RECV,
3314                                   (libssh2_cb_generic *)ssh_tls_recv);
3315     libssh2_session_callback_set2(sshc->ssh_session,
3316                                   LIBSSH2_CALLBACK_SEND,
3317                                   (libssh2_cb_generic *)ssh_tls_send);
3318 #else
3319     /*
3320      * This crazy union dance is here to avoid assigning a void pointer a
3321      * function pointer as it is invalid C. The problem is of course that
3322      * libssh2 has such an API...
3323      */
3324     union receive {
3325       void *recvp;
3326       ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
3327     };
3328     union transfer {
3329       void *sendp;
3330       ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
3331     };
3332     union receive sshrecv;
3333     union transfer sshsend;
3334 
3335     sshrecv.recvptr = ssh_tls_recv;
3336     sshsend.sendptr = ssh_tls_send;
3337 
3338     infof(data, "Uses HTTPS proxy");
3339     libssh2_session_callback_set(sshc->ssh_session,
3340                                  LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
3341     libssh2_session_callback_set(sshc->ssh_session,
3342                                  LIBSSH2_CALLBACK_SEND, sshsend.sendp);
3343 #endif
3344 
3345     /* Store the underlying TLS recv/send function pointers to be used when
3346        reading from the proxy */
3347     sshc->tls_recv = conn->recv[FIRSTSOCKET];
3348     sshc->tls_send = conn->send[FIRSTSOCKET];
3349   }
3350 
3351 #endif /* CURL_DISABLE_PROXY */
3352   if(conn->handler->protocol & CURLPROTO_SCP) {
3353     conn->recv[FIRSTSOCKET] = scp_recv;
3354     conn->send[FIRSTSOCKET] = scp_send;
3355   }
3356   else {
3357     conn->recv[FIRSTSOCKET] = sftp_recv;
3358     conn->send[FIRSTSOCKET] = sftp_send;
3359   }
3360 
3361   if(data->set.ssh_compression) {
3362 #if LIBSSH2_VERSION_NUM >= 0x010208
3363     if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
3364 #endif
3365       infof(data, "Failed to enable compression for ssh session");
3366   }
3367 
3368 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
3369   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
3370     int rc;
3371     sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
3372     if(!sshc->kh) {
3373       libssh2_session_free(sshc->ssh_session);
3374       sshc->ssh_session = NULL;
3375       return CURLE_FAILED_INIT;
3376     }
3377 
3378     /* read all known hosts from there */
3379     rc = libssh2_knownhost_readfile(sshc->kh,
3380                                     data->set.str[STRING_SSH_KNOWNHOSTS],
3381                                     LIBSSH2_KNOWNHOST_FILE_OPENSSH);
3382     if(rc < 0)
3383       infof(data, "Failed to read known hosts from %s",
3384             data->set.str[STRING_SSH_KNOWNHOSTS]);
3385   }
3386 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
3387 
3388 #ifdef CURL_LIBSSH2_DEBUG
3389   libssh2_trace(sshc->ssh_session, ~0);
3390   infof(data, "SSH socket: %d", (int)sock);
3391 #endif /* CURL_LIBSSH2_DEBUG */
3392 
3393   state(data, SSH_INIT);
3394 
3395   result = ssh_multi_statemach(data, done);
3396 
3397   return result;
3398 }
3399 
3400 /*
3401  ***********************************************************************
3402  *
3403  * scp_perform()
3404  *
3405  * This is the actual DO function for SCP. Get a file according to
3406  * the options previously setup.
3407  */
3408 
3409 static
scp_perform(struct Curl_easy * data,bool * connected,bool * dophase_done)3410 CURLcode scp_perform(struct Curl_easy *data,
3411                      bool *connected,
3412                      bool *dophase_done)
3413 {
3414   CURLcode result = CURLE_OK;
3415 
3416   DEBUGF(infof(data, "DO phase starts"));
3417 
3418   *dophase_done = FALSE; /* not done yet */
3419 
3420   /* start the first command in the DO phase */
3421   state(data, SSH_SCP_TRANS_INIT);
3422 
3423   /* run the state-machine */
3424   result = ssh_multi_statemach(data, dophase_done);
3425 
3426   *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3427 
3428   if(*dophase_done) {
3429     DEBUGF(infof(data, "DO phase is complete"));
3430   }
3431 
3432   return result;
3433 }
3434 
3435 /* called from multi.c while DOing */
scp_doing(struct Curl_easy * data,bool * dophase_done)3436 static CURLcode scp_doing(struct Curl_easy *data,
3437                           bool *dophase_done)
3438 {
3439   CURLcode result;
3440   result = ssh_multi_statemach(data, dophase_done);
3441 
3442   if(*dophase_done) {
3443     DEBUGF(infof(data, "DO phase is complete"));
3444   }
3445   return result;
3446 }
3447 
3448 /*
3449  * The DO function is generic for both protocols. There was previously two
3450  * separate ones but this way means less duplicated code.
3451  */
3452 
ssh_do(struct Curl_easy * data,bool * done)3453 static CURLcode ssh_do(struct Curl_easy *data, bool *done)
3454 {
3455   CURLcode result;
3456   bool connected = 0;
3457   struct connectdata *conn = data->conn;
3458   struct ssh_conn *sshc = &conn->proto.sshc;
3459 
3460   *done = FALSE; /* default to false */
3461 
3462   data->req.size = -1; /* make sure this is unknown at this point */
3463 
3464   sshc->actualcode = CURLE_OK; /* reset error code */
3465   sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
3466                                    variable */
3467 
3468   Curl_pgrsSetUploadCounter(data, 0);
3469   Curl_pgrsSetDownloadCounter(data, 0);
3470   Curl_pgrsSetUploadSize(data, -1);
3471   Curl_pgrsSetDownloadSize(data, -1);
3472 
3473   if(conn->handler->protocol & CURLPROTO_SCP)
3474     result = scp_perform(data, &connected,  done);
3475   else
3476     result = sftp_perform(data, &connected,  done);
3477 
3478   return result;
3479 }
3480 
3481 /* BLOCKING, but the function is using the state machine so the only reason
3482    this is still blocking is that the multi interface code has no support for
3483    disconnecting operations that takes a while */
scp_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)3484 static CURLcode scp_disconnect(struct Curl_easy *data,
3485                                struct connectdata *conn,
3486                                bool dead_connection)
3487 {
3488   CURLcode result = CURLE_OK;
3489   struct ssh_conn *sshc = &conn->proto.sshc;
3490   (void) dead_connection;
3491 
3492   if(sshc->ssh_session) {
3493     /* only if there is a session still around to use! */
3494     state(data, SSH_SESSION_DISCONNECT);
3495     result = ssh_block_statemach(data, conn, TRUE);
3496   }
3497 
3498   return result;
3499 }
3500 
3501 /* generic done function for both SCP and SFTP called from their specific
3502    done functions */
ssh_done(struct Curl_easy * data,CURLcode status)3503 static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
3504 {
3505   CURLcode result = CURLE_OK;
3506   struct SSHPROTO *sshp = data->req.p.ssh;
3507   struct connectdata *conn = data->conn;
3508 
3509   if(!status)
3510     /* run the state-machine */
3511     result = ssh_block_statemach(data, conn, FALSE);
3512   else
3513     result = status;
3514 
3515   Curl_safefree(sshp->path);
3516   Curl_safefree(sshp->readdir_filename);
3517   Curl_safefree(sshp->readdir_longentry);
3518   Curl_dyn_free(&sshp->readdir);
3519 
3520   if(Curl_pgrsDone(data))
3521     return CURLE_ABORTED_BY_CALLBACK;
3522 
3523   data->req.keepon = 0; /* clear all bits */
3524   return result;
3525 }
3526 
3527 
scp_done(struct Curl_easy * data,CURLcode status,bool premature)3528 static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
3529                          bool premature)
3530 {
3531   (void)premature; /* not used */
3532 
3533   if(!status)
3534     state(data, SSH_SCP_DONE);
3535 
3536   return ssh_done(data, status);
3537 
3538 }
3539 
scp_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,bool eos,CURLcode * err)3540 static ssize_t scp_send(struct Curl_easy *data, int sockindex,
3541                         const void *mem, size_t len, bool eos, CURLcode *err)
3542 {
3543   ssize_t nwrite;
3544   struct connectdata *conn = data->conn;
3545   struct ssh_conn *sshc = &conn->proto.sshc;
3546   (void)sockindex; /* we only support SCP on the fixed known primary socket */
3547   (void)eos;
3548 
3549   /* libssh2_channel_write() returns int! */
3550   nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
3551 
3552   ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN) ? TRUE : FALSE);
3553 
3554   if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3555     *err = CURLE_AGAIN;
3556     nwrite = 0;
3557   }
3558   else if(nwrite < LIBSSH2_ERROR_NONE) {
3559     *err = libssh2_session_error_to_CURLE((int)nwrite);
3560     nwrite = -1;
3561   }
3562 
3563   return nwrite;
3564 }
3565 
scp_recv(struct Curl_easy * data,int sockindex,char * mem,size_t len,CURLcode * err)3566 static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
3567                         char *mem, size_t len, CURLcode *err)
3568 {
3569   ssize_t nread;
3570   struct connectdata *conn = data->conn;
3571   struct ssh_conn *sshc = &conn->proto.sshc;
3572   (void)sockindex; /* we only support SCP on the fixed known primary socket */
3573 
3574   /* libssh2_channel_read() returns int */
3575   nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
3576 
3577   ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN) ? TRUE : FALSE);
3578   if(nread == LIBSSH2_ERROR_EAGAIN) {
3579     *err = CURLE_AGAIN;
3580     nread = -1;
3581   }
3582 
3583   return nread;
3584 }
3585 
3586 /*
3587  * =============== SFTP ===============
3588  */
3589 
3590 /*
3591  ***********************************************************************
3592  *
3593  * sftp_perform()
3594  *
3595  * This is the actual DO function for SFTP. Get a file/directory according to
3596  * the options previously setup.
3597  */
3598 
3599 static
sftp_perform(struct Curl_easy * data,bool * connected,bool * dophase_done)3600 CURLcode sftp_perform(struct Curl_easy *data,
3601                       bool *connected,
3602                       bool *dophase_done)
3603 {
3604   CURLcode result = CURLE_OK;
3605 
3606   DEBUGF(infof(data, "DO phase starts"));
3607 
3608   *dophase_done = FALSE; /* not done yet */
3609 
3610   /* start the first command in the DO phase */
3611   state(data, SSH_SFTP_QUOTE_INIT);
3612 
3613   /* run the state-machine */
3614   result = ssh_multi_statemach(data, dophase_done);
3615 
3616   *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3617 
3618   if(*dophase_done) {
3619     DEBUGF(infof(data, "DO phase is complete"));
3620   }
3621 
3622   return result;
3623 }
3624 
3625 /* called from multi.c while DOing */
sftp_doing(struct Curl_easy * data,bool * dophase_done)3626 static CURLcode sftp_doing(struct Curl_easy *data,
3627                            bool *dophase_done)
3628 {
3629   CURLcode result = ssh_multi_statemach(data, dophase_done);
3630 
3631   if(*dophase_done) {
3632     DEBUGF(infof(data, "DO phase is complete"));
3633   }
3634   return result;
3635 }
3636 
3637 /* BLOCKING, but the function is using the state machine so the only reason
3638    this is still blocking is that the multi interface code has no support for
3639    disconnecting operations that takes a while */
sftp_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)3640 static CURLcode sftp_disconnect(struct Curl_easy *data,
3641                                 struct connectdata *conn, bool dead_connection)
3642 {
3643   CURLcode result = CURLE_OK;
3644   struct ssh_conn *sshc = &conn->proto.sshc;
3645   (void) dead_connection;
3646 
3647   DEBUGF(infof(data, "SSH DISCONNECT starts now"));
3648 
3649   if(sshc->ssh_session) {
3650     /* only if there is a session still around to use! */
3651     state(data, SSH_SFTP_SHUTDOWN);
3652     result = ssh_block_statemach(data, conn, TRUE);
3653   }
3654 
3655   DEBUGF(infof(data, "SSH DISCONNECT is done"));
3656 
3657   return result;
3658 
3659 }
3660 
sftp_done(struct Curl_easy * data,CURLcode status,bool premature)3661 static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
3662                                bool premature)
3663 {
3664   struct connectdata *conn = data->conn;
3665   struct ssh_conn *sshc = &conn->proto.sshc;
3666 
3667   if(!status) {
3668     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3669        errors that could happen due to open file handles during POSTQUOTE
3670        operation */
3671     if(!premature && data->set.postquote && !conn->bits.retry)
3672       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3673     state(data, SSH_SFTP_CLOSE);
3674   }
3675   return ssh_done(data, status);
3676 }
3677 
3678 /* return number of sent bytes */
sftp_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,bool eos,CURLcode * err)3679 static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
3680                          const void *mem, size_t len, bool eos, CURLcode *err)
3681 {
3682   ssize_t nwrite;
3683   struct connectdata *conn = data->conn;
3684   struct ssh_conn *sshc = &conn->proto.sshc;
3685   (void)sockindex;
3686   (void)eos;
3687 
3688   nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
3689 
3690   ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN) ? TRUE : FALSE);
3691 
3692   if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3693     *err = CURLE_AGAIN;
3694     nwrite = 0;
3695   }
3696   else if(nwrite < LIBSSH2_ERROR_NONE) {
3697     *err = libssh2_session_error_to_CURLE((int)nwrite);
3698     nwrite = -1;
3699   }
3700 
3701   return nwrite;
3702 }
3703 
3704 /*
3705  * Return number of received (decrypted) bytes
3706  * or <0 on error
3707  */
sftp_recv(struct Curl_easy * data,int sockindex,char * mem,size_t len,CURLcode * err)3708 static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
3709                          char *mem, size_t len, CURLcode *err)
3710 {
3711   ssize_t nread;
3712   struct connectdata *conn = data->conn;
3713   struct ssh_conn *sshc = &conn->proto.sshc;
3714   (void)sockindex;
3715 
3716   nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
3717 
3718   ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN) ? TRUE : FALSE);
3719 
3720   if(nread == LIBSSH2_ERROR_EAGAIN) {
3721     *err = CURLE_AGAIN;
3722     nread = -1;
3723 
3724   }
3725   else if(nread < 0) {
3726     *err = libssh2_session_error_to_CURLE((int)nread);
3727   }
3728   return nread;
3729 }
3730 
sftp_libssh2_strerror(unsigned long err)3731 static const char *sftp_libssh2_strerror(unsigned long err)
3732 {
3733   switch(err) {
3734     case LIBSSH2_FX_NO_SUCH_FILE:
3735       return "No such file or directory";
3736 
3737     case LIBSSH2_FX_PERMISSION_DENIED:
3738       return "Permission denied";
3739 
3740     case LIBSSH2_FX_FAILURE:
3741       return "Operation failed";
3742 
3743     case LIBSSH2_FX_BAD_MESSAGE:
3744       return "Bad message from SFTP server";
3745 
3746     case LIBSSH2_FX_NO_CONNECTION:
3747       return "Not connected to SFTP server";
3748 
3749     case LIBSSH2_FX_CONNECTION_LOST:
3750       return "Connection to SFTP server lost";
3751 
3752     case LIBSSH2_FX_OP_UNSUPPORTED:
3753       return "Operation not supported by SFTP server";
3754 
3755     case LIBSSH2_FX_INVALID_HANDLE:
3756       return "Invalid handle";
3757 
3758     case LIBSSH2_FX_NO_SUCH_PATH:
3759       return "No such file or directory";
3760 
3761     case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3762       return "File already exists";
3763 
3764     case LIBSSH2_FX_WRITE_PROTECT:
3765       return "File is write protected";
3766 
3767     case LIBSSH2_FX_NO_MEDIA:
3768       return "No media";
3769 
3770     case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3771       return "Disk full";
3772 
3773     case LIBSSH2_FX_QUOTA_EXCEEDED:
3774       return "User quota exceeded";
3775 
3776     case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3777       return "Unknown principle";
3778 
3779     case LIBSSH2_FX_LOCK_CONFlICT:
3780       return "File lock conflict";
3781 
3782     case LIBSSH2_FX_DIR_NOT_EMPTY:
3783       return "Directory not empty";
3784 
3785     case LIBSSH2_FX_NOT_A_DIRECTORY:
3786       return "Not a directory";
3787 
3788     case LIBSSH2_FX_INVALID_FILENAME:
3789       return "Invalid filename";
3790 
3791     case LIBSSH2_FX_LINK_LOOP:
3792       return "Link points to itself";
3793   }
3794   return "Unknown error in libssh2";
3795 }
3796 
Curl_ssh_init(void)3797 CURLcode Curl_ssh_init(void)
3798 {
3799 #ifdef HAVE_LIBSSH2_INIT
3800   if(libssh2_init(0)) {
3801     DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
3802     return CURLE_FAILED_INIT;
3803   }
3804 #endif
3805   return CURLE_OK;
3806 }
3807 
Curl_ssh_cleanup(void)3808 void Curl_ssh_cleanup(void)
3809 {
3810 #ifdef HAVE_LIBSSH2_EXIT
3811   (void)libssh2_exit();
3812 #endif
3813 }
3814 
Curl_ssh_version(char * buffer,size_t buflen)3815 void Curl_ssh_version(char *buffer, size_t buflen)
3816 {
3817   (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION);
3818 }
3819 
3820 /* The SSH session is associated with the *CONNECTION* but the callback user
3821  * pointer is an easy handle pointer. This function allows us to reassign the
3822  * user pointer to the *CURRENT* (new) easy handle.
3823  */
ssh_attach(struct Curl_easy * data,struct connectdata * conn)3824 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
3825 {
3826   DEBUGASSERT(data);
3827   DEBUGASSERT(conn);
3828   if(conn->handler->protocol & PROTO_FAMILY_SSH) {
3829     struct ssh_conn *sshc = &conn->proto.sshc;
3830     if(sshc->ssh_session) {
3831       /* only re-attach if the session already exists */
3832       void **abstract = libssh2_session_abstract(sshc->ssh_session);
3833       *abstract = data;
3834     }
3835   }
3836 }
3837 #endif /* USE_LIBSSH2 */
3838