Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 2017 Red Hat, Inc.
      9  *
     10  * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
     11  *          Robert Kolcun, Andreas Schneider
     12  *
     13  * This software is licensed as described in the file COPYING, which
     14  * you should have received as part of this distribution. The terms
     15  * are also available at https://curl.haxx.se/docs/copyright.html.
     16  *
     17  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     18  * copies of the Software, and permit persons to whom the Software is
     19  * furnished to do so, under the terms of the COPYING file.
     20  *
     21  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     22  * KIND, either express or implied.
     23  *
     24  ***************************************************************************/
     25 
     26 #include "curl_setup.h"
     27 
     28 #ifdef USE_LIBSSH
     29 
     30 #include <limits.h>
     31 
     32 #include <libssh/libssh.h>
     33 #include <libssh/sftp.h>
     34 
     35 #ifdef HAVE_FCNTL_H
     36 #include <fcntl.h>
     37 #endif
     38 
     39 #ifdef HAVE_NETINET_IN_H
     40 #include <netinet/in.h>
     41 #endif
     42 #ifdef HAVE_ARPA_INET_H
     43 #include <arpa/inet.h>
     44 #endif
     45 #ifdef HAVE_UTSNAME_H
     46 #include <sys/utsname.h>
     47 #endif
     48 #ifdef HAVE_NETDB_H
     49 #include <netdb.h>
     50 #endif
     51 #ifdef __VMS
     52 #include <in.h>
     53 #include <inet.h>
     54 #endif
     55 
     56 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
     57 #undef in_addr_t
     58 #define in_addr_t unsigned long
     59 #endif
     60 
     61 #include <curl/curl.h>
     62 #include "urldata.h"
     63 #include "sendf.h"
     64 #include "hostip.h"
     65 #include "progress.h"
     66 #include "transfer.h"
     67 #include "escape.h"
     68 #include "http.h"               /* for HTTP proxy tunnel stuff */
     69 #include "ssh.h"
     70 #include "url.h"
     71 #include "speedcheck.h"
     72 #include "getinfo.h"
     73 #include "strdup.h"
     74 #include "strcase.h"
     75 #include "vtls/vtls.h"
     76 #include "connect.h"
     77 #include "strerror.h"
     78 #include "inet_ntop.h"
     79 #include "parsedate.h"          /* for the week day and month names */
     80 #include "sockaddr.h"           /* required for Curl_sockaddr_storage */
     81 #include "strtoofft.h"
     82 #include "multiif.h"
     83 #include "select.h"
     84 #include "warnless.h"
     85 
     86 /* for permission and open flags */
     87 #include <sys/types.h>
     88 #include <sys/stat.h>
     89 #include <unistd.h>
     90 #include <fcntl.h>
     91 
     92 /* The last 3 #include files should be in this order */
     93 #include "curl_printf.h"
     94 #include "curl_memory.h"
     95 #include "memdebug.h"
     96 #include "curl_path.h"
     97 
     98 /* Local functions: */
     99 static CURLcode myssh_connect(struct connectdata *conn, bool *done);
    100 static CURLcode myssh_multi_statemach(struct connectdata *conn,
    101                                       bool *done);
    102 static CURLcode myssh_do_it(struct connectdata *conn, bool *done);
    103 
    104 static CURLcode scp_done(struct connectdata *conn,
    105                          CURLcode, bool premature);
    106 static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done);
    107 static CURLcode scp_disconnect(struct connectdata *conn,
    108                                bool dead_connection);
    109 
    110 static CURLcode sftp_done(struct connectdata *conn,
    111                           CURLcode, bool premature);
    112 static CURLcode sftp_doing(struct connectdata *conn,
    113                            bool *dophase_done);
    114 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
    115 static
    116 CURLcode sftp_perform(struct connectdata *conn,
    117                       bool *connected,
    118                       bool *dophase_done);
    119 
    120 static void sftp_quote(struct connectdata *conn);
    121 static void sftp_quote_stat(struct connectdata *conn);
    122 
    123 static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock,
    124                          int numsocks);
    125 
    126 static int myssh_perform_getsock(const struct connectdata *conn,
    127                                  curl_socket_t *sock,
    128                                  int numsocks);
    129 
    130 static CURLcode myssh_setup_connection(struct connectdata *conn);
    131 
    132 /*
    133  * SCP protocol handler.
    134  */
    135 
    136 const struct Curl_handler Curl_handler_scp = {
    137   "SCP",                        /* scheme */
    138   myssh_setup_connection,       /* setup_connection */
    139   myssh_do_it,                  /* do_it */
    140   scp_done,                     /* done */
    141   ZERO_NULL,                    /* do_more */
    142   myssh_connect,                /* connect_it */
    143   myssh_multi_statemach,        /* connecting */
    144   scp_doing,                    /* doing */
    145   myssh_getsock,                /* proto_getsock */
    146   myssh_getsock,                /* doing_getsock */
    147   ZERO_NULL,                    /* domore_getsock */
    148   myssh_perform_getsock,        /* perform_getsock */
    149   scp_disconnect,               /* disconnect */
    150   ZERO_NULL,                    /* readwrite */
    151   ZERO_NULL,                    /* connection_check */
    152   PORT_SSH,                     /* defport */
    153   CURLPROTO_SCP,                /* protocol */
    154   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */
    155 };
    156 
    157 /*
    158  * SFTP protocol handler.
    159  */
    160 
    161 const struct Curl_handler Curl_handler_sftp = {
    162   "SFTP",                               /* scheme */
    163   myssh_setup_connection,               /* setup_connection */
    164   myssh_do_it,                          /* do_it */
    165   sftp_done,                            /* done */
    166   ZERO_NULL,                            /* do_more */
    167   myssh_connect,                        /* connect_it */
    168   myssh_multi_statemach,                /* connecting */
    169   sftp_doing,                           /* doing */
    170   myssh_getsock,                        /* proto_getsock */
    171   myssh_getsock,                        /* doing_getsock */
    172   ZERO_NULL,                            /* domore_getsock */
    173   myssh_perform_getsock,                /* perform_getsock */
    174   sftp_disconnect,                      /* disconnect */
    175   ZERO_NULL,                            /* readwrite */
    176   ZERO_NULL,                            /* connection_check */
    177   PORT_SSH,                             /* defport */
    178   CURLPROTO_SFTP,                       /* protocol */
    179   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
    180   | PROTOPT_NOURLQUERY                  /* flags */
    181 };
    182 
    183 static CURLcode sftp_error_to_CURLE(int err)
    184 {
    185   switch(err) {
    186     case SSH_FX_OK:
    187       return CURLE_OK;
    188 
    189     case SSH_FX_NO_SUCH_FILE:
    190     case SSH_FX_NO_SUCH_PATH:
    191       return CURLE_REMOTE_FILE_NOT_FOUND;
    192 
    193     case SSH_FX_PERMISSION_DENIED:
    194     case SSH_FX_WRITE_PROTECT:
    195       return CURLE_REMOTE_ACCESS_DENIED;
    196 
    197     case SSH_FX_FILE_ALREADY_EXISTS:
    198       return CURLE_REMOTE_FILE_EXISTS;
    199 
    200     default:
    201       break;
    202   }
    203 
    204   return CURLE_SSH;
    205 }
    206 
    207 /*
    208  * SSH State machine related code
    209  */
    210 /* This is the ONLY way to change SSH state! */
    211 static void state(struct connectdata *conn, sshstate nowstate)
    212 {
    213   struct ssh_conn *sshc = &conn->proto.sshc;
    214 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
    215   /* for debug purposes */
    216   static const char *const names[] = {
    217     "SSH_STOP",
    218     "SSH_INIT",
    219     "SSH_S_STARTUP",
    220     "SSH_HOSTKEY",
    221     "SSH_AUTHLIST",
    222     "SSH_AUTH_PKEY_INIT",
    223     "SSH_AUTH_PKEY",
    224     "SSH_AUTH_PASS_INIT",
    225     "SSH_AUTH_PASS",
    226     "SSH_AUTH_AGENT_INIT",
    227     "SSH_AUTH_AGENT_LIST",
    228     "SSH_AUTH_AGENT",
    229     "SSH_AUTH_HOST_INIT",
    230     "SSH_AUTH_HOST",
    231     "SSH_AUTH_KEY_INIT",
    232     "SSH_AUTH_KEY",
    233     "SSH_AUTH_GSSAPI",
    234     "SSH_AUTH_DONE",
    235     "SSH_SFTP_INIT",
    236     "SSH_SFTP_REALPATH",
    237     "SSH_SFTP_QUOTE_INIT",
    238     "SSH_SFTP_POSTQUOTE_INIT",
    239     "SSH_SFTP_QUOTE",
    240     "SSH_SFTP_NEXT_QUOTE",
    241     "SSH_SFTP_QUOTE_STAT",
    242     "SSH_SFTP_QUOTE_SETSTAT",
    243     "SSH_SFTP_QUOTE_SYMLINK",
    244     "SSH_SFTP_QUOTE_MKDIR",
    245     "SSH_SFTP_QUOTE_RENAME",
    246     "SSH_SFTP_QUOTE_RMDIR",
    247     "SSH_SFTP_QUOTE_UNLINK",
    248     "SSH_SFTP_QUOTE_STATVFS",
    249     "SSH_SFTP_GETINFO",
    250     "SSH_SFTP_FILETIME",
    251     "SSH_SFTP_TRANS_INIT",
    252     "SSH_SFTP_UPLOAD_INIT",
    253     "SSH_SFTP_CREATE_DIRS_INIT",
    254     "SSH_SFTP_CREATE_DIRS",
    255     "SSH_SFTP_CREATE_DIRS_MKDIR",
    256     "SSH_SFTP_READDIR_INIT",
    257     "SSH_SFTP_READDIR",
    258     "SSH_SFTP_READDIR_LINK",
    259     "SSH_SFTP_READDIR_BOTTOM",
    260     "SSH_SFTP_READDIR_DONE",
    261     "SSH_SFTP_DOWNLOAD_INIT",
    262     "SSH_SFTP_DOWNLOAD_STAT",
    263     "SSH_SFTP_CLOSE",
    264     "SSH_SFTP_SHUTDOWN",
    265     "SSH_SCP_TRANS_INIT",
    266     "SSH_SCP_UPLOAD_INIT",
    267     "SSH_SCP_DOWNLOAD_INIT",
    268     "SSH_SCP_DOWNLOAD",
    269     "SSH_SCP_DONE",
    270     "SSH_SCP_SEND_EOF",
    271     "SSH_SCP_WAIT_EOF",
    272     "SSH_SCP_WAIT_CLOSE",
    273     "SSH_SCP_CHANNEL_FREE",
    274     "SSH_SESSION_DISCONNECT",
    275     "SSH_SESSION_FREE",
    276     "QUIT"
    277   };
    278 
    279 
    280   if(sshc->state != nowstate) {
    281     infof(conn->data, "SSH %p state change from %s to %s\n",
    282           (void *) sshc, names[sshc->state], names[nowstate]);
    283   }
    284 #endif
    285 
    286   sshc->state = nowstate;
    287 }
    288 
    289 /* Multiple options:
    290  * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
    291  *    hash (90s style auth, not sure we should have it here)
    292  * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
    293  *    use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
    294  *    is returned by it.
    295  * 3. none of the above. We only accept if it is present on known hosts.
    296  *
    297  * Returns SSH_OK or SSH_ERROR.
    298  */
    299 static int myssh_is_known(struct connectdata *conn)
    300 {
    301   int rc;
    302   struct Curl_easy *data = conn->data;
    303   struct ssh_conn *sshc = &conn->proto.sshc;
    304   ssh_key pubkey;
    305   size_t hlen;
    306   unsigned char *hash = NULL;
    307   char *base64 = NULL;
    308   int vstate;
    309   enum curl_khmatch keymatch;
    310   struct curl_khkey foundkey;
    311   curl_sshkeycallback func =
    312     data->set.ssh_keyfunc;
    313 
    314   rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
    315   if(rc != SSH_OK)
    316     return rc;
    317 
    318   if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
    319     rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
    320                                 &hash, &hlen);
    321     if(rc != SSH_OK)
    322       goto cleanup;
    323 
    324     if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) ||
    325        memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) {
    326       rc = SSH_ERROR;
    327       goto cleanup;
    328     }
    329 
    330     rc = SSH_OK;
    331     goto cleanup;
    332   }
    333 
    334   if(data->set.ssl.primary.verifyhost != TRUE) {
    335     rc = SSH_OK;
    336     goto cleanup;
    337   }
    338 
    339   vstate = ssh_is_server_known(sshc->ssh_session);
    340   switch(vstate) {
    341     case SSH_SERVER_KNOWN_OK:
    342       keymatch = CURLKHMATCH_OK;
    343       break;
    344     case SSH_SERVER_FILE_NOT_FOUND:
    345       /* fallthrough */
    346     case SSH_SERVER_NOT_KNOWN:
    347       keymatch = CURLKHMATCH_MISSING;
    348       break;
    349   default:
    350       keymatch = CURLKHMATCH_MISMATCH;
    351       break;
    352   }
    353 
    354   if(func) { /* use callback to determine action */
    355     rc = ssh_pki_export_pubkey_base64(pubkey, &base64);
    356     if(rc != SSH_OK)
    357       goto cleanup;
    358 
    359     foundkey.key = base64;
    360     foundkey.len = strlen(base64);
    361 
    362     switch(ssh_key_type(pubkey)) {
    363       case SSH_KEYTYPE_RSA:
    364         foundkey.keytype = CURLKHTYPE_RSA;
    365         break;
    366       case SSH_KEYTYPE_RSA1:
    367         foundkey.keytype = CURLKHTYPE_RSA1;
    368         break;
    369       case SSH_KEYTYPE_ECDSA:
    370         foundkey.keytype = CURLKHTYPE_ECDSA;
    371         break;
    372 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
    373       case SSH_KEYTYPE_ED25519:
    374         foundkey.keytype = CURLKHTYPE_ED25519;
    375         break;
    376 #endif
    377       case SSH_KEYTYPE_DSS:
    378         foundkey.keytype = CURLKHTYPE_DSS;
    379         break;
    380       default:
    381         rc = SSH_ERROR;
    382         goto cleanup;
    383     }
    384 
    385     /* we don't have anything equivalent to knownkey. Always NULL */
    386     rc = func(data, NULL, &foundkey, /* from the remote host */
    387               keymatch, data->set.ssh_keyfunc_userp);
    388 
    389     switch(rc) {
    390       case CURLKHSTAT_FINE_ADD_TO_FILE:
    391         rc = ssh_write_knownhost(sshc->ssh_session);
    392         if(rc != SSH_OK) {
    393           goto cleanup;
    394         }
    395         break;
    396       case CURLKHSTAT_FINE:
    397         break;
    398       default: /* REJECT/DEFER */
    399         rc = SSH_ERROR;
    400         goto cleanup;
    401     }
    402   }
    403   else {
    404     if(keymatch != CURLKHMATCH_OK) {
    405       rc = SSH_ERROR;
    406       goto cleanup;
    407     }
    408   }
    409   rc = SSH_OK;
    410 
    411 cleanup:
    412   if(hash)
    413     ssh_clean_pubkey_hash(&hash);
    414   ssh_key_free(pubkey);
    415   return rc;
    416 }
    417 
    418 #define MOVE_TO_ERROR_STATE(_r) { \
    419   state(conn, SSH_SESSION_FREE); \
    420   sshc->actualcode = _r; \
    421   rc = SSH_ERROR; \
    422   break; \
    423 }
    424 
    425 #define MOVE_TO_SFTP_CLOSE_STATE() { \
    426   state(conn, SSH_SFTP_CLOSE); \
    427   sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
    428   rc = SSH_ERROR; \
    429   break; \
    430 }
    431 
    432 #define MOVE_TO_LAST_AUTH \
    433   if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
    434     rc = SSH_OK; \
    435     state(conn, SSH_AUTH_PASS_INIT); \
    436     break; \
    437   } \
    438   else { \
    439     MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
    440   }
    441 
    442 #define MOVE_TO_TERTIARY_AUTH \
    443   if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
    444     rc = SSH_OK; \
    445     state(conn, SSH_AUTH_KEY_INIT); \
    446     break; \
    447   } \
    448   else { \
    449     MOVE_TO_LAST_AUTH; \
    450   }
    451 
    452 #define MOVE_TO_SECONDARY_AUTH \
    453   if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
    454     rc = SSH_OK; \
    455     state(conn, SSH_AUTH_GSSAPI); \
    456     break; \
    457   } \
    458   else { \
    459     MOVE_TO_TERTIARY_AUTH; \
    460   }
    461 
    462 static
    463 int myssh_auth_interactive(struct connectdata *conn)
    464 {
    465   int rc;
    466   struct ssh_conn *sshc = &conn->proto.sshc;
    467   int nprompts;
    468 
    469 restart:
    470   switch(sshc->kbd_state) {
    471     case 0:
    472       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
    473       if(rc == SSH_AUTH_AGAIN)
    474         return SSH_AGAIN;
    475 
    476       if(rc != SSH_AUTH_INFO)
    477         return SSH_ERROR;
    478 
    479       nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
    480       if(nprompts == SSH_ERROR || nprompts != 1)
    481         return SSH_ERROR;
    482 
    483       rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd);
    484       if(rc < 0)
    485         return SSH_ERROR;
    486 
    487     /* fallthrough */
    488     case 1:
    489       sshc->kbd_state = 1;
    490 
    491       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
    492       if(rc == SSH_AUTH_AGAIN)
    493         return SSH_AGAIN;
    494       else if(rc == SSH_AUTH_SUCCESS)
    495         rc = SSH_OK;
    496       else if(rc == SSH_AUTH_INFO) {
    497         nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
    498         if(nprompts != 0)
    499           return SSH_ERROR;
    500 
    501         sshc->kbd_state = 2;
    502         goto restart;
    503       }
    504       else
    505         rc = SSH_ERROR;
    506       break;
    507     case 2:
    508       sshc->kbd_state = 2;
    509 
    510       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
    511       if(rc == SSH_AUTH_AGAIN)
    512         return SSH_AGAIN;
    513       else if(rc == SSH_AUTH_SUCCESS)
    514         rc = SSH_OK;
    515       else
    516         rc = SSH_ERROR;
    517 
    518       break;
    519     default:
    520       return SSH_ERROR;
    521   }
    522 
    523   sshc->kbd_state = 0;
    524   return rc;
    525 }
    526 
    527 /*
    528  * ssh_statemach_act() runs the SSH state machine as far as it can without
    529  * blocking and without reaching the end.  The data the pointer 'block' points
    530  * to will be set to TRUE if the libssh function returns SSH_AGAIN
    531  * meaning it wants to be called again when the socket is ready
    532  */
    533 static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
    534 {
    535   CURLcode result = CURLE_OK;
    536   struct Curl_easy *data = conn->data;
    537   struct SSHPROTO *protop = data->req.protop;
    538   struct ssh_conn *sshc = &conn->proto.sshc;
    539   int rc = SSH_NO_ERROR, err;
    540   char *new_readdir_line;
    541   int seekerr = CURL_SEEKFUNC_OK;
    542   const char *err_msg;
    543   *block = 0;                   /* we're not blocking by default */
    544 
    545   do {
    546 
    547     switch(sshc->state) {
    548     case SSH_INIT:
    549       sshc->secondCreateDirs = 0;
    550       sshc->nextstate = SSH_NO_STATE;
    551       sshc->actualcode = CURLE_OK;
    552 
    553 #if 0
    554       ssh_set_log_level(SSH_LOG_PROTOCOL);
    555 #endif
    556 
    557       /* Set libssh to non-blocking, since everything internally is
    558          non-blocking */
    559       ssh_set_blocking(sshc->ssh_session, 0);
    560 
    561       state(conn, SSH_S_STARTUP);
    562       /* fall-through */
    563 
    564     case SSH_S_STARTUP:
    565       rc = ssh_connect(sshc->ssh_session);
    566       if(rc == SSH_AGAIN)
    567         break;
    568 
    569       if(rc != SSH_OK) {
    570         failf(data, "Failure establishing ssh session");
    571         MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
    572       }
    573 
    574       state(conn, SSH_HOSTKEY);
    575 
    576       /* fall-through */
    577     case SSH_HOSTKEY:
    578 
    579       rc = myssh_is_known(conn);
    580       if(rc != SSH_OK) {
    581         MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
    582       }
    583 
    584       state(conn, SSH_AUTHLIST);
    585       /* fall through */
    586     case SSH_AUTHLIST:{
    587         sshc->authed = FALSE;
    588 
    589         rc = ssh_userauth_none(sshc->ssh_session, NULL);
    590         if(rc == SSH_AUTH_AGAIN) {
    591           rc = SSH_AGAIN;
    592           break;
    593         }
    594 
    595         if(rc == SSH_AUTH_SUCCESS) {
    596           sshc->authed = TRUE;
    597           infof(data, "Authenticated with none\n");
    598           state(conn, SSH_AUTH_DONE);
    599           break;
    600         }
    601         else if(rc == SSH_AUTH_ERROR) {
    602           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
    603         }
    604 
    605         sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
    606         if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
    607           state(conn, SSH_AUTH_PKEY_INIT);
    608         }
    609         else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
    610           state(conn, SSH_AUTH_GSSAPI);
    611         }
    612         else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
    613           state(conn, SSH_AUTH_KEY_INIT);
    614         }
    615         else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
    616           state(conn, SSH_AUTH_PASS_INIT);
    617         }
    618         else {                  /* unsupported authentication method */
    619           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
    620         }
    621 
    622         break;
    623       }
    624     case SSH_AUTH_PKEY_INIT:
    625       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
    626         MOVE_TO_SECONDARY_AUTH;
    627       }
    628 
    629       /* Two choices, (1) private key was given on CMD,
    630        * (2) use the "default" keys. */
    631       if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
    632         if(sshc->pubkey && !data->set.ssl.key_passwd) {
    633           rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
    634                                           sshc->pubkey);
    635           if(rc == SSH_AUTH_AGAIN) {
    636             rc = SSH_AGAIN;
    637             break;
    638           }
    639 
    640           if(rc != SSH_OK) {
    641             MOVE_TO_SECONDARY_AUTH;
    642           }
    643         }
    644 
    645         rc = ssh_pki_import_privkey_file(data->
    646                                          set.str[STRING_SSH_PRIVATE_KEY],
    647                                          data->set.ssl.key_passwd, NULL,
    648                                          NULL, &sshc->privkey);
    649         if(rc != SSH_OK) {
    650           failf(data, "Could not load private key file %s",
    651                 data->set.str[STRING_SSH_PRIVATE_KEY]);
    652           break;
    653         }
    654 
    655         state(conn, SSH_AUTH_PKEY);
    656         break;
    657 
    658       }
    659       else {
    660         infof(data, "Authentication using SSH public key file\n");
    661 
    662         rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
    663                                          data->set.ssl.key_passwd);
    664         if(rc == SSH_AUTH_AGAIN) {
    665           rc = SSH_AGAIN;
    666           break;
    667         }
    668         if(rc == SSH_AUTH_SUCCESS) {
    669           rc = SSH_OK;
    670           sshc->authed = TRUE;
    671           infof(data, "Completed public key authentication\n");
    672           state(conn, SSH_AUTH_DONE);
    673           break;
    674         }
    675 
    676         MOVE_TO_SECONDARY_AUTH;
    677       }
    678       break;
    679     case SSH_AUTH_PKEY:
    680       rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
    681       if(rc == SSH_AUTH_AGAIN) {
    682         rc = SSH_AGAIN;
    683         break;
    684       }
    685 
    686       if(rc == SSH_AUTH_SUCCESS) {
    687         sshc->authed = TRUE;
    688         infof(data, "Completed public key authentication\n");
    689         state(conn, SSH_AUTH_DONE);
    690         break;
    691       }
    692       else {
    693         infof(data, "Failed public key authentication (rc: %d)\n", rc);
    694         MOVE_TO_SECONDARY_AUTH;
    695       }
    696       break;
    697 
    698     case SSH_AUTH_GSSAPI:
    699       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
    700         MOVE_TO_TERTIARY_AUTH;
    701       }
    702 
    703       rc = ssh_userauth_gssapi(sshc->ssh_session);
    704       if(rc == SSH_AUTH_AGAIN) {
    705         rc = SSH_AGAIN;
    706         break;
    707       }
    708 
    709       if(rc == SSH_AUTH_SUCCESS) {
    710         rc = SSH_OK;
    711         sshc->authed = TRUE;
    712         infof(data, "Completed gssapi authentication\n");
    713         state(conn, SSH_AUTH_DONE);
    714         break;
    715       }
    716 
    717       MOVE_TO_TERTIARY_AUTH;
    718       break;
    719 
    720     case SSH_AUTH_KEY_INIT:
    721       if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
    722         state(conn, SSH_AUTH_KEY);
    723       }
    724       else {
    725         MOVE_TO_LAST_AUTH;
    726       }
    727       break;
    728 
    729     case SSH_AUTH_KEY:
    730 
    731       /* Authentication failed. Continue with keyboard-interactive now. */
    732       rc = myssh_auth_interactive(conn);
    733       if(rc == SSH_AGAIN) {
    734         break;
    735       }
    736       if(rc == SSH_OK) {
    737         sshc->authed = TRUE;
    738         infof(data, "completed keyboard interactive authentication\n");
    739       }
    740       state(conn, SSH_AUTH_DONE);
    741       break;
    742 
    743     case SSH_AUTH_PASS_INIT:
    744       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
    745         /* Host key authentication is intentionally not implemented */
    746         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
    747       }
    748       state(conn, SSH_AUTH_PASS);
    749       /* fall through */
    750 
    751     case SSH_AUTH_PASS:
    752       rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
    753       if(rc == SSH_AUTH_AGAIN) {
    754         rc = SSH_AGAIN;
    755         break;
    756       }
    757 
    758       if(rc == SSH_AUTH_SUCCESS) {
    759         sshc->authed = TRUE;
    760         infof(data, "Completed password authentication\n");
    761         state(conn, SSH_AUTH_DONE);
    762       }
    763       else {
    764         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
    765       }
    766       break;
    767 
    768     case SSH_AUTH_DONE:
    769       if(!sshc->authed) {
    770         failf(data, "Authentication failure");
    771         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
    772         break;
    773       }
    774 
    775       /*
    776        * At this point we have an authenticated ssh session.
    777        */
    778       infof(data, "Authentication complete\n");
    779 
    780       Curl_pgrsTime(conn->data, TIMER_APPCONNECT);      /* SSH is connected */
    781 
    782       conn->sockfd = ssh_get_fd(sshc->ssh_session);
    783       conn->writesockfd = CURL_SOCKET_BAD;
    784 
    785       if(conn->handler->protocol == CURLPROTO_SFTP) {
    786         state(conn, SSH_SFTP_INIT);
    787         break;
    788       }
    789       infof(data, "SSH CONNECT phase done\n");
    790       state(conn, SSH_STOP);
    791       break;
    792 
    793     case SSH_SFTP_INIT:
    794       ssh_set_blocking(sshc->ssh_session, 1);
    795 
    796       sshc->sftp_session = sftp_new(sshc->ssh_session);
    797       if(!sshc->sftp_session) {
    798         failf(data, "Failure initializing sftp session: %s",
    799               ssh_get_error(sshc->ssh_session));
    800         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
    801         break;
    802       }
    803 
    804       rc = sftp_init(sshc->sftp_session);
    805       if(rc != SSH_OK) {
    806         rc = sftp_get_error(sshc->sftp_session);
    807         failf(data, "Failure initializing sftp session: %s",
    808               ssh_get_error(sshc->ssh_session));
    809         MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
    810         break;
    811       }
    812       state(conn, SSH_SFTP_REALPATH);
    813       /* fall through */
    814     case SSH_SFTP_REALPATH:
    815       /*
    816        * Get the "home" directory
    817        */
    818       sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
    819       if(sshc->homedir == NULL) {
    820         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
    821       }
    822       conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
    823 
    824       /* This is the last step in the SFTP connect phase. Do note that while
    825          we get the homedir here, we get the "workingpath" in the DO action
    826          since the homedir will remain the same between request but the
    827          working path will not. */
    828       DEBUGF(infof(data, "SSH CONNECT phase done\n"));
    829       state(conn, SSH_STOP);
    830       break;
    831 
    832     case SSH_SFTP_QUOTE_INIT:
    833 
    834       result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
    835       if(result) {
    836         sshc->actualcode = result;
    837         state(conn, SSH_STOP);
    838         break;
    839       }
    840 
    841       if(data->set.quote) {
    842         infof(data, "Sending quote commands\n");
    843         sshc->quote_item = data->set.quote;
    844         state(conn, SSH_SFTP_QUOTE);
    845       }
    846       else {
    847         state(conn, SSH_SFTP_GETINFO);
    848       }
    849       break;
    850 
    851     case SSH_SFTP_POSTQUOTE_INIT:
    852       if(data->set.postquote) {
    853         infof(data, "Sending quote commands\n");
    854         sshc->quote_item = data->set.postquote;
    855         state(conn, SSH_SFTP_QUOTE);
    856       }
    857       else {
    858         state(conn, SSH_STOP);
    859       }
    860       break;
    861 
    862     case SSH_SFTP_QUOTE:
    863       /* Send any quote commands */
    864       sftp_quote(conn);
    865       break;
    866 
    867     case SSH_SFTP_NEXT_QUOTE:
    868       Curl_safefree(sshc->quote_path1);
    869       Curl_safefree(sshc->quote_path2);
    870 
    871       sshc->quote_item = sshc->quote_item->next;
    872 
    873       if(sshc->quote_item) {
    874         state(conn, SSH_SFTP_QUOTE);
    875       }
    876       else {
    877         if(sshc->nextstate != SSH_NO_STATE) {
    878           state(conn, sshc->nextstate);
    879           sshc->nextstate = SSH_NO_STATE;
    880         }
    881         else {
    882           state(conn, SSH_SFTP_GETINFO);
    883         }
    884       }
    885       break;
    886 
    887     case SSH_SFTP_QUOTE_STAT:
    888       sftp_quote_stat(conn);
    889       break;
    890 
    891     case SSH_SFTP_QUOTE_SETSTAT:
    892       rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
    893                         sshc->quote_attrs);
    894       if(rc != 0 && !sshc->acceptfail) {
    895         Curl_safefree(sshc->quote_path1);
    896         Curl_safefree(sshc->quote_path2);
    897         failf(data, "Attempt to set SFTP stats failed: %s",
    898               ssh_get_error(sshc->ssh_session));
    899         state(conn, SSH_SFTP_CLOSE);
    900         sshc->nextstate = SSH_NO_STATE;
    901         sshc->actualcode = CURLE_QUOTE_ERROR;
    902         /* sshc->actualcode = sftp_error_to_CURLE(err);
    903          * we do not send the actual error; we return
    904          * the error the libssh2 backend is returning */
    905         break;
    906       }
    907       state(conn, SSH_SFTP_NEXT_QUOTE);
    908       break;
    909 
    910     case SSH_SFTP_QUOTE_SYMLINK:
    911       rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
    912                         sshc->quote_path1);
    913       if(rc != 0 && !sshc->acceptfail) {
    914         Curl_safefree(sshc->quote_path1);
    915         Curl_safefree(sshc->quote_path2);
    916         failf(data, "symlink command failed: %s",
    917               ssh_get_error(sshc->ssh_session));
    918         state(conn, SSH_SFTP_CLOSE);
    919         sshc->nextstate = SSH_NO_STATE;
    920         sshc->actualcode = CURLE_QUOTE_ERROR;
    921         break;
    922       }
    923       state(conn, SSH_SFTP_NEXT_QUOTE);
    924       break;
    925 
    926     case SSH_SFTP_QUOTE_MKDIR:
    927       rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
    928                       (mode_t)data->set.new_directory_perms);
    929       if(rc != 0 && !sshc->acceptfail) {
    930         Curl_safefree(sshc->quote_path1);
    931         failf(data, "mkdir command failed: %s",
    932               ssh_get_error(sshc->ssh_session));
    933         state(conn, SSH_SFTP_CLOSE);
    934         sshc->nextstate = SSH_NO_STATE;
    935         sshc->actualcode = CURLE_QUOTE_ERROR;
    936         break;
    937       }
    938       state(conn, SSH_SFTP_NEXT_QUOTE);
    939       break;
    940 
    941     case SSH_SFTP_QUOTE_RENAME:
    942       rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
    943                        sshc->quote_path2);
    944       if(rc != 0 && !sshc->acceptfail) {
    945         Curl_safefree(sshc->quote_path1);
    946         Curl_safefree(sshc->quote_path2);
    947         failf(data, "rename command failed: %s",
    948               ssh_get_error(sshc->ssh_session));
    949         state(conn, SSH_SFTP_CLOSE);
    950         sshc->nextstate = SSH_NO_STATE;
    951         sshc->actualcode = CURLE_QUOTE_ERROR;
    952         break;
    953       }
    954       state(conn, SSH_SFTP_NEXT_QUOTE);
    955       break;
    956 
    957     case SSH_SFTP_QUOTE_RMDIR:
    958       rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
    959       if(rc != 0 && !sshc->acceptfail) {
    960         Curl_safefree(sshc->quote_path1);
    961         failf(data, "rmdir command failed: %s",
    962               ssh_get_error(sshc->ssh_session));
    963         state(conn, SSH_SFTP_CLOSE);
    964         sshc->nextstate = SSH_NO_STATE;
    965         sshc->actualcode = CURLE_QUOTE_ERROR;
    966         break;
    967       }
    968       state(conn, SSH_SFTP_NEXT_QUOTE);
    969       break;
    970 
    971     case SSH_SFTP_QUOTE_UNLINK:
    972       rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
    973       if(rc != 0 && !sshc->acceptfail) {
    974         Curl_safefree(sshc->quote_path1);
    975         failf(data, "rm command failed: %s",
    976               ssh_get_error(sshc->ssh_session));
    977         state(conn, SSH_SFTP_CLOSE);
    978         sshc->nextstate = SSH_NO_STATE;
    979         sshc->actualcode = CURLE_QUOTE_ERROR;
    980         break;
    981       }
    982       state(conn, SSH_SFTP_NEXT_QUOTE);
    983       break;
    984 
    985     case SSH_SFTP_QUOTE_STATVFS:
    986     {
    987       sftp_statvfs_t statvfs;
    988 
    989       statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
    990       if(!statvfs && !sshc->acceptfail) {
    991         Curl_safefree(sshc->quote_path1);
    992         failf(data, "statvfs command failed: %s",
    993               ssh_get_error(sshc->ssh_session));
    994         state(conn, SSH_SFTP_CLOSE);
    995         sshc->nextstate = SSH_NO_STATE;
    996         sshc->actualcode = CURLE_QUOTE_ERROR;
    997         break;
    998       }
    999       else if(statvfs) {
   1000         char *tmp = aprintf("statvfs:\n"
   1001                             "f_bsize: %llu\n" "f_frsize: %llu\n"
   1002                             "f_blocks: %llu\n" "f_bfree: %llu\n"
   1003                             "f_bavail: %llu\n" "f_files: %llu\n"
   1004                             "f_ffree: %llu\n" "f_favail: %llu\n"
   1005                             "f_fsid: %llu\n" "f_flag: %llu\n"
   1006                             "f_namemax: %llu\n",
   1007                             statvfs->f_bsize, statvfs->f_frsize,
   1008                             statvfs->f_blocks, statvfs->f_bfree,
   1009                             statvfs->f_bavail, statvfs->f_files,
   1010                             statvfs->f_ffree, statvfs->f_favail,
   1011                             statvfs->f_fsid, statvfs->f_flag,
   1012                             statvfs->f_namemax);
   1013         sftp_statvfs_free(statvfs);
   1014 
   1015         if(!tmp) {
   1016           result = CURLE_OUT_OF_MEMORY;
   1017           state(conn, SSH_SFTP_CLOSE);
   1018           sshc->nextstate = SSH_NO_STATE;
   1019           break;
   1020         }
   1021 
   1022         result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
   1023         free(tmp);
   1024         if(result) {
   1025           state(conn, SSH_SFTP_CLOSE);
   1026           sshc->nextstate = SSH_NO_STATE;
   1027           sshc->actualcode = result;
   1028         }
   1029       }
   1030       state(conn, SSH_SFTP_NEXT_QUOTE);
   1031       break;
   1032     }
   1033 
   1034     case SSH_SFTP_GETINFO:
   1035       if(data->set.get_filetime) {
   1036         state(conn, SSH_SFTP_FILETIME);
   1037       }
   1038       else {
   1039         state(conn, SSH_SFTP_TRANS_INIT);
   1040       }
   1041       break;
   1042 
   1043     case SSH_SFTP_FILETIME:
   1044     {
   1045       sftp_attributes attrs;
   1046 
   1047       attrs = sftp_stat(sshc->sftp_session, protop->path);
   1048       if(attrs != 0) {
   1049         data->info.filetime = (long)attrs->mtime;
   1050         sftp_attributes_free(attrs);
   1051       }
   1052 
   1053       state(conn, SSH_SFTP_TRANS_INIT);
   1054       break;
   1055     }
   1056 
   1057     case SSH_SFTP_TRANS_INIT:
   1058       if(data->set.upload)
   1059         state(conn, SSH_SFTP_UPLOAD_INIT);
   1060       else {
   1061         if(protop->path[strlen(protop->path)-1] == '/')
   1062           state(conn, SSH_SFTP_READDIR_INIT);
   1063         else
   1064           state(conn, SSH_SFTP_DOWNLOAD_INIT);
   1065       }
   1066       break;
   1067 
   1068     case SSH_SFTP_UPLOAD_INIT:
   1069     {
   1070       int flags;
   1071 
   1072       if(data->state.resume_from != 0) {
   1073         sftp_attributes attrs;
   1074 
   1075         if(data->state.resume_from < 0) {
   1076           attrs = sftp_stat(sshc->sftp_session, protop->path);
   1077           if(attrs != 0) {
   1078             curl_off_t size = attrs->size;
   1079             if(size < 0) {
   1080               failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
   1081               MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
   1082             }
   1083             data->state.resume_from = attrs->size;
   1084 
   1085             sftp_attributes_free(attrs);
   1086           }
   1087           else {
   1088             data->state.resume_from = 0;
   1089           }
   1090         }
   1091       }
   1092 
   1093       if(data->set.ftp_append)
   1094         /* Try to open for append, but create if nonexisting */
   1095         flags = O_WRONLY|O_CREAT|O_APPEND;
   1096       else if(data->state.resume_from > 0)
   1097         /* If we have restart position then open for append */
   1098         flags = O_WRONLY|O_APPEND;
   1099       else
   1100         /* Clear file before writing (normal behaviour) */
   1101         flags = O_WRONLY|O_APPEND|O_CREAT|O_TRUNC;
   1102 
   1103       if(sshc->sftp_file)
   1104         sftp_close(sshc->sftp_file);
   1105       sshc->sftp_file =
   1106         sftp_open(sshc->sftp_session, protop->path,
   1107                   flags, (mode_t)data->set.new_file_perms);
   1108       if(!sshc->sftp_file) {
   1109         err = sftp_get_error(sshc->sftp_session);
   1110 
   1111         if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
   1112              err == SSH_FX_NO_SUCH_PATH)) &&
   1113              (data->set.ftp_create_missing_dirs &&
   1114              (strlen(protop->path) > 1))) {
   1115                /* try to create the path remotely */
   1116                rc = 0;
   1117                sshc->secondCreateDirs = 1;
   1118                state(conn, SSH_SFTP_CREATE_DIRS_INIT);
   1119                break;
   1120         }
   1121         else {
   1122           MOVE_TO_SFTP_CLOSE_STATE();
   1123         }
   1124       }
   1125 
   1126       /* If we have a restart point then we need to seek to the correct
   1127          position. */
   1128       if(data->state.resume_from > 0) {
   1129         /* Let's read off the proper amount of bytes from the input. */
   1130         if(conn->seek_func) {
   1131           seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
   1132                                     SEEK_SET);
   1133         }
   1134 
   1135         if(seekerr != CURL_SEEKFUNC_OK) {
   1136           curl_off_t passed = 0;
   1137 
   1138           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
   1139             failf(data, "Could not seek stream");
   1140             return CURLE_FTP_COULDNT_USE_REST;
   1141           }
   1142           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
   1143           do {
   1144             size_t readthisamountnow =
   1145               (data->state.resume_from - passed > data->set.buffer_size) ?
   1146               (size_t)data->set.buffer_size :
   1147               curlx_sotouz(data->state.resume_from - passed);
   1148 
   1149             size_t actuallyread =
   1150               data->state.fread_func(data->state.buffer, 1,
   1151                                      readthisamountnow, data->state.in);
   1152 
   1153             passed += actuallyread;
   1154             if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
   1155               /* this checks for greater-than only to make sure that the
   1156                  CURL_READFUNC_ABORT return code still aborts */
   1157               failf(data, "Failed to read data");
   1158               MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
   1159             }
   1160           } while(passed < data->state.resume_from);
   1161         }
   1162 
   1163         /* now, decrease the size of the read */
   1164         if(data->state.infilesize > 0) {
   1165           data->state.infilesize -= data->state.resume_from;
   1166           data->req.size = data->state.infilesize;
   1167           Curl_pgrsSetUploadSize(data, data->state.infilesize);
   1168         }
   1169 
   1170         rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
   1171         if(rc != 0) {
   1172           MOVE_TO_SFTP_CLOSE_STATE();
   1173         }
   1174       }
   1175       if(data->state.infilesize > 0) {
   1176         data->req.size = data->state.infilesize;
   1177         Curl_pgrsSetUploadSize(data, data->state.infilesize);
   1178       }
   1179       /* upload data */
   1180       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
   1181 
   1182       /* not set by Curl_setup_transfer to preserve keepon bits */
   1183       conn->sockfd = conn->writesockfd;
   1184 
   1185       /* store this original bitmask setup to use later on if we can't
   1186          figure out a "real" bitmask */
   1187       sshc->orig_waitfor = data->req.keepon;
   1188 
   1189       /* we want to use the _sending_ function even when the socket turns
   1190          out readable as the underlying libssh sftp send function will deal
   1191          with both accordingly */
   1192       conn->cselect_bits = CURL_CSELECT_OUT;
   1193 
   1194       /* since we don't really wait for anything at this point, we want the
   1195          state machine to move on as soon as possible so we set a very short
   1196          timeout here */
   1197       Curl_expire(data, 0, EXPIRE_RUN_NOW);
   1198 
   1199       state(conn, SSH_STOP);
   1200       break;
   1201     }
   1202 
   1203     case SSH_SFTP_CREATE_DIRS_INIT:
   1204       if(strlen(protop->path) > 1) {
   1205         sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
   1206         state(conn, SSH_SFTP_CREATE_DIRS);
   1207       }
   1208       else {
   1209         state(conn, SSH_SFTP_UPLOAD_INIT);
   1210       }
   1211       break;
   1212 
   1213     case SSH_SFTP_CREATE_DIRS:
   1214       sshc->slash_pos = strchr(sshc->slash_pos, '/');
   1215       if(sshc->slash_pos) {
   1216         *sshc->slash_pos = 0;
   1217 
   1218         infof(data, "Creating directory '%s'\n", protop->path);
   1219         state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
   1220         break;
   1221       }
   1222       state(conn, SSH_SFTP_UPLOAD_INIT);
   1223       break;
   1224 
   1225     case SSH_SFTP_CREATE_DIRS_MKDIR:
   1226       /* 'mode' - parameter is preliminary - default to 0644 */
   1227       rc = sftp_mkdir(sshc->sftp_session, protop->path,
   1228                       (mode_t)data->set.new_directory_perms);
   1229       *sshc->slash_pos = '/';
   1230       ++sshc->slash_pos;
   1231       if(rc < 0) {
   1232         /*
   1233          * Abort if failure wasn't that the dir already exists or the
   1234          * permission was denied (creation might succeed further down the
   1235          * path) - retry on unspecific FAILURE also
   1236          */
   1237         err = sftp_get_error(sshc->sftp_session);
   1238         if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
   1239            (err != SSH_FX_FAILURE) &&
   1240            (err != SSH_FX_PERMISSION_DENIED)) {
   1241           MOVE_TO_SFTP_CLOSE_STATE();
   1242         }
   1243         rc = 0; /* clear rc and continue */
   1244       }
   1245       state(conn, SSH_SFTP_CREATE_DIRS);
   1246       break;
   1247 
   1248     case SSH_SFTP_READDIR_INIT:
   1249       Curl_pgrsSetDownloadSize(data, -1);
   1250       if(data->set.opt_no_body) {
   1251         state(conn, SSH_STOP);
   1252         break;
   1253       }
   1254 
   1255       /*
   1256        * This is a directory that we are trying to get, so produce a directory
   1257        * listing
   1258        */
   1259       sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
   1260                                     protop->path);
   1261       if(!sshc->sftp_dir) {
   1262         failf(data, "Could not open directory for reading: %s",
   1263               ssh_get_error(sshc->ssh_session));
   1264         MOVE_TO_SFTP_CLOSE_STATE();
   1265       }
   1266       state(conn, SSH_SFTP_READDIR);
   1267       break;
   1268 
   1269     case SSH_SFTP_READDIR:
   1270 
   1271       if(sshc->readdir_attrs)
   1272         sftp_attributes_free(sshc->readdir_attrs);
   1273 
   1274       sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
   1275       if(sshc->readdir_attrs) {
   1276         sshc->readdir_filename = sshc->readdir_attrs->name;
   1277         sshc->readdir_longentry = sshc->readdir_attrs->longname;
   1278         sshc->readdir_len = (int)strlen(sshc->readdir_filename);
   1279 
   1280         if(data->set.ftp_list_only) {
   1281           char *tmpLine;
   1282 
   1283           tmpLine = aprintf("%s\n", sshc->readdir_filename);
   1284           if(tmpLine == NULL) {
   1285             state(conn, SSH_SFTP_CLOSE);
   1286             sshc->actualcode = CURLE_OUT_OF_MEMORY;
   1287             break;
   1288           }
   1289           result = Curl_client_write(conn, CLIENTWRITE_BODY,
   1290                                      tmpLine, sshc->readdir_len + 1);
   1291           free(tmpLine);
   1292 
   1293           if(result) {
   1294             state(conn, SSH_STOP);
   1295             break;
   1296           }
   1297           /* since this counts what we send to the client, we include the
   1298              newline in this counter */
   1299           data->req.bytecount += sshc->readdir_len + 1;
   1300 
   1301           /* output debug output if that is requested */
   1302           if(data->set.verbose) {
   1303             Curl_debug(data, CURLINFO_DATA_OUT,
   1304                        (char *)sshc->readdir_filename,
   1305                        sshc->readdir_len, conn);
   1306           }
   1307         }
   1308         else {
   1309           sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
   1310           sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
   1311           sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
   1312           if(!sshc->readdir_line) {
   1313             state(conn, SSH_SFTP_CLOSE);
   1314             sshc->actualcode = CURLE_OUT_OF_MEMORY;
   1315             break;
   1316           }
   1317 
   1318           memcpy(sshc->readdir_line, sshc->readdir_longentry,
   1319                  sshc->readdir_currLen);
   1320           if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
   1321              ((sshc->readdir_attrs->permissions & S_IFMT) ==
   1322               S_IFLNK)) {
   1323             sshc->readdir_linkPath = malloc(PATH_MAX + 1);
   1324             if(sshc->readdir_linkPath == NULL) {
   1325               state(conn, SSH_SFTP_CLOSE);
   1326               sshc->actualcode = CURLE_OUT_OF_MEMORY;
   1327               break;
   1328             }
   1329 
   1330             snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
   1331                      sshc->readdir_filename);
   1332 
   1333             state(conn, SSH_SFTP_READDIR_LINK);
   1334             break;
   1335           }
   1336           state(conn, SSH_SFTP_READDIR_BOTTOM);
   1337           break;
   1338         }
   1339       }
   1340       else if(sshc->readdir_attrs == NULL && sftp_dir_eof(sshc->sftp_dir)) {
   1341         state(conn, SSH_SFTP_READDIR_DONE);
   1342         break;
   1343       }
   1344       else {
   1345         failf(data, "Could not open remote file for reading: %s",
   1346               ssh_get_error(sshc->ssh_session));
   1347         MOVE_TO_SFTP_CLOSE_STATE();
   1348         break;
   1349       }
   1350       break;
   1351 
   1352     case SSH_SFTP_READDIR_LINK:
   1353       if(sshc->readdir_link_attrs)
   1354         sftp_attributes_free(sshc->readdir_link_attrs);
   1355 
   1356       sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session,
   1357                                             sshc->readdir_linkPath);
   1358       if(sshc->readdir_link_attrs == 0) {
   1359         failf(data, "Could not read symlink for reading: %s",
   1360               ssh_get_error(sshc->ssh_session));
   1361         MOVE_TO_SFTP_CLOSE_STATE();
   1362       }
   1363 
   1364       if(sshc->readdir_link_attrs->name == NULL) {
   1365         sshc->readdir_tmp = sftp_readlink(sshc->sftp_session,
   1366                                           sshc->readdir_linkPath);
   1367         if(sshc->readdir_filename == NULL)
   1368           sshc->readdir_len = 0;
   1369         else
   1370           sshc->readdir_len = (int)strlen(sshc->readdir_tmp);
   1371         sshc->readdir_longentry = NULL;
   1372         sshc->readdir_filename = sshc->readdir_tmp;
   1373       }
   1374       else {
   1375         sshc->readdir_len = (int)strlen(sshc->readdir_link_attrs->name);
   1376         sshc->readdir_filename = sshc->readdir_link_attrs->name;
   1377         sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
   1378       }
   1379 
   1380       Curl_safefree(sshc->readdir_linkPath);
   1381 
   1382       /* get room for the filename and extra output */
   1383       sshc->readdir_totalLen += 4 + sshc->readdir_len;
   1384       new_readdir_line = Curl_saferealloc(sshc->readdir_line,
   1385                                           sshc->readdir_totalLen);
   1386       if(!new_readdir_line) {
   1387         sshc->readdir_line = NULL;
   1388         state(conn, SSH_SFTP_CLOSE);
   1389         sshc->actualcode = CURLE_OUT_OF_MEMORY;
   1390         break;
   1391       }
   1392       sshc->readdir_line = new_readdir_line;
   1393 
   1394       sshc->readdir_currLen += snprintf(sshc->readdir_line +
   1395                                         sshc->readdir_currLen,
   1396                                         sshc->readdir_totalLen -
   1397                                         sshc->readdir_currLen,
   1398                                         " -> %s",
   1399                                         sshc->readdir_filename);
   1400 
   1401       sftp_attributes_free(sshc->readdir_link_attrs);
   1402       sshc->readdir_link_attrs = NULL;
   1403       sshc->readdir_filename = NULL;
   1404       sshc->readdir_longentry = NULL;
   1405 
   1406       state(conn, SSH_SFTP_READDIR_BOTTOM);
   1407       /* fall through */
   1408     case SSH_SFTP_READDIR_BOTTOM:
   1409       sshc->readdir_currLen += snprintf(sshc->readdir_line +
   1410                                         sshc->readdir_currLen,
   1411                                         sshc->readdir_totalLen -
   1412                                         sshc->readdir_currLen, "\n");
   1413       result = Curl_client_write(conn, CLIENTWRITE_BODY,
   1414                                  sshc->readdir_line,
   1415                                  sshc->readdir_currLen);
   1416 
   1417       if(!result) {
   1418 
   1419         /* output debug output if that is requested */
   1420         if(data->set.verbose) {
   1421           Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
   1422                      sshc->readdir_currLen, conn);
   1423         }
   1424         data->req.bytecount += sshc->readdir_currLen;
   1425       }
   1426       Curl_safefree(sshc->readdir_line);
   1427       ssh_string_free_char(sshc->readdir_tmp);
   1428       sshc->readdir_tmp = NULL;
   1429 
   1430       if(result) {
   1431         state(conn, SSH_STOP);
   1432       }
   1433       else
   1434         state(conn, SSH_SFTP_READDIR);
   1435       break;
   1436 
   1437     case SSH_SFTP_READDIR_DONE:
   1438       sftp_closedir(sshc->sftp_dir);
   1439       sshc->sftp_dir = NULL;
   1440 
   1441       /* no data to transfer */
   1442       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
   1443       state(conn, SSH_STOP);
   1444       break;
   1445 
   1446     case SSH_SFTP_DOWNLOAD_INIT:
   1447       /*
   1448        * Work on getting the specified file
   1449        */
   1450       if(sshc->sftp_file)
   1451         sftp_close(sshc->sftp_file);
   1452 
   1453       sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
   1454                                   O_RDONLY, (mode_t)data->set.new_file_perms);
   1455       if(!sshc->sftp_file) {
   1456         failf(data, "Could not open remote file for reading: %s",
   1457               ssh_get_error(sshc->ssh_session));
   1458 
   1459         MOVE_TO_SFTP_CLOSE_STATE();
   1460       }
   1461 
   1462       state(conn, SSH_SFTP_DOWNLOAD_STAT);
   1463       break;
   1464 
   1465     case SSH_SFTP_DOWNLOAD_STAT:
   1466     {
   1467       sftp_attributes attrs;
   1468       curl_off_t size;
   1469 
   1470       attrs = sftp_fstat(sshc->sftp_file);
   1471       if(!attrs ||
   1472               !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
   1473               (attrs->size == 0)) {
   1474         /*
   1475          * sftp_fstat didn't return an error, so maybe the server
   1476          * just doesn't support stat()
   1477          * OR the server doesn't return a file size with a stat()
   1478          * OR file size is 0
   1479          */
   1480         data->req.size = -1;
   1481         data->req.maxdownload = -1;
   1482         Curl_pgrsSetDownloadSize(data, -1);
   1483         size = 0;
   1484       }
   1485       else {
   1486         size = attrs->size;
   1487 
   1488         sftp_attributes_free(attrs);
   1489 
   1490         if(size < 0) {
   1491           failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
   1492           return CURLE_BAD_DOWNLOAD_RESUME;
   1493         }
   1494         if(conn->data->state.use_range) {
   1495           curl_off_t from, to;
   1496           char *ptr;
   1497           char *ptr2;
   1498           CURLofft to_t;
   1499           CURLofft from_t;
   1500 
   1501           from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
   1502           if(from_t == CURL_OFFT_FLOW) {
   1503             return CURLE_RANGE_ERROR;
   1504           }
   1505           while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
   1506             ptr++;
   1507           to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
   1508           if(to_t == CURL_OFFT_FLOW) {
   1509             return CURLE_RANGE_ERROR;
   1510           }
   1511           if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
   1512              || (to >= size)) {
   1513             to = size - 1;
   1514           }
   1515           if(from_t) {
   1516             /* from is relative to end of file */
   1517             from = size - to;
   1518             to = size - 1;
   1519           }
   1520           if(from > size) {
   1521             failf(data, "Offset (%"
   1522                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
   1523                   CURL_FORMAT_CURL_OFF_T ")", from, size);
   1524             return CURLE_BAD_DOWNLOAD_RESUME;
   1525           }
   1526           if(from > to) {
   1527             from = to;
   1528             size = 0;
   1529           }
   1530           else {
   1531             size = to - from + 1;
   1532           }
   1533 
   1534           rc = sftp_seek64(sshc->sftp_file, from);
   1535           if(rc != 0) {
   1536             MOVE_TO_SFTP_CLOSE_STATE();
   1537           }
   1538         }
   1539         data->req.size = size;
   1540         data->req.maxdownload = size;
   1541         Curl_pgrsSetDownloadSize(data, size);
   1542       }
   1543 
   1544       /* We can resume if we can seek to the resume position */
   1545       if(data->state.resume_from) {
   1546         if(data->state.resume_from < 0) {
   1547           /* We're supposed to download the last abs(from) bytes */
   1548           if((curl_off_t)size < -data->state.resume_from) {
   1549             failf(data, "Offset (%"
   1550                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
   1551                   CURL_FORMAT_CURL_OFF_T ")",
   1552                   data->state.resume_from, size);
   1553             return CURLE_BAD_DOWNLOAD_RESUME;
   1554           }
   1555           /* download from where? */
   1556           data->state.resume_from += size;
   1557         }
   1558         else {
   1559           if((curl_off_t)size < data->state.resume_from) {
   1560             failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
   1561                   ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
   1562                   data->state.resume_from, size);
   1563             return CURLE_BAD_DOWNLOAD_RESUME;
   1564           }
   1565         }
   1566         /* Does a completed file need to be seeked and started or closed ? */
   1567         /* Now store the number of bytes we are expected to download */
   1568         data->req.size = size - data->state.resume_from;
   1569         data->req.maxdownload = size - data->state.resume_from;
   1570         Curl_pgrsSetDownloadSize(data,
   1571                                  size - data->state.resume_from);
   1572 
   1573         rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
   1574         if(rc != 0) {
   1575           MOVE_TO_SFTP_CLOSE_STATE();
   1576         }
   1577       }
   1578     }
   1579 
   1580     /* Setup the actual download */
   1581     if(data->req.size == 0) {
   1582       /* no data to transfer */
   1583       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
   1584       infof(data, "File already completely downloaded\n");
   1585       state(conn, SSH_STOP);
   1586       break;
   1587     }
   1588     Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
   1589                         FALSE, NULL, -1, NULL);
   1590 
   1591     /* not set by Curl_setup_transfer to preserve keepon bits */
   1592     conn->writesockfd = conn->sockfd;
   1593 
   1594     /* we want to use the _receiving_ function even when the socket turns
   1595        out writableable as the underlying libssh recv function will deal
   1596        with both accordingly */
   1597     conn->cselect_bits = CURL_CSELECT_IN;
   1598 
   1599     if(result) {
   1600       /* this should never occur; the close state should be entered
   1601          at the time the error occurs */
   1602       state(conn, SSH_SFTP_CLOSE);
   1603       sshc->actualcode = result;
   1604     }
   1605     else {
   1606       sshc->sftp_recv_state = 0;
   1607       state(conn, SSH_STOP);
   1608     }
   1609     break;
   1610 
   1611     case SSH_SFTP_CLOSE:
   1612       if(sshc->sftp_file) {
   1613         sftp_close(sshc->sftp_file);
   1614         sshc->sftp_file = NULL;
   1615       }
   1616       Curl_safefree(protop->path);
   1617 
   1618       DEBUGF(infof(data, "SFTP DONE done\n"));
   1619 
   1620       /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
   1621          After nextstate is executed, the control should come back to
   1622          SSH_SFTP_CLOSE to pass the correct result back  */
   1623       if(sshc->nextstate != SSH_NO_STATE &&
   1624          sshc->nextstate != SSH_SFTP_CLOSE) {
   1625         state(conn, sshc->nextstate);
   1626         sshc->nextstate = SSH_SFTP_CLOSE;
   1627       }
   1628       else {
   1629         state(conn, SSH_STOP);
   1630         result = sshc->actualcode;
   1631       }
   1632       break;
   1633 
   1634     case SSH_SFTP_SHUTDOWN:
   1635       /* during times we get here due to a broken transfer and then the
   1636          sftp_handle might not have been taken down so make sure that is done
   1637          before we proceed */
   1638 
   1639       if(sshc->sftp_file) {
   1640         sftp_close(sshc->sftp_file);
   1641         sshc->sftp_file = NULL;
   1642       }
   1643 
   1644       if(sshc->sftp_session) {
   1645         sftp_free(sshc->sftp_session);
   1646         sshc->sftp_session = NULL;
   1647       }
   1648 
   1649       Curl_safefree(sshc->homedir);
   1650       conn->data->state.most_recent_ftp_entrypath = NULL;
   1651 
   1652       state(conn, SSH_SESSION_DISCONNECT);
   1653       break;
   1654 
   1655 
   1656     case SSH_SCP_TRANS_INIT:
   1657       result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
   1658       if(result) {
   1659         sshc->actualcode = result;
   1660         state(conn, SSH_STOP);
   1661         break;
   1662       }
   1663 
   1664       /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
   1665       ssh_set_blocking(sshc->ssh_session, 1);
   1666 
   1667       if(data->set.upload) {
   1668         if(data->state.infilesize < 0) {
   1669           failf(data, "SCP requires a known file size for upload");
   1670           sshc->actualcode = CURLE_UPLOAD_FAILED;
   1671           MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
   1672         }
   1673 
   1674         sshc->scp_session =
   1675           ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
   1676         state(conn, SSH_SCP_UPLOAD_INIT);
   1677       }
   1678       else {
   1679         sshc->scp_session =
   1680           ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
   1681         state(conn, SSH_SCP_DOWNLOAD_INIT);
   1682       }
   1683 
   1684       if(!sshc->scp_session) {
   1685         err_msg = ssh_get_error(sshc->ssh_session);
   1686         failf(conn->data, "%s", err_msg);
   1687         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
   1688       }
   1689 
   1690       break;
   1691 
   1692     case SSH_SCP_UPLOAD_INIT:
   1693 
   1694       rc = ssh_scp_init(sshc->scp_session);
   1695       if(rc != SSH_OK) {
   1696         err_msg = ssh_get_error(sshc->ssh_session);
   1697         failf(conn->data, "%s", err_msg);
   1698         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
   1699       }
   1700 
   1701       rc = ssh_scp_push_file(sshc->scp_session, protop->path,
   1702                              data->state.infilesize,
   1703                              (int)data->set.new_file_perms);
   1704       if(rc != SSH_OK) {
   1705         err_msg = ssh_get_error(sshc->ssh_session);
   1706         failf(conn->data, "%s", err_msg);
   1707         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
   1708       }
   1709 
   1710       /* upload data */
   1711       Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
   1712                           FIRSTSOCKET, NULL);
   1713 
   1714       /* not set by Curl_setup_transfer to preserve keepon bits */
   1715       conn->sockfd = conn->writesockfd;
   1716 
   1717       /* store this original bitmask setup to use later on if we can't
   1718          figure out a "real" bitmask */
   1719       sshc->orig_waitfor = data->req.keepon;
   1720 
   1721       /* we want to use the _sending_ function even when the socket turns
   1722          out readable as the underlying libssh scp send function will deal
   1723          with both accordingly */
   1724       conn->cselect_bits = CURL_CSELECT_OUT;
   1725 
   1726       state(conn, SSH_STOP);
   1727 
   1728       break;
   1729 
   1730     case SSH_SCP_DOWNLOAD_INIT:
   1731 
   1732       rc = ssh_scp_init(sshc->scp_session);
   1733       if(rc != SSH_OK) {
   1734         err_msg = ssh_get_error(sshc->ssh_session);
   1735         failf(conn->data, "%s", err_msg);
   1736         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
   1737       }
   1738       state(conn, SSH_SCP_DOWNLOAD);
   1739       /* fall through */
   1740 
   1741     case SSH_SCP_DOWNLOAD:{
   1742         curl_off_t bytecount;
   1743 
   1744         rc = ssh_scp_pull_request(sshc->scp_session);
   1745         if(rc != SSH_SCP_REQUEST_NEWFILE) {
   1746           err_msg = ssh_get_error(sshc->ssh_session);
   1747           failf(conn->data, "%s", err_msg);
   1748           MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
   1749           break;
   1750         }
   1751 
   1752         /* download data */
   1753         bytecount = ssh_scp_request_get_size(sshc->scp_session);
   1754         data->req.maxdownload = (curl_off_t) bytecount;
   1755         Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1,
   1756                             NULL);
   1757 
   1758         /* not set by Curl_setup_transfer to preserve keepon bits */
   1759         conn->writesockfd = conn->sockfd;
   1760 
   1761         /* we want to use the _receiving_ function even when the socket turns
   1762            out writableable as the underlying libssh recv function will deal
   1763            with both accordingly */
   1764         conn->cselect_bits = CURL_CSELECT_IN;
   1765 
   1766         state(conn, SSH_STOP);
   1767         break;
   1768       }
   1769     case SSH_SCP_DONE:
   1770       if(data->set.upload)
   1771         state(conn, SSH_SCP_SEND_EOF);
   1772       else
   1773         state(conn, SSH_SCP_CHANNEL_FREE);
   1774       break;
   1775 
   1776     case SSH_SCP_SEND_EOF:
   1777       if(sshc->scp_session) {
   1778         rc = ssh_scp_close(sshc->scp_session);
   1779         if(rc == SSH_AGAIN) {
   1780           /* Currently the ssh_scp_close handles waiting for EOF in
   1781            * blocking way.
   1782            */
   1783           break;
   1784         }
   1785         if(rc != SSH_OK) {
   1786           infof(data, "Failed to close libssh scp channel: %s\n",
   1787                 ssh_get_error(sshc->ssh_session));
   1788         }
   1789       }
   1790 
   1791       state(conn, SSH_SCP_CHANNEL_FREE);
   1792       break;
   1793 
   1794     case SSH_SCP_CHANNEL_FREE:
   1795       if(sshc->scp_session) {
   1796         ssh_scp_free(sshc->scp_session);
   1797         sshc->scp_session = NULL;
   1798       }
   1799       DEBUGF(infof(data, "SCP DONE phase complete\n"));
   1800 
   1801       ssh_set_blocking(sshc->ssh_session, 0);
   1802 
   1803       state(conn, SSH_SESSION_DISCONNECT);
   1804       /* fall through */
   1805 
   1806     case SSH_SESSION_DISCONNECT:
   1807       /* during weird times when we've been prematurely aborted, the channel
   1808          is still alive when we reach this state and we MUST kill the channel
   1809          properly first */
   1810       if(sshc->scp_session) {
   1811         ssh_scp_free(sshc->scp_session);
   1812         sshc->scp_session = NULL;
   1813       }
   1814 
   1815       ssh_disconnect(sshc->ssh_session);
   1816 
   1817       Curl_safefree(sshc->homedir);
   1818       conn->data->state.most_recent_ftp_entrypath = NULL;
   1819 
   1820       state(conn, SSH_SESSION_FREE);
   1821       /* fall through */
   1822     case SSH_SESSION_FREE:
   1823       if(sshc->ssh_session) {
   1824         ssh_free(sshc->ssh_session);
   1825         sshc->ssh_session = NULL;
   1826       }
   1827 
   1828       /* worst-case scenario cleanup */
   1829 
   1830       DEBUGASSERT(sshc->ssh_session == NULL);
   1831       DEBUGASSERT(sshc->scp_session == NULL);
   1832 
   1833       if(sshc->readdir_tmp) {
   1834         ssh_string_free_char(sshc->readdir_tmp);
   1835         sshc->readdir_tmp = NULL;
   1836       }
   1837 
   1838       if(sshc->quote_attrs)
   1839         sftp_attributes_free(sshc->quote_attrs);
   1840 
   1841       if(sshc->readdir_attrs)
   1842         sftp_attributes_free(sshc->readdir_attrs);
   1843 
   1844       if(sshc->readdir_link_attrs)
   1845         sftp_attributes_free(sshc->readdir_link_attrs);
   1846 
   1847       if(sshc->privkey)
   1848         ssh_key_free(sshc->privkey);
   1849       if(sshc->pubkey)
   1850         ssh_key_free(sshc->pubkey);
   1851 
   1852       Curl_safefree(sshc->rsa_pub);
   1853       Curl_safefree(sshc->rsa);
   1854 
   1855       Curl_safefree(sshc->quote_path1);
   1856       Curl_safefree(sshc->quote_path2);
   1857 
   1858       Curl_safefree(sshc->homedir);
   1859 
   1860       Curl_safefree(sshc->readdir_line);
   1861       Curl_safefree(sshc->readdir_linkPath);
   1862 
   1863       /* the code we are about to return */
   1864       result = sshc->actualcode;
   1865 
   1866       memset(sshc, 0, sizeof(struct ssh_conn));
   1867 
   1868       connclose(conn, "SSH session free");
   1869       sshc->state = SSH_SESSION_FREE;   /* current */
   1870       sshc->nextstate = SSH_NO_STATE;
   1871       state(conn, SSH_STOP);
   1872       break;
   1873 
   1874     case SSH_QUIT:
   1875       /* fallthrough, just stop! */
   1876     default:
   1877       /* internal error */
   1878       sshc->nextstate = SSH_NO_STATE;
   1879       state(conn, SSH_STOP);
   1880       break;
   1881 
   1882     }
   1883   } while(!rc && (sshc->state != SSH_STOP));
   1884 
   1885 
   1886   if(rc == SSH_AGAIN) {
   1887     /* we would block, we need to wait for the socket to be ready (in the
   1888        right direction too)! */
   1889     *block = TRUE;
   1890   }
   1891 
   1892   return result;
   1893 }
   1894 
   1895 
   1896 /* called by the multi interface to figure out what socket(s) to wait for and
   1897    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
   1898 static int myssh_perform_getsock(const struct connectdata *conn,
   1899                                  curl_socket_t *sock,  /* points to numsocks
   1900                                                           number of sockets */
   1901                                  int numsocks)
   1902 {
   1903   int bitmap = GETSOCK_BLANK;
   1904   (void) numsocks;
   1905 
   1906   sock[0] = conn->sock[FIRSTSOCKET];
   1907 
   1908   if(conn->waitfor & KEEP_RECV)
   1909     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
   1910 
   1911   if(conn->waitfor & KEEP_SEND)
   1912     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
   1913 
   1914   return bitmap;
   1915 }
   1916 
   1917 /* Generic function called by the multi interface to figure out what socket(s)
   1918    to wait for and for what actions during the DOING and PROTOCONNECT states*/
   1919 static int myssh_getsock(struct connectdata *conn,
   1920                          curl_socket_t *sock,  /* points to numsocks
   1921                                                    number of sockets */
   1922                          int numsocks)
   1923 {
   1924   /* if we know the direction we can use the generic *_getsock() function even
   1925      for the protocol_connect and doing states */
   1926   return myssh_perform_getsock(conn, sock, numsocks);
   1927 }
   1928 
   1929 static void myssh_block2waitfor(struct connectdata *conn, bool block)
   1930 {
   1931   struct ssh_conn *sshc = &conn->proto.sshc;
   1932   int dir;
   1933 
   1934   /* If it didn't block, or nothing was returned by ssh_get_poll_flags
   1935    * have the original set */
   1936   conn->waitfor = sshc->orig_waitfor;
   1937 
   1938   if(block) {
   1939     dir = ssh_get_poll_flags(sshc->ssh_session);
   1940     if(dir & SSH_READ_PENDING) {
   1941       /* translate the libssh define bits into our own bit defines */
   1942       conn->waitfor = KEEP_RECV;
   1943     }
   1944     else if(dir & SSH_WRITE_PENDING) {
   1945       conn->waitfor = KEEP_SEND;
   1946     }
   1947   }
   1948 }
   1949 
   1950 /* called repeatedly until done from multi.c */
   1951 static CURLcode myssh_multi_statemach(struct connectdata *conn,
   1952                                       bool *done)
   1953 {
   1954   struct ssh_conn *sshc = &conn->proto.sshc;
   1955   CURLcode result = CURLE_OK;
   1956   bool block;    /* we store the status and use that to provide a ssh_getsock()
   1957                     implementation */
   1958 
   1959   result = myssh_statemach_act(conn, &block);
   1960   *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
   1961   myssh_block2waitfor(conn, block);
   1962 
   1963   return result;
   1964 }
   1965 
   1966 static CURLcode myssh_block_statemach(struct connectdata *conn,
   1967                                       bool disconnect)
   1968 {
   1969   struct ssh_conn *sshc = &conn->proto.sshc;
   1970   CURLcode result = CURLE_OK;
   1971   struct Curl_easy *data = conn->data;
   1972 
   1973   while((sshc->state != SSH_STOP) && !result) {
   1974     bool block;
   1975     timediff_t left = 1000;
   1976     struct curltime now = Curl_now();
   1977 
   1978     result = myssh_statemach_act(conn, &block);
   1979     if(result)
   1980       break;
   1981 
   1982     if(!disconnect) {
   1983       if(Curl_pgrsUpdate(conn))
   1984         return CURLE_ABORTED_BY_CALLBACK;
   1985 
   1986       result = Curl_speedcheck(data, now);
   1987       if(result)
   1988         break;
   1989 
   1990       left = Curl_timeleft(data, NULL, FALSE);
   1991       if(left < 0) {
   1992         failf(data, "Operation timed out");
   1993         return CURLE_OPERATION_TIMEDOUT;
   1994       }
   1995     }
   1996 
   1997     if(!result && block) {
   1998       curl_socket_t sock = conn->sock[FIRSTSOCKET];
   1999       curl_socket_t fd_read = CURL_SOCKET_BAD;
   2000       fd_read = sock;
   2001       /* wait for the socket to become ready */
   2002       (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD,
   2003                                CURL_SOCKET_BAD, left > 1000 ? 1000 : left);
   2004     }
   2005 
   2006   }
   2007 
   2008   return result;
   2009 }
   2010 
   2011 /*
   2012  * SSH setup connection
   2013  */
   2014 static CURLcode myssh_setup_connection(struct connectdata *conn)
   2015 {
   2016   struct SSHPROTO *ssh;
   2017 
   2018   conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
   2019   if(!ssh)
   2020     return CURLE_OUT_OF_MEMORY;
   2021 
   2022   return CURLE_OK;
   2023 }
   2024 
   2025 static Curl_recv scp_recv, sftp_recv;
   2026 static Curl_send scp_send, sftp_send;
   2027 
   2028 /*
   2029  * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
   2030  * do protocol-specific actions at connect-time.
   2031  */
   2032 static CURLcode myssh_connect(struct connectdata *conn, bool *done)
   2033 {
   2034   struct ssh_conn *ssh;
   2035   CURLcode result;
   2036   struct Curl_easy *data = conn->data;
   2037   int rc;
   2038 
   2039   /* initialize per-handle data if not already */
   2040   if(!data->req.protop)
   2041     myssh_setup_connection(conn);
   2042 
   2043   /* We default to persistent connections. We set this already in this connect
   2044      function to make the re-use checks properly be able to check this bit. */
   2045   connkeep(conn, "SSH default");
   2046 
   2047   if(conn->handler->protocol & CURLPROTO_SCP) {
   2048     conn->recv[FIRSTSOCKET] = scp_recv;
   2049     conn->send[FIRSTSOCKET] = scp_send;
   2050   }
   2051   else {
   2052     conn->recv[FIRSTSOCKET] = sftp_recv;
   2053     conn->send[FIRSTSOCKET] = sftp_send;
   2054   }
   2055 
   2056   ssh = &conn->proto.sshc;
   2057 
   2058   ssh->ssh_session = ssh_new();
   2059   if(ssh->ssh_session == NULL) {
   2060     failf(data, "Failure initialising ssh session");
   2061     return CURLE_FAILED_INIT;
   2062   }
   2063 
   2064   if(conn->user) {
   2065     infof(data, "User: %s\n", conn->user);
   2066     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
   2067   }
   2068 
   2069   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
   2070     infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]);
   2071     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
   2072                     data->set.str[STRING_SSH_KNOWNHOSTS]);
   2073   }
   2074 
   2075   ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
   2076   if(conn->remote_port)
   2077     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT,
   2078                     &conn->remote_port);
   2079 
   2080   if(data->set.ssh_compression) {
   2081     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION,
   2082                     "zlib,zlib (at) openssh.com,none");
   2083   }
   2084 
   2085   ssh->privkey = NULL;
   2086   ssh->pubkey = NULL;
   2087 
   2088   if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
   2089     rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
   2090                                     &ssh->pubkey);
   2091     if(rc != SSH_OK) {
   2092       failf(data, "Could not load public key file");
   2093       /* ignore */
   2094     }
   2095   }
   2096 
   2097   /* we do not verify here, we do it at the state machine,
   2098    * after connection */
   2099 
   2100   state(conn, SSH_INIT);
   2101 
   2102   result = myssh_multi_statemach(conn, done);
   2103 
   2104   return result;
   2105 }
   2106 
   2107 /* called from multi.c while DOing */
   2108 static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
   2109 {
   2110   CURLcode result;
   2111 
   2112   result = myssh_multi_statemach(conn, dophase_done);
   2113 
   2114   if(*dophase_done) {
   2115     DEBUGF(infof(conn->data, "DO phase is complete\n"));
   2116   }
   2117   return result;
   2118 }
   2119 
   2120 /*
   2121  ***********************************************************************
   2122  *
   2123  * scp_perform()
   2124  *
   2125  * This is the actual DO function for SCP. Get a file according to
   2126  * the options previously setup.
   2127  */
   2128 
   2129 static
   2130 CURLcode scp_perform(struct connectdata *conn,
   2131                      bool *connected, bool *dophase_done)
   2132 {
   2133   CURLcode result = CURLE_OK;
   2134 
   2135   DEBUGF(infof(conn->data, "DO phase starts\n"));
   2136 
   2137   *dophase_done = FALSE;        /* not done yet */
   2138 
   2139   /* start the first command in the DO phase */
   2140   state(conn, SSH_SCP_TRANS_INIT);
   2141 
   2142   result = myssh_multi_statemach(conn, dophase_done);
   2143 
   2144   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
   2145 
   2146   if(*dophase_done) {
   2147     DEBUGF(infof(conn->data, "DO phase is complete\n"));
   2148   }
   2149 
   2150   return result;
   2151 }
   2152 
   2153 static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
   2154 {
   2155   CURLcode result;
   2156   bool connected = 0;
   2157   struct Curl_easy *data = conn->data;
   2158   struct ssh_conn *sshc = &conn->proto.sshc;
   2159 
   2160   *done = FALSE;                /* default to false */
   2161 
   2162   data->req.size = -1;          /* make sure this is unknown at this point */
   2163 
   2164   sshc->actualcode = CURLE_OK;  /* reset error code */
   2165   sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
   2166                                    variable */
   2167 
   2168   Curl_pgrsSetUploadCounter(data, 0);
   2169   Curl_pgrsSetDownloadCounter(data, 0);
   2170   Curl_pgrsSetUploadSize(data, -1);
   2171   Curl_pgrsSetDownloadSize(data, -1);
   2172 
   2173   if(conn->handler->protocol & CURLPROTO_SCP)
   2174     result = scp_perform(conn, &connected, done);
   2175   else
   2176     result = sftp_perform(conn, &connected, done);
   2177 
   2178   return result;
   2179 }
   2180 
   2181 /* BLOCKING, but the function is using the state machine so the only reason
   2182    this is still blocking is that the multi interface code has no support for
   2183    disconnecting operations that takes a while */
   2184 static CURLcode scp_disconnect(struct connectdata *conn,
   2185                                bool dead_connection)
   2186 {
   2187   CURLcode result = CURLE_OK;
   2188   struct ssh_conn *ssh = &conn->proto.sshc;
   2189   (void) dead_connection;
   2190 
   2191   if(ssh->ssh_session) {
   2192     /* only if there's a session still around to use! */
   2193 
   2194     state(conn, SSH_SESSION_DISCONNECT);
   2195 
   2196     result = myssh_block_statemach(conn, TRUE);
   2197   }
   2198 
   2199   return result;
   2200 }
   2201 
   2202 /* generic done function for both SCP and SFTP called from their specific
   2203    done functions */
   2204 static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
   2205 {
   2206   CURLcode result = CURLE_OK;
   2207   struct SSHPROTO *protop = conn->data->req.protop;
   2208 
   2209   if(!status) {
   2210     /* run the state-machine
   2211 
   2212        TODO: when the multi interface is used, this _really_ should be using
   2213        the ssh_multi_statemach function but we have no general support for
   2214        non-blocking DONE operations!
   2215      */
   2216     result = myssh_block_statemach(conn, FALSE);
   2217   }
   2218   else
   2219     result = status;
   2220 
   2221   if(protop)
   2222     Curl_safefree(protop->path);
   2223   if(Curl_pgrsDone(conn))
   2224     return CURLE_ABORTED_BY_CALLBACK;
   2225 
   2226   conn->data->req.keepon = 0;   /* clear all bits */
   2227   return result;
   2228 }
   2229 
   2230 
   2231 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
   2232                          bool premature)
   2233 {
   2234   (void) premature;             /* not used */
   2235 
   2236   if(!status)
   2237     state(conn, SSH_SCP_DONE);
   2238 
   2239   return myssh_done(conn, status);
   2240 
   2241 }
   2242 
   2243 static ssize_t scp_send(struct connectdata *conn, int sockindex,
   2244                         const void *mem, size_t len, CURLcode *err)
   2245 {
   2246   int rc;
   2247   (void) sockindex; /* we only support SCP on the fixed known primary socket */
   2248   (void) err;
   2249 
   2250   rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);
   2251 
   2252 #if 0
   2253   /* The following code is misleading, mostly added as wishful thinking
   2254    * that libssh at some point will implement non-blocking ssh_scp_write/read.
   2255    * Currently rc can only be number of bytes read or SSH_ERROR. */
   2256   myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE);
   2257 
   2258   if(rc == SSH_AGAIN) {
   2259     *err = CURLE_AGAIN;
   2260     return 0;
   2261   }
   2262   else
   2263 #endif
   2264   if(rc != SSH_OK) {
   2265     *err = CURLE_SSH;
   2266     return -1;
   2267   }
   2268 
   2269   return len;
   2270 }
   2271 
   2272 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
   2273                         char *mem, size_t len, CURLcode *err)
   2274 {
   2275   ssize_t nread;
   2276   (void) err;
   2277   (void) sockindex; /* we only support SCP on the fixed known primary socket */
   2278 
   2279   /* libssh returns int */
   2280   nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);
   2281 
   2282 #if 0
   2283   /* The following code is misleading, mostly added as wishful thinking
   2284    * that libssh at some point will implement non-blocking ssh_scp_write/read.
   2285    * Currently rc can only be SSH_OK or SSH_ERROR. */
   2286 
   2287   myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE);
   2288   if(nread == SSH_AGAIN) {
   2289     *err = CURLE_AGAIN;
   2290     nread = -1;
   2291   }
   2292 #endif
   2293 
   2294   return nread;
   2295 }
   2296 
   2297 /*
   2298  * =============== SFTP ===============
   2299  */
   2300 
   2301 /*
   2302  ***********************************************************************
   2303  *
   2304  * sftp_perform()
   2305  *
   2306  * This is the actual DO function for SFTP. Get a file/directory according to
   2307  * the options previously setup.
   2308  */
   2309 
   2310 static
   2311 CURLcode sftp_perform(struct connectdata *conn,
   2312                       bool *connected,
   2313                       bool *dophase_done)
   2314 {
   2315   CURLcode result = CURLE_OK;
   2316 
   2317   DEBUGF(infof(conn->data, "DO phase starts\n"));
   2318 
   2319   *dophase_done = FALSE; /* not done yet */
   2320 
   2321   /* start the first command in the DO phase */
   2322   state(conn, SSH_SFTP_QUOTE_INIT);
   2323 
   2324   /* run the state-machine */
   2325   result = myssh_multi_statemach(conn, dophase_done);
   2326 
   2327   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
   2328 
   2329   if(*dophase_done) {
   2330     DEBUGF(infof(conn->data, "DO phase is complete\n"));
   2331   }
   2332 
   2333   return result;
   2334 }
   2335 
   2336 /* called from multi.c while DOing */
   2337 static CURLcode sftp_doing(struct connectdata *conn,
   2338                            bool *dophase_done)
   2339 {
   2340   CURLcode result = myssh_multi_statemach(conn, dophase_done);
   2341   if(*dophase_done) {
   2342     DEBUGF(infof(conn->data, "DO phase is complete\n"));
   2343   }
   2344   return result;
   2345 }
   2346 
   2347 /* BLOCKING, but the function is using the state machine so the only reason
   2348    this is still blocking is that the multi interface code has no support for
   2349    disconnecting operations that takes a while */
   2350 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
   2351 {
   2352   CURLcode result = CURLE_OK;
   2353   (void) dead_connection;
   2354 
   2355   DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
   2356 
   2357   if(conn->proto.sshc.ssh_session) {
   2358     /* only if there's a session still around to use! */
   2359     state(conn, SSH_SFTP_SHUTDOWN);
   2360     result = myssh_block_statemach(conn, TRUE);
   2361   }
   2362 
   2363   DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
   2364 
   2365   return result;
   2366 
   2367 }
   2368 
   2369 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
   2370                                bool premature)
   2371 {
   2372   struct ssh_conn *sshc = &conn->proto.sshc;
   2373 
   2374   if(!status) {
   2375     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
   2376        errors that could happen due to open file handles during POSTQUOTE
   2377        operation */
   2378     if(!status && !premature && conn->data->set.postquote) {
   2379       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
   2380       state(conn, SSH_SFTP_CLOSE);
   2381     }
   2382     else
   2383       state(conn, SSH_SFTP_CLOSE);
   2384   }
   2385   return myssh_done(conn, status);
   2386 }
   2387 
   2388 /* return number of sent bytes */
   2389 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
   2390                          const void *mem, size_t len, CURLcode *err)
   2391 {
   2392   ssize_t nwrite;
   2393   (void)sockindex;
   2394 
   2395   nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
   2396 
   2397   myssh_block2waitfor(conn, FALSE);
   2398 
   2399 #if 0 /* not returned by libssh on write */
   2400   if(nwrite == SSH_AGAIN) {
   2401     *err = CURLE_AGAIN;
   2402     nwrite = 0;
   2403   }
   2404   else
   2405 #endif
   2406   if(nwrite < 0) {
   2407     *err = CURLE_SSH;
   2408     nwrite = -1;
   2409   }
   2410 
   2411   return nwrite;
   2412 }
   2413 
   2414 /*
   2415  * Return number of received (decrypted) bytes
   2416  * or <0 on error
   2417  */
   2418 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
   2419                          char *mem, size_t len, CURLcode *err)
   2420 {
   2421   ssize_t nread;
   2422   (void)sockindex;
   2423 
   2424   if(len >= (size_t)1<<32)
   2425     len = (size_t)(1<<31)-1;
   2426 
   2427   switch(conn->proto.sshc.sftp_recv_state) {
   2428     case 0:
   2429       conn->proto.sshc.sftp_file_index =
   2430             sftp_async_read_begin(conn->proto.sshc.sftp_file,
   2431                                   (uint32_t)len);
   2432       if(conn->proto.sshc.sftp_file_index < 0) {
   2433         *err = CURLE_RECV_ERROR;
   2434         return -1;
   2435       }
   2436 
   2437       /* fall-through */
   2438     case 1:
   2439       conn->proto.sshc.sftp_recv_state = 1;
   2440 
   2441       nread = sftp_async_read(conn->proto.sshc.sftp_file,
   2442                               mem, (uint32_t)len,
   2443                               conn->proto.sshc.sftp_file_index);
   2444 
   2445       myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE);
   2446 
   2447       if(nread == SSH_AGAIN) {
   2448         *err = CURLE_AGAIN;
   2449         return -1;
   2450       }
   2451       else if(nread < 0) {
   2452         *err = CURLE_RECV_ERROR;
   2453         return -1;
   2454       }
   2455 
   2456       conn->proto.sshc.sftp_recv_state = 0;
   2457       return nread;
   2458 
   2459     default:
   2460       /* we never reach here */
   2461       return -1;
   2462   }
   2463 }
   2464 
   2465 static void sftp_quote(struct connectdata *conn)
   2466 {
   2467   const char *cp;
   2468   struct Curl_easy *data = conn->data;
   2469   struct SSHPROTO *protop = data->req.protop;
   2470   struct ssh_conn *sshc = &conn->proto.sshc;
   2471   CURLcode result;
   2472 
   2473   /*
   2474    * Support some of the "FTP" commands
   2475    */
   2476   char *cmd = sshc->quote_item->data;
   2477   sshc->acceptfail = FALSE;
   2478 
   2479   /* if a command starts with an asterisk, which a legal SFTP command never
   2480      can, the command will be allowed to fail without it causing any
   2481      aborts or cancels etc. It will cause libcurl to act as if the command
   2482      is successful, whatever the server reponds. */
   2483 
   2484   if(cmd[0] == '*') {
   2485     cmd++;
   2486     sshc->acceptfail = TRUE;
   2487   }
   2488 
   2489   if(strcasecompare("pwd", cmd)) {
   2490     /* output debug output if that is requested */
   2491     char *tmp = aprintf("257 \"%s\" is current directory.\n",
   2492                         protop->path);
   2493     if(!tmp) {
   2494       sshc->actualcode = CURLE_OUT_OF_MEMORY;
   2495       state(conn, SSH_SFTP_CLOSE);
   2496       sshc->nextstate = SSH_NO_STATE;
   2497       return;
   2498     }
   2499     if(data->set.verbose) {
   2500       Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4, conn);
   2501       Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
   2502     }
   2503     /* this sends an FTP-like "header" to the header callback so that the
   2504        current directory can be read very similar to how it is read when
   2505        using ordinary FTP. */
   2506     result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
   2507     free(tmp);
   2508     if(result) {
   2509       state(conn, SSH_SFTP_CLOSE);
   2510       sshc->nextstate = SSH_NO_STATE;
   2511       sshc->actualcode = result;
   2512     }
   2513     else
   2514       state(conn, SSH_SFTP_NEXT_QUOTE);
   2515     return;
   2516   }
   2517 
   2518   /*
   2519    * the arguments following the command must be separated from the
   2520    * command with a space so we can check for it unconditionally
   2521    */
   2522   cp = strchr(cmd, ' ');
   2523   if(cp == NULL) {
   2524     failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
   2525     state(conn, SSH_SFTP_CLOSE);
   2526     sshc->nextstate = SSH_NO_STATE;
   2527     sshc->actualcode = CURLE_QUOTE_ERROR;
   2528     return;
   2529   }
   2530 
   2531   /*
   2532    * also, every command takes at least one argument so we get that
   2533    * first argument right now
   2534    */
   2535   result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
   2536   if(result) {
   2537     if(result == CURLE_OUT_OF_MEMORY)
   2538       failf(data, "Out of memory");
   2539     else
   2540       failf(data, "Syntax error: Bad first parameter");
   2541     state(conn, SSH_SFTP_CLOSE);
   2542     sshc->nextstate = SSH_NO_STATE;
   2543     sshc->actualcode = result;
   2544     return;
   2545   }
   2546 
   2547   /*
   2548    * SFTP is a binary protocol, so we don't send text commands
   2549    * to the server. Instead, we scan for commands used by
   2550    * OpenSSH's sftp program and call the appropriate libssh
   2551    * functions.
   2552    */
   2553   if(strncasecompare(cmd, "chgrp ", 6) ||
   2554      strncasecompare(cmd, "chmod ", 6) ||
   2555      strncasecompare(cmd, "chown ", 6)) {
   2556     /* attribute change */
   2557 
   2558     /* sshc->quote_path1 contains the mode to set */
   2559     /* get the destination */
   2560     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
   2561     if(result) {
   2562       if(result == CURLE_OUT_OF_MEMORY)
   2563         failf(data, "Out of memory");
   2564       else
   2565         failf(data, "Syntax error in chgrp/chmod/chown: "
   2566               "Bad second parameter");
   2567       Curl_safefree(sshc->quote_path1);
   2568       state(conn, SSH_SFTP_CLOSE);
   2569       sshc->nextstate = SSH_NO_STATE;
   2570       sshc->actualcode = result;
   2571       return;
   2572     }
   2573     sshc->quote_attrs = NULL;
   2574     state(conn, SSH_SFTP_QUOTE_STAT);
   2575     return;
   2576   }
   2577   if(strncasecompare(cmd, "ln ", 3) ||
   2578      strncasecompare(cmd, "symlink ", 8)) {
   2579     /* symbolic linking */
   2580     /* sshc->quote_path1 is the source */
   2581     /* get the destination */
   2582     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
   2583     if(result) {
   2584       if(result == CURLE_OUT_OF_MEMORY)
   2585         failf(data, "Out of memory");
   2586       else
   2587         failf(data, "Syntax error in ln/symlink: Bad second parameter");
   2588       Curl_safefree(sshc->quote_path1);
   2589       state(conn, SSH_SFTP_CLOSE);
   2590       sshc->nextstate = SSH_NO_STATE;
   2591       sshc->actualcode = result;
   2592       return;
   2593     }
   2594     state(conn, SSH_SFTP_QUOTE_SYMLINK);
   2595     return;
   2596   }
   2597   else if(strncasecompare(cmd, "mkdir ", 6)) {
   2598     /* create dir */
   2599     state(conn, SSH_SFTP_QUOTE_MKDIR);
   2600     return;
   2601   }
   2602   else if(strncasecompare(cmd, "rename ", 7)) {
   2603     /* rename file */
   2604     /* first param is the source path */
   2605     /* second param is the dest. path */
   2606     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
   2607     if(result) {
   2608       if(result == CURLE_OUT_OF_MEMORY)
   2609         failf(data, "Out of memory");
   2610       else
   2611         failf(data, "Syntax error in rename: Bad second parameter");
   2612       Curl_safefree(sshc->quote_path1);
   2613       state(conn, SSH_SFTP_CLOSE);
   2614       sshc->nextstate = SSH_NO_STATE;
   2615       sshc->actualcode = result;
   2616       return;
   2617     }
   2618     state(conn, SSH_SFTP_QUOTE_RENAME);
   2619     return;
   2620   }
   2621   else if(strncasecompare(cmd, "rmdir ", 6)) {
   2622     /* delete dir */
   2623     state(conn, SSH_SFTP_QUOTE_RMDIR);
   2624     return;
   2625   }
   2626   else if(strncasecompare(cmd, "rm ", 3)) {
   2627     state(conn, SSH_SFTP_QUOTE_UNLINK);
   2628     return;
   2629   }
   2630 #ifdef HAS_STATVFS_SUPPORT
   2631   else if(strncasecompare(cmd, "statvfs ", 8)) {
   2632     state(conn, SSH_SFTP_QUOTE_STATVFS);
   2633     return;
   2634   }
   2635 #endif
   2636 
   2637   failf(data, "Unknown SFTP command");
   2638   Curl_safefree(sshc->quote_path1);
   2639   Curl_safefree(sshc->quote_path2);
   2640   state(conn, SSH_SFTP_CLOSE);
   2641   sshc->nextstate = SSH_NO_STATE;
   2642   sshc->actualcode = CURLE_QUOTE_ERROR;
   2643 }
   2644 
   2645 static void sftp_quote_stat(struct connectdata *conn)
   2646 {
   2647   struct Curl_easy *data = conn->data;
   2648   struct ssh_conn *sshc = &conn->proto.sshc;
   2649   char *cmd = sshc->quote_item->data;
   2650   sshc->acceptfail = FALSE;
   2651 
   2652   /* if a command starts with an asterisk, which a legal SFTP command never
   2653      can, the command will be allowed to fail without it causing any
   2654      aborts or cancels etc. It will cause libcurl to act as if the command
   2655      is successful, whatever the server reponds. */
   2656 
   2657   if(cmd[0] == '*') {
   2658     cmd++;
   2659     sshc->acceptfail = TRUE;
   2660   }
   2661 
   2662   /* We read the file attributes, store them in sshc->quote_attrs
   2663    * and modify them accordingly to command. Then we switch to
   2664    * QUOTE_SETSTAT state to write new ones.
   2665    */
   2666 
   2667   if(sshc->quote_attrs)
   2668     sftp_attributes_free(sshc->quote_attrs);
   2669   sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
   2670   if(sshc->quote_attrs == NULL) {
   2671     Curl_safefree(sshc->quote_path1);
   2672     Curl_safefree(sshc->quote_path2);
   2673     failf(data, "Attempt to get SFTP stats failed: %d",
   2674           sftp_get_error(sshc->sftp_session));
   2675     state(conn, SSH_SFTP_CLOSE);
   2676     sshc->nextstate = SSH_NO_STATE;
   2677     sshc->actualcode = CURLE_QUOTE_ERROR;
   2678     return;
   2679   }
   2680 
   2681   /* Now set the new attributes... */
   2682   if(strncasecompare(cmd, "chgrp", 5)) {
   2683     sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
   2684     if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
   2685         !sshc->acceptfail) {
   2686       Curl_safefree(sshc->quote_path1);
   2687       Curl_safefree(sshc->quote_path2);
   2688       failf(data, "Syntax error: chgrp gid not a number");
   2689       state(conn, SSH_SFTP_CLOSE);
   2690       sshc->nextstate = SSH_NO_STATE;
   2691       sshc->actualcode = CURLE_QUOTE_ERROR;
   2692       return;
   2693     }
   2694     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
   2695   }
   2696   else if(strncasecompare(cmd, "chmod", 5)) {
   2697     mode_t perms;
   2698     perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
   2699     /* permissions are octal */
   2700     if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
   2701       Curl_safefree(sshc->quote_path1);
   2702       Curl_safefree(sshc->quote_path2);
   2703       failf(data, "Syntax error: chmod permissions not a number");
   2704       state(conn, SSH_SFTP_CLOSE);
   2705       sshc->nextstate = SSH_NO_STATE;
   2706       sshc->actualcode = CURLE_QUOTE_ERROR;
   2707       return;
   2708     }
   2709     sshc->quote_attrs->permissions = perms;
   2710     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
   2711   }
   2712   else if(strncasecompare(cmd, "chown", 5)) {
   2713     sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
   2714     if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
   2715         !sshc->acceptfail) {
   2716       Curl_safefree(sshc->quote_path1);
   2717       Curl_safefree(sshc->quote_path2);
   2718       failf(data, "Syntax error: chown uid not a number");
   2719       state(conn, SSH_SFTP_CLOSE);
   2720       sshc->nextstate = SSH_NO_STATE;
   2721       sshc->actualcode = CURLE_QUOTE_ERROR;
   2722       return;
   2723     }
   2724     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
   2725   }
   2726 
   2727   /* Now send the completed structure... */
   2728   state(conn, SSH_SFTP_QUOTE_SETSTAT);
   2729   return;
   2730 }
   2731 
   2732 
   2733 #endif                          /* USE_LIBSSH */
   2734