Annotation of embedaddon/curl/lib/vssh/libssh2.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>