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