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