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