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