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