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