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