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