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