ssh.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 /* #define CURL_LIBSSH2_DEBUG */
00024 
00025 #include "curl_setup.h"
00026 
00027 #ifdef USE_LIBSSH2
00028 
00029 #ifdef HAVE_LIMITS_H
00030 #  include <limits.h>
00031 #endif
00032 
00033 #include <libssh2.h>
00034 #include <libssh2_sftp.h>
00035 
00036 #ifdef HAVE_FCNTL_H
00037 #include <fcntl.h>
00038 #endif
00039 
00040 #ifdef HAVE_NETINET_IN_H
00041 #include <netinet/in.h>
00042 #endif
00043 #ifdef HAVE_ARPA_INET_H
00044 #include <arpa/inet.h>
00045 #endif
00046 #ifdef HAVE_UTSNAME_H
00047 #include <sys/utsname.h>
00048 #endif
00049 #ifdef HAVE_NETDB_H
00050 #include <netdb.h>
00051 #endif
00052 #ifdef __VMS
00053 #include <in.h>
00054 #include <inet.h>
00055 #endif
00056 
00057 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
00058 #undef in_addr_t
00059 #define in_addr_t unsigned long
00060 #endif
00061 
00062 #include <curl/curl.h>
00063 #include "urldata.h"
00064 #include "sendf.h"
00065 #include "hostip.h"
00066 #include "progress.h"
00067 #include "transfer.h"
00068 #include "escape.h"
00069 #include "http.h" /* for HTTP proxy tunnel stuff */
00070 #include "ssh.h"
00071 #include "url.h"
00072 #include "speedcheck.h"
00073 #include "getinfo.h"
00074 #include "strdup.h"
00075 #include "strcase.h"
00076 #include "vtls/vtls.h"
00077 #include "connect.h"
00078 #include "strerror.h"
00079 #include "inet_ntop.h"
00080 #include "parsedate.h" /* for the week day and month names */
00081 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
00082 #include "strtoofft.h"
00083 #include "multiif.h"
00084 #include "select.h"
00085 #include "warnless.h"
00086 
00087 /* The last 3 #include files should be in this order */
00088 #include "curl_printf.h"
00089 #include "curl_memory.h"
00090 #include "memdebug.h"
00091 
00092 #ifdef WIN32
00093 #  undef  PATH_MAX
00094 #  define PATH_MAX MAX_PATH
00095 #  ifndef R_OK
00096 #    define R_OK 4
00097 #  endif
00098 #endif
00099 
00100 #ifndef PATH_MAX
00101 #define PATH_MAX 1024 /* just an extra precaution since there are systems that
00102                          have their definition hidden well */
00103 #endif
00104 
00105 #if LIBSSH2_VERSION_NUM >= 0x010206
00106 /* libssh2_sftp_statvfs and friends were added in 1.2.6 */
00107 #define HAS_STATVFS_SUPPORT 1
00108 #endif
00109 
00110 #define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
00111 
00112 #define sftp_libssh2_realpath(s,p,t,m) \
00113         libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
00114                                 (t), (m), LIBSSH2_SFTP_REALPATH)
00115 
00116 /* Local functions: */
00117 static const char *sftp_libssh2_strerror(int err);
00118 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
00119 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
00120 static LIBSSH2_FREE_FUNC(my_libssh2_free);
00121 
00122 static CURLcode get_pathname(const char **cpp, char **path);
00123 
00124 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
00125 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
00126 static CURLcode ssh_do(struct connectdata *conn, bool *done);
00127 
00128 static CURLcode ssh_getworkingpath(struct connectdata *conn,
00129                                    char *homedir, /* when SFTP is used */
00130                                    char **path);
00131 
00132 static CURLcode scp_done(struct connectdata *conn,
00133                          CURLcode, bool premature);
00134 static CURLcode scp_doing(struct connectdata *conn,
00135                           bool *dophase_done);
00136 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
00137 
00138 static CURLcode sftp_done(struct connectdata *conn,
00139                           CURLcode, bool premature);
00140 static CURLcode sftp_doing(struct connectdata *conn,
00141                            bool *dophase_done);
00142 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
00143 static
00144 CURLcode sftp_perform(struct connectdata *conn,
00145                       bool *connected,
00146                       bool *dophase_done);
00147 
00148 static int ssh_getsock(struct connectdata *conn,
00149                        curl_socket_t *sock, /* points to numsocks number
00150                                                of sockets */
00151                        int numsocks);
00152 
00153 static int ssh_perform_getsock(const struct connectdata *conn,
00154                                curl_socket_t *sock, /* points to numsocks
00155                                                        number of sockets */
00156                                int numsocks);
00157 
00158 static CURLcode ssh_setup_connection(struct connectdata *conn);
00159 
00160 /*
00161  * SCP protocol handler.
00162  */
00163 
00164 const struct Curl_handler Curl_handler_scp = {
00165   "SCP",                                /* scheme */
00166   ssh_setup_connection,                 /* setup_connection */
00167   ssh_do,                               /* do_it */
00168   scp_done,                             /* done */
00169   ZERO_NULL,                            /* do_more */
00170   ssh_connect,                          /* connect_it */
00171   ssh_multi_statemach,                  /* connecting */
00172   scp_doing,                            /* doing */
00173   ssh_getsock,                          /* proto_getsock */
00174   ssh_getsock,                          /* doing_getsock */
00175   ZERO_NULL,                            /* domore_getsock */
00176   ssh_perform_getsock,                  /* perform_getsock */
00177   scp_disconnect,                       /* disconnect */
00178   ZERO_NULL,                            /* readwrite */
00179   PORT_SSH,                             /* defport */
00180   CURLPROTO_SCP,                        /* protocol */
00181   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
00182   | PROTOPT_NOURLQUERY                  /* flags */
00183 };
00184 
00185 
00186 /*
00187  * SFTP protocol handler.
00188  */
00189 
00190 const struct Curl_handler Curl_handler_sftp = {
00191   "SFTP",                               /* scheme */
00192   ssh_setup_connection,                 /* setup_connection */
00193   ssh_do,                               /* do_it */
00194   sftp_done,                            /* done */
00195   ZERO_NULL,                            /* do_more */
00196   ssh_connect,                          /* connect_it */
00197   ssh_multi_statemach,                  /* connecting */
00198   sftp_doing,                           /* doing */
00199   ssh_getsock,                          /* proto_getsock */
00200   ssh_getsock,                          /* doing_getsock */
00201   ZERO_NULL,                            /* domore_getsock */
00202   ssh_perform_getsock,                  /* perform_getsock */
00203   sftp_disconnect,                      /* disconnect */
00204   ZERO_NULL,                            /* readwrite */
00205   PORT_SSH,                             /* defport */
00206   CURLPROTO_SFTP,                       /* protocol */
00207   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
00208   | PROTOPT_NOURLQUERY                  /* flags */
00209 };
00210 
00211 static void
00212 kbd_callback(const char *name, int name_len, const char *instruction,
00213              int instruction_len, int num_prompts,
00214              const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
00215              LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
00216              void **abstract)
00217 {
00218   struct connectdata *conn = (struct connectdata *)*abstract;
00219 
00220 #ifdef CURL_LIBSSH2_DEBUG
00221   fprintf(stderr, "name=%s\n", name);
00222   fprintf(stderr, "name_len=%d\n", name_len);
00223   fprintf(stderr, "instruction=%s\n", instruction);
00224   fprintf(stderr, "instruction_len=%d\n", instruction_len);
00225   fprintf(stderr, "num_prompts=%d\n", num_prompts);
00226 #else
00227   (void)name;
00228   (void)name_len;
00229   (void)instruction;
00230   (void)instruction_len;
00231 #endif  /* CURL_LIBSSH2_DEBUG */
00232   if(num_prompts == 1) {
00233     responses[0].text = strdup(conn->passwd);
00234     responses[0].length = curlx_uztoui(strlen(conn->passwd));
00235   }
00236   (void)prompts;
00237   (void)abstract;
00238 } /* kbd_callback */
00239 
00240 static CURLcode sftp_libssh2_error_to_CURLE(int err)
00241 {
00242   switch(err) {
00243     case LIBSSH2_FX_OK:
00244       return CURLE_OK;
00245 
00246     case LIBSSH2_FX_NO_SUCH_FILE:
00247     case LIBSSH2_FX_NO_SUCH_PATH:
00248       return CURLE_REMOTE_FILE_NOT_FOUND;
00249 
00250     case LIBSSH2_FX_PERMISSION_DENIED:
00251     case LIBSSH2_FX_WRITE_PROTECT:
00252     case LIBSSH2_FX_LOCK_CONFlICT:
00253       return CURLE_REMOTE_ACCESS_DENIED;
00254 
00255     case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
00256     case LIBSSH2_FX_QUOTA_EXCEEDED:
00257       return CURLE_REMOTE_DISK_FULL;
00258 
00259     case LIBSSH2_FX_FILE_ALREADY_EXISTS:
00260       return CURLE_REMOTE_FILE_EXISTS;
00261 
00262     case LIBSSH2_FX_DIR_NOT_EMPTY:
00263       return CURLE_QUOTE_ERROR;
00264 
00265     default:
00266       break;
00267   }
00268 
00269   return CURLE_SSH;
00270 }
00271 
00272 static CURLcode libssh2_session_error_to_CURLE(int err)
00273 {
00274   switch(err) {
00275     /* Ordered by order of appearance in libssh2.h */
00276     case LIBSSH2_ERROR_NONE:
00277       return CURLE_OK;
00278 
00279     case LIBSSH2_ERROR_SOCKET_NONE:
00280       return CURLE_COULDNT_CONNECT;
00281 
00282     case LIBSSH2_ERROR_ALLOC:
00283       return CURLE_OUT_OF_MEMORY;
00284 
00285     case LIBSSH2_ERROR_SOCKET_SEND:
00286       return CURLE_SEND_ERROR;
00287 
00288     case LIBSSH2_ERROR_HOSTKEY_INIT:
00289     case LIBSSH2_ERROR_HOSTKEY_SIGN:
00290     case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
00291     case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
00292       return CURLE_PEER_FAILED_VERIFICATION;
00293 
00294     case LIBSSH2_ERROR_PASSWORD_EXPIRED:
00295       return CURLE_LOGIN_DENIED;
00296 
00297     case LIBSSH2_ERROR_SOCKET_TIMEOUT:
00298     case LIBSSH2_ERROR_TIMEOUT:
00299       return CURLE_OPERATION_TIMEDOUT;
00300 
00301     case LIBSSH2_ERROR_EAGAIN:
00302       return CURLE_AGAIN;
00303   }
00304 
00305   /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
00306      error code, and possibly add a few new SSH-related one. We must however
00307      not return or even depend on libssh2 errors in the public libcurl API */
00308 
00309   return CURLE_SSH;
00310 }
00311 
00312 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
00313 {
00314   (void)abstract; /* arg not used */
00315   return malloc(count);
00316 }
00317 
00318 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
00319 {
00320   (void)abstract; /* arg not used */
00321   return realloc(ptr, count);
00322 }
00323 
00324 static LIBSSH2_FREE_FUNC(my_libssh2_free)
00325 {
00326   (void)abstract; /* arg not used */
00327   if(ptr) /* ssh2 agent sometimes call free with null ptr */
00328     free(ptr);
00329 }
00330 
00331 /*
00332  * SSH State machine related code
00333  */
00334 /* This is the ONLY way to change SSH state! */
00335 static void state(struct connectdata *conn, sshstate nowstate)
00336 {
00337   struct ssh_conn *sshc = &conn->proto.sshc;
00338 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
00339   /* for debug purposes */
00340   static const char * const names[] = {
00341     "SSH_STOP",
00342     "SSH_INIT",
00343     "SSH_S_STARTUP",
00344     "SSH_HOSTKEY",
00345     "SSH_AUTHLIST",
00346     "SSH_AUTH_PKEY_INIT",
00347     "SSH_AUTH_PKEY",
00348     "SSH_AUTH_PASS_INIT",
00349     "SSH_AUTH_PASS",
00350     "SSH_AUTH_AGENT_INIT",
00351     "SSH_AUTH_AGENT_LIST",
00352     "SSH_AUTH_AGENT",
00353     "SSH_AUTH_HOST_INIT",
00354     "SSH_AUTH_HOST",
00355     "SSH_AUTH_KEY_INIT",
00356     "SSH_AUTH_KEY",
00357     "SSH_AUTH_DONE",
00358     "SSH_SFTP_INIT",
00359     "SSH_SFTP_REALPATH",
00360     "SSH_SFTP_QUOTE_INIT",
00361     "SSH_SFTP_POSTQUOTE_INIT",
00362     "SSH_SFTP_QUOTE",
00363     "SSH_SFTP_NEXT_QUOTE",
00364     "SSH_SFTP_QUOTE_STAT",
00365     "SSH_SFTP_QUOTE_SETSTAT",
00366     "SSH_SFTP_QUOTE_SYMLINK",
00367     "SSH_SFTP_QUOTE_MKDIR",
00368     "SSH_SFTP_QUOTE_RENAME",
00369     "SSH_SFTP_QUOTE_RMDIR",
00370     "SSH_SFTP_QUOTE_UNLINK",
00371     "SSH_SFTP_QUOTE_STATVFS",
00372     "SSH_SFTP_GETINFO",
00373     "SSH_SFTP_FILETIME",
00374     "SSH_SFTP_TRANS_INIT",
00375     "SSH_SFTP_UPLOAD_INIT",
00376     "SSH_SFTP_CREATE_DIRS_INIT",
00377     "SSH_SFTP_CREATE_DIRS",
00378     "SSH_SFTP_CREATE_DIRS_MKDIR",
00379     "SSH_SFTP_READDIR_INIT",
00380     "SSH_SFTP_READDIR",
00381     "SSH_SFTP_READDIR_LINK",
00382     "SSH_SFTP_READDIR_BOTTOM",
00383     "SSH_SFTP_READDIR_DONE",
00384     "SSH_SFTP_DOWNLOAD_INIT",
00385     "SSH_SFTP_DOWNLOAD_STAT",
00386     "SSH_SFTP_CLOSE",
00387     "SSH_SFTP_SHUTDOWN",
00388     "SSH_SCP_TRANS_INIT",
00389     "SSH_SCP_UPLOAD_INIT",
00390     "SSH_SCP_DOWNLOAD_INIT",
00391     "SSH_SCP_DONE",
00392     "SSH_SCP_SEND_EOF",
00393     "SSH_SCP_WAIT_EOF",
00394     "SSH_SCP_WAIT_CLOSE",
00395     "SSH_SCP_CHANNEL_FREE",
00396     "SSH_SESSION_DISCONNECT",
00397     "SSH_SESSION_FREE",
00398     "QUIT"
00399   };
00400 
00401   if(sshc->state != nowstate) {
00402     infof(conn->data, "SFTP %p state change from %s to %s\n",
00403           (void *)sshc, names[sshc->state], names[nowstate]);
00404   }
00405 #endif
00406 
00407   sshc->state = nowstate;
00408 }
00409 
00410 /* figure out the path to work with in this particular request */
00411 static CURLcode ssh_getworkingpath(struct connectdata *conn,
00412                                    char *homedir,  /* when SFTP is used */
00413                                    char **path) /* returns the  allocated
00414                                                    real path to work with */
00415 {
00416   struct Curl_easy *data = conn->data;
00417   char *real_path = NULL;
00418   char *working_path;
00419   size_t working_path_len;
00420   CURLcode result =
00421     Curl_urldecode(data, data->state.path, 0, &working_path,
00422                    &working_path_len, FALSE);
00423   if(result)
00424     return result;
00425 
00426   /* Check for /~/, indicating relative to the user's home directory */
00427   if(conn->handler->protocol & CURLPROTO_SCP) {
00428     real_path = malloc(working_path_len+1);
00429     if(real_path == NULL) {
00430       free(working_path);
00431       return CURLE_OUT_OF_MEMORY;
00432     }
00433     if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
00434       /* It is referenced to the home directory, so strip the leading '/~/' */
00435       memcpy(real_path, working_path+3, 4 + working_path_len-3);
00436     else
00437       memcpy(real_path, working_path, 1 + working_path_len);
00438   }
00439   else if(conn->handler->protocol & CURLPROTO_SFTP) {
00440     if((working_path_len > 1) && (working_path[1] == '~')) {
00441       size_t homelen = strlen(homedir);
00442       real_path = malloc(homelen + working_path_len + 1);
00443       if(real_path == NULL) {
00444         free(working_path);
00445         return CURLE_OUT_OF_MEMORY;
00446       }
00447       /* It is referenced to the home directory, so strip the
00448          leading '/' */
00449       memcpy(real_path, homedir, homelen);
00450       real_path[homelen] = '/';
00451       real_path[homelen+1] = '\0';
00452       if(working_path_len > 3) {
00453         memcpy(real_path+homelen+1, working_path + 3,
00454                1 + working_path_len -3);
00455       }
00456     }
00457     else {
00458       real_path = malloc(working_path_len+1);
00459       if(real_path == NULL) {
00460         free(working_path);
00461         return CURLE_OUT_OF_MEMORY;
00462       }
00463       memcpy(real_path, working_path, 1+working_path_len);
00464     }
00465   }
00466 
00467   free(working_path);
00468 
00469   /* store the pointer for the caller to receive */
00470   *path = real_path;
00471 
00472   return CURLE_OK;
00473 }
00474 
00475 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
00476 static int sshkeycallback(struct Curl_easy *easy,
00477                           const struct curl_khkey *knownkey, /* known */
00478                           const struct curl_khkey *foundkey, /* found */
00479                           enum curl_khmatch match,
00480                           void *clientp)
00481 {
00482   (void)easy;
00483   (void)knownkey;
00484   (void)foundkey;
00485   (void)clientp;
00486 
00487   /* we only allow perfect matches, and we reject everything else */
00488   return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
00489 }
00490 #endif
00491 
00492 /*
00493  * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
00494  * with 32bit size_t.
00495  */
00496 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
00497 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
00498 #else
00499 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
00500 #endif
00501 
00502 /*
00503  * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
00504  * architectures so we check of the necessary function is present.
00505  */
00506 #ifndef HAVE_LIBSSH2_SCP_SEND64
00507 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
00508 #else
00509 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c),            \
00510                                              (libssh2_uint64_t)d, 0, 0)
00511 #endif
00512 
00513 /*
00514  * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
00515  */
00516 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
00517 #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
00518 #endif
00519 
00520 static CURLcode ssh_knownhost(struct connectdata *conn)
00521 {
00522   CURLcode result = CURLE_OK;
00523 
00524 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
00525   struct Curl_easy *data = conn->data;
00526 
00527   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
00528     /* we're asked to verify the host against a file */
00529     struct ssh_conn *sshc = &conn->proto.sshc;
00530     int rc;
00531     int keytype;
00532     size_t keylen;
00533     const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
00534                                                     &keylen, &keytype);
00535     int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
00536     int keybit = 0;
00537 
00538     if(remotekey) {
00539       /*
00540        * A subject to figure out is what host name we need to pass in here.
00541        * What host name does OpenSSH store in its file if an IDN name is
00542        * used?
00543        */
00544       struct libssh2_knownhost *host;
00545       enum curl_khmatch keymatch;
00546       curl_sshkeycallback func =
00547         data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
00548       struct curl_khkey knownkey;
00549       struct curl_khkey *knownkeyp = NULL;
00550       struct curl_khkey foundkey;
00551 
00552       keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
00553         LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
00554 
00555 #ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
00556       keycheck = libssh2_knownhost_checkp(sshc->kh,
00557                                           conn->host.name,
00558                                           (conn->remote_port != PORT_SSH)?
00559                                           conn->remote_port:-1,
00560                                           remotekey, keylen,
00561                                           LIBSSH2_KNOWNHOST_TYPE_PLAIN|
00562                                           LIBSSH2_KNOWNHOST_KEYENC_RAW|
00563                                           keybit,
00564                                           &host);
00565 #else
00566       keycheck = libssh2_knownhost_check(sshc->kh,
00567                                          conn->host.name,
00568                                          remotekey, keylen,
00569                                          LIBSSH2_KNOWNHOST_TYPE_PLAIN|
00570                                          LIBSSH2_KNOWNHOST_KEYENC_RAW|
00571                                          keybit,
00572                                          &host);
00573 #endif
00574 
00575       infof(data, "SSH host check: %d, key: %s\n", keycheck,
00576             (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
00577             host->key:"<none>");
00578 
00579       /* setup 'knownkey' */
00580       if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
00581         knownkey.key = host->key;
00582         knownkey.len = 0;
00583         knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
00584           CURLKHTYPE_RSA : CURLKHTYPE_DSS;
00585         knownkeyp = &knownkey;
00586       }
00587 
00588       /* setup 'foundkey' */
00589       foundkey.key = remotekey;
00590       foundkey.len = keylen;
00591       foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
00592         CURLKHTYPE_RSA : CURLKHTYPE_DSS;
00593 
00594       /*
00595        * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
00596        * curl_khmatch enum are ever modified, we need to introduce a
00597        * translation table here!
00598        */
00599       keymatch = (enum curl_khmatch)keycheck;
00600 
00601       /* Ask the callback how to behave */
00602       rc = func(data, knownkeyp, /* from the knownhosts file */
00603                 &foundkey, /* from the remote host */
00604                 keymatch, data->set.ssh_keyfunc_userp);
00605     }
00606     else
00607       /* no remotekey means failure! */
00608       rc = CURLKHSTAT_REJECT;
00609 
00610     switch(rc) {
00611     default: /* unknown return codes will equal reject */
00612       /* FALLTHROUGH */
00613     case CURLKHSTAT_REJECT:
00614       state(conn, SSH_SESSION_FREE);
00615       /* FALLTHROUGH */
00616     case CURLKHSTAT_DEFER:
00617       /* DEFER means bail out but keep the SSH_HOSTKEY state */
00618       result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
00619       break;
00620     case CURLKHSTAT_FINE:
00621     case CURLKHSTAT_FINE_ADD_TO_FILE:
00622       /* proceed */
00623       if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
00624         /* the found host+key didn't match but has been told to be fine
00625            anyway so we add it in memory */
00626         int addrc = libssh2_knownhost_add(sshc->kh,
00627                                           conn->host.name, NULL,
00628                                           remotekey, keylen,
00629                                           LIBSSH2_KNOWNHOST_TYPE_PLAIN|
00630                                           LIBSSH2_KNOWNHOST_KEYENC_RAW|
00631                                           keybit, NULL);
00632         if(addrc)
00633           infof(data, "Warning adding the known host %s failed!\n",
00634                 conn->host.name);
00635         else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
00636           /* now we write the entire in-memory list of known hosts to the
00637              known_hosts file */
00638           int wrc =
00639             libssh2_knownhost_writefile(sshc->kh,
00640                                         data->set.str[STRING_SSH_KNOWNHOSTS],
00641                                         LIBSSH2_KNOWNHOST_FILE_OPENSSH);
00642           if(wrc) {
00643             infof(data, "Warning, writing %s failed!\n",
00644                   data->set.str[STRING_SSH_KNOWNHOSTS]);
00645           }
00646         }
00647       }
00648       break;
00649     }
00650   }
00651 #else /* HAVE_LIBSSH2_KNOWNHOST_API */
00652   (void)conn;
00653 #endif
00654   return result;
00655 }
00656 
00657 static CURLcode ssh_check_fingerprint(struct connectdata *conn)
00658 {
00659   struct ssh_conn *sshc = &conn->proto.sshc;
00660   struct Curl_easy *data = conn->data;
00661   const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
00662   char md5buffer[33];
00663   int i;
00664 
00665   const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
00666       LIBSSH2_HOSTKEY_HASH_MD5);
00667 
00668   if(fingerprint) {
00669     /* The fingerprint points to static storage (!), don't free() it. */
00670     for(i = 0; i < 16; i++)
00671       snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
00672     infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
00673   }
00674 
00675   /* Before we authenticate we check the hostkey's MD5 fingerprint
00676    * against a known fingerprint, if available.
00677    */
00678   if(pubkey_md5 && strlen(pubkey_md5) == 32) {
00679     if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
00680       if(fingerprint)
00681         failf(data,
00682             "Denied establishing ssh session: mismatch md5 fingerprint. "
00683             "Remote %s is not equal to %s", md5buffer, pubkey_md5);
00684       else
00685         failf(data,
00686             "Denied establishing ssh session: md5 fingerprint not available");
00687       state(conn, SSH_SESSION_FREE);
00688       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
00689       return sshc->actualcode;
00690     }
00691     else {
00692       infof(data, "MD5 checksum match!\n");
00693       /* as we already matched, we skip the check for known hosts */
00694       return CURLE_OK;
00695     }
00696   }
00697   else
00698     return ssh_knownhost(conn);
00699 }
00700 
00701 /*
00702  * ssh_statemach_act() runs the SSH state machine as far as it can without
00703  * blocking and without reaching the end.  The data the pointer 'block' points
00704  * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
00705  * meaning it wants to be called again when the socket is ready
00706  */
00707 
00708 static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
00709 {
00710   CURLcode result = CURLE_OK;
00711   struct Curl_easy *data = conn->data;
00712   struct SSHPROTO *sftp_scp = data->req.protop;
00713   struct ssh_conn *sshc = &conn->proto.sshc;
00714   curl_socket_t sock = conn->sock[FIRSTSOCKET];
00715   char *new_readdir_line;
00716   int rc = LIBSSH2_ERROR_NONE;
00717   int err;
00718   int seekerr = CURL_SEEKFUNC_OK;
00719   *block = 0; /* we're not blocking by default */
00720 
00721   do {
00722 
00723     switch(sshc->state) {
00724     case SSH_INIT:
00725       sshc->secondCreateDirs = 0;
00726       sshc->nextstate = SSH_NO_STATE;
00727       sshc->actualcode = CURLE_OK;
00728 
00729       /* Set libssh2 to non-blocking, since everything internally is
00730          non-blocking */
00731       libssh2_session_set_blocking(sshc->ssh_session, 0);
00732 
00733       state(conn, SSH_S_STARTUP);
00734       /* fall-through */
00735 
00736     case SSH_S_STARTUP:
00737       rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
00738       if(rc == LIBSSH2_ERROR_EAGAIN) {
00739         break;
00740       }
00741       else if(rc) {
00742         failf(data, "Failure establishing ssh session");
00743         state(conn, SSH_SESSION_FREE);
00744         sshc->actualcode = CURLE_FAILED_INIT;
00745         break;
00746       }
00747 
00748       state(conn, SSH_HOSTKEY);
00749 
00750       /* fall-through */
00751     case SSH_HOSTKEY:
00752       /*
00753        * Before we authenticate we should check the hostkey's fingerprint
00754        * against our known hosts. How that is handled (reading from file,
00755        * whatever) is up to us.
00756        */
00757       result = ssh_check_fingerprint(conn);
00758       if(!result)
00759         state(conn, SSH_AUTHLIST);
00760       /* ssh_check_fingerprint sets state appropriately on error */
00761       break;
00762 
00763     case SSH_AUTHLIST:
00764       /*
00765        * Figure out authentication methods
00766        * NB: As soon as we have provided a username to an openssh server we
00767        * must never change it later. Thus, always specify the correct username
00768        * here, even though the libssh2 docs kind of indicate that it should be
00769        * possible to get a 'generic' list (not user-specific) of authentication
00770        * methods, presumably with a blank username. That won't work in my
00771        * experience.
00772        * So always specify it here.
00773        */
00774       sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
00775                                              conn->user,
00776                                              curlx_uztoui(strlen(conn->user)));
00777 
00778       if(!sshc->authlist) {
00779         if(libssh2_userauth_authenticated(sshc->ssh_session)) {
00780           sshc->authed = TRUE;
00781           infof(data, "SSH user accepted with no authentication\n");
00782           state(conn, SSH_AUTH_DONE);
00783           break;
00784         }
00785         else {
00786           err = libssh2_session_last_errno(sshc->ssh_session);
00787           if(err == LIBSSH2_ERROR_EAGAIN)
00788             rc = LIBSSH2_ERROR_EAGAIN;
00789           else {
00790             state(conn, SSH_SESSION_FREE);
00791             sshc->actualcode = libssh2_session_error_to_CURLE(err);
00792           }
00793           break;
00794         }
00795       }
00796       infof(data, "SSH authentication methods available: %s\n",
00797             sshc->authlist);
00798 
00799       state(conn, SSH_AUTH_PKEY_INIT);
00800       break;
00801 
00802     case SSH_AUTH_PKEY_INIT:
00803       /*
00804        * Check the supported auth types in the order I feel is most secure
00805        * with the requested type of authentication
00806        */
00807       sshc->authed = FALSE;
00808 
00809       if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
00810          (strstr(sshc->authlist, "publickey") != NULL)) {
00811         char *home = NULL;
00812         bool out_of_memory = FALSE;
00813 
00814         sshc->rsa_pub = sshc->rsa = NULL;
00815 
00816         /* To ponder about: should really the lib be messing about with the
00817            HOME environment variable etc? */
00818         home = curl_getenv("HOME");
00819 
00820         if(data->set.str[STRING_SSH_PRIVATE_KEY])
00821           sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
00822         else {
00823           /* If no private key file is specified, try some common paths. */
00824           if(home) {
00825             /* Try ~/.ssh first. */
00826             sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
00827             if(!sshc->rsa)
00828               out_of_memory = TRUE;
00829             else if(access(sshc->rsa, R_OK) != 0) {
00830               Curl_safefree(sshc->rsa);
00831               sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
00832               if(!sshc->rsa)
00833                 out_of_memory = TRUE;
00834               else if(access(sshc->rsa, R_OK) != 0) {
00835                 Curl_safefree(sshc->rsa);
00836               }
00837             }
00838           }
00839           if(!out_of_memory && !sshc->rsa) {
00840             /* Nothing found; try the current dir. */
00841             sshc->rsa = strdup("id_rsa");
00842             if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
00843               Curl_safefree(sshc->rsa);
00844               sshc->rsa = strdup("id_dsa");
00845               if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
00846                 Curl_safefree(sshc->rsa);
00847                 /* Out of guesses. Set to the empty string to avoid
00848                  * surprising info messages. */
00849                 sshc->rsa = strdup("");
00850               }
00851             }
00852           }
00853         }
00854 
00855         /*
00856          * Unless the user explicitly specifies a public key file, let
00857          * libssh2 extract the public key from the private key file.
00858          * This is done by simply passing sshc->rsa_pub = NULL.
00859          */
00860         if(data->set.str[STRING_SSH_PUBLIC_KEY]
00861             /* treat empty string the same way as NULL */
00862             && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
00863           sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
00864           if(!sshc->rsa_pub)
00865             out_of_memory = TRUE;
00866         }
00867 
00868         if(out_of_memory || sshc->rsa == NULL) {
00869           free(home);
00870           Curl_safefree(sshc->rsa);
00871           Curl_safefree(sshc->rsa_pub);
00872           state(conn, SSH_SESSION_FREE);
00873           sshc->actualcode = CURLE_OUT_OF_MEMORY;
00874           break;
00875         }
00876 
00877         sshc->passphrase = data->set.ssl.key_passwd;
00878         if(!sshc->passphrase)
00879           sshc->passphrase = "";
00880 
00881         free(home);
00882 
00883         if(sshc->rsa_pub)
00884           infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
00885         infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
00886 
00887         state(conn, SSH_AUTH_PKEY);
00888       }
00889       else {
00890         state(conn, SSH_AUTH_PASS_INIT);
00891       }
00892       break;
00893 
00894     case SSH_AUTH_PKEY:
00895       /* The function below checks if the files exists, no need to stat() here.
00896        */
00897       rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
00898                                                   conn->user,
00899                                                   curlx_uztoui(
00900                                                     strlen(conn->user)),
00901                                                   sshc->rsa_pub,
00902                                                   sshc->rsa, sshc->passphrase);
00903       if(rc == LIBSSH2_ERROR_EAGAIN) {
00904         break;
00905       }
00906 
00907       Curl_safefree(sshc->rsa_pub);
00908       Curl_safefree(sshc->rsa);
00909 
00910       if(rc == 0) {
00911         sshc->authed = TRUE;
00912         infof(data, "Initialized SSH public key authentication\n");
00913         state(conn, SSH_AUTH_DONE);
00914       }
00915       else {
00916         char *err_msg;
00917         (void)libssh2_session_last_error(sshc->ssh_session,
00918                                          &err_msg, NULL, 0);
00919         infof(data, "SSH public key authentication failed: %s\n", err_msg);
00920         state(conn, SSH_AUTH_PASS_INIT);
00921       }
00922       break;
00923 
00924     case SSH_AUTH_PASS_INIT:
00925       if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
00926          (strstr(sshc->authlist, "password") != NULL)) {
00927         state(conn, SSH_AUTH_PASS);
00928       }
00929       else {
00930         state(conn, SSH_AUTH_HOST_INIT);
00931       }
00932       break;
00933 
00934     case SSH_AUTH_PASS:
00935       rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
00936                                         curlx_uztoui(strlen(conn->user)),
00937                                         conn->passwd,
00938                                         curlx_uztoui(strlen(conn->passwd)),
00939                                         NULL);
00940       if(rc == LIBSSH2_ERROR_EAGAIN) {
00941         break;
00942       }
00943       else if(rc == 0) {
00944         sshc->authed = TRUE;
00945         infof(data, "Initialized password authentication\n");
00946         state(conn, SSH_AUTH_DONE);
00947       }
00948       else {
00949         state(conn, SSH_AUTH_HOST_INIT);
00950         rc = 0; /* clear rc and continue */
00951       }
00952       break;
00953 
00954     case SSH_AUTH_HOST_INIT:
00955       if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
00956          (strstr(sshc->authlist, "hostbased") != NULL)) {
00957         state(conn, SSH_AUTH_HOST);
00958       }
00959       else {
00960         state(conn, SSH_AUTH_AGENT_INIT);
00961       }
00962       break;
00963 
00964     case SSH_AUTH_HOST:
00965       state(conn, SSH_AUTH_AGENT_INIT);
00966       break;
00967 
00968     case SSH_AUTH_AGENT_INIT:
00969 #ifdef HAVE_LIBSSH2_AGENT_API
00970       if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
00971          && (strstr(sshc->authlist, "publickey") != NULL)) {
00972 
00973         /* Connect to the ssh-agent */
00974         /* The agent could be shared by a curl thread i believe
00975            but nothing obvious as keys can be added/removed at any time */
00976         if(!sshc->ssh_agent) {
00977           sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
00978           if(!sshc->ssh_agent) {
00979             infof(data, "Could not create agent object\n");
00980 
00981             state(conn, SSH_AUTH_KEY_INIT);
00982             break;
00983           }
00984         }
00985 
00986         rc = libssh2_agent_connect(sshc->ssh_agent);
00987         if(rc == LIBSSH2_ERROR_EAGAIN)
00988           break;
00989         if(rc < 0) {
00990           infof(data, "Failure connecting to agent\n");
00991           state(conn, SSH_AUTH_KEY_INIT);
00992         }
00993         else {
00994           state(conn, SSH_AUTH_AGENT_LIST);
00995         }
00996       }
00997       else
00998 #endif /* HAVE_LIBSSH2_AGENT_API */
00999         state(conn, SSH_AUTH_KEY_INIT);
01000       break;
01001 
01002     case SSH_AUTH_AGENT_LIST:
01003 #ifdef HAVE_LIBSSH2_AGENT_API
01004       rc = libssh2_agent_list_identities(sshc->ssh_agent);
01005 
01006       if(rc == LIBSSH2_ERROR_EAGAIN)
01007         break;
01008       if(rc < 0) {
01009         infof(data, "Failure requesting identities to agent\n");
01010         state(conn, SSH_AUTH_KEY_INIT);
01011       }
01012       else {
01013         state(conn, SSH_AUTH_AGENT);
01014         sshc->sshagent_prev_identity = NULL;
01015       }
01016 #endif
01017       break;
01018 
01019     case SSH_AUTH_AGENT:
01020 #ifdef HAVE_LIBSSH2_AGENT_API
01021       /* as prev_identity evolves only after an identity user auth finished we
01022          can safely request it again as long as EAGAIN is returned here or by
01023          libssh2_agent_userauth */
01024       rc = libssh2_agent_get_identity(sshc->ssh_agent,
01025                                       &sshc->sshagent_identity,
01026                                       sshc->sshagent_prev_identity);
01027       if(rc == LIBSSH2_ERROR_EAGAIN)
01028         break;
01029 
01030       if(rc == 0) {
01031         rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
01032                                     sshc->sshagent_identity);
01033 
01034         if(rc < 0) {
01035           if(rc != LIBSSH2_ERROR_EAGAIN)
01036             /* tried and failed? go to next identity */
01037             sshc->sshagent_prev_identity = sshc->sshagent_identity;
01038           else
01039             break;
01040         }
01041       }
01042 
01043       if(rc < 0)
01044         infof(data, "Failure requesting identities to agent\n");
01045       else if(rc == 1)
01046         infof(data, "No identity would match\n");
01047 
01048       if(rc == LIBSSH2_ERROR_NONE) {
01049         sshc->authed = TRUE;
01050         infof(data, "Agent based authentication successful\n");
01051         state(conn, SSH_AUTH_DONE);
01052       }
01053       else {
01054         state(conn, SSH_AUTH_KEY_INIT);
01055         rc = 0; /* clear rc and continue */
01056       }
01057 #endif
01058       break;
01059 
01060     case SSH_AUTH_KEY_INIT:
01061       if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
01062          && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
01063         state(conn, SSH_AUTH_KEY);
01064       }
01065       else {
01066         state(conn, SSH_AUTH_DONE);
01067       }
01068       break;
01069 
01070     case SSH_AUTH_KEY:
01071       /* Authentication failed. Continue with keyboard-interactive now. */
01072       rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
01073                                                     conn->user,
01074                                                     curlx_uztoui(
01075                                                       strlen(conn->user)),
01076                                                     &kbd_callback);
01077       if(rc == LIBSSH2_ERROR_EAGAIN) {
01078         break;
01079       }
01080       else if(rc == 0) {
01081         sshc->authed = TRUE;
01082         infof(data, "Initialized keyboard interactive authentication\n");
01083       }
01084       state(conn, SSH_AUTH_DONE);
01085       break;
01086 
01087     case SSH_AUTH_DONE:
01088       if(!sshc->authed) {
01089         failf(data, "Authentication failure");
01090         state(conn, SSH_SESSION_FREE);
01091         sshc->actualcode = CURLE_LOGIN_DENIED;
01092         break;
01093       }
01094 
01095       /*
01096        * At this point we have an authenticated ssh session.
01097        */
01098       infof(data, "Authentication complete\n");
01099 
01100       Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
01101 
01102       conn->sockfd = sock;
01103       conn->writesockfd = CURL_SOCKET_BAD;
01104 
01105       if(conn->handler->protocol == CURLPROTO_SFTP) {
01106         state(conn, SSH_SFTP_INIT);
01107         break;
01108       }
01109       infof(data, "SSH CONNECT phase done\n");
01110       state(conn, SSH_STOP);
01111       break;
01112 
01113     case SSH_SFTP_INIT:
01114       /*
01115        * Start the libssh2 sftp session
01116        */
01117       sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
01118       if(!sshc->sftp_session) {
01119         if(libssh2_session_last_errno(sshc->ssh_session) ==
01120            LIBSSH2_ERROR_EAGAIN) {
01121           rc = LIBSSH2_ERROR_EAGAIN;
01122           break;
01123         }
01124         else {
01125           char *err_msg;
01126 
01127           (void)libssh2_session_last_error(sshc->ssh_session,
01128                                            &err_msg, NULL, 0);
01129           failf(data, "Failure initializing sftp session: %s", err_msg);
01130           state(conn, SSH_SESSION_FREE);
01131           sshc->actualcode = CURLE_FAILED_INIT;
01132           break;
01133         }
01134       }
01135       state(conn, SSH_SFTP_REALPATH);
01136       break;
01137 
01138     case SSH_SFTP_REALPATH:
01139     {
01140       char tempHome[PATH_MAX];
01141 
01142       /*
01143        * Get the "home" directory
01144        */
01145       rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
01146                                  tempHome, PATH_MAX-1);
01147       if(rc == LIBSSH2_ERROR_EAGAIN) {
01148         break;
01149       }
01150       else if(rc > 0) {
01151         /* It seems that this string is not always NULL terminated */
01152         tempHome[rc] = '\0';
01153         sshc->homedir = strdup(tempHome);
01154         if(!sshc->homedir) {
01155           state(conn, SSH_SFTP_CLOSE);
01156           sshc->actualcode = CURLE_OUT_OF_MEMORY;
01157           break;
01158         }
01159         conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
01160       }
01161       else {
01162         /* Return the error type */
01163         err = sftp_libssh2_last_error(sshc->sftp_session);
01164         if(err)
01165           result = sftp_libssh2_error_to_CURLE(err);
01166         else
01167           /* in this case, the error wasn't in the SFTP level but for example
01168              a time-out or similar */
01169           result = CURLE_SSH;
01170         sshc->actualcode = result;
01171         DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
01172                      err, (int)result));
01173         state(conn, SSH_STOP);
01174         break;
01175       }
01176     }
01177     /* This is the last step in the SFTP connect phase. Do note that while
01178        we get the homedir here, we get the "workingpath" in the DO action
01179        since the homedir will remain the same between request but the
01180        working path will not. */
01181     DEBUGF(infof(data, "SSH CONNECT phase done\n"));
01182     state(conn, SSH_STOP);
01183     break;
01184 
01185     case SSH_SFTP_QUOTE_INIT:
01186 
01187       result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
01188       if(result) {
01189         sshc->actualcode = result;
01190         state(conn, SSH_STOP);
01191         break;
01192       }
01193 
01194       if(data->set.quote) {
01195         infof(data, "Sending quote commands\n");
01196         sshc->quote_item = data->set.quote;
01197         state(conn, SSH_SFTP_QUOTE);
01198       }
01199       else {
01200         state(conn, SSH_SFTP_GETINFO);
01201       }
01202       break;
01203 
01204     case SSH_SFTP_POSTQUOTE_INIT:
01205       if(data->set.postquote) {
01206         infof(data, "Sending quote commands\n");
01207         sshc->quote_item = data->set.postquote;
01208         state(conn, SSH_SFTP_QUOTE);
01209       }
01210       else {
01211         state(conn, SSH_STOP);
01212       }
01213       break;
01214 
01215     case SSH_SFTP_QUOTE:
01216       /* Send any quote commands */
01217     {
01218       const char *cp;
01219 
01220       /*
01221        * Support some of the "FTP" commands
01222        */
01223       char *cmd = sshc->quote_item->data;
01224       sshc->acceptfail = FALSE;
01225 
01226       /* if a command starts with an asterisk, which a legal SFTP command never
01227          can, the command will be allowed to fail without it causing any
01228          aborts or cancels etc. It will cause libcurl to act as if the command
01229          is successful, whatever the server reponds. */
01230 
01231       if(cmd[0] == '*') {
01232         cmd++;
01233         sshc->acceptfail = TRUE;
01234       }
01235 
01236       if(strcasecompare("pwd", cmd)) {
01237         /* output debug output if that is requested */
01238         char *tmp = aprintf("257 \"%s\" is current directory.\n",
01239                             sftp_scp->path);
01240         if(!tmp) {
01241           result = CURLE_OUT_OF_MEMORY;
01242           state(conn, SSH_SFTP_CLOSE);
01243           sshc->nextstate = SSH_NO_STATE;
01244           break;
01245         }
01246         if(data->set.verbose) {
01247           Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
01248           Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
01249         }
01250         /* this sends an FTP-like "header" to the header callback so that the
01251            current directory can be read very similar to how it is read when
01252            using ordinary FTP. */
01253         result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
01254         free(tmp);
01255         if(result) {
01256           state(conn, SSH_SFTP_CLOSE);
01257           sshc->nextstate = SSH_NO_STATE;
01258           sshc->actualcode = result;
01259         }
01260         else
01261           state(conn, SSH_SFTP_NEXT_QUOTE);
01262         break;
01263       }
01264       else if(cmd) {
01265         /*
01266          * the arguments following the command must be separated from the
01267          * command with a space so we can check for it unconditionally
01268          */
01269         cp = strchr(cmd, ' ');
01270         if(cp == NULL) {
01271           failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
01272           state(conn, SSH_SFTP_CLOSE);
01273           sshc->nextstate = SSH_NO_STATE;
01274           sshc->actualcode = CURLE_QUOTE_ERROR;
01275           break;
01276         }
01277 
01278         /*
01279          * also, every command takes at least one argument so we get that
01280          * first argument right now
01281          */
01282         result = get_pathname(&cp, &sshc->quote_path1);
01283         if(result) {
01284           if(result == CURLE_OUT_OF_MEMORY)
01285             failf(data, "Out of memory");
01286           else
01287             failf(data, "Syntax error: Bad first parameter");
01288           state(conn, SSH_SFTP_CLOSE);
01289           sshc->nextstate = SSH_NO_STATE;
01290           sshc->actualcode = result;
01291           break;
01292         }
01293 
01294         /*
01295          * SFTP is a binary protocol, so we don't send text commands
01296          * to the server. Instead, we scan for commands used by
01297          * OpenSSH's sftp program and call the appropriate libssh2
01298          * functions.
01299          */
01300         if(strncasecompare(cmd, "chgrp ", 6) ||
01301            strncasecompare(cmd, "chmod ", 6) ||
01302            strncasecompare(cmd, "chown ", 6) ) {
01303           /* attribute change */
01304 
01305           /* sshc->quote_path1 contains the mode to set */
01306           /* get the destination */
01307           result = get_pathname(&cp, &sshc->quote_path2);
01308           if(result) {
01309             if(result == CURLE_OUT_OF_MEMORY)
01310               failf(data, "Out of memory");
01311             else
01312               failf(data, "Syntax error in chgrp/chmod/chown: "
01313                     "Bad second parameter");
01314             Curl_safefree(sshc->quote_path1);
01315             state(conn, SSH_SFTP_CLOSE);
01316             sshc->nextstate = SSH_NO_STATE;
01317             sshc->actualcode = result;
01318             break;
01319           }
01320           memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
01321           state(conn, SSH_SFTP_QUOTE_STAT);
01322           break;
01323         }
01324         else if(strncasecompare(cmd, "ln ", 3) ||
01325                 strncasecompare(cmd, "symlink ", 8)) {
01326           /* symbolic linking */
01327           /* sshc->quote_path1 is the source */
01328           /* get the destination */
01329           result = get_pathname(&cp, &sshc->quote_path2);
01330           if(result) {
01331             if(result == CURLE_OUT_OF_MEMORY)
01332               failf(data, "Out of memory");
01333             else
01334               failf(data,
01335                     "Syntax error in ln/symlink: Bad second parameter");
01336             Curl_safefree(sshc->quote_path1);
01337             state(conn, SSH_SFTP_CLOSE);
01338             sshc->nextstate = SSH_NO_STATE;
01339             sshc->actualcode = result;
01340             break;
01341           }
01342           state(conn, SSH_SFTP_QUOTE_SYMLINK);
01343           break;
01344         }
01345         else if(strncasecompare(cmd, "mkdir ", 6)) {
01346           /* create dir */
01347           state(conn, SSH_SFTP_QUOTE_MKDIR);
01348           break;
01349         }
01350         else if(strncasecompare(cmd, "rename ", 7)) {
01351           /* rename file */
01352           /* first param is the source path */
01353           /* second param is the dest. path */
01354           result = get_pathname(&cp, &sshc->quote_path2);
01355           if(result) {
01356             if(result == CURLE_OUT_OF_MEMORY)
01357               failf(data, "Out of memory");
01358             else
01359               failf(data, "Syntax error in rename: Bad second parameter");
01360             Curl_safefree(sshc->quote_path1);
01361             state(conn, SSH_SFTP_CLOSE);
01362             sshc->nextstate = SSH_NO_STATE;
01363             sshc->actualcode = result;
01364             break;
01365           }
01366           state(conn, SSH_SFTP_QUOTE_RENAME);
01367           break;
01368         }
01369         else if(strncasecompare(cmd, "rmdir ", 6)) {
01370           /* delete dir */
01371           state(conn, SSH_SFTP_QUOTE_RMDIR);
01372           break;
01373         }
01374         else if(strncasecompare(cmd, "rm ", 3)) {
01375           state(conn, SSH_SFTP_QUOTE_UNLINK);
01376           break;
01377         }
01378 #ifdef HAS_STATVFS_SUPPORT
01379         else if(strncasecompare(cmd, "statvfs ", 8)) {
01380           state(conn, SSH_SFTP_QUOTE_STATVFS);
01381           break;
01382         }
01383 #endif
01384 
01385         failf(data, "Unknown SFTP command");
01386         Curl_safefree(sshc->quote_path1);
01387         Curl_safefree(sshc->quote_path2);
01388         state(conn, SSH_SFTP_CLOSE);
01389         sshc->nextstate = SSH_NO_STATE;
01390         sshc->actualcode = CURLE_QUOTE_ERROR;
01391         break;
01392       }
01393     }
01394     if(!sshc->quote_item) {
01395       state(conn, SSH_SFTP_GETINFO);
01396     }
01397     break;
01398 
01399     case SSH_SFTP_NEXT_QUOTE:
01400       Curl_safefree(sshc->quote_path1);
01401       Curl_safefree(sshc->quote_path2);
01402 
01403       sshc->quote_item = sshc->quote_item->next;
01404 
01405       if(sshc->quote_item) {
01406         state(conn, SSH_SFTP_QUOTE);
01407       }
01408       else {
01409         if(sshc->nextstate != SSH_NO_STATE) {
01410           state(conn, sshc->nextstate);
01411           sshc->nextstate = SSH_NO_STATE;
01412         }
01413         else {
01414           state(conn, SSH_SFTP_GETINFO);
01415         }
01416       }
01417       break;
01418 
01419     case SSH_SFTP_QUOTE_STAT:
01420     {
01421       char *cmd = sshc->quote_item->data;
01422       sshc->acceptfail = FALSE;
01423 
01424       /* if a command starts with an asterisk, which a legal SFTP command never
01425          can, the command will be allowed to fail without it causing any
01426          aborts or cancels etc. It will cause libcurl to act as if the command
01427          is successful, whatever the server reponds. */
01428 
01429       if(cmd[0] == '*') {
01430         cmd++;
01431         sshc->acceptfail = TRUE;
01432       }
01433 
01434       if(!strncasecompare(cmd, "chmod", 5)) {
01435         /* Since chown and chgrp only set owner OR group but libssh2 wants to
01436          * set them both at once, we need to obtain the current ownership
01437          * first.  This takes an extra protocol round trip.
01438          */
01439         rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
01440                                   curlx_uztoui(strlen(sshc->quote_path2)),
01441                                   LIBSSH2_SFTP_STAT,
01442                                   &sshc->quote_attrs);
01443         if(rc == LIBSSH2_ERROR_EAGAIN) {
01444           break;
01445         }
01446         else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
01447           err = sftp_libssh2_last_error(sshc->sftp_session);
01448           Curl_safefree(sshc->quote_path1);
01449           Curl_safefree(sshc->quote_path2);
01450           failf(data, "Attempt to get SFTP stats failed: %s",
01451                 sftp_libssh2_strerror(err));
01452           state(conn, SSH_SFTP_CLOSE);
01453           sshc->nextstate = SSH_NO_STATE;
01454           sshc->actualcode = CURLE_QUOTE_ERROR;
01455           break;
01456         }
01457       }
01458 
01459       /* Now set the new attributes... */
01460       if(strncasecompare(cmd, "chgrp", 5)) {
01461         sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
01462         sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
01463         if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
01464            !sshc->acceptfail) {
01465           Curl_safefree(sshc->quote_path1);
01466           Curl_safefree(sshc->quote_path2);
01467           failf(data, "Syntax error: chgrp gid not a number");
01468           state(conn, SSH_SFTP_CLOSE);
01469           sshc->nextstate = SSH_NO_STATE;
01470           sshc->actualcode = CURLE_QUOTE_ERROR;
01471           break;
01472         }
01473       }
01474       else if(strncasecompare(cmd, "chmod", 5)) {
01475         sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
01476         sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
01477         /* permissions are octal */
01478         if(sshc->quote_attrs.permissions == 0 &&
01479            !ISDIGIT(sshc->quote_path1[0])) {
01480           Curl_safefree(sshc->quote_path1);
01481           Curl_safefree(sshc->quote_path2);
01482           failf(data, "Syntax error: chmod permissions not a number");
01483           state(conn, SSH_SFTP_CLOSE);
01484           sshc->nextstate = SSH_NO_STATE;
01485           sshc->actualcode = CURLE_QUOTE_ERROR;
01486           break;
01487         }
01488       }
01489       else if(strncasecompare(cmd, "chown", 5)) {
01490         sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
01491         sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
01492         if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
01493            !sshc->acceptfail) {
01494           Curl_safefree(sshc->quote_path1);
01495           Curl_safefree(sshc->quote_path2);
01496           failf(data, "Syntax error: chown uid not a number");
01497           state(conn, SSH_SFTP_CLOSE);
01498           sshc->nextstate = SSH_NO_STATE;
01499           sshc->actualcode = CURLE_QUOTE_ERROR;
01500           break;
01501         }
01502       }
01503 
01504       /* Now send the completed structure... */
01505       state(conn, SSH_SFTP_QUOTE_SETSTAT);
01506       break;
01507     }
01508 
01509     case SSH_SFTP_QUOTE_SETSTAT:
01510       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
01511                                 curlx_uztoui(strlen(sshc->quote_path2)),
01512                                 LIBSSH2_SFTP_SETSTAT,
01513                                 &sshc->quote_attrs);
01514       if(rc == LIBSSH2_ERROR_EAGAIN) {
01515         break;
01516       }
01517       else if(rc != 0 && !sshc->acceptfail) {
01518         err = sftp_libssh2_last_error(sshc->sftp_session);
01519         Curl_safefree(sshc->quote_path1);
01520         Curl_safefree(sshc->quote_path2);
01521         failf(data, "Attempt to set SFTP stats failed: %s",
01522               sftp_libssh2_strerror(err));
01523         state(conn, SSH_SFTP_CLOSE);
01524         sshc->nextstate = SSH_NO_STATE;
01525         sshc->actualcode = CURLE_QUOTE_ERROR;
01526         break;
01527       }
01528       state(conn, SSH_SFTP_NEXT_QUOTE);
01529       break;
01530 
01531     case SSH_SFTP_QUOTE_SYMLINK:
01532       rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
01533                                    curlx_uztoui(strlen(sshc->quote_path1)),
01534                                    sshc->quote_path2,
01535                                    curlx_uztoui(strlen(sshc->quote_path2)),
01536                                    LIBSSH2_SFTP_SYMLINK);
01537       if(rc == LIBSSH2_ERROR_EAGAIN) {
01538         break;
01539       }
01540       else if(rc != 0 && !sshc->acceptfail) {
01541         err = sftp_libssh2_last_error(sshc->sftp_session);
01542         Curl_safefree(sshc->quote_path1);
01543         Curl_safefree(sshc->quote_path2);
01544         failf(data, "symlink command failed: %s",
01545               sftp_libssh2_strerror(err));
01546         state(conn, SSH_SFTP_CLOSE);
01547         sshc->nextstate = SSH_NO_STATE;
01548         sshc->actualcode = CURLE_QUOTE_ERROR;
01549         break;
01550       }
01551       state(conn, SSH_SFTP_NEXT_QUOTE);
01552       break;
01553 
01554     case SSH_SFTP_QUOTE_MKDIR:
01555       rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
01556                                  curlx_uztoui(strlen(sshc->quote_path1)),
01557                                  data->set.new_directory_perms);
01558       if(rc == LIBSSH2_ERROR_EAGAIN) {
01559         break;
01560       }
01561       else if(rc != 0 && !sshc->acceptfail) {
01562         err = sftp_libssh2_last_error(sshc->sftp_session);
01563         Curl_safefree(sshc->quote_path1);
01564         failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
01565         state(conn, SSH_SFTP_CLOSE);
01566         sshc->nextstate = SSH_NO_STATE;
01567         sshc->actualcode = CURLE_QUOTE_ERROR;
01568         break;
01569       }
01570       state(conn, SSH_SFTP_NEXT_QUOTE);
01571       break;
01572 
01573     case SSH_SFTP_QUOTE_RENAME:
01574       rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
01575                                   curlx_uztoui(strlen(sshc->quote_path1)),
01576                                   sshc->quote_path2,
01577                                   curlx_uztoui(strlen(sshc->quote_path2)),
01578                                   LIBSSH2_SFTP_RENAME_OVERWRITE |
01579                                   LIBSSH2_SFTP_RENAME_ATOMIC |
01580                                   LIBSSH2_SFTP_RENAME_NATIVE);
01581 
01582       if(rc == LIBSSH2_ERROR_EAGAIN) {
01583         break;
01584       }
01585       else if(rc != 0 && !sshc->acceptfail) {
01586         err = sftp_libssh2_last_error(sshc->sftp_session);
01587         Curl_safefree(sshc->quote_path1);
01588         Curl_safefree(sshc->quote_path2);
01589         failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
01590         state(conn, SSH_SFTP_CLOSE);
01591         sshc->nextstate = SSH_NO_STATE;
01592         sshc->actualcode = CURLE_QUOTE_ERROR;
01593         break;
01594       }
01595       state(conn, SSH_SFTP_NEXT_QUOTE);
01596       break;
01597 
01598     case SSH_SFTP_QUOTE_RMDIR:
01599       rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
01600                                  curlx_uztoui(strlen(sshc->quote_path1)));
01601       if(rc == LIBSSH2_ERROR_EAGAIN) {
01602         break;
01603       }
01604       else if(rc != 0 && !sshc->acceptfail) {
01605         err = sftp_libssh2_last_error(sshc->sftp_session);
01606         Curl_safefree(sshc->quote_path1);
01607         failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
01608         state(conn, SSH_SFTP_CLOSE);
01609         sshc->nextstate = SSH_NO_STATE;
01610         sshc->actualcode = CURLE_QUOTE_ERROR;
01611         break;
01612       }
01613       state(conn, SSH_SFTP_NEXT_QUOTE);
01614       break;
01615 
01616     case SSH_SFTP_QUOTE_UNLINK:
01617       rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
01618                                   curlx_uztoui(strlen(sshc->quote_path1)));
01619       if(rc == LIBSSH2_ERROR_EAGAIN) {
01620         break;
01621       }
01622       else if(rc != 0 && !sshc->acceptfail) {
01623         err = sftp_libssh2_last_error(sshc->sftp_session);
01624         Curl_safefree(sshc->quote_path1);
01625         failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
01626         state(conn, SSH_SFTP_CLOSE);
01627         sshc->nextstate = SSH_NO_STATE;
01628         sshc->actualcode = CURLE_QUOTE_ERROR;
01629         break;
01630       }
01631       state(conn, SSH_SFTP_NEXT_QUOTE);
01632       break;
01633 
01634 #ifdef HAS_STATVFS_SUPPORT
01635     case SSH_SFTP_QUOTE_STATVFS:
01636     {
01637       LIBSSH2_SFTP_STATVFS statvfs;
01638       rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
01639                                 curlx_uztoui(strlen(sshc->quote_path1)),
01640                                 &statvfs);
01641 
01642       if(rc == LIBSSH2_ERROR_EAGAIN) {
01643         break;
01644       }
01645       else if(rc != 0 && !sshc->acceptfail) {
01646         err = sftp_libssh2_last_error(sshc->sftp_session);
01647         Curl_safefree(sshc->quote_path1);
01648         failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err));
01649         state(conn, SSH_SFTP_CLOSE);
01650         sshc->nextstate = SSH_NO_STATE;
01651         sshc->actualcode = CURLE_QUOTE_ERROR;
01652         break;
01653       }
01654       else if(rc == 0) {
01655         char *tmp = aprintf("statvfs:\n"
01656                             "f_bsize: %llu\n" "f_frsize: %llu\n"
01657                             "f_blocks: %llu\n" "f_bfree: %llu\n"
01658                             "f_bavail: %llu\n" "f_files: %llu\n"
01659                             "f_ffree: %llu\n" "f_favail: %llu\n"
01660                             "f_fsid: %llu\n" "f_flag: %llu\n"
01661                             "f_namemax: %llu\n",
01662                             statvfs.f_bsize, statvfs.f_frsize,
01663                             statvfs.f_blocks, statvfs.f_bfree,
01664                             statvfs.f_bavail, statvfs.f_files,
01665                             statvfs.f_ffree, statvfs.f_favail,
01666                             statvfs.f_fsid, statvfs.f_flag,
01667                             statvfs.f_namemax);
01668         if(!tmp) {
01669           result = CURLE_OUT_OF_MEMORY;
01670           state(conn, SSH_SFTP_CLOSE);
01671           sshc->nextstate = SSH_NO_STATE;
01672           break;
01673         }
01674 
01675         result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
01676         free(tmp);
01677         if(result) {
01678           state(conn, SSH_SFTP_CLOSE);
01679           sshc->nextstate = SSH_NO_STATE;
01680           sshc->actualcode = result;
01681         }
01682       }
01683       state(conn, SSH_SFTP_NEXT_QUOTE);
01684       break;
01685     }
01686 #endif
01687     case SSH_SFTP_GETINFO:
01688     {
01689       if(data->set.get_filetime) {
01690         state(conn, SSH_SFTP_FILETIME);
01691       }
01692       else {
01693         state(conn, SSH_SFTP_TRANS_INIT);
01694       }
01695       break;
01696     }
01697 
01698     case SSH_SFTP_FILETIME:
01699     {
01700       LIBSSH2_SFTP_ATTRIBUTES attrs;
01701 
01702       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
01703                                 curlx_uztoui(strlen(sftp_scp->path)),
01704                                 LIBSSH2_SFTP_STAT, &attrs);
01705       if(rc == LIBSSH2_ERROR_EAGAIN) {
01706         break;
01707       }
01708       else if(rc == 0) {
01709         data->info.filetime = (long)attrs.mtime;
01710       }
01711 
01712       state(conn, SSH_SFTP_TRANS_INIT);
01713       break;
01714     }
01715 
01716     case SSH_SFTP_TRANS_INIT:
01717       if(data->set.upload)
01718         state(conn, SSH_SFTP_UPLOAD_INIT);
01719       else {
01720         if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
01721           state(conn, SSH_SFTP_READDIR_INIT);
01722         else
01723           state(conn, SSH_SFTP_DOWNLOAD_INIT);
01724       }
01725       break;
01726 
01727     case SSH_SFTP_UPLOAD_INIT:
01728     {
01729       unsigned long flags;
01730       /*
01731        * NOTE!!!  libssh2 requires that the destination path is a full path
01732        *          that includes the destination file and name OR ends in a "/"
01733        *          If this is not done the destination file will be named the
01734        *          same name as the last directory in the path.
01735        */
01736 
01737       if(data->state.resume_from != 0) {
01738         LIBSSH2_SFTP_ATTRIBUTES attrs;
01739         if(data->state.resume_from < 0) {
01740           rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
01741                                     curlx_uztoui(strlen(sftp_scp->path)),
01742                                     LIBSSH2_SFTP_STAT, &attrs);
01743           if(rc == LIBSSH2_ERROR_EAGAIN) {
01744             break;
01745           }
01746           else if(rc) {
01747             data->state.resume_from = 0;
01748           }
01749           else {
01750             curl_off_t size = attrs.filesize;
01751             if(size < 0) {
01752               failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
01753               return CURLE_BAD_DOWNLOAD_RESUME;
01754             }
01755             data->state.resume_from = attrs.filesize;
01756           }
01757         }
01758       }
01759 
01760       if(data->set.ftp_append)
01761         /* Try to open for append, but create if nonexisting */
01762         flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
01763       else if(data->state.resume_from > 0)
01764         /* If we have restart position then open for append */
01765         flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
01766       else
01767         /* Clear file before writing (normal behaviour) */
01768         flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
01769 
01770       sshc->sftp_handle =
01771         libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
01772                              curlx_uztoui(strlen(sftp_scp->path)),
01773                              flags, data->set.new_file_perms,
01774                              LIBSSH2_SFTP_OPENFILE);
01775 
01776       if(!sshc->sftp_handle) {
01777         rc = libssh2_session_last_errno(sshc->ssh_session);
01778 
01779         if(LIBSSH2_ERROR_EAGAIN == rc)
01780           break;
01781         else {
01782           if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
01783             /* only when there was an SFTP protocol error can we extract
01784                the sftp error! */
01785             err = sftp_libssh2_last_error(sshc->sftp_session);
01786           else
01787             err = -1; /* not an sftp error at all */
01788 
01789           if(sshc->secondCreateDirs) {
01790             state(conn, SSH_SFTP_CLOSE);
01791             sshc->actualcode = err>= LIBSSH2_FX_OK?
01792               sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
01793             failf(data, "Creating the dir/file failed: %s",
01794                   sftp_libssh2_strerror(err));
01795             break;
01796           }
01797           else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
01798                    (err == LIBSSH2_FX_FAILURE) ||
01799                    (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
01800                   (data->set.ftp_create_missing_dirs &&
01801                    (strlen(sftp_scp->path) > 1))) {
01802             /* try to create the path remotely */
01803             sshc->secondCreateDirs = 1;
01804             state(conn, SSH_SFTP_CREATE_DIRS_INIT);
01805             break;
01806           }
01807           state(conn, SSH_SFTP_CLOSE);
01808           sshc->actualcode = err>= LIBSSH2_FX_OK?
01809             sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
01810           if(!sshc->actualcode) {
01811             /* Sometimes, for some reason libssh2_sftp_last_error() returns
01812                zero even though libssh2_sftp_open() failed previously! We need
01813                to work around that! */
01814             sshc->actualcode = CURLE_SSH;
01815             err=-1;
01816           }
01817           failf(data, "Upload failed: %s (%d/%d)",
01818                 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
01819                 err, rc);
01820           break;
01821         }
01822       }
01823 
01824       /* If we have a restart point then we need to seek to the correct
01825          position. */
01826       if(data->state.resume_from > 0) {
01827         /* Let's read off the proper amount of bytes from the input. */
01828         if(conn->seek_func) {
01829           seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
01830                                     SEEK_SET);
01831         }
01832 
01833         if(seekerr != CURL_SEEKFUNC_OK) {
01834 
01835           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
01836             failf(data, "Could not seek stream");
01837             return CURLE_FTP_COULDNT_USE_REST;
01838           }
01839           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
01840           else {
01841             curl_off_t passed=0;
01842             do {
01843               size_t readthisamountnow =
01844                 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
01845                 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
01846 
01847               size_t actuallyread =
01848                 data->state.fread_func(data->state.buffer, 1,
01849                                        readthisamountnow, data->state.in);
01850 
01851               passed += actuallyread;
01852               if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
01853                 /* this checks for greater-than only to make sure that the
01854                    CURL_READFUNC_ABORT return code still aborts */
01855                 failf(data, "Failed to read data");
01856                 return CURLE_FTP_COULDNT_USE_REST;
01857               }
01858             } while(passed < data->state.resume_from);
01859           }
01860         }
01861 
01862         /* now, decrease the size of the read */
01863         if(data->state.infilesize > 0) {
01864           data->state.infilesize -= data->state.resume_from;
01865           data->req.size = data->state.infilesize;
01866           Curl_pgrsSetUploadSize(data, data->state.infilesize);
01867         }
01868 
01869         SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
01870       }
01871       if(data->state.infilesize > 0) {
01872         data->req.size = data->state.infilesize;
01873         Curl_pgrsSetUploadSize(data, data->state.infilesize);
01874       }
01875       /* upload data */
01876       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
01877 
01878       /* not set by Curl_setup_transfer to preserve keepon bits */
01879       conn->sockfd = conn->writesockfd;
01880 
01881       if(result) {
01882         state(conn, SSH_SFTP_CLOSE);
01883         sshc->actualcode = result;
01884       }
01885       else {
01886         /* store this original bitmask setup to use later on if we can't
01887            figure out a "real" bitmask */
01888         sshc->orig_waitfor = data->req.keepon;
01889 
01890         /* we want to use the _sending_ function even when the socket turns
01891            out readable as the underlying libssh2 sftp send function will deal
01892            with both accordingly */
01893         conn->cselect_bits = CURL_CSELECT_OUT;
01894 
01895         /* since we don't really wait for anything at this point, we want the
01896            state machine to move on as soon as possible so we set a very short
01897            timeout here */
01898         Curl_expire(data, 0);
01899 
01900         state(conn, SSH_STOP);
01901       }
01902       break;
01903     }
01904 
01905     case SSH_SFTP_CREATE_DIRS_INIT:
01906       if(strlen(sftp_scp->path) > 1) {
01907         sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
01908         state(conn, SSH_SFTP_CREATE_DIRS);
01909       }
01910       else {
01911         state(conn, SSH_SFTP_UPLOAD_INIT);
01912       }
01913       break;
01914 
01915     case SSH_SFTP_CREATE_DIRS:
01916       sshc->slash_pos = strchr(sshc->slash_pos, '/');
01917       if(sshc->slash_pos) {
01918         *sshc->slash_pos = 0;
01919 
01920         infof(data, "Creating directory '%s'\n", sftp_scp->path);
01921         state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
01922         break;
01923       }
01924       else {
01925         state(conn, SSH_SFTP_UPLOAD_INIT);
01926       }
01927       break;
01928 
01929     case SSH_SFTP_CREATE_DIRS_MKDIR:
01930       /* 'mode' - parameter is preliminary - default to 0644 */
01931       rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
01932                                  curlx_uztoui(strlen(sftp_scp->path)),
01933                                  data->set.new_directory_perms);
01934       if(rc == LIBSSH2_ERROR_EAGAIN) {
01935         break;
01936       }
01937       *sshc->slash_pos = '/';
01938       ++sshc->slash_pos;
01939       if(rc == -1) {
01940         /*
01941          * Abort if failure wasn't that the dir already exists or the
01942          * permission was denied (creation might succeed further down the
01943          * path) - retry on unspecific FAILURE also
01944          */
01945         err = sftp_libssh2_last_error(sshc->sftp_session);
01946         if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
01947            (err != LIBSSH2_FX_FAILURE) &&
01948            (err != LIBSSH2_FX_PERMISSION_DENIED)) {
01949           result = sftp_libssh2_error_to_CURLE(err);
01950           state(conn, SSH_SFTP_CLOSE);
01951           sshc->actualcode = result?result:CURLE_SSH;
01952           break;
01953         }
01954       }
01955       state(conn, SSH_SFTP_CREATE_DIRS);
01956       break;
01957 
01958     case SSH_SFTP_READDIR_INIT:
01959       Curl_pgrsSetDownloadSize(data, -1);
01960       if(data->set.opt_no_body) {
01961         state(conn, SSH_STOP);
01962         break;
01963       }
01964 
01965       /*
01966        * This is a directory that we are trying to get, so produce a directory
01967        * listing
01968        */
01969       sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
01970                                                sftp_scp->path,
01971                                                curlx_uztoui(
01972                                                  strlen(sftp_scp->path)),
01973                                                0, 0, LIBSSH2_SFTP_OPENDIR);
01974       if(!sshc->sftp_handle) {
01975         if(libssh2_session_last_errno(sshc->ssh_session) ==
01976            LIBSSH2_ERROR_EAGAIN) {
01977           rc = LIBSSH2_ERROR_EAGAIN;
01978           break;
01979         }
01980         else {
01981           err = sftp_libssh2_last_error(sshc->sftp_session);
01982           failf(data, "Could not open directory for reading: %s",
01983                 sftp_libssh2_strerror(err));
01984           state(conn, SSH_SFTP_CLOSE);
01985           result = sftp_libssh2_error_to_CURLE(err);
01986           sshc->actualcode = result?result:CURLE_SSH;
01987           break;
01988         }
01989       }
01990       sshc->readdir_filename = malloc(PATH_MAX+1);
01991       if(!sshc->readdir_filename) {
01992         state(conn, SSH_SFTP_CLOSE);
01993         sshc->actualcode = CURLE_OUT_OF_MEMORY;
01994         break;
01995       }
01996       sshc->readdir_longentry = malloc(PATH_MAX+1);
01997       if(!sshc->readdir_longentry) {
01998         Curl_safefree(sshc->readdir_filename);
01999         state(conn, SSH_SFTP_CLOSE);
02000         sshc->actualcode = CURLE_OUT_OF_MEMORY;
02001         break;
02002       }
02003       state(conn, SSH_SFTP_READDIR);
02004       break;
02005 
02006     case SSH_SFTP_READDIR:
02007       sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
02008                                                   sshc->readdir_filename,
02009                                                   PATH_MAX,
02010                                                   sshc->readdir_longentry,
02011                                                   PATH_MAX,
02012                                                   &sshc->readdir_attrs);
02013       if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
02014         rc = LIBSSH2_ERROR_EAGAIN;
02015         break;
02016       }
02017       if(sshc->readdir_len > 0) {
02018         sshc->readdir_filename[sshc->readdir_len] = '\0';
02019 
02020         if(data->set.ftp_list_only) {
02021           char *tmpLine;
02022 
02023           tmpLine = aprintf("%s\n", sshc->readdir_filename);
02024           if(tmpLine == NULL) {
02025             state(conn, SSH_SFTP_CLOSE);
02026             sshc->actualcode = CURLE_OUT_OF_MEMORY;
02027             break;
02028           }
02029           result = Curl_client_write(conn, CLIENTWRITE_BODY,
02030                                      tmpLine, sshc->readdir_len+1);
02031           free(tmpLine);
02032 
02033           if(result) {
02034             state(conn, SSH_STOP);
02035             break;
02036           }
02037           /* since this counts what we send to the client, we include the
02038              newline in this counter */
02039           data->req.bytecount += sshc->readdir_len+1;
02040 
02041           /* output debug output if that is requested */
02042           if(data->set.verbose) {
02043             Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
02044                        sshc->readdir_len, conn);
02045           }
02046         }
02047         else {
02048           sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
02049           sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
02050           sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
02051           if(!sshc->readdir_line) {
02052             Curl_safefree(sshc->readdir_filename);
02053             Curl_safefree(sshc->readdir_longentry);
02054             state(conn, SSH_SFTP_CLOSE);
02055             sshc->actualcode = CURLE_OUT_OF_MEMORY;
02056             break;
02057           }
02058 
02059           memcpy(sshc->readdir_line, sshc->readdir_longentry,
02060                  sshc->readdir_currLen);
02061           if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
02062              ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
02063               LIBSSH2_SFTP_S_IFLNK)) {
02064             sshc->readdir_linkPath = malloc(PATH_MAX + 1);
02065             if(sshc->readdir_linkPath == NULL) {
02066               Curl_safefree(sshc->readdir_filename);
02067               Curl_safefree(sshc->readdir_longentry);
02068               state(conn, SSH_SFTP_CLOSE);
02069               sshc->actualcode = CURLE_OUT_OF_MEMORY;
02070               break;
02071             }
02072 
02073             snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
02074                      sshc->readdir_filename);
02075             state(conn, SSH_SFTP_READDIR_LINK);
02076             break;
02077           }
02078           state(conn, SSH_SFTP_READDIR_BOTTOM);
02079           break;
02080         }
02081       }
02082       else if(sshc->readdir_len == 0) {
02083         Curl_safefree(sshc->readdir_filename);
02084         Curl_safefree(sshc->readdir_longentry);
02085         state(conn, SSH_SFTP_READDIR_DONE);
02086         break;
02087       }
02088       else if(sshc->readdir_len <= 0) {
02089         err = sftp_libssh2_last_error(sshc->sftp_session);
02090         result = sftp_libssh2_error_to_CURLE(err);
02091         sshc->actualcode = result?result:CURLE_SSH;
02092         failf(data, "Could not open remote file for reading: %s :: %d",
02093               sftp_libssh2_strerror(err),
02094               libssh2_session_last_errno(sshc->ssh_session));
02095         Curl_safefree(sshc->readdir_filename);
02096         Curl_safefree(sshc->readdir_longentry);
02097         state(conn, SSH_SFTP_CLOSE);
02098         break;
02099       }
02100       break;
02101 
02102     case SSH_SFTP_READDIR_LINK:
02103       sshc->readdir_len =
02104         libssh2_sftp_symlink_ex(sshc->sftp_session,
02105                                 sshc->readdir_linkPath,
02106                                 curlx_uztoui(strlen(sshc->readdir_linkPath)),
02107                                 sshc->readdir_filename,
02108                                 PATH_MAX, LIBSSH2_SFTP_READLINK);
02109       if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
02110         rc = LIBSSH2_ERROR_EAGAIN;
02111         break;
02112       }
02113       Curl_safefree(sshc->readdir_linkPath);
02114 
02115       /* get room for the filename and extra output */
02116       sshc->readdir_totalLen += 4 + sshc->readdir_len;
02117       new_readdir_line = Curl_saferealloc(sshc->readdir_line,
02118                                           sshc->readdir_totalLen);
02119       if(!new_readdir_line) {
02120         sshc->readdir_line = NULL;
02121         Curl_safefree(sshc->readdir_filename);
02122         Curl_safefree(sshc->readdir_longentry);
02123         state(conn, SSH_SFTP_CLOSE);
02124         sshc->actualcode = CURLE_OUT_OF_MEMORY;
02125         break;
02126       }
02127       sshc->readdir_line = new_readdir_line;
02128 
02129       sshc->readdir_currLen += snprintf(sshc->readdir_line +
02130                                         sshc->readdir_currLen,
02131                                         sshc->readdir_totalLen -
02132                                         sshc->readdir_currLen,
02133                                         " -> %s",
02134                                         sshc->readdir_filename);
02135 
02136       state(conn, SSH_SFTP_READDIR_BOTTOM);
02137       break;
02138 
02139     case SSH_SFTP_READDIR_BOTTOM:
02140       sshc->readdir_currLen += snprintf(sshc->readdir_line +
02141                                         sshc->readdir_currLen,
02142                                         sshc->readdir_totalLen -
02143                                         sshc->readdir_currLen, "\n");
02144       result = Curl_client_write(conn, CLIENTWRITE_BODY,
02145                                  sshc->readdir_line,
02146                                  sshc->readdir_currLen);
02147 
02148       if(!result) {
02149 
02150         /* output debug output if that is requested */
02151         if(data->set.verbose) {
02152           Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
02153                      sshc->readdir_currLen, conn);
02154         }
02155         data->req.bytecount += sshc->readdir_currLen;
02156       }
02157       Curl_safefree(sshc->readdir_line);
02158       if(result) {
02159         state(conn, SSH_STOP);
02160       }
02161       else
02162         state(conn, SSH_SFTP_READDIR);
02163       break;
02164 
02165     case SSH_SFTP_READDIR_DONE:
02166       if(libssh2_sftp_closedir(sshc->sftp_handle) ==
02167          LIBSSH2_ERROR_EAGAIN) {
02168         rc = LIBSSH2_ERROR_EAGAIN;
02169         break;
02170       }
02171       sshc->sftp_handle = NULL;
02172       Curl_safefree(sshc->readdir_filename);
02173       Curl_safefree(sshc->readdir_longentry);
02174 
02175       /* no data to transfer */
02176       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
02177       state(conn, SSH_STOP);
02178       break;
02179 
02180     case SSH_SFTP_DOWNLOAD_INIT:
02181       /*
02182        * Work on getting the specified file
02183        */
02184       sshc->sftp_handle =
02185         libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
02186                              curlx_uztoui(strlen(sftp_scp->path)),
02187                              LIBSSH2_FXF_READ, data->set.new_file_perms,
02188                              LIBSSH2_SFTP_OPENFILE);
02189       if(!sshc->sftp_handle) {
02190         if(libssh2_session_last_errno(sshc->ssh_session) ==
02191            LIBSSH2_ERROR_EAGAIN) {
02192           rc = LIBSSH2_ERROR_EAGAIN;
02193           break;
02194         }
02195         else {
02196           err = sftp_libssh2_last_error(sshc->sftp_session);
02197           failf(data, "Could not open remote file for reading: %s",
02198                 sftp_libssh2_strerror(err));
02199           state(conn, SSH_SFTP_CLOSE);
02200           result = sftp_libssh2_error_to_CURLE(err);
02201           sshc->actualcode = result?result:CURLE_SSH;
02202           break;
02203         }
02204       }
02205       state(conn, SSH_SFTP_DOWNLOAD_STAT);
02206       break;
02207 
02208     case SSH_SFTP_DOWNLOAD_STAT:
02209     {
02210       LIBSSH2_SFTP_ATTRIBUTES attrs;
02211 
02212       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
02213                                 curlx_uztoui(strlen(sftp_scp->path)),
02214                                 LIBSSH2_SFTP_STAT, &attrs);
02215       if(rc == LIBSSH2_ERROR_EAGAIN) {
02216         break;
02217       }
02218       else if(rc ||
02219               !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
02220               (attrs.filesize == 0)) {
02221         /*
02222          * libssh2_sftp_open() didn't return an error, so maybe the server
02223          * just doesn't support stat()
02224          * OR the server doesn't return a file size with a stat()
02225          * OR file size is 0
02226          */
02227         data->req.size = -1;
02228         data->req.maxdownload = -1;
02229         Curl_pgrsSetDownloadSize(data, -1);
02230       }
02231       else {
02232         curl_off_t size = attrs.filesize;
02233 
02234         if(size < 0) {
02235           failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
02236           return CURLE_BAD_DOWNLOAD_RESUME;
02237         }
02238         if(conn->data->state.use_range) {
02239           curl_off_t from, to;
02240           char *ptr;
02241           char *ptr2;
02242 
02243           from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
02244           while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
02245             ptr++;
02246           to=curlx_strtoofft(ptr, &ptr2, 0);
02247           if((ptr == ptr2) /* no "to" value given */
02248              || (to >= size)) {
02249             to = size - 1;
02250           }
02251           if(from < 0) {
02252             /* from is relative to end of file */
02253             from += size;
02254           }
02255           if(from > size) {
02256             failf(data, "Offset (%"
02257                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
02258                   CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
02259             return CURLE_BAD_DOWNLOAD_RESUME;
02260           }
02261           if(from > to) {
02262             from = to;
02263             size = 0;
02264           }
02265           else {
02266             size = to - from + 1;
02267           }
02268 
02269           SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
02270         }
02271         data->req.size = size;
02272         data->req.maxdownload = size;
02273         Curl_pgrsSetDownloadSize(data, size);
02274       }
02275 
02276       /* We can resume if we can seek to the resume position */
02277       if(data->state.resume_from) {
02278         if(data->state.resume_from < 0) {
02279           /* We're supposed to download the last abs(from) bytes */
02280           if((curl_off_t)attrs.filesize < -data->state.resume_from) {
02281             failf(data, "Offset (%"
02282                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
02283                   CURL_FORMAT_CURL_OFF_T ")",
02284                   data->state.resume_from, attrs.filesize);
02285             return CURLE_BAD_DOWNLOAD_RESUME;
02286           }
02287           /* download from where? */
02288           data->state.resume_from += attrs.filesize;
02289         }
02290         else {
02291           if((curl_off_t)attrs.filesize < data->state.resume_from) {
02292             failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
02293                   ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
02294                   data->state.resume_from, attrs.filesize);
02295             return CURLE_BAD_DOWNLOAD_RESUME;
02296           }
02297         }
02298         /* Does a completed file need to be seeked and started or closed ? */
02299         /* Now store the number of bytes we are expected to download */
02300         data->req.size = attrs.filesize - data->state.resume_from;
02301         data->req.maxdownload = attrs.filesize - data->state.resume_from;
02302         Curl_pgrsSetDownloadSize(data,
02303                                  attrs.filesize - data->state.resume_from);
02304         SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
02305       }
02306     }
02307 
02308     /* Setup the actual download */
02309     if(data->req.size == 0) {
02310       /* no data to transfer */
02311       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
02312       infof(data, "File already completely downloaded\n");
02313       state(conn, SSH_STOP);
02314       break;
02315     }
02316     else {
02317       Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
02318                           FALSE, NULL, -1, NULL);
02319 
02320       /* not set by Curl_setup_transfer to preserve keepon bits */
02321       conn->writesockfd = conn->sockfd;
02322 
02323       /* we want to use the _receiving_ function even when the socket turns
02324          out writableable as the underlying libssh2 recv function will deal
02325          with both accordingly */
02326       conn->cselect_bits = CURL_CSELECT_IN;
02327     }
02328     if(result) {
02329       /* this should never occur; the close state should be entered
02330          at the time the error occurs */
02331       state(conn, SSH_SFTP_CLOSE);
02332       sshc->actualcode = result;
02333     }
02334     else {
02335       state(conn, SSH_STOP);
02336     }
02337     break;
02338 
02339     case SSH_SFTP_CLOSE:
02340       if(sshc->sftp_handle) {
02341         rc = libssh2_sftp_close(sshc->sftp_handle);
02342         if(rc == LIBSSH2_ERROR_EAGAIN) {
02343           break;
02344         }
02345         else if(rc < 0) {
02346           infof(data, "Failed to close libssh2 file\n");
02347         }
02348         sshc->sftp_handle = NULL;
02349       }
02350       if(sftp_scp)
02351         Curl_safefree(sftp_scp->path);
02352 
02353       DEBUGF(infof(data, "SFTP DONE done\n"));
02354 
02355       /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
02356          After nextstate is executed, the control should come back to
02357          SSH_SFTP_CLOSE to pass the correct result back  */
02358       if(sshc->nextstate != SSH_NO_STATE &&
02359          sshc->nextstate != SSH_SFTP_CLOSE) {
02360         state(conn, sshc->nextstate);
02361         sshc->nextstate = SSH_SFTP_CLOSE;
02362       }
02363       else {
02364         state(conn, SSH_STOP);
02365         result = sshc->actualcode;
02366       }
02367       break;
02368 
02369     case SSH_SFTP_SHUTDOWN:
02370       /* during times we get here due to a broken transfer and then the
02371          sftp_handle might not have been taken down so make sure that is done
02372          before we proceed */
02373 
02374       if(sshc->sftp_handle) {
02375         rc = libssh2_sftp_close(sshc->sftp_handle);
02376         if(rc == LIBSSH2_ERROR_EAGAIN) {
02377           break;
02378         }
02379         else if(rc < 0) {
02380           infof(data, "Failed to close libssh2 file\n");
02381         }
02382         sshc->sftp_handle = NULL;
02383       }
02384       if(sshc->sftp_session) {
02385         rc = libssh2_sftp_shutdown(sshc->sftp_session);
02386         if(rc == LIBSSH2_ERROR_EAGAIN) {
02387           break;
02388         }
02389         else if(rc < 0) {
02390           infof(data, "Failed to stop libssh2 sftp subsystem\n");
02391         }
02392         sshc->sftp_session = NULL;
02393       }
02394 
02395       Curl_safefree(sshc->homedir);
02396       conn->data->state.most_recent_ftp_entrypath = NULL;
02397 
02398       state(conn, SSH_SESSION_DISCONNECT);
02399       break;
02400 
02401     case SSH_SCP_TRANS_INIT:
02402       result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
02403       if(result) {
02404         sshc->actualcode = result;
02405         state(conn, SSH_STOP);
02406         break;
02407       }
02408 
02409       if(data->set.upload) {
02410         if(data->state.infilesize < 0) {
02411           failf(data, "SCP requires a known file size for upload");
02412           sshc->actualcode = CURLE_UPLOAD_FAILED;
02413           state(conn, SSH_SCP_CHANNEL_FREE);
02414           break;
02415         }
02416         state(conn, SSH_SCP_UPLOAD_INIT);
02417       }
02418       else {
02419         state(conn, SSH_SCP_DOWNLOAD_INIT);
02420       }
02421       break;
02422 
02423     case SSH_SCP_UPLOAD_INIT:
02424       /*
02425        * libssh2 requires that the destination path is a full path that
02426        * includes the destination file and name OR ends in a "/" .  If this is
02427        * not done the destination file will be named the same name as the last
02428        * directory in the path.
02429        */
02430       sshc->ssh_channel =
02431         SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
02432                  data->state.infilesize);
02433       if(!sshc->ssh_channel) {
02434         if(libssh2_session_last_errno(sshc->ssh_session) ==
02435            LIBSSH2_ERROR_EAGAIN) {
02436           rc = LIBSSH2_ERROR_EAGAIN;
02437           break;
02438         }
02439         else {
02440           int ssh_err;
02441           char *err_msg;
02442 
02443           ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
02444                                                      &err_msg, NULL, 0));
02445           failf(conn->data, "%s", err_msg);
02446           state(conn, SSH_SCP_CHANNEL_FREE);
02447           sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
02448           break;
02449         }
02450       }
02451 
02452       /* upload data */
02453       Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
02454                           FIRSTSOCKET, NULL);
02455 
02456       /* not set by Curl_setup_transfer to preserve keepon bits */
02457       conn->sockfd = conn->writesockfd;
02458 
02459       if(result) {
02460         state(conn, SSH_SCP_CHANNEL_FREE);
02461         sshc->actualcode = result;
02462       }
02463       else {
02464         /* store this original bitmask setup to use later on if we can't
02465            figure out a "real" bitmask */
02466         sshc->orig_waitfor = data->req.keepon;
02467 
02468         /* we want to use the _sending_ function even when the socket turns
02469            out readable as the underlying libssh2 scp send function will deal
02470            with both accordingly */
02471         conn->cselect_bits = CURL_CSELECT_OUT;
02472 
02473         state(conn, SSH_STOP);
02474       }
02475       break;
02476 
02477     case SSH_SCP_DOWNLOAD_INIT:
02478     {
02479       curl_off_t bytecount;
02480 
02481       /*
02482        * We must check the remote file; if it is a directory no values will
02483        * be set in sb
02484        */
02485 
02486        /*
02487         * If support for >2GB files exists, use it.
02488         */
02489 
02490       /* get a fresh new channel from the ssh layer */
02491 #if LIBSSH2_VERSION_NUM < 0x010700
02492       struct stat sb;
02493       memset(&sb, 0, sizeof(struct stat));
02494       sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
02495                                            sftp_scp->path, &sb);
02496 #else
02497       libssh2_struct_stat sb;
02498       memset(&sb, 0, sizeof(libssh2_struct_stat));
02499       sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
02500                                             sftp_scp->path, &sb);
02501 #endif
02502 
02503       if(!sshc->ssh_channel) {
02504         if(libssh2_session_last_errno(sshc->ssh_session) ==
02505            LIBSSH2_ERROR_EAGAIN) {
02506           rc = LIBSSH2_ERROR_EAGAIN;
02507           break;
02508         }
02509         else {
02510           int ssh_err;
02511           char *err_msg;
02512 
02513           ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
02514                                                      &err_msg, NULL, 0));
02515           failf(conn->data, "%s", err_msg);
02516           state(conn, SSH_SCP_CHANNEL_FREE);
02517           sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
02518           break;
02519         }
02520       }
02521 
02522       /* download data */
02523       bytecount = (curl_off_t)sb.st_size;
02524       data->req.maxdownload =  (curl_off_t)sb.st_size;
02525       Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
02526 
02527       /* not set by Curl_setup_transfer to preserve keepon bits */
02528       conn->writesockfd = conn->sockfd;
02529 
02530       /* we want to use the _receiving_ function even when the socket turns
02531          out writableable as the underlying libssh2 recv function will deal
02532          with both accordingly */
02533       conn->cselect_bits = CURL_CSELECT_IN;
02534 
02535       if(result) {
02536         state(conn, SSH_SCP_CHANNEL_FREE);
02537         sshc->actualcode = result;
02538       }
02539       else
02540         state(conn, SSH_STOP);
02541     }
02542     break;
02543 
02544     case SSH_SCP_DONE:
02545       if(data->set.upload)
02546         state(conn, SSH_SCP_SEND_EOF);
02547       else
02548         state(conn, SSH_SCP_CHANNEL_FREE);
02549       break;
02550 
02551     case SSH_SCP_SEND_EOF:
02552       if(sshc->ssh_channel) {
02553         rc = libssh2_channel_send_eof(sshc->ssh_channel);
02554         if(rc == LIBSSH2_ERROR_EAGAIN) {
02555           break;
02556         }
02557         else if(rc) {
02558           infof(data, "Failed to send libssh2 channel EOF\n");
02559         }
02560       }
02561       state(conn, SSH_SCP_WAIT_EOF);
02562       break;
02563 
02564     case SSH_SCP_WAIT_EOF:
02565       if(sshc->ssh_channel) {
02566         rc = libssh2_channel_wait_eof(sshc->ssh_channel);
02567         if(rc == LIBSSH2_ERROR_EAGAIN) {
02568           break;
02569         }
02570         else if(rc) {
02571           infof(data, "Failed to get channel EOF: %d\n", rc);
02572         }
02573       }
02574       state(conn, SSH_SCP_WAIT_CLOSE);
02575       break;
02576 
02577     case SSH_SCP_WAIT_CLOSE:
02578       if(sshc->ssh_channel) {
02579         rc = libssh2_channel_wait_closed(sshc->ssh_channel);
02580         if(rc == LIBSSH2_ERROR_EAGAIN) {
02581           break;
02582         }
02583         else if(rc) {
02584           infof(data, "Channel failed to close: %d\n", rc);
02585         }
02586       }
02587       state(conn, SSH_SCP_CHANNEL_FREE);
02588       break;
02589 
02590     case SSH_SCP_CHANNEL_FREE:
02591       if(sshc->ssh_channel) {
02592         rc = libssh2_channel_free(sshc->ssh_channel);
02593         if(rc == LIBSSH2_ERROR_EAGAIN) {
02594           break;
02595         }
02596         else if(rc < 0) {
02597           infof(data, "Failed to free libssh2 scp subsystem\n");
02598         }
02599         sshc->ssh_channel = NULL;
02600       }
02601       DEBUGF(infof(data, "SCP DONE phase complete\n"));
02602 #if 0 /* PREV */
02603       state(conn, SSH_SESSION_DISCONNECT);
02604 #endif
02605       state(conn, SSH_STOP);
02606       result = sshc->actualcode;
02607       break;
02608 
02609     case SSH_SESSION_DISCONNECT:
02610       /* during weird times when we've been prematurely aborted, the channel
02611          is still alive when we reach this state and we MUST kill the channel
02612          properly first */
02613       if(sshc->ssh_channel) {
02614         rc = libssh2_channel_free(sshc->ssh_channel);
02615         if(rc == LIBSSH2_ERROR_EAGAIN) {
02616           break;
02617         }
02618         else if(rc < 0) {
02619           infof(data, "Failed to free libssh2 scp subsystem\n");
02620         }
02621         sshc->ssh_channel = NULL;
02622       }
02623 
02624       if(sshc->ssh_session) {
02625         rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
02626         if(rc == LIBSSH2_ERROR_EAGAIN) {
02627           break;
02628         }
02629         else if(rc < 0) {
02630           infof(data, "Failed to disconnect libssh2 session\n");
02631         }
02632       }
02633 
02634       Curl_safefree(sshc->homedir);
02635       conn->data->state.most_recent_ftp_entrypath = NULL;
02636 
02637       state(conn, SSH_SESSION_FREE);
02638       break;
02639 
02640     case SSH_SESSION_FREE:
02641 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02642       if(sshc->kh) {
02643         libssh2_knownhost_free(sshc->kh);
02644         sshc->kh = NULL;
02645       }
02646 #endif
02647 
02648 #ifdef HAVE_LIBSSH2_AGENT_API
02649       if(sshc->ssh_agent) {
02650         rc = libssh2_agent_disconnect(sshc->ssh_agent);
02651         if(rc == LIBSSH2_ERROR_EAGAIN) {
02652           break;
02653         }
02654         else if(rc < 0) {
02655           infof(data, "Failed to disconnect from libssh2 agent\n");
02656         }
02657         libssh2_agent_free(sshc->ssh_agent);
02658         sshc->ssh_agent = NULL;
02659 
02660         /* NB: there is no need to free identities, they are part of internal
02661            agent stuff */
02662         sshc->sshagent_identity = NULL;
02663         sshc->sshagent_prev_identity = NULL;
02664       }
02665 #endif
02666 
02667       if(sshc->ssh_session) {
02668         rc = libssh2_session_free(sshc->ssh_session);
02669         if(rc == LIBSSH2_ERROR_EAGAIN) {
02670           break;
02671         }
02672         else if(rc < 0) {
02673           infof(data, "Failed to free libssh2 session\n");
02674         }
02675         sshc->ssh_session = NULL;
02676       }
02677 
02678       /* worst-case scenario cleanup */
02679 
02680       DEBUGASSERT(sshc->ssh_session == NULL);
02681       DEBUGASSERT(sshc->ssh_channel == NULL);
02682       DEBUGASSERT(sshc->sftp_session == NULL);
02683       DEBUGASSERT(sshc->sftp_handle == NULL);
02684 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02685       DEBUGASSERT(sshc->kh == NULL);
02686 #endif
02687 #ifdef HAVE_LIBSSH2_AGENT_API
02688       DEBUGASSERT(sshc->ssh_agent == NULL);
02689 #endif
02690 
02691       Curl_safefree(sshc->rsa_pub);
02692       Curl_safefree(sshc->rsa);
02693 
02694       Curl_safefree(sshc->quote_path1);
02695       Curl_safefree(sshc->quote_path2);
02696 
02697       Curl_safefree(sshc->homedir);
02698 
02699       Curl_safefree(sshc->readdir_filename);
02700       Curl_safefree(sshc->readdir_longentry);
02701       Curl_safefree(sshc->readdir_line);
02702       Curl_safefree(sshc->readdir_linkPath);
02703 
02704       /* the code we are about to return */
02705       result = sshc->actualcode;
02706 
02707       memset(sshc, 0, sizeof(struct ssh_conn));
02708 
02709       connclose(conn, "SSH session free");
02710       sshc->state = SSH_SESSION_FREE; /* current */
02711       sshc->nextstate = SSH_NO_STATE;
02712       state(conn, SSH_STOP);
02713       break;
02714 
02715     case SSH_QUIT:
02716       /* fallthrough, just stop! */
02717     default:
02718       /* internal error */
02719       sshc->nextstate = SSH_NO_STATE;
02720       state(conn, SSH_STOP);
02721       break;
02722     }
02723 
02724   } while(!rc && (sshc->state != SSH_STOP));
02725 
02726   if(rc == LIBSSH2_ERROR_EAGAIN) {
02727     /* we would block, we need to wait for the socket to be ready (in the
02728        right direction too)! */
02729     *block = TRUE;
02730   }
02731 
02732   return result;
02733 }
02734 
02735 /* called by the multi interface to figure out what socket(s) to wait for and
02736    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
02737 static int ssh_perform_getsock(const struct connectdata *conn,
02738                                curl_socket_t *sock, /* points to numsocks
02739                                                        number of sockets */
02740                                int numsocks)
02741 {
02742 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02743   int bitmap = GETSOCK_BLANK;
02744   (void)numsocks;
02745 
02746   sock[0] = conn->sock[FIRSTSOCKET];
02747 
02748   if(conn->waitfor & KEEP_RECV)
02749     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
02750 
02751   if(conn->waitfor & KEEP_SEND)
02752     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
02753 
02754   return bitmap;
02755 #else
02756   /* if we don't know the direction we can use the generic *_getsock()
02757      function even for the protocol_connect and doing states */
02758   return Curl_single_getsock(conn, sock, numsocks);
02759 #endif
02760 }
02761 
02762 /* Generic function called by the multi interface to figure out what socket(s)
02763    to wait for and for what actions during the DOING and PROTOCONNECT states*/
02764 static int ssh_getsock(struct connectdata *conn,
02765                        curl_socket_t *sock, /* points to numsocks number
02766                                                of sockets */
02767                        int numsocks)
02768 {
02769 #ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02770   (void)conn;
02771   (void)sock;
02772   (void)numsocks;
02773   /* if we don't know any direction we can just play along as we used to and
02774      not provide any sensible info */
02775   return GETSOCK_BLANK;
02776 #else
02777   /* if we know the direction we can use the generic *_getsock() function even
02778      for the protocol_connect and doing states */
02779   return ssh_perform_getsock(conn, sock, numsocks);
02780 #endif
02781 }
02782 
02783 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02784 /*
02785  * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
02786  * function is used to figure out in what direction and stores this info so
02787  * that the multi interface can take advantage of it. Make sure to call this
02788  * function in all cases so that when it _doesn't_ return EAGAIN we can
02789  * restore the default wait bits.
02790  */
02791 static void ssh_block2waitfor(struct connectdata *conn, bool block)
02792 {
02793   struct ssh_conn *sshc = &conn->proto.sshc;
02794   int dir = 0;
02795   if(block) {
02796     dir = libssh2_session_block_directions(sshc->ssh_session);
02797     if(dir) {
02798       /* translate the libssh2 define bits into our own bit defines */
02799       conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
02800         ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
02801     }
02802   }
02803   if(!dir)
02804     /* It didn't block or libssh2 didn't reveal in which direction, put back
02805        the original set */
02806     conn->waitfor = sshc->orig_waitfor;
02807 }
02808 #else
02809   /* no libssh2 directional support so we simply don't know */
02810 #define ssh_block2waitfor(x,y) Curl_nop_stmt
02811 #endif
02812 
02813 /* called repeatedly until done from multi.c */
02814 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
02815 {
02816   struct ssh_conn *sshc = &conn->proto.sshc;
02817   CURLcode result = CURLE_OK;
02818   bool block; /* we store the status and use that to provide a ssh_getsock()
02819                  implementation */
02820 
02821   result = ssh_statemach_act(conn, &block);
02822   *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
02823   ssh_block2waitfor(conn, block);
02824 
02825   return result;
02826 }
02827 
02828 static CURLcode ssh_block_statemach(struct connectdata *conn,
02829                                    bool duringconnect)
02830 {
02831   struct ssh_conn *sshc = &conn->proto.sshc;
02832   CURLcode result = CURLE_OK;
02833   struct Curl_easy *data = conn->data;
02834 
02835   while((sshc->state != SSH_STOP) && !result) {
02836     bool block;
02837     long left;
02838 
02839     result = ssh_statemach_act(conn, &block);
02840     if(result)
02841       break;
02842 
02843     if(Curl_pgrsUpdate(conn))
02844       return CURLE_ABORTED_BY_CALLBACK;
02845     else {
02846       struct timeval now = Curl_tvnow();
02847       result = Curl_speedcheck(data, now);
02848       if(result)
02849         break;
02850     }
02851 
02852     left = Curl_timeleft(data, NULL, duringconnect);
02853     if(left < 0) {
02854       failf(data, "Operation timed out");
02855       return CURLE_OPERATION_TIMEDOUT;
02856     }
02857 
02858 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02859     if(!result && block) {
02860       int dir = libssh2_session_block_directions(sshc->ssh_session);
02861       curl_socket_t sock = conn->sock[FIRSTSOCKET];
02862       curl_socket_t fd_read = CURL_SOCKET_BAD;
02863       curl_socket_t fd_write = CURL_SOCKET_BAD;
02864       if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
02865         fd_read = sock;
02866       if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
02867         fd_write = sock;
02868       /* wait for the socket to become ready */
02869       (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
02870                               left>1000?1000:left); /* ignore result */
02871     }
02872 #endif
02873 
02874   }
02875 
02876   return result;
02877 }
02878 
02879 /*
02880  * SSH setup and connection
02881  */
02882 static CURLcode ssh_setup_connection(struct connectdata *conn)
02883 {
02884   struct SSHPROTO *ssh;
02885 
02886   conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
02887   if(!ssh)
02888     return CURLE_OUT_OF_MEMORY;
02889 
02890   return CURLE_OK;
02891 }
02892 
02893 static Curl_recv scp_recv, sftp_recv;
02894 static Curl_send scp_send, sftp_send;
02895 
02896 /*
02897  * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
02898  * do protocol-specific actions at connect-time.
02899  */
02900 static CURLcode ssh_connect(struct connectdata *conn, bool *done)
02901 {
02902 #ifdef CURL_LIBSSH2_DEBUG
02903   curl_socket_t sock;
02904 #endif
02905   struct ssh_conn *ssh;
02906   CURLcode result;
02907   struct Curl_easy *data = conn->data;
02908 
02909   /* initialize per-handle data if not already */
02910   if(!data->req.protop)
02911     ssh_setup_connection(conn);
02912 
02913   /* We default to persistent connections. We set this already in this connect
02914      function to make the re-use checks properly be able to check this bit. */
02915   connkeep(conn, "SSH default");
02916 
02917   if(conn->handler->protocol & CURLPROTO_SCP) {
02918     conn->recv[FIRSTSOCKET] = scp_recv;
02919     conn->send[FIRSTSOCKET] = scp_send;
02920   }
02921   else {
02922     conn->recv[FIRSTSOCKET] = sftp_recv;
02923     conn->send[FIRSTSOCKET] = sftp_send;
02924   }
02925   ssh = &conn->proto.sshc;
02926 
02927 #ifdef CURL_LIBSSH2_DEBUG
02928   if(conn->user) {
02929     infof(data, "User: %s\n", conn->user);
02930   }
02931   if(conn->passwd) {
02932     infof(data, "Password: %s\n", conn->passwd);
02933   }
02934   sock = conn->sock[FIRSTSOCKET];
02935 #endif /* CURL_LIBSSH2_DEBUG */
02936 
02937   ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
02938                                              my_libssh2_free,
02939                                              my_libssh2_realloc, conn);
02940   if(ssh->ssh_session == NULL) {
02941     failf(data, "Failure initialising ssh session");
02942     return CURLE_FAILED_INIT;
02943   }
02944 
02945 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02946   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
02947     int rc;
02948     ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
02949     if(!ssh->kh) {
02950       /* eeek. TODO: free the ssh_session! */
02951       return CURLE_FAILED_INIT;
02952     }
02953 
02954     /* read all known hosts from there */
02955     rc = libssh2_knownhost_readfile(ssh->kh,
02956                                     data->set.str[STRING_SSH_KNOWNHOSTS],
02957                                     LIBSSH2_KNOWNHOST_FILE_OPENSSH);
02958     if(rc < 0)
02959       infof(data, "Failed to read known hosts from %s\n",
02960             data->set.str[STRING_SSH_KNOWNHOSTS]);
02961   }
02962 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
02963 
02964 #ifdef CURL_LIBSSH2_DEBUG
02965   libssh2_trace(ssh->ssh_session, ~0);
02966   infof(data, "SSH socket: %d\n", (int)sock);
02967 #endif /* CURL_LIBSSH2_DEBUG */
02968 
02969   state(conn, SSH_INIT);
02970 
02971   result = ssh_multi_statemach(conn, done);
02972 
02973   return result;
02974 }
02975 
02976 /*
02977  ***********************************************************************
02978  *
02979  * scp_perform()
02980  *
02981  * This is the actual DO function for SCP. Get a file according to
02982  * the options previously setup.
02983  */
02984 
02985 static
02986 CURLcode scp_perform(struct connectdata *conn,
02987                       bool *connected,
02988                       bool *dophase_done)
02989 {
02990   CURLcode result = CURLE_OK;
02991 
02992   DEBUGF(infof(conn->data, "DO phase starts\n"));
02993 
02994   *dophase_done = FALSE; /* not done yet */
02995 
02996   /* start the first command in the DO phase */
02997   state(conn, SSH_SCP_TRANS_INIT);
02998 
02999   /* run the state-machine */
03000   result = ssh_multi_statemach(conn, dophase_done);
03001 
03002   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
03003 
03004   if(*dophase_done) {
03005     DEBUGF(infof(conn->data, "DO phase is complete\n"));
03006   }
03007 
03008   return result;
03009 }
03010 
03011 /* called from multi.c while DOing */
03012 static CURLcode scp_doing(struct connectdata *conn,
03013                                bool *dophase_done)
03014 {
03015   CURLcode result;
03016   result = ssh_multi_statemach(conn, dophase_done);
03017 
03018   if(*dophase_done) {
03019     DEBUGF(infof(conn->data, "DO phase is complete\n"));
03020   }
03021   return result;
03022 }
03023 
03024 /*
03025  * The DO function is generic for both protocols. There was previously two
03026  * separate ones but this way means less duplicated code.
03027  */
03028 
03029 static CURLcode ssh_do(struct connectdata *conn, bool *done)
03030 {
03031   CURLcode result;
03032   bool connected = 0;
03033   struct Curl_easy *data = conn->data;
03034   struct ssh_conn *sshc = &conn->proto.sshc;
03035 
03036   *done = FALSE; /* default to false */
03037 
03038   data->req.size = -1; /* make sure this is unknown at this point */
03039 
03040   sshc->actualcode = CURLE_OK; /* reset error code */
03041   sshc->secondCreateDirs =0;   /* reset the create dir attempt state
03042                                   variable */
03043 
03044   Curl_pgrsSetUploadCounter(data, 0);
03045   Curl_pgrsSetDownloadCounter(data, 0);
03046   Curl_pgrsSetUploadSize(data, -1);
03047   Curl_pgrsSetDownloadSize(data, -1);
03048 
03049   if(conn->handler->protocol & CURLPROTO_SCP)
03050     result = scp_perform(conn, &connected,  done);
03051   else
03052     result = sftp_perform(conn, &connected,  done);
03053 
03054   return result;
03055 }
03056 
03057 /* BLOCKING, but the function is using the state machine so the only reason
03058    this is still blocking is that the multi interface code has no support for
03059    disconnecting operations that takes a while */
03060 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
03061 {
03062   CURLcode result = CURLE_OK;
03063   struct ssh_conn *ssh = &conn->proto.sshc;
03064   (void) dead_connection;
03065 
03066   if(ssh->ssh_session) {
03067     /* only if there's a session still around to use! */
03068 
03069     state(conn, SSH_SESSION_DISCONNECT);
03070 
03071     result = ssh_block_statemach(conn, FALSE);
03072   }
03073 
03074   return result;
03075 }
03076 
03077 /* generic done function for both SCP and SFTP called from their specific
03078    done functions */
03079 static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
03080 {
03081   CURLcode result = CURLE_OK;
03082   struct SSHPROTO *sftp_scp = conn->data->req.protop;
03083 
03084   if(!status) {
03085     /* run the state-machine
03086 
03087        TODO: when the multi interface is used, this _really_ should be using
03088        the ssh_multi_statemach function but we have no general support for
03089        non-blocking DONE operations!
03090     */
03091     result = ssh_block_statemach(conn, FALSE);
03092   }
03093   else
03094     result = status;
03095 
03096   if(sftp_scp)
03097     Curl_safefree(sftp_scp->path);
03098   if(Curl_pgrsDone(conn))
03099     return CURLE_ABORTED_BY_CALLBACK;
03100 
03101   conn->data->req.keepon = 0; /* clear all bits */
03102   return result;
03103 }
03104 
03105 
03106 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
03107                          bool premature)
03108 {
03109   (void)premature; /* not used */
03110 
03111   if(!status)
03112     state(conn, SSH_SCP_DONE);
03113 
03114   return ssh_done(conn, status);
03115 
03116 }
03117 
03118 static ssize_t scp_send(struct connectdata *conn, int sockindex,
03119                         const void *mem, size_t len, CURLcode *err)
03120 {
03121   ssize_t nwrite;
03122   (void)sockindex; /* we only support SCP on the fixed known primary socket */
03123 
03124   /* libssh2_channel_write() returns int! */
03125   nwrite = (ssize_t)
03126     libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
03127 
03128   ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03129 
03130   if(nwrite == LIBSSH2_ERROR_EAGAIN) {
03131     *err = CURLE_AGAIN;
03132     nwrite = 0;
03133   }
03134   else if(nwrite < LIBSSH2_ERROR_NONE) {
03135     *err = libssh2_session_error_to_CURLE((int)nwrite);
03136     nwrite = -1;
03137   }
03138 
03139   return nwrite;
03140 }
03141 
03142 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
03143                         char *mem, size_t len, CURLcode *err)
03144 {
03145   ssize_t nread;
03146   (void)sockindex; /* we only support SCP on the fixed known primary socket */
03147 
03148   /* libssh2_channel_read() returns int */
03149   nread = (ssize_t)
03150     libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
03151 
03152   ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03153   if(nread == LIBSSH2_ERROR_EAGAIN) {
03154     *err = CURLE_AGAIN;
03155     nread = -1;
03156   }
03157 
03158   return nread;
03159 }
03160 
03161 /*
03162  * =============== SFTP ===============
03163  */
03164 
03165 /*
03166  ***********************************************************************
03167  *
03168  * sftp_perform()
03169  *
03170  * This is the actual DO function for SFTP. Get a file/directory according to
03171  * the options previously setup.
03172  */
03173 
03174 static
03175 CURLcode sftp_perform(struct connectdata *conn,
03176                       bool *connected,
03177                       bool *dophase_done)
03178 {
03179   CURLcode result = CURLE_OK;
03180 
03181   DEBUGF(infof(conn->data, "DO phase starts\n"));
03182 
03183   *dophase_done = FALSE; /* not done yet */
03184 
03185   /* start the first command in the DO phase */
03186   state(conn, SSH_SFTP_QUOTE_INIT);
03187 
03188   /* run the state-machine */
03189   result = ssh_multi_statemach(conn, dophase_done);
03190 
03191   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
03192 
03193   if(*dophase_done) {
03194     DEBUGF(infof(conn->data, "DO phase is complete\n"));
03195   }
03196 
03197   return result;
03198 }
03199 
03200 /* called from multi.c while DOing */
03201 static CURLcode sftp_doing(struct connectdata *conn,
03202                            bool *dophase_done)
03203 {
03204   CURLcode result = ssh_multi_statemach(conn, dophase_done);
03205 
03206   if(*dophase_done) {
03207     DEBUGF(infof(conn->data, "DO phase is complete\n"));
03208   }
03209   return result;
03210 }
03211 
03212 /* BLOCKING, but the function is using the state machine so the only reason
03213    this is still blocking is that the multi interface code has no support for
03214    disconnecting operations that takes a while */
03215 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
03216 {
03217   CURLcode result = CURLE_OK;
03218   (void) dead_connection;
03219 
03220   DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
03221 
03222   if(conn->proto.sshc.ssh_session) {
03223     /* only if there's a session still around to use! */
03224     state(conn, SSH_SFTP_SHUTDOWN);
03225     result = ssh_block_statemach(conn, FALSE);
03226   }
03227 
03228   DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
03229 
03230   return result;
03231 
03232 }
03233 
03234 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
03235                                bool premature)
03236 {
03237   struct ssh_conn *sshc = &conn->proto.sshc;
03238 
03239   if(!status) {
03240     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
03241        errors that could happen due to open file handles during POSTQUOTE
03242        operation */
03243     if(!status && !premature && conn->data->set.postquote) {
03244       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
03245       state(conn, SSH_SFTP_CLOSE);
03246     }
03247     else
03248       state(conn, SSH_SFTP_CLOSE);
03249   }
03250   return ssh_done(conn, status);
03251 }
03252 
03253 /* return number of sent bytes */
03254 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
03255                          const void *mem, size_t len, CURLcode *err)
03256 {
03257   ssize_t nwrite;   /* libssh2_sftp_write() used to return size_t in 0.14
03258                        but is changed to ssize_t in 0.15. These days we don't
03259                        support libssh2 0.15*/
03260   (void)sockindex;
03261 
03262   nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
03263 
03264   ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03265 
03266   if(nwrite == LIBSSH2_ERROR_EAGAIN) {
03267     *err = CURLE_AGAIN;
03268     nwrite = 0;
03269   }
03270   else if(nwrite < LIBSSH2_ERROR_NONE) {
03271     *err = libssh2_session_error_to_CURLE((int)nwrite);
03272     nwrite = -1;
03273   }
03274 
03275   return nwrite;
03276 }
03277 
03278 /*
03279  * Return number of received (decrypted) bytes
03280  * or <0 on error
03281  */
03282 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
03283                          char *mem, size_t len, CURLcode *err)
03284 {
03285   ssize_t nread;
03286   (void)sockindex;
03287 
03288   nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
03289 
03290   ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03291 
03292   if(nread == LIBSSH2_ERROR_EAGAIN) {
03293     *err = CURLE_AGAIN;
03294     nread = -1;
03295 
03296   }
03297   else if(nread < 0) {
03298     *err = libssh2_session_error_to_CURLE((int)nread);
03299   }
03300   return nread;
03301 }
03302 
03303 /* The get_pathname() function is being borrowed from OpenSSH sftp.c
03304    version 4.6p1. */
03305 /*
03306  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
03307  *
03308  * Permission to use, copy, modify, and distribute this software for any
03309  * purpose with or without fee is hereby granted, provided that the above
03310  * copyright notice and this permission notice appear in all copies.
03311  *
03312  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
03313  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
03314  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
03315  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
03316  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
03317  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
03318  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
03319  */
03320 static CURLcode
03321 get_pathname(const char **cpp, char **path)
03322 {
03323   const char *cp = *cpp, *end;
03324   char quot;
03325   unsigned int i, j;
03326   static const char WHITESPACE[] = " \t\r\n";
03327 
03328   cp += strspn(cp, WHITESPACE);
03329   if(!*cp) {
03330     *cpp = cp;
03331     *path = NULL;
03332     return CURLE_QUOTE_ERROR;
03333   }
03334 
03335   *path = malloc(strlen(cp) + 1);
03336   if(*path == NULL)
03337     return CURLE_OUT_OF_MEMORY;
03338 
03339   /* Check for quoted filenames */
03340   if(*cp == '\"' || *cp == '\'') {
03341     quot = *cp++;
03342 
03343     /* Search for terminating quote, unescape some chars */
03344     for(i = j = 0; i <= strlen(cp); i++) {
03345       if(cp[i] == quot) {  /* Found quote */
03346         i++;
03347         (*path)[j] = '\0';
03348         break;
03349       }
03350       if(cp[i] == '\0') {  /* End of string */
03351         /*error("Unterminated quote");*/
03352         goto fail;
03353       }
03354       if(cp[i] == '\\') {  /* Escaped characters */
03355         i++;
03356         if(cp[i] != '\'' && cp[i] != '\"' &&
03357             cp[i] != '\\') {
03358           /*error("Bad escaped character '\\%c'",
03359               cp[i]);*/
03360           goto fail;
03361         }
03362       }
03363       (*path)[j++] = cp[i];
03364     }
03365 
03366     if(j == 0) {
03367       /*error("Empty quotes");*/
03368       goto fail;
03369     }
03370     *cpp = cp + i + strspn(cp + i, WHITESPACE);
03371   }
03372   else {
03373     /* Read to end of filename */
03374     end = strpbrk(cp, WHITESPACE);
03375     if(end == NULL)
03376       end = strchr(cp, '\0');
03377     *cpp = end + strspn(end, WHITESPACE);
03378 
03379     memcpy(*path, cp, end - cp);
03380     (*path)[end - cp] = '\0';
03381   }
03382   return CURLE_OK;
03383 
03384   fail:
03385   Curl_safefree(*path);
03386   return CURLE_QUOTE_ERROR;
03387 }
03388 
03389 
03390 static const char *sftp_libssh2_strerror(int err)
03391 {
03392   switch(err) {
03393     case LIBSSH2_FX_NO_SUCH_FILE:
03394       return "No such file or directory";
03395 
03396     case LIBSSH2_FX_PERMISSION_DENIED:
03397       return "Permission denied";
03398 
03399     case LIBSSH2_FX_FAILURE:
03400       return "Operation failed";
03401 
03402     case LIBSSH2_FX_BAD_MESSAGE:
03403       return "Bad message from SFTP server";
03404 
03405     case LIBSSH2_FX_NO_CONNECTION:
03406       return "Not connected to SFTP server";
03407 
03408     case LIBSSH2_FX_CONNECTION_LOST:
03409       return "Connection to SFTP server lost";
03410 
03411     case LIBSSH2_FX_OP_UNSUPPORTED:
03412       return "Operation not supported by SFTP server";
03413 
03414     case LIBSSH2_FX_INVALID_HANDLE:
03415       return "Invalid handle";
03416 
03417     case LIBSSH2_FX_NO_SUCH_PATH:
03418       return "No such file or directory";
03419 
03420     case LIBSSH2_FX_FILE_ALREADY_EXISTS:
03421       return "File already exists";
03422 
03423     case LIBSSH2_FX_WRITE_PROTECT:
03424       return "File is write protected";
03425 
03426     case LIBSSH2_FX_NO_MEDIA:
03427       return "No media";
03428 
03429     case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
03430       return "Disk full";
03431 
03432     case LIBSSH2_FX_QUOTA_EXCEEDED:
03433       return "User quota exceeded";
03434 
03435     case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
03436       return "Unknown principle";
03437 
03438     case LIBSSH2_FX_LOCK_CONFlICT:
03439       return "File lock conflict";
03440 
03441     case LIBSSH2_FX_DIR_NOT_EMPTY:
03442       return "Directory not empty";
03443 
03444     case LIBSSH2_FX_NOT_A_DIRECTORY:
03445       return "Not a directory";
03446 
03447     case LIBSSH2_FX_INVALID_FILENAME:
03448       return "Invalid filename";
03449 
03450     case LIBSSH2_FX_LINK_LOOP:
03451       return "Link points to itself";
03452   }
03453   return "Unknown error in libssh2";
03454 }
03455 
03456 #endif /* USE_LIBSSH2 */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06