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