libcurl: updated to 7.49.1
[tomato.git] / release / src / router / libcurl / lib / ssh.c
blobd5a1a2a8cf9242721b6964bcfc42e015de8a6fdf
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 /* #define CURL_LIBSSH2_DEBUG */
25 #include "curl_setup.h"
27 #ifdef USE_LIBSSH2
29 #ifdef HAVE_LIMITS_H
30 # include <limits.h>
31 #endif
33 #include <libssh2.h>
34 #include <libssh2_sftp.h>
36 #ifdef HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif
40 #ifdef HAVE_NETINET_IN_H
41 #include <netinet/in.h>
42 #endif
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
45 #endif
46 #ifdef HAVE_UTSNAME_H
47 #include <sys/utsname.h>
48 #endif
49 #ifdef HAVE_NETDB_H
50 #include <netdb.h>
51 #endif
52 #ifdef __VMS
53 #include <in.h>
54 #include <inet.h>
55 #endif
57 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
58 #undef in_addr_t
59 #define in_addr_t unsigned long
60 #endif
62 #include <curl/curl.h>
63 #include "urldata.h"
64 #include "sendf.h"
65 #include "hostip.h"
66 #include "progress.h"
67 #include "transfer.h"
68 #include "escape.h"
69 #include "http.h" /* for HTTP proxy tunnel stuff */
70 #include "ssh.h"
71 #include "url.h"
72 #include "speedcheck.h"
73 #include "getinfo.h"
75 #include "strequal.h"
76 #include "vtls/vtls.h"
77 #include "connect.h"
78 #include "strerror.h"
79 #include "inet_ntop.h"
80 #include "parsedate.h" /* for the week day and month names */
81 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
82 #include "strtoofft.h"
83 #include "multiif.h"
84 #include "select.h"
85 #include "warnless.h"
87 /* The last 3 #include files should be in this order */
88 #include "curl_printf.h"
89 #include "curl_memory.h"
90 #include "memdebug.h"
92 #ifdef WIN32
93 # undef PATH_MAX
94 # define PATH_MAX MAX_PATH
95 # ifndef R_OK
96 # define R_OK 4
97 # endif
98 #endif
100 #ifndef PATH_MAX
101 #define PATH_MAX 1024 /* just an extra precaution since there are systems that
102 have their definition hidden well */
103 #endif
105 #if LIBSSH2_VERSION_NUM >= 0x010206
106 /* libssh2_sftp_statvfs and friends were added in 1.2.6 */
107 #define HAS_STATVFS_SUPPORT 1
108 #endif
110 #define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
112 #define sftp_libssh2_realpath(s,p,t,m) \
113 libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
114 (t), (m), LIBSSH2_SFTP_REALPATH)
116 /* Local functions: */
117 static const char *sftp_libssh2_strerror(int err);
118 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
119 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
120 static LIBSSH2_FREE_FUNC(my_libssh2_free);
122 static CURLcode get_pathname(const char **cpp, char **path);
124 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
125 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
126 static CURLcode ssh_do(struct connectdata *conn, bool *done);
128 static CURLcode ssh_getworkingpath(struct connectdata *conn,
129 char *homedir, /* when SFTP is used */
130 char **path);
132 static CURLcode scp_done(struct connectdata *conn,
133 CURLcode, bool premature);
134 static CURLcode scp_doing(struct connectdata *conn,
135 bool *dophase_done);
136 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
138 static CURLcode sftp_done(struct connectdata *conn,
139 CURLcode, bool premature);
140 static CURLcode sftp_doing(struct connectdata *conn,
141 bool *dophase_done);
142 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
143 static
144 CURLcode sftp_perform(struct connectdata *conn,
145 bool *connected,
146 bool *dophase_done);
148 static int ssh_getsock(struct connectdata *conn,
149 curl_socket_t *sock, /* points to numsocks number
150 of sockets */
151 int numsocks);
153 static int ssh_perform_getsock(const struct connectdata *conn,
154 curl_socket_t *sock, /* points to numsocks
155 number of sockets */
156 int numsocks);
158 static CURLcode ssh_setup_connection(struct connectdata *conn);
161 * SCP protocol handler.
164 const struct Curl_handler Curl_handler_scp = {
165 "SCP", /* scheme */
166 ssh_setup_connection, /* setup_connection */
167 ssh_do, /* do_it */
168 scp_done, /* done */
169 ZERO_NULL, /* do_more */
170 ssh_connect, /* connect_it */
171 ssh_multi_statemach, /* connecting */
172 scp_doing, /* doing */
173 ssh_getsock, /* proto_getsock */
174 ssh_getsock, /* doing_getsock */
175 ZERO_NULL, /* domore_getsock */
176 ssh_perform_getsock, /* perform_getsock */
177 scp_disconnect, /* disconnect */
178 ZERO_NULL, /* readwrite */
179 PORT_SSH, /* defport */
180 CURLPROTO_SCP, /* protocol */
181 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
182 | PROTOPT_NOURLQUERY /* flags */
187 * SFTP protocol handler.
190 const struct Curl_handler Curl_handler_sftp = {
191 "SFTP", /* scheme */
192 ssh_setup_connection, /* setup_connection */
193 ssh_do, /* do_it */
194 sftp_done, /* done */
195 ZERO_NULL, /* do_more */
196 ssh_connect, /* connect_it */
197 ssh_multi_statemach, /* connecting */
198 sftp_doing, /* doing */
199 ssh_getsock, /* proto_getsock */
200 ssh_getsock, /* doing_getsock */
201 ZERO_NULL, /* domore_getsock */
202 ssh_perform_getsock, /* perform_getsock */
203 sftp_disconnect, /* disconnect */
204 ZERO_NULL, /* readwrite */
205 PORT_SSH, /* defport */
206 CURLPROTO_SFTP, /* protocol */
207 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
208 | PROTOPT_NOURLQUERY /* flags */
211 static void
212 kbd_callback(const char *name, int name_len, const char *instruction,
213 int instruction_len, int num_prompts,
214 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
215 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
216 void **abstract)
218 struct connectdata *conn = (struct connectdata *)*abstract;
220 #ifdef CURL_LIBSSH2_DEBUG
221 fprintf(stderr, "name=%s\n", name);
222 fprintf(stderr, "name_len=%d\n", name_len);
223 fprintf(stderr, "instruction=%s\n", instruction);
224 fprintf(stderr, "instruction_len=%d\n", instruction_len);
225 fprintf(stderr, "num_prompts=%d\n", num_prompts);
226 #else
227 (void)name;
228 (void)name_len;
229 (void)instruction;
230 (void)instruction_len;
231 #endif /* CURL_LIBSSH2_DEBUG */
232 if(num_prompts == 1) {
233 responses[0].text = strdup(conn->passwd);
234 responses[0].length = curlx_uztoui(strlen(conn->passwd));
236 (void)prompts;
237 (void)abstract;
238 } /* kbd_callback */
240 static CURLcode sftp_libssh2_error_to_CURLE(int err)
242 switch (err) {
243 case LIBSSH2_FX_OK:
244 return CURLE_OK;
246 case LIBSSH2_FX_NO_SUCH_FILE:
247 case LIBSSH2_FX_NO_SUCH_PATH:
248 return CURLE_REMOTE_FILE_NOT_FOUND;
250 case LIBSSH2_FX_PERMISSION_DENIED:
251 case LIBSSH2_FX_WRITE_PROTECT:
252 case LIBSSH2_FX_LOCK_CONFlICT:
253 return CURLE_REMOTE_ACCESS_DENIED;
255 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
256 case LIBSSH2_FX_QUOTA_EXCEEDED:
257 return CURLE_REMOTE_DISK_FULL;
259 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
260 return CURLE_REMOTE_FILE_EXISTS;
262 case LIBSSH2_FX_DIR_NOT_EMPTY:
263 return CURLE_QUOTE_ERROR;
265 default:
266 break;
269 return CURLE_SSH;
272 static CURLcode libssh2_session_error_to_CURLE(int err)
274 switch (err) {
275 /* Ordered by order of appearance in libssh2.h */
276 case LIBSSH2_ERROR_NONE:
277 return CURLE_OK;
279 case LIBSSH2_ERROR_SOCKET_NONE:
280 return CURLE_COULDNT_CONNECT;
282 case LIBSSH2_ERROR_ALLOC:
283 return CURLE_OUT_OF_MEMORY;
285 case LIBSSH2_ERROR_SOCKET_SEND:
286 return CURLE_SEND_ERROR;
288 case LIBSSH2_ERROR_HOSTKEY_INIT:
289 case LIBSSH2_ERROR_HOSTKEY_SIGN:
290 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
291 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
292 return CURLE_PEER_FAILED_VERIFICATION;
294 case LIBSSH2_ERROR_PASSWORD_EXPIRED:
295 return CURLE_LOGIN_DENIED;
297 case LIBSSH2_ERROR_SOCKET_TIMEOUT:
298 case LIBSSH2_ERROR_TIMEOUT:
299 return CURLE_OPERATION_TIMEDOUT;
301 case LIBSSH2_ERROR_EAGAIN:
302 return CURLE_AGAIN;
305 /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
306 error code, and possibly add a few new SSH-related one. We must however
307 not return or even depend on libssh2 errors in the public libcurl API */
309 return CURLE_SSH;
312 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
314 (void)abstract; /* arg not used */
315 return malloc(count);
318 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
320 (void)abstract; /* arg not used */
321 return realloc(ptr, count);
324 static LIBSSH2_FREE_FUNC(my_libssh2_free)
326 (void)abstract; /* arg not used */
327 if(ptr) /* ssh2 agent sometimes call free with null ptr */
328 free(ptr);
332 * SSH State machine related code
334 /* This is the ONLY way to change SSH state! */
335 static void state(struct connectdata *conn, sshstate nowstate)
337 struct ssh_conn *sshc = &conn->proto.sshc;
338 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
339 /* for debug purposes */
340 static const char * const names[] = {
341 "SSH_STOP",
342 "SSH_INIT",
343 "SSH_S_STARTUP",
344 "SSH_HOSTKEY",
345 "SSH_AUTHLIST",
346 "SSH_AUTH_PKEY_INIT",
347 "SSH_AUTH_PKEY",
348 "SSH_AUTH_PASS_INIT",
349 "SSH_AUTH_PASS",
350 "SSH_AUTH_AGENT_INIT",
351 "SSH_AUTH_AGENT_LIST",
352 "SSH_AUTH_AGENT",
353 "SSH_AUTH_HOST_INIT",
354 "SSH_AUTH_HOST",
355 "SSH_AUTH_KEY_INIT",
356 "SSH_AUTH_KEY",
357 "SSH_AUTH_DONE",
358 "SSH_SFTP_INIT",
359 "SSH_SFTP_REALPATH",
360 "SSH_SFTP_QUOTE_INIT",
361 "SSH_SFTP_POSTQUOTE_INIT",
362 "SSH_SFTP_QUOTE",
363 "SSH_SFTP_NEXT_QUOTE",
364 "SSH_SFTP_QUOTE_STAT",
365 "SSH_SFTP_QUOTE_SETSTAT",
366 "SSH_SFTP_QUOTE_SYMLINK",
367 "SSH_SFTP_QUOTE_MKDIR",
368 "SSH_SFTP_QUOTE_RENAME",
369 "SSH_SFTP_QUOTE_RMDIR",
370 "SSH_SFTP_QUOTE_UNLINK",
371 "SSH_SFTP_QUOTE_STATVFS",
372 "SSH_SFTP_GETINFO",
373 "SSH_SFTP_FILETIME",
374 "SSH_SFTP_TRANS_INIT",
375 "SSH_SFTP_UPLOAD_INIT",
376 "SSH_SFTP_CREATE_DIRS_INIT",
377 "SSH_SFTP_CREATE_DIRS",
378 "SSH_SFTP_CREATE_DIRS_MKDIR",
379 "SSH_SFTP_READDIR_INIT",
380 "SSH_SFTP_READDIR",
381 "SSH_SFTP_READDIR_LINK",
382 "SSH_SFTP_READDIR_BOTTOM",
383 "SSH_SFTP_READDIR_DONE",
384 "SSH_SFTP_DOWNLOAD_INIT",
385 "SSH_SFTP_DOWNLOAD_STAT",
386 "SSH_SFTP_CLOSE",
387 "SSH_SFTP_SHUTDOWN",
388 "SSH_SCP_TRANS_INIT",
389 "SSH_SCP_UPLOAD_INIT",
390 "SSH_SCP_DOWNLOAD_INIT",
391 "SSH_SCP_DONE",
392 "SSH_SCP_SEND_EOF",
393 "SSH_SCP_WAIT_EOF",
394 "SSH_SCP_WAIT_CLOSE",
395 "SSH_SCP_CHANNEL_FREE",
396 "SSH_SESSION_DISCONNECT",
397 "SSH_SESSION_FREE",
398 "QUIT"
401 if(sshc->state != nowstate) {
402 infof(conn->data, "SFTP %p state change from %s to %s\n",
403 (void *)sshc, names[sshc->state], names[nowstate]);
405 #endif
407 sshc->state = nowstate;
410 /* figure out the path to work with in this particular request */
411 static CURLcode ssh_getworkingpath(struct connectdata *conn,
412 char *homedir, /* when SFTP is used */
413 char **path) /* returns the allocated
414 real path to work with */
416 struct SessionHandle *data = conn->data;
417 char *real_path = NULL;
418 char *working_path;
419 int working_path_len;
421 working_path = curl_easy_unescape(data, data->state.path, 0,
422 &working_path_len);
423 if(!working_path)
424 return CURLE_OUT_OF_MEMORY;
426 /* Check for /~/, indicating relative to the user's home directory */
427 if(conn->handler->protocol & CURLPROTO_SCP) {
428 real_path = malloc(working_path_len+1);
429 if(real_path == NULL) {
430 free(working_path);
431 return CURLE_OUT_OF_MEMORY;
433 if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
434 /* It is referenced to the home directory, so strip the leading '/~/' */
435 memcpy(real_path, working_path+3, 4 + working_path_len-3);
436 else
437 memcpy(real_path, working_path, 1 + working_path_len);
439 else if(conn->handler->protocol & CURLPROTO_SFTP) {
440 if((working_path_len > 1) && (working_path[1] == '~')) {
441 size_t homelen = strlen(homedir);
442 real_path = malloc(homelen + working_path_len + 1);
443 if(real_path == NULL) {
444 free(working_path);
445 return CURLE_OUT_OF_MEMORY;
447 /* It is referenced to the home directory, so strip the
448 leading '/' */
449 memcpy(real_path, homedir, homelen);
450 real_path[homelen] = '/';
451 real_path[homelen+1] = '\0';
452 if(working_path_len > 3) {
453 memcpy(real_path+homelen+1, working_path + 3,
454 1 + working_path_len -3);
457 else {
458 real_path = malloc(working_path_len+1);
459 if(real_path == NULL) {
460 free(working_path);
461 return CURLE_OUT_OF_MEMORY;
463 memcpy(real_path, working_path, 1+working_path_len);
467 free(working_path);
469 /* store the pointer for the caller to receive */
470 *path = real_path;
472 return CURLE_OK;
475 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
476 static int sshkeycallback(CURL *easy,
477 const struct curl_khkey *knownkey, /* known */
478 const struct curl_khkey *foundkey, /* found */
479 enum curl_khmatch match,
480 void *clientp)
482 (void)easy;
483 (void)knownkey;
484 (void)foundkey;
485 (void)clientp;
487 /* we only allow perfect matches, and we reject everything else */
488 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
490 #endif
493 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
494 * with 32bit size_t.
496 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
497 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
498 #else
499 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
500 #endif
503 * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
504 * architectures so we check of the necessary function is present.
506 #ifndef HAVE_LIBSSH2_SCP_SEND64
507 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
508 #else
509 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
510 (libssh2_uint64_t)d, 0, 0)
511 #endif
514 * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
516 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
517 #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
518 #endif
520 static CURLcode ssh_knownhost(struct connectdata *conn)
522 CURLcode result = CURLE_OK;
524 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
525 struct SessionHandle *data = conn->data;
527 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
528 /* we're asked to verify the host against a file */
529 struct ssh_conn *sshc = &conn->proto.sshc;
530 int rc;
531 int keytype;
532 size_t keylen;
533 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
534 &keylen, &keytype);
535 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
536 int keybit = 0;
538 if(remotekey) {
540 * A subject to figure out is what host name we need to pass in here.
541 * What host name does OpenSSH store in its file if an IDN name is
542 * used?
544 struct libssh2_knownhost *host;
545 enum curl_khmatch keymatch;
546 curl_sshkeycallback func =
547 data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
548 struct curl_khkey knownkey;
549 struct curl_khkey *knownkeyp = NULL;
550 struct curl_khkey foundkey;
552 keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
553 LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
555 #ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
556 keycheck = libssh2_knownhost_checkp(sshc->kh,
557 conn->host.name,
558 (conn->remote_port != PORT_SSH)?
559 conn->remote_port:-1,
560 remotekey, keylen,
561 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
562 LIBSSH2_KNOWNHOST_KEYENC_RAW|
563 keybit,
564 &host);
565 #else
566 keycheck = libssh2_knownhost_check(sshc->kh,
567 conn->host.name,
568 remotekey, keylen,
569 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
570 LIBSSH2_KNOWNHOST_KEYENC_RAW|
571 keybit,
572 &host);
573 #endif
575 infof(data, "SSH host check: %d, key: %s\n", keycheck,
576 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
577 host->key:"<none>");
579 /* setup 'knownkey' */
580 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
581 knownkey.key = host->key;
582 knownkey.len = 0;
583 knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
584 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
585 knownkeyp = &knownkey;
588 /* setup 'foundkey' */
589 foundkey.key = remotekey;
590 foundkey.len = keylen;
591 foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
592 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
595 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
596 * curl_khmatch enum are ever modified, we need to introduce a
597 * translation table here!
599 keymatch = (enum curl_khmatch)keycheck;
601 /* Ask the callback how to behave */
602 rc = func(data, knownkeyp, /* from the knownhosts file */
603 &foundkey, /* from the remote host */
604 keymatch, data->set.ssh_keyfunc_userp);
606 else
607 /* no remotekey means failure! */
608 rc = CURLKHSTAT_REJECT;
610 switch(rc) {
611 default: /* unknown return codes will equal reject */
612 /* FALLTHROUGH */
613 case CURLKHSTAT_REJECT:
614 state(conn, SSH_SESSION_FREE);
615 /* FALLTHROUGH */
616 case CURLKHSTAT_DEFER:
617 /* DEFER means bail out but keep the SSH_HOSTKEY state */
618 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
619 break;
620 case CURLKHSTAT_FINE:
621 case CURLKHSTAT_FINE_ADD_TO_FILE:
622 /* proceed */
623 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
624 /* the found host+key didn't match but has been told to be fine
625 anyway so we add it in memory */
626 int addrc = libssh2_knownhost_add(sshc->kh,
627 conn->host.name, NULL,
628 remotekey, keylen,
629 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
630 LIBSSH2_KNOWNHOST_KEYENC_RAW|
631 keybit, NULL);
632 if(addrc)
633 infof(data, "Warning adding the known host %s failed!\n",
634 conn->host.name);
635 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
636 /* now we write the entire in-memory list of known hosts to the
637 known_hosts file */
638 int wrc =
639 libssh2_knownhost_writefile(sshc->kh,
640 data->set.str[STRING_SSH_KNOWNHOSTS],
641 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
642 if(wrc) {
643 infof(data, "Warning, writing %s failed!\n",
644 data->set.str[STRING_SSH_KNOWNHOSTS]);
648 break;
651 #else /* HAVE_LIBSSH2_KNOWNHOST_API */
652 (void)conn;
653 #endif
654 return result;
657 static CURLcode ssh_check_fingerprint(struct connectdata *conn)
659 struct ssh_conn *sshc = &conn->proto.sshc;
660 struct SessionHandle *data = conn->data;
661 const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
662 char md5buffer[33];
663 int i;
665 const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
666 LIBSSH2_HOSTKEY_HASH_MD5);
668 if(fingerprint) {
669 /* The fingerprint points to static storage (!), don't free() it. */
670 for(i = 0; i < 16; i++)
671 snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
672 infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
675 /* Before we authenticate we check the hostkey's MD5 fingerprint
676 * against a known fingerprint, if available.
678 if(pubkey_md5 && strlen(pubkey_md5) == 32) {
679 if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
680 if(fingerprint)
681 failf(data,
682 "Denied establishing ssh session: mismatch md5 fingerprint. "
683 "Remote %s is not equal to %s", md5buffer, pubkey_md5);
684 else
685 failf(data,
686 "Denied establishing ssh session: md5 fingerprint not available");
687 state(conn, SSH_SESSION_FREE);
688 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
689 return sshc->actualcode;
691 else {
692 infof(data, "MD5 checksum match!\n");
693 /* as we already matched, we skip the check for known hosts */
694 return CURLE_OK;
697 else
698 return ssh_knownhost(conn);
702 * ssh_statemach_act() runs the SSH state machine as far as it can without
703 * blocking and without reaching the end. The data the pointer 'block' points
704 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
705 * meaning it wants to be called again when the socket is ready
708 static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
710 CURLcode result = CURLE_OK;
711 struct SessionHandle *data = conn->data;
712 struct SSHPROTO *sftp_scp = data->req.protop;
713 struct ssh_conn *sshc = &conn->proto.sshc;
714 curl_socket_t sock = conn->sock[FIRSTSOCKET];
715 char *new_readdir_line;
716 int rc = LIBSSH2_ERROR_NONE;
717 int err;
718 int seekerr = CURL_SEEKFUNC_OK;
719 *block = 0; /* we're not blocking by default */
721 do {
723 switch(sshc->state) {
724 case SSH_INIT:
725 sshc->secondCreateDirs = 0;
726 sshc->nextstate = SSH_NO_STATE;
727 sshc->actualcode = CURLE_OK;
729 /* Set libssh2 to non-blocking, since everything internally is
730 non-blocking */
731 libssh2_session_set_blocking(sshc->ssh_session, 0);
733 state(conn, SSH_S_STARTUP);
734 /* fall-through */
736 case SSH_S_STARTUP:
737 rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
738 if(rc == LIBSSH2_ERROR_EAGAIN) {
739 break;
741 else if(rc) {
742 failf(data, "Failure establishing ssh session");
743 state(conn, SSH_SESSION_FREE);
744 sshc->actualcode = CURLE_FAILED_INIT;
745 break;
748 state(conn, SSH_HOSTKEY);
750 /* fall-through */
751 case SSH_HOSTKEY:
753 * Before we authenticate we should check the hostkey's fingerprint
754 * against our known hosts. How that is handled (reading from file,
755 * whatever) is up to us.
757 result = ssh_check_fingerprint(conn);
758 if(!result)
759 state(conn, SSH_AUTHLIST);
760 /* ssh_check_fingerprint sets state appropriately on error */
761 break;
763 case SSH_AUTHLIST:
765 * Figure out authentication methods
766 * NB: As soon as we have provided a username to an openssh server we
767 * must never change it later. Thus, always specify the correct username
768 * here, even though the libssh2 docs kind of indicate that it should be
769 * possible to get a 'generic' list (not user-specific) of authentication
770 * methods, presumably with a blank username. That won't work in my
771 * experience.
772 * So always specify it here.
774 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
775 conn->user,
776 curlx_uztoui(strlen(conn->user)));
778 if(!sshc->authlist) {
779 if(libssh2_userauth_authenticated(sshc->ssh_session)) {
780 sshc->authed = TRUE;
781 infof(data, "SSH user accepted with no authentication\n");
782 state(conn, SSH_AUTH_DONE);
783 break;
785 else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
786 LIBSSH2_ERROR_EAGAIN) {
787 rc = LIBSSH2_ERROR_EAGAIN;
788 break;
790 else {
791 state(conn, SSH_SESSION_FREE);
792 sshc->actualcode = libssh2_session_error_to_CURLE(err);
793 break;
796 infof(data, "SSH authentication methods available: %s\n",
797 sshc->authlist);
799 state(conn, SSH_AUTH_PKEY_INIT);
800 break;
802 case SSH_AUTH_PKEY_INIT:
804 * Check the supported auth types in the order I feel is most secure
805 * with the requested type of authentication
807 sshc->authed = FALSE;
809 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
810 (strstr(sshc->authlist, "publickey") != NULL)) {
811 char *home = NULL;
812 bool out_of_memory = FALSE;
814 sshc->rsa_pub = sshc->rsa = NULL;
816 /* To ponder about: should really the lib be messing about with the
817 HOME environment variable etc? */
818 home = curl_getenv("HOME");
820 if(data->set.str[STRING_SSH_PRIVATE_KEY])
821 sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
822 else {
823 /* If no private key file is specified, try some common paths. */
824 if(home) {
825 /* Try ~/.ssh first. */
826 sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
827 if(!sshc->rsa)
828 out_of_memory = TRUE;
829 else if(access(sshc->rsa, R_OK) != 0) {
830 Curl_safefree(sshc->rsa);
831 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
832 if(!sshc->rsa)
833 out_of_memory = TRUE;
834 else if(access(sshc->rsa, R_OK) != 0) {
835 Curl_safefree(sshc->rsa);
839 if(!out_of_memory && !sshc->rsa) {
840 /* Nothing found; try the current dir. */
841 sshc->rsa = strdup("id_rsa");
842 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
843 Curl_safefree(sshc->rsa);
844 sshc->rsa = strdup("id_dsa");
845 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
846 Curl_safefree(sshc->rsa);
847 /* Out of guesses. Set to the empty string to avoid
848 * surprising info messages. */
849 sshc->rsa = strdup("");
856 * Unless the user explicitly specifies a public key file, let
857 * libssh2 extract the public key from the private key file.
858 * This is done by simply passing sshc->rsa_pub = NULL.
860 if(data->set.str[STRING_SSH_PUBLIC_KEY]
861 /* treat empty string the same way as NULL */
862 && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
863 sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
864 if(!sshc->rsa_pub)
865 out_of_memory = TRUE;
868 if(out_of_memory || sshc->rsa == NULL) {
869 free(home);
870 Curl_safefree(sshc->rsa);
871 Curl_safefree(sshc->rsa_pub);
872 state(conn, SSH_SESSION_FREE);
873 sshc->actualcode = CURLE_OUT_OF_MEMORY;
874 break;
877 sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
878 if(!sshc->passphrase)
879 sshc->passphrase = "";
881 free(home);
883 if(sshc->rsa_pub)
884 infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
885 infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
887 state(conn, SSH_AUTH_PKEY);
889 else {
890 state(conn, SSH_AUTH_PASS_INIT);
892 break;
894 case SSH_AUTH_PKEY:
895 /* The function below checks if the files exists, no need to stat() here.
897 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
898 conn->user,
899 curlx_uztoui(
900 strlen(conn->user)),
901 sshc->rsa_pub,
902 sshc->rsa, sshc->passphrase);
903 if(rc == LIBSSH2_ERROR_EAGAIN) {
904 break;
907 Curl_safefree(sshc->rsa_pub);
908 Curl_safefree(sshc->rsa);
910 if(rc == 0) {
911 sshc->authed = TRUE;
912 infof(data, "Initialized SSH public key authentication\n");
913 state(conn, SSH_AUTH_DONE);
915 else {
916 char *err_msg;
917 (void)libssh2_session_last_error(sshc->ssh_session,
918 &err_msg, NULL, 0);
919 infof(data, "SSH public key authentication failed: %s\n", err_msg);
920 state(conn, SSH_AUTH_PASS_INIT);
922 break;
924 case SSH_AUTH_PASS_INIT:
925 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
926 (strstr(sshc->authlist, "password") != NULL)) {
927 state(conn, SSH_AUTH_PASS);
929 else {
930 state(conn, SSH_AUTH_HOST_INIT);
932 break;
934 case SSH_AUTH_PASS:
935 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
936 curlx_uztoui(strlen(conn->user)),
937 conn->passwd,
938 curlx_uztoui(strlen(conn->passwd)),
939 NULL);
940 if(rc == LIBSSH2_ERROR_EAGAIN) {
941 break;
943 else if(rc == 0) {
944 sshc->authed = TRUE;
945 infof(data, "Initialized password authentication\n");
946 state(conn, SSH_AUTH_DONE);
948 else {
949 state(conn, SSH_AUTH_HOST_INIT);
950 rc = 0; /* clear rc and continue */
952 break;
954 case SSH_AUTH_HOST_INIT:
955 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
956 (strstr(sshc->authlist, "hostbased") != NULL)) {
957 state(conn, SSH_AUTH_HOST);
959 else {
960 state(conn, SSH_AUTH_AGENT_INIT);
962 break;
964 case SSH_AUTH_HOST:
965 state(conn, SSH_AUTH_AGENT_INIT);
966 break;
968 case SSH_AUTH_AGENT_INIT:
969 #ifdef HAVE_LIBSSH2_AGENT_API
970 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
971 && (strstr(sshc->authlist, "publickey") != NULL)) {
973 /* Connect to the ssh-agent */
974 /* The agent could be shared by a curl thread i believe
975 but nothing obvious as keys can be added/removed at any time */
976 if(!sshc->ssh_agent) {
977 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
978 if(!sshc->ssh_agent) {
979 infof(data, "Could not create agent object\n");
981 state(conn, SSH_AUTH_KEY_INIT);
982 break;
986 rc = libssh2_agent_connect(sshc->ssh_agent);
987 if(rc == LIBSSH2_ERROR_EAGAIN)
988 break;
989 if(rc < 0) {
990 infof(data, "Failure connecting to agent\n");
991 state(conn, SSH_AUTH_KEY_INIT);
993 else {
994 state(conn, SSH_AUTH_AGENT_LIST);
997 else
998 #endif /* HAVE_LIBSSH2_AGENT_API */
999 state(conn, SSH_AUTH_KEY_INIT);
1000 break;
1002 case SSH_AUTH_AGENT_LIST:
1003 #ifdef HAVE_LIBSSH2_AGENT_API
1004 rc = libssh2_agent_list_identities(sshc->ssh_agent);
1006 if(rc == LIBSSH2_ERROR_EAGAIN)
1007 break;
1008 if(rc < 0) {
1009 infof(data, "Failure requesting identities to agent\n");
1010 state(conn, SSH_AUTH_KEY_INIT);
1012 else {
1013 state(conn, SSH_AUTH_AGENT);
1014 sshc->sshagent_prev_identity = NULL;
1016 #endif
1017 break;
1019 case SSH_AUTH_AGENT:
1020 #ifdef HAVE_LIBSSH2_AGENT_API
1021 /* as prev_identity evolves only after an identity user auth finished we
1022 can safely request it again as long as EAGAIN is returned here or by
1023 libssh2_agent_userauth */
1024 rc = libssh2_agent_get_identity(sshc->ssh_agent,
1025 &sshc->sshagent_identity,
1026 sshc->sshagent_prev_identity);
1027 if(rc == LIBSSH2_ERROR_EAGAIN)
1028 break;
1030 if(rc == 0) {
1031 rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
1032 sshc->sshagent_identity);
1034 if(rc < 0) {
1035 if(rc != LIBSSH2_ERROR_EAGAIN)
1036 /* tried and failed? go to next identity */
1037 sshc->sshagent_prev_identity = sshc->sshagent_identity;
1038 else
1039 break;
1043 if(rc < 0)
1044 infof(data, "Failure requesting identities to agent\n");
1045 else if(rc == 1)
1046 infof(data, "No identity would match\n");
1048 if(rc == LIBSSH2_ERROR_NONE) {
1049 sshc->authed = TRUE;
1050 infof(data, "Agent based authentication successful\n");
1051 state(conn, SSH_AUTH_DONE);
1053 else {
1054 state(conn, SSH_AUTH_KEY_INIT);
1055 rc = 0; /* clear rc and continue */
1057 #endif
1058 break;
1060 case SSH_AUTH_KEY_INIT:
1061 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
1062 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
1063 state(conn, SSH_AUTH_KEY);
1065 else {
1066 state(conn, SSH_AUTH_DONE);
1068 break;
1070 case SSH_AUTH_KEY:
1071 /* Authentication failed. Continue with keyboard-interactive now. */
1072 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
1073 conn->user,
1074 curlx_uztoui(
1075 strlen(conn->user)),
1076 &kbd_callback);
1077 if(rc == LIBSSH2_ERROR_EAGAIN) {
1078 break;
1080 else if(rc == 0) {
1081 sshc->authed = TRUE;
1082 infof(data, "Initialized keyboard interactive authentication\n");
1084 state(conn, SSH_AUTH_DONE);
1085 break;
1087 case SSH_AUTH_DONE:
1088 if(!sshc->authed) {
1089 failf(data, "Authentication failure");
1090 state(conn, SSH_SESSION_FREE);
1091 sshc->actualcode = CURLE_LOGIN_DENIED;
1092 break;
1096 * At this point we have an authenticated ssh session.
1098 infof(data, "Authentication complete\n");
1100 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
1102 conn->sockfd = sock;
1103 conn->writesockfd = CURL_SOCKET_BAD;
1105 if(conn->handler->protocol == CURLPROTO_SFTP) {
1106 state(conn, SSH_SFTP_INIT);
1107 break;
1109 infof(data, "SSH CONNECT phase done\n");
1110 state(conn, SSH_STOP);
1111 break;
1113 case SSH_SFTP_INIT:
1115 * Start the libssh2 sftp session
1117 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
1118 if(!sshc->sftp_session) {
1119 if(libssh2_session_last_errno(sshc->ssh_session) ==
1120 LIBSSH2_ERROR_EAGAIN) {
1121 rc = LIBSSH2_ERROR_EAGAIN;
1122 break;
1124 else {
1125 char *err_msg;
1127 (void)libssh2_session_last_error(sshc->ssh_session,
1128 &err_msg, NULL, 0);
1129 failf(data, "Failure initializing sftp session: %s", err_msg);
1130 state(conn, SSH_SESSION_FREE);
1131 sshc->actualcode = CURLE_FAILED_INIT;
1132 break;
1135 state(conn, SSH_SFTP_REALPATH);
1136 break;
1138 case SSH_SFTP_REALPATH:
1140 char tempHome[PATH_MAX];
1143 * Get the "home" directory
1145 rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
1146 tempHome, PATH_MAX-1);
1147 if(rc == LIBSSH2_ERROR_EAGAIN) {
1148 break;
1150 else if(rc > 0) {
1151 /* It seems that this string is not always NULL terminated */
1152 tempHome[rc] = '\0';
1153 sshc->homedir = strdup(tempHome);
1154 if(!sshc->homedir) {
1155 state(conn, SSH_SFTP_CLOSE);
1156 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1157 break;
1159 conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
1161 else {
1162 /* Return the error type */
1163 err = sftp_libssh2_last_error(sshc->sftp_session);
1164 result = sftp_libssh2_error_to_CURLE(err);
1165 sshc->actualcode = result?result:CURLE_SSH;
1166 DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
1167 err, (int)result));
1168 state(conn, SSH_STOP);
1169 break;
1172 /* This is the last step in the SFTP connect phase. Do note that while
1173 we get the homedir here, we get the "workingpath" in the DO action
1174 since the homedir will remain the same between request but the
1175 working path will not. */
1176 DEBUGF(infof(data, "SSH CONNECT phase done\n"));
1177 state(conn, SSH_STOP);
1178 break;
1180 case SSH_SFTP_QUOTE_INIT:
1182 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
1183 if(result) {
1184 sshc->actualcode = result;
1185 state(conn, SSH_STOP);
1186 break;
1189 if(data->set.quote) {
1190 infof(data, "Sending quote commands\n");
1191 sshc->quote_item = data->set.quote;
1192 state(conn, SSH_SFTP_QUOTE);
1194 else {
1195 state(conn, SSH_SFTP_GETINFO);
1197 break;
1199 case SSH_SFTP_POSTQUOTE_INIT:
1200 if(data->set.postquote) {
1201 infof(data, "Sending quote commands\n");
1202 sshc->quote_item = data->set.postquote;
1203 state(conn, SSH_SFTP_QUOTE);
1205 else {
1206 state(conn, SSH_STOP);
1208 break;
1210 case SSH_SFTP_QUOTE:
1211 /* Send any quote commands */
1213 const char *cp;
1216 * Support some of the "FTP" commands
1218 char *cmd = sshc->quote_item->data;
1219 sshc->acceptfail = FALSE;
1221 /* if a command starts with an asterisk, which a legal SFTP command never
1222 can, the command will be allowed to fail without it causing any
1223 aborts or cancels etc. It will cause libcurl to act as if the command
1224 is successful, whatever the server reponds. */
1226 if(cmd[0] == '*') {
1227 cmd++;
1228 sshc->acceptfail = TRUE;
1231 if(curl_strequal("pwd", cmd)) {
1232 /* output debug output if that is requested */
1233 char *tmp = aprintf("257 \"%s\" is current directory.\n",
1234 sftp_scp->path);
1235 if(!tmp) {
1236 result = CURLE_OUT_OF_MEMORY;
1237 state(conn, SSH_SFTP_CLOSE);
1238 sshc->nextstate = SSH_NO_STATE;
1239 break;
1241 if(data->set.verbose) {
1242 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
1243 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
1245 /* this sends an FTP-like "header" to the header callback so that the
1246 current directory can be read very similar to how it is read when
1247 using ordinary FTP. */
1248 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1249 free(tmp);
1250 if(result) {
1251 state(conn, SSH_SFTP_CLOSE);
1252 sshc->nextstate = SSH_NO_STATE;
1253 sshc->actualcode = result;
1255 else
1256 state(conn, SSH_SFTP_NEXT_QUOTE);
1257 break;
1259 else if(cmd) {
1261 * the arguments following the command must be separated from the
1262 * command with a space so we can check for it unconditionally
1264 cp = strchr(cmd, ' ');
1265 if(cp == NULL) {
1266 failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
1267 state(conn, SSH_SFTP_CLOSE);
1268 sshc->nextstate = SSH_NO_STATE;
1269 sshc->actualcode = CURLE_QUOTE_ERROR;
1270 break;
1274 * also, every command takes at least one argument so we get that
1275 * first argument right now
1277 result = get_pathname(&cp, &sshc->quote_path1);
1278 if(result) {
1279 if(result == CURLE_OUT_OF_MEMORY)
1280 failf(data, "Out of memory");
1281 else
1282 failf(data, "Syntax error: Bad first parameter");
1283 state(conn, SSH_SFTP_CLOSE);
1284 sshc->nextstate = SSH_NO_STATE;
1285 sshc->actualcode = result;
1286 break;
1290 * SFTP is a binary protocol, so we don't send text commands
1291 * to the server. Instead, we scan for commands used by
1292 * OpenSSH's sftp program and call the appropriate libssh2
1293 * functions.
1295 if(curl_strnequal(cmd, "chgrp ", 6) ||
1296 curl_strnequal(cmd, "chmod ", 6) ||
1297 curl_strnequal(cmd, "chown ", 6) ) {
1298 /* attribute change */
1300 /* sshc->quote_path1 contains the mode to set */
1301 /* get the destination */
1302 result = get_pathname(&cp, &sshc->quote_path2);
1303 if(result) {
1304 if(result == CURLE_OUT_OF_MEMORY)
1305 failf(data, "Out of memory");
1306 else
1307 failf(data, "Syntax error in chgrp/chmod/chown: "
1308 "Bad second parameter");
1309 Curl_safefree(sshc->quote_path1);
1310 state(conn, SSH_SFTP_CLOSE);
1311 sshc->nextstate = SSH_NO_STATE;
1312 sshc->actualcode = result;
1313 break;
1315 memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1316 state(conn, SSH_SFTP_QUOTE_STAT);
1317 break;
1319 else if(curl_strnequal(cmd, "ln ", 3) ||
1320 curl_strnequal(cmd, "symlink ", 8)) {
1321 /* symbolic linking */
1322 /* sshc->quote_path1 is the source */
1323 /* get the destination */
1324 result = get_pathname(&cp, &sshc->quote_path2);
1325 if(result) {
1326 if(result == CURLE_OUT_OF_MEMORY)
1327 failf(data, "Out of memory");
1328 else
1329 failf(data,
1330 "Syntax error in ln/symlink: Bad second parameter");
1331 Curl_safefree(sshc->quote_path1);
1332 state(conn, SSH_SFTP_CLOSE);
1333 sshc->nextstate = SSH_NO_STATE;
1334 sshc->actualcode = result;
1335 break;
1337 state(conn, SSH_SFTP_QUOTE_SYMLINK);
1338 break;
1340 else if(curl_strnequal(cmd, "mkdir ", 6)) {
1341 /* create dir */
1342 state(conn, SSH_SFTP_QUOTE_MKDIR);
1343 break;
1345 else if(curl_strnequal(cmd, "rename ", 7)) {
1346 /* rename file */
1347 /* first param is the source path */
1348 /* second param is the dest. path */
1349 result = get_pathname(&cp, &sshc->quote_path2);
1350 if(result) {
1351 if(result == CURLE_OUT_OF_MEMORY)
1352 failf(data, "Out of memory");
1353 else
1354 failf(data, "Syntax error in rename: Bad second parameter");
1355 Curl_safefree(sshc->quote_path1);
1356 state(conn, SSH_SFTP_CLOSE);
1357 sshc->nextstate = SSH_NO_STATE;
1358 sshc->actualcode = result;
1359 break;
1361 state(conn, SSH_SFTP_QUOTE_RENAME);
1362 break;
1364 else if(curl_strnequal(cmd, "rmdir ", 6)) {
1365 /* delete dir */
1366 state(conn, SSH_SFTP_QUOTE_RMDIR);
1367 break;
1369 else if(curl_strnequal(cmd, "rm ", 3)) {
1370 state(conn, SSH_SFTP_QUOTE_UNLINK);
1371 break;
1373 #ifdef HAS_STATVFS_SUPPORT
1374 else if(curl_strnequal(cmd, "statvfs ", 8)) {
1375 state(conn, SSH_SFTP_QUOTE_STATVFS);
1376 break;
1378 #endif
1380 failf(data, "Unknown SFTP command");
1381 Curl_safefree(sshc->quote_path1);
1382 Curl_safefree(sshc->quote_path2);
1383 state(conn, SSH_SFTP_CLOSE);
1384 sshc->nextstate = SSH_NO_STATE;
1385 sshc->actualcode = CURLE_QUOTE_ERROR;
1386 break;
1389 if(!sshc->quote_item) {
1390 state(conn, SSH_SFTP_GETINFO);
1392 break;
1394 case SSH_SFTP_NEXT_QUOTE:
1395 Curl_safefree(sshc->quote_path1);
1396 Curl_safefree(sshc->quote_path2);
1398 sshc->quote_item = sshc->quote_item->next;
1400 if(sshc->quote_item) {
1401 state(conn, SSH_SFTP_QUOTE);
1403 else {
1404 if(sshc->nextstate != SSH_NO_STATE) {
1405 state(conn, sshc->nextstate);
1406 sshc->nextstate = SSH_NO_STATE;
1408 else {
1409 state(conn, SSH_SFTP_GETINFO);
1412 break;
1414 case SSH_SFTP_QUOTE_STAT:
1416 char *cmd = sshc->quote_item->data;
1417 sshc->acceptfail = FALSE;
1419 /* if a command starts with an asterisk, which a legal SFTP command never
1420 can, the command will be allowed to fail without it causing any
1421 aborts or cancels etc. It will cause libcurl to act as if the command
1422 is successful, whatever the server reponds. */
1424 if(cmd[0] == '*') {
1425 cmd++;
1426 sshc->acceptfail = TRUE;
1429 if(!curl_strnequal(cmd, "chmod", 5)) {
1430 /* Since chown and chgrp only set owner OR group but libssh2 wants to
1431 * set them both at once, we need to obtain the current ownership
1432 * first. This takes an extra protocol round trip.
1434 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1435 curlx_uztoui(strlen(sshc->quote_path2)),
1436 LIBSSH2_SFTP_STAT,
1437 &sshc->quote_attrs);
1438 if(rc == LIBSSH2_ERROR_EAGAIN) {
1439 break;
1441 else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
1442 err = sftp_libssh2_last_error(sshc->sftp_session);
1443 Curl_safefree(sshc->quote_path1);
1444 Curl_safefree(sshc->quote_path2);
1445 failf(data, "Attempt to get SFTP stats failed: %s",
1446 sftp_libssh2_strerror(err));
1447 state(conn, SSH_SFTP_CLOSE);
1448 sshc->nextstate = SSH_NO_STATE;
1449 sshc->actualcode = CURLE_QUOTE_ERROR;
1450 break;
1454 /* Now set the new attributes... */
1455 if(curl_strnequal(cmd, "chgrp", 5)) {
1456 sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
1457 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1458 if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1459 !sshc->acceptfail) {
1460 Curl_safefree(sshc->quote_path1);
1461 Curl_safefree(sshc->quote_path2);
1462 failf(data, "Syntax error: chgrp gid not a number");
1463 state(conn, SSH_SFTP_CLOSE);
1464 sshc->nextstate = SSH_NO_STATE;
1465 sshc->actualcode = CURLE_QUOTE_ERROR;
1466 break;
1469 else if(curl_strnequal(cmd, "chmod", 5)) {
1470 sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
1471 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1472 /* permissions are octal */
1473 if(sshc->quote_attrs.permissions == 0 &&
1474 !ISDIGIT(sshc->quote_path1[0])) {
1475 Curl_safefree(sshc->quote_path1);
1476 Curl_safefree(sshc->quote_path2);
1477 failf(data, "Syntax error: chmod permissions not a number");
1478 state(conn, SSH_SFTP_CLOSE);
1479 sshc->nextstate = SSH_NO_STATE;
1480 sshc->actualcode = CURLE_QUOTE_ERROR;
1481 break;
1484 else if(curl_strnequal(cmd, "chown", 5)) {
1485 sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
1486 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1487 if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1488 !sshc->acceptfail) {
1489 Curl_safefree(sshc->quote_path1);
1490 Curl_safefree(sshc->quote_path2);
1491 failf(data, "Syntax error: chown uid not a number");
1492 state(conn, SSH_SFTP_CLOSE);
1493 sshc->nextstate = SSH_NO_STATE;
1494 sshc->actualcode = CURLE_QUOTE_ERROR;
1495 break;
1499 /* Now send the completed structure... */
1500 state(conn, SSH_SFTP_QUOTE_SETSTAT);
1501 break;
1504 case SSH_SFTP_QUOTE_SETSTAT:
1505 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1506 curlx_uztoui(strlen(sshc->quote_path2)),
1507 LIBSSH2_SFTP_SETSTAT,
1508 &sshc->quote_attrs);
1509 if(rc == LIBSSH2_ERROR_EAGAIN) {
1510 break;
1512 else if(rc != 0 && !sshc->acceptfail) {
1513 err = sftp_libssh2_last_error(sshc->sftp_session);
1514 Curl_safefree(sshc->quote_path1);
1515 Curl_safefree(sshc->quote_path2);
1516 failf(data, "Attempt to set SFTP stats failed: %s",
1517 sftp_libssh2_strerror(err));
1518 state(conn, SSH_SFTP_CLOSE);
1519 sshc->nextstate = SSH_NO_STATE;
1520 sshc->actualcode = CURLE_QUOTE_ERROR;
1521 break;
1523 state(conn, SSH_SFTP_NEXT_QUOTE);
1524 break;
1526 case SSH_SFTP_QUOTE_SYMLINK:
1527 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
1528 curlx_uztoui(strlen(sshc->quote_path1)),
1529 sshc->quote_path2,
1530 curlx_uztoui(strlen(sshc->quote_path2)),
1531 LIBSSH2_SFTP_SYMLINK);
1532 if(rc == LIBSSH2_ERROR_EAGAIN) {
1533 break;
1535 else if(rc != 0 && !sshc->acceptfail) {
1536 err = sftp_libssh2_last_error(sshc->sftp_session);
1537 Curl_safefree(sshc->quote_path1);
1538 Curl_safefree(sshc->quote_path2);
1539 failf(data, "symlink command failed: %s",
1540 sftp_libssh2_strerror(err));
1541 state(conn, SSH_SFTP_CLOSE);
1542 sshc->nextstate = SSH_NO_STATE;
1543 sshc->actualcode = CURLE_QUOTE_ERROR;
1544 break;
1546 state(conn, SSH_SFTP_NEXT_QUOTE);
1547 break;
1549 case SSH_SFTP_QUOTE_MKDIR:
1550 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
1551 curlx_uztoui(strlen(sshc->quote_path1)),
1552 data->set.new_directory_perms);
1553 if(rc == LIBSSH2_ERROR_EAGAIN) {
1554 break;
1556 else if(rc != 0 && !sshc->acceptfail) {
1557 err = sftp_libssh2_last_error(sshc->sftp_session);
1558 Curl_safefree(sshc->quote_path1);
1559 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
1560 state(conn, SSH_SFTP_CLOSE);
1561 sshc->nextstate = SSH_NO_STATE;
1562 sshc->actualcode = CURLE_QUOTE_ERROR;
1563 break;
1565 state(conn, SSH_SFTP_NEXT_QUOTE);
1566 break;
1568 case SSH_SFTP_QUOTE_RENAME:
1569 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
1570 curlx_uztoui(strlen(sshc->quote_path1)),
1571 sshc->quote_path2,
1572 curlx_uztoui(strlen(sshc->quote_path2)),
1573 LIBSSH2_SFTP_RENAME_OVERWRITE |
1574 LIBSSH2_SFTP_RENAME_ATOMIC |
1575 LIBSSH2_SFTP_RENAME_NATIVE);
1577 if(rc == LIBSSH2_ERROR_EAGAIN) {
1578 break;
1580 else if(rc != 0 && !sshc->acceptfail) {
1581 err = sftp_libssh2_last_error(sshc->sftp_session);
1582 Curl_safefree(sshc->quote_path1);
1583 Curl_safefree(sshc->quote_path2);
1584 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
1585 state(conn, SSH_SFTP_CLOSE);
1586 sshc->nextstate = SSH_NO_STATE;
1587 sshc->actualcode = CURLE_QUOTE_ERROR;
1588 break;
1590 state(conn, SSH_SFTP_NEXT_QUOTE);
1591 break;
1593 case SSH_SFTP_QUOTE_RMDIR:
1594 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
1595 curlx_uztoui(strlen(sshc->quote_path1)));
1596 if(rc == LIBSSH2_ERROR_EAGAIN) {
1597 break;
1599 else if(rc != 0 && !sshc->acceptfail) {
1600 err = sftp_libssh2_last_error(sshc->sftp_session);
1601 Curl_safefree(sshc->quote_path1);
1602 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
1603 state(conn, SSH_SFTP_CLOSE);
1604 sshc->nextstate = SSH_NO_STATE;
1605 sshc->actualcode = CURLE_QUOTE_ERROR;
1606 break;
1608 state(conn, SSH_SFTP_NEXT_QUOTE);
1609 break;
1611 case SSH_SFTP_QUOTE_UNLINK:
1612 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
1613 curlx_uztoui(strlen(sshc->quote_path1)));
1614 if(rc == LIBSSH2_ERROR_EAGAIN) {
1615 break;
1617 else if(rc != 0 && !sshc->acceptfail) {
1618 err = sftp_libssh2_last_error(sshc->sftp_session);
1619 Curl_safefree(sshc->quote_path1);
1620 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
1621 state(conn, SSH_SFTP_CLOSE);
1622 sshc->nextstate = SSH_NO_STATE;
1623 sshc->actualcode = CURLE_QUOTE_ERROR;
1624 break;
1626 state(conn, SSH_SFTP_NEXT_QUOTE);
1627 break;
1629 #ifdef HAS_STATVFS_SUPPORT
1630 case SSH_SFTP_QUOTE_STATVFS:
1632 LIBSSH2_SFTP_STATVFS statvfs;
1633 rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
1634 curlx_uztoui(strlen(sshc->quote_path1)),
1635 &statvfs);
1637 if(rc == LIBSSH2_ERROR_EAGAIN) {
1638 break;
1640 else if(rc != 0 && !sshc->acceptfail) {
1641 err = sftp_libssh2_last_error(sshc->sftp_session);
1642 Curl_safefree(sshc->quote_path1);
1643 failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err));
1644 state(conn, SSH_SFTP_CLOSE);
1645 sshc->nextstate = SSH_NO_STATE;
1646 sshc->actualcode = CURLE_QUOTE_ERROR;
1647 break;
1649 else if(rc == 0) {
1650 char *tmp = aprintf("statvfs:\n"
1651 "f_bsize: %llu\n" "f_frsize: %llu\n"
1652 "f_blocks: %llu\n" "f_bfree: %llu\n"
1653 "f_bavail: %llu\n" "f_files: %llu\n"
1654 "f_ffree: %llu\n" "f_favail: %llu\n"
1655 "f_fsid: %llu\n" "f_flag: %llu\n"
1656 "f_namemax: %llu\n",
1657 statvfs.f_bsize, statvfs.f_frsize,
1658 statvfs.f_blocks, statvfs.f_bfree,
1659 statvfs.f_bavail, statvfs.f_files,
1660 statvfs.f_ffree, statvfs.f_favail,
1661 statvfs.f_fsid, statvfs.f_flag,
1662 statvfs.f_namemax);
1663 if(!tmp) {
1664 result = CURLE_OUT_OF_MEMORY;
1665 state(conn, SSH_SFTP_CLOSE);
1666 sshc->nextstate = SSH_NO_STATE;
1667 break;
1670 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1671 free(tmp);
1672 if(result) {
1673 state(conn, SSH_SFTP_CLOSE);
1674 sshc->nextstate = SSH_NO_STATE;
1675 sshc->actualcode = result;
1678 state(conn, SSH_SFTP_NEXT_QUOTE);
1679 break;
1681 #endif
1682 case SSH_SFTP_GETINFO:
1684 if(data->set.get_filetime) {
1685 state(conn, SSH_SFTP_FILETIME);
1687 else {
1688 state(conn, SSH_SFTP_TRANS_INIT);
1690 break;
1693 case SSH_SFTP_FILETIME:
1695 LIBSSH2_SFTP_ATTRIBUTES attrs;
1697 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
1698 curlx_uztoui(strlen(sftp_scp->path)),
1699 LIBSSH2_SFTP_STAT, &attrs);
1700 if(rc == LIBSSH2_ERROR_EAGAIN) {
1701 break;
1703 else if(rc == 0) {
1704 data->info.filetime = (long)attrs.mtime;
1707 state(conn, SSH_SFTP_TRANS_INIT);
1708 break;
1711 case SSH_SFTP_TRANS_INIT:
1712 if(data->set.upload)
1713 state(conn, SSH_SFTP_UPLOAD_INIT);
1714 else {
1715 if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
1716 state(conn, SSH_SFTP_READDIR_INIT);
1717 else
1718 state(conn, SSH_SFTP_DOWNLOAD_INIT);
1720 break;
1722 case SSH_SFTP_UPLOAD_INIT:
1724 unsigned long flags;
1726 * NOTE!!! libssh2 requires that the destination path is a full path
1727 * that includes the destination file and name OR ends in a "/"
1728 * If this is not done the destination file will be named the
1729 * same name as the last directory in the path.
1732 if(data->state.resume_from != 0) {
1733 LIBSSH2_SFTP_ATTRIBUTES attrs;
1734 if(data->state.resume_from < 0) {
1735 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
1736 curlx_uztoui(strlen(sftp_scp->path)),
1737 LIBSSH2_SFTP_STAT, &attrs);
1738 if(rc == LIBSSH2_ERROR_EAGAIN) {
1739 break;
1741 else if(rc) {
1742 data->state.resume_from = 0;
1744 else {
1745 curl_off_t size = attrs.filesize;
1746 if(size < 0) {
1747 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
1748 return CURLE_BAD_DOWNLOAD_RESUME;
1750 data->state.resume_from = attrs.filesize;
1755 if(data->set.ftp_append)
1756 /* Try to open for append, but create if nonexisting */
1757 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
1758 else if(data->state.resume_from > 0)
1759 /* If we have restart position then open for append */
1760 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
1761 else
1762 /* Clear file before writing (normal behaviour) */
1763 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
1765 sshc->sftp_handle =
1766 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
1767 curlx_uztoui(strlen(sftp_scp->path)),
1768 flags, data->set.new_file_perms,
1769 LIBSSH2_SFTP_OPENFILE);
1771 if(!sshc->sftp_handle) {
1772 rc = libssh2_session_last_errno(sshc->ssh_session);
1774 if(LIBSSH2_ERROR_EAGAIN == rc)
1775 break;
1776 else {
1777 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
1778 /* only when there was an SFTP protocol error can we extract
1779 the sftp error! */
1780 err = sftp_libssh2_last_error(sshc->sftp_session);
1781 else
1782 err = -1; /* not an sftp error at all */
1784 if(sshc->secondCreateDirs) {
1785 state(conn, SSH_SFTP_CLOSE);
1786 sshc->actualcode = err>= LIBSSH2_FX_OK?
1787 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1788 failf(data, "Creating the dir/file failed: %s",
1789 sftp_libssh2_strerror(err));
1790 break;
1792 else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
1793 (err == LIBSSH2_FX_FAILURE) ||
1794 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
1795 (data->set.ftp_create_missing_dirs &&
1796 (strlen(sftp_scp->path) > 1))) {
1797 /* try to create the path remotely */
1798 sshc->secondCreateDirs = 1;
1799 state(conn, SSH_SFTP_CREATE_DIRS_INIT);
1800 break;
1802 state(conn, SSH_SFTP_CLOSE);
1803 sshc->actualcode = err>= LIBSSH2_FX_OK?
1804 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1805 if(!sshc->actualcode) {
1806 /* Sometimes, for some reason libssh2_sftp_last_error() returns
1807 zero even though libssh2_sftp_open() failed previously! We need
1808 to work around that! */
1809 sshc->actualcode = CURLE_SSH;
1810 err=-1;
1812 failf(data, "Upload failed: %s (%d/%d)",
1813 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
1814 err, rc);
1815 break;
1819 /* If we have a restart point then we need to seek to the correct
1820 position. */
1821 if(data->state.resume_from > 0) {
1822 /* Let's read off the proper amount of bytes from the input. */
1823 if(conn->seek_func) {
1824 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1825 SEEK_SET);
1828 if(seekerr != CURL_SEEKFUNC_OK) {
1830 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1831 failf(data, "Could not seek stream");
1832 return CURLE_FTP_COULDNT_USE_REST;
1834 /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
1835 else {
1836 curl_off_t passed=0;
1837 do {
1838 size_t readthisamountnow =
1839 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
1840 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
1842 size_t actuallyread =
1843 data->state.fread_func(data->state.buffer, 1,
1844 readthisamountnow, data->state.in);
1846 passed += actuallyread;
1847 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1848 /* this checks for greater-than only to make sure that the
1849 CURL_READFUNC_ABORT return code still aborts */
1850 failf(data, "Failed to read data");
1851 return CURLE_FTP_COULDNT_USE_REST;
1853 } while(passed < data->state.resume_from);
1857 /* now, decrease the size of the read */
1858 if(data->state.infilesize > 0) {
1859 data->state.infilesize -= data->state.resume_from;
1860 data->req.size = data->state.infilesize;
1861 Curl_pgrsSetUploadSize(data, data->state.infilesize);
1864 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1866 if(data->state.infilesize > 0) {
1867 data->req.size = data->state.infilesize;
1868 Curl_pgrsSetUploadSize(data, data->state.infilesize);
1870 /* upload data */
1871 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
1873 /* not set by Curl_setup_transfer to preserve keepon bits */
1874 conn->sockfd = conn->writesockfd;
1876 if(result) {
1877 state(conn, SSH_SFTP_CLOSE);
1878 sshc->actualcode = result;
1880 else {
1881 /* store this original bitmask setup to use later on if we can't
1882 figure out a "real" bitmask */
1883 sshc->orig_waitfor = data->req.keepon;
1885 /* we want to use the _sending_ function even when the socket turns
1886 out readable as the underlying libssh2 sftp send function will deal
1887 with both accordingly */
1888 conn->cselect_bits = CURL_CSELECT_OUT;
1890 /* since we don't really wait for anything at this point, we want the
1891 state machine to move on as soon as possible so we set a very short
1892 timeout here */
1893 Curl_expire(data, 1);
1895 state(conn, SSH_STOP);
1897 break;
1900 case SSH_SFTP_CREATE_DIRS_INIT:
1901 if(strlen(sftp_scp->path) > 1) {
1902 sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
1903 state(conn, SSH_SFTP_CREATE_DIRS);
1905 else {
1906 state(conn, SSH_SFTP_UPLOAD_INIT);
1908 break;
1910 case SSH_SFTP_CREATE_DIRS:
1911 sshc->slash_pos = strchr(sshc->slash_pos, '/');
1912 if(sshc->slash_pos) {
1913 *sshc->slash_pos = 0;
1915 infof(data, "Creating directory '%s'\n", sftp_scp->path);
1916 state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
1917 break;
1919 else {
1920 state(conn, SSH_SFTP_UPLOAD_INIT);
1922 break;
1924 case SSH_SFTP_CREATE_DIRS_MKDIR:
1925 /* 'mode' - parameter is preliminary - default to 0644 */
1926 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
1927 curlx_uztoui(strlen(sftp_scp->path)),
1928 data->set.new_directory_perms);
1929 if(rc == LIBSSH2_ERROR_EAGAIN) {
1930 break;
1932 *sshc->slash_pos = '/';
1933 ++sshc->slash_pos;
1934 if(rc == -1) {
1936 * Abort if failure wasn't that the dir already exists or the
1937 * permission was denied (creation might succeed further down the
1938 * path) - retry on unspecific FAILURE also
1940 err = sftp_libssh2_last_error(sshc->sftp_session);
1941 if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
1942 (err != LIBSSH2_FX_FAILURE) &&
1943 (err != LIBSSH2_FX_PERMISSION_DENIED)) {
1944 result = sftp_libssh2_error_to_CURLE(err);
1945 state(conn, SSH_SFTP_CLOSE);
1946 sshc->actualcode = result?result:CURLE_SSH;
1947 break;
1950 state(conn, SSH_SFTP_CREATE_DIRS);
1951 break;
1953 case SSH_SFTP_READDIR_INIT:
1954 Curl_pgrsSetDownloadSize(data, -1);
1955 if(data->set.opt_no_body) {
1956 state(conn, SSH_STOP);
1957 break;
1961 * This is a directory that we are trying to get, so produce a directory
1962 * listing
1964 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
1965 sftp_scp->path,
1966 curlx_uztoui(
1967 strlen(sftp_scp->path)),
1968 0, 0, LIBSSH2_SFTP_OPENDIR);
1969 if(!sshc->sftp_handle) {
1970 if(libssh2_session_last_errno(sshc->ssh_session) ==
1971 LIBSSH2_ERROR_EAGAIN) {
1972 rc = LIBSSH2_ERROR_EAGAIN;
1973 break;
1975 else {
1976 err = sftp_libssh2_last_error(sshc->sftp_session);
1977 failf(data, "Could not open directory for reading: %s",
1978 sftp_libssh2_strerror(err));
1979 state(conn, SSH_SFTP_CLOSE);
1980 result = sftp_libssh2_error_to_CURLE(err);
1981 sshc->actualcode = result?result:CURLE_SSH;
1982 break;
1985 if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
1986 state(conn, SSH_SFTP_CLOSE);
1987 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1988 break;
1990 if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
1991 Curl_safefree(sshc->readdir_filename);
1992 state(conn, SSH_SFTP_CLOSE);
1993 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1994 break;
1996 state(conn, SSH_SFTP_READDIR);
1997 break;
1999 case SSH_SFTP_READDIR:
2000 sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
2001 sshc->readdir_filename,
2002 PATH_MAX,
2003 sshc->readdir_longentry,
2004 PATH_MAX,
2005 &sshc->readdir_attrs);
2006 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
2007 rc = LIBSSH2_ERROR_EAGAIN;
2008 break;
2010 if(sshc->readdir_len > 0) {
2011 sshc->readdir_filename[sshc->readdir_len] = '\0';
2013 if(data->set.ftp_list_only) {
2014 char *tmpLine;
2016 tmpLine = aprintf("%s\n", sshc->readdir_filename);
2017 if(tmpLine == NULL) {
2018 state(conn, SSH_SFTP_CLOSE);
2019 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2020 break;
2022 result = Curl_client_write(conn, CLIENTWRITE_BODY,
2023 tmpLine, sshc->readdir_len+1);
2024 free(tmpLine);
2026 if(result) {
2027 state(conn, SSH_STOP);
2028 break;
2030 /* since this counts what we send to the client, we include the
2031 newline in this counter */
2032 data->req.bytecount += sshc->readdir_len+1;
2034 /* output debug output if that is requested */
2035 if(data->set.verbose) {
2036 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
2037 sshc->readdir_len, conn);
2040 else {
2041 sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
2042 sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
2043 sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
2044 if(!sshc->readdir_line) {
2045 Curl_safefree(sshc->readdir_filename);
2046 Curl_safefree(sshc->readdir_longentry);
2047 state(conn, SSH_SFTP_CLOSE);
2048 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2049 break;
2052 memcpy(sshc->readdir_line, sshc->readdir_longentry,
2053 sshc->readdir_currLen);
2054 if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
2055 ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
2056 LIBSSH2_SFTP_S_IFLNK)) {
2057 sshc->readdir_linkPath = malloc(PATH_MAX + 1);
2058 if(sshc->readdir_linkPath == NULL) {
2059 Curl_safefree(sshc->readdir_filename);
2060 Curl_safefree(sshc->readdir_longentry);
2061 state(conn, SSH_SFTP_CLOSE);
2062 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2063 break;
2066 snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
2067 sshc->readdir_filename);
2068 state(conn, SSH_SFTP_READDIR_LINK);
2069 break;
2071 state(conn, SSH_SFTP_READDIR_BOTTOM);
2072 break;
2075 else if(sshc->readdir_len == 0) {
2076 Curl_safefree(sshc->readdir_filename);
2077 Curl_safefree(sshc->readdir_longentry);
2078 state(conn, SSH_SFTP_READDIR_DONE);
2079 break;
2081 else if(sshc->readdir_len <= 0) {
2082 err = sftp_libssh2_last_error(sshc->sftp_session);
2083 result = sftp_libssh2_error_to_CURLE(err);
2084 sshc->actualcode = result?result:CURLE_SSH;
2085 failf(data, "Could not open remote file for reading: %s :: %d",
2086 sftp_libssh2_strerror(err),
2087 libssh2_session_last_errno(sshc->ssh_session));
2088 Curl_safefree(sshc->readdir_filename);
2089 Curl_safefree(sshc->readdir_longentry);
2090 state(conn, SSH_SFTP_CLOSE);
2091 break;
2093 break;
2095 case SSH_SFTP_READDIR_LINK:
2096 sshc->readdir_len =
2097 libssh2_sftp_symlink_ex(sshc->sftp_session,
2098 sshc->readdir_linkPath,
2099 curlx_uztoui(strlen(sshc->readdir_linkPath)),
2100 sshc->readdir_filename,
2101 PATH_MAX, LIBSSH2_SFTP_READLINK);
2102 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
2103 rc = LIBSSH2_ERROR_EAGAIN;
2104 break;
2106 Curl_safefree(sshc->readdir_linkPath);
2108 /* get room for the filename and extra output */
2109 sshc->readdir_totalLen += 4 + sshc->readdir_len;
2110 new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
2111 if(!new_readdir_line) {
2112 Curl_safefree(sshc->readdir_line);
2113 Curl_safefree(sshc->readdir_filename);
2114 Curl_safefree(sshc->readdir_longentry);
2115 state(conn, SSH_SFTP_CLOSE);
2116 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2117 break;
2119 sshc->readdir_line = new_readdir_line;
2121 sshc->readdir_currLen += snprintf(sshc->readdir_line +
2122 sshc->readdir_currLen,
2123 sshc->readdir_totalLen -
2124 sshc->readdir_currLen,
2125 " -> %s",
2126 sshc->readdir_filename);
2128 state(conn, SSH_SFTP_READDIR_BOTTOM);
2129 break;
2131 case SSH_SFTP_READDIR_BOTTOM:
2132 sshc->readdir_currLen += snprintf(sshc->readdir_line +
2133 sshc->readdir_currLen,
2134 sshc->readdir_totalLen -
2135 sshc->readdir_currLen, "\n");
2136 result = Curl_client_write(conn, CLIENTWRITE_BODY,
2137 sshc->readdir_line,
2138 sshc->readdir_currLen);
2140 if(!result) {
2142 /* output debug output if that is requested */
2143 if(data->set.verbose) {
2144 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
2145 sshc->readdir_currLen, conn);
2147 data->req.bytecount += sshc->readdir_currLen;
2149 Curl_safefree(sshc->readdir_line);
2150 if(result) {
2151 state(conn, SSH_STOP);
2153 else
2154 state(conn, SSH_SFTP_READDIR);
2155 break;
2157 case SSH_SFTP_READDIR_DONE:
2158 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2159 LIBSSH2_ERROR_EAGAIN) {
2160 rc = LIBSSH2_ERROR_EAGAIN;
2161 break;
2163 sshc->sftp_handle = NULL;
2164 Curl_safefree(sshc->readdir_filename);
2165 Curl_safefree(sshc->readdir_longentry);
2167 /* no data to transfer */
2168 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
2169 state(conn, SSH_STOP);
2170 break;
2172 case SSH_SFTP_DOWNLOAD_INIT:
2174 * Work on getting the specified file
2176 sshc->sftp_handle =
2177 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
2178 curlx_uztoui(strlen(sftp_scp->path)),
2179 LIBSSH2_FXF_READ, data->set.new_file_perms,
2180 LIBSSH2_SFTP_OPENFILE);
2181 if(!sshc->sftp_handle) {
2182 if(libssh2_session_last_errno(sshc->ssh_session) ==
2183 LIBSSH2_ERROR_EAGAIN) {
2184 rc = LIBSSH2_ERROR_EAGAIN;
2185 break;
2187 else {
2188 err = sftp_libssh2_last_error(sshc->sftp_session);
2189 failf(data, "Could not open remote file for reading: %s",
2190 sftp_libssh2_strerror(err));
2191 state(conn, SSH_SFTP_CLOSE);
2192 result = sftp_libssh2_error_to_CURLE(err);
2193 sshc->actualcode = result?result:CURLE_SSH;
2194 break;
2197 state(conn, SSH_SFTP_DOWNLOAD_STAT);
2198 break;
2200 case SSH_SFTP_DOWNLOAD_STAT:
2202 LIBSSH2_SFTP_ATTRIBUTES attrs;
2204 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
2205 curlx_uztoui(strlen(sftp_scp->path)),
2206 LIBSSH2_SFTP_STAT, &attrs);
2207 if(rc == LIBSSH2_ERROR_EAGAIN) {
2208 break;
2210 else if(rc ||
2211 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
2212 (attrs.filesize == 0)) {
2214 * libssh2_sftp_open() didn't return an error, so maybe the server
2215 * just doesn't support stat()
2216 * OR the server doesn't return a file size with a stat()
2217 * OR file size is 0
2219 data->req.size = -1;
2220 data->req.maxdownload = -1;
2221 Curl_pgrsSetDownloadSize(data, -1);
2223 else {
2224 curl_off_t size = attrs.filesize;
2226 if(size < 0) {
2227 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
2228 return CURLE_BAD_DOWNLOAD_RESUME;
2230 if(conn->data->state.use_range) {
2231 curl_off_t from, to;
2232 char *ptr;
2233 char *ptr2;
2235 from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
2236 while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
2237 ptr++;
2238 to=curlx_strtoofft(ptr, &ptr2, 0);
2239 if((ptr == ptr2) /* no "to" value given */
2240 || (to >= size)) {
2241 to = size - 1;
2243 if(from < 0) {
2244 /* from is relative to end of file */
2245 from += size;
2247 if(from > size) {
2248 failf(data, "Offset (%"
2249 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
2250 CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
2251 return CURLE_BAD_DOWNLOAD_RESUME;
2253 if(from > to) {
2254 from = to;
2255 size = 0;
2257 else {
2258 size = to - from + 1;
2261 SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
2263 data->req.size = size;
2264 data->req.maxdownload = size;
2265 Curl_pgrsSetDownloadSize(data, size);
2268 /* We can resume if we can seek to the resume position */
2269 if(data->state.resume_from) {
2270 if(data->state.resume_from < 0) {
2271 /* We're supposed to download the last abs(from) bytes */
2272 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
2273 failf(data, "Offset (%"
2274 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
2275 CURL_FORMAT_CURL_OFF_T ")",
2276 data->state.resume_from, attrs.filesize);
2277 return CURLE_BAD_DOWNLOAD_RESUME;
2279 /* download from where? */
2280 data->state.resume_from += attrs.filesize;
2282 else {
2283 if((curl_off_t)attrs.filesize < data->state.resume_from) {
2284 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2285 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
2286 data->state.resume_from, attrs.filesize);
2287 return CURLE_BAD_DOWNLOAD_RESUME;
2290 /* Does a completed file need to be seeked and started or closed ? */
2291 /* Now store the number of bytes we are expected to download */
2292 data->req.size = attrs.filesize - data->state.resume_from;
2293 data->req.maxdownload = attrs.filesize - data->state.resume_from;
2294 Curl_pgrsSetDownloadSize(data,
2295 attrs.filesize - data->state.resume_from);
2296 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2300 /* Setup the actual download */
2301 if(data->req.size == 0) {
2302 /* no data to transfer */
2303 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
2304 infof(data, "File already completely downloaded\n");
2305 state(conn, SSH_STOP);
2306 break;
2308 else {
2309 Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
2310 FALSE, NULL, -1, NULL);
2312 /* not set by Curl_setup_transfer to preserve keepon bits */
2313 conn->writesockfd = conn->sockfd;
2315 /* we want to use the _receiving_ function even when the socket turns
2316 out writableable as the underlying libssh2 recv function will deal
2317 with both accordingly */
2318 conn->cselect_bits = CURL_CSELECT_IN;
2320 if(result) {
2321 /* this should never occur; the close state should be entered
2322 at the time the error occurs */
2323 state(conn, SSH_SFTP_CLOSE);
2324 sshc->actualcode = result;
2326 else {
2327 state(conn, SSH_STOP);
2329 break;
2331 case SSH_SFTP_CLOSE:
2332 if(sshc->sftp_handle) {
2333 rc = libssh2_sftp_close(sshc->sftp_handle);
2334 if(rc == LIBSSH2_ERROR_EAGAIN) {
2335 break;
2337 else if(rc < 0) {
2338 infof(data, "Failed to close libssh2 file\n");
2340 sshc->sftp_handle = NULL;
2342 if(sftp_scp)
2343 Curl_safefree(sftp_scp->path);
2345 DEBUGF(infof(data, "SFTP DONE done\n"));
2347 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2348 After nextstate is executed, the control should come back to
2349 SSH_SFTP_CLOSE to pass the correct result back */
2350 if(sshc->nextstate != SSH_NO_STATE &&
2351 sshc->nextstate != SSH_SFTP_CLOSE) {
2352 state(conn, sshc->nextstate);
2353 sshc->nextstate = SSH_SFTP_CLOSE;
2355 else {
2356 state(conn, SSH_STOP);
2357 result = sshc->actualcode;
2359 break;
2361 case SSH_SFTP_SHUTDOWN:
2362 /* during times we get here due to a broken transfer and then the
2363 sftp_handle might not have been taken down so make sure that is done
2364 before we proceed */
2366 if(sshc->sftp_handle) {
2367 rc = libssh2_sftp_close(sshc->sftp_handle);
2368 if(rc == LIBSSH2_ERROR_EAGAIN) {
2369 break;
2371 else if(rc < 0) {
2372 infof(data, "Failed to close libssh2 file\n");
2374 sshc->sftp_handle = NULL;
2376 if(sshc->sftp_session) {
2377 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2378 if(rc == LIBSSH2_ERROR_EAGAIN) {
2379 break;
2381 else if(rc < 0) {
2382 infof(data, "Failed to stop libssh2 sftp subsystem\n");
2384 sshc->sftp_session = NULL;
2387 Curl_safefree(sshc->homedir);
2388 conn->data->state.most_recent_ftp_entrypath = NULL;
2390 state(conn, SSH_SESSION_DISCONNECT);
2391 break;
2393 case SSH_SCP_TRANS_INIT:
2394 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
2395 if(result) {
2396 sshc->actualcode = result;
2397 state(conn, SSH_STOP);
2398 break;
2401 if(data->set.upload) {
2402 if(data->state.infilesize < 0) {
2403 failf(data, "SCP requires a known file size for upload");
2404 sshc->actualcode = CURLE_UPLOAD_FAILED;
2405 state(conn, SSH_SCP_CHANNEL_FREE);
2406 break;
2408 state(conn, SSH_SCP_UPLOAD_INIT);
2410 else {
2411 state(conn, SSH_SCP_DOWNLOAD_INIT);
2413 break;
2415 case SSH_SCP_UPLOAD_INIT:
2417 * libssh2 requires that the destination path is a full path that
2418 * includes the destination file and name OR ends in a "/" . If this is
2419 * not done the destination file will be named the same name as the last
2420 * directory in the path.
2422 sshc->ssh_channel =
2423 SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
2424 data->state.infilesize);
2425 if(!sshc->ssh_channel) {
2426 if(libssh2_session_last_errno(sshc->ssh_session) ==
2427 LIBSSH2_ERROR_EAGAIN) {
2428 rc = LIBSSH2_ERROR_EAGAIN;
2429 break;
2431 else {
2432 int ssh_err;
2433 char *err_msg;
2435 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2436 &err_msg, NULL, 0));
2437 failf(conn->data, "%s", err_msg);
2438 state(conn, SSH_SCP_CHANNEL_FREE);
2439 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2440 break;
2444 /* upload data */
2445 Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
2446 FIRSTSOCKET, NULL);
2448 /* not set by Curl_setup_transfer to preserve keepon bits */
2449 conn->sockfd = conn->writesockfd;
2451 if(result) {
2452 state(conn, SSH_SCP_CHANNEL_FREE);
2453 sshc->actualcode = result;
2455 else {
2456 /* store this original bitmask setup to use later on if we can't
2457 figure out a "real" bitmask */
2458 sshc->orig_waitfor = data->req.keepon;
2460 /* we want to use the _sending_ function even when the socket turns
2461 out readable as the underlying libssh2 scp send function will deal
2462 with both accordingly */
2463 conn->cselect_bits = CURL_CSELECT_OUT;
2465 state(conn, SSH_STOP);
2467 break;
2469 case SSH_SCP_DOWNLOAD_INIT:
2471 curl_off_t bytecount;
2474 * We must check the remote file; if it is a directory no values will
2475 * be set in sb
2479 * If support for >2GB files exists, use it.
2482 /* get a fresh new channel from the ssh layer */
2483 #if LIBSSH2_VERSION_NUM < 0x010700
2484 struct stat sb;
2485 memset(&sb, 0, sizeof(struct stat));
2486 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2487 sftp_scp->path, &sb);
2488 #else
2489 libssh2_struct_stat sb;
2490 memset(&sb, 0, sizeof(libssh2_struct_stat));
2491 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
2492 sftp_scp->path, &sb);
2493 #endif
2495 if(!sshc->ssh_channel) {
2496 if(libssh2_session_last_errno(sshc->ssh_session) ==
2497 LIBSSH2_ERROR_EAGAIN) {
2498 rc = LIBSSH2_ERROR_EAGAIN;
2499 break;
2501 else {
2502 int ssh_err;
2503 char *err_msg;
2505 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2506 &err_msg, NULL, 0));
2507 failf(conn->data, "%s", err_msg);
2508 state(conn, SSH_SCP_CHANNEL_FREE);
2509 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2510 break;
2514 /* download data */
2515 bytecount = (curl_off_t)sb.st_size;
2516 data->req.maxdownload = (curl_off_t)sb.st_size;
2517 Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
2519 /* not set by Curl_setup_transfer to preserve keepon bits */
2520 conn->writesockfd = conn->sockfd;
2522 /* we want to use the _receiving_ function even when the socket turns
2523 out writableable as the underlying libssh2 recv function will deal
2524 with both accordingly */
2525 conn->cselect_bits = CURL_CSELECT_IN;
2527 if(result) {
2528 state(conn, SSH_SCP_CHANNEL_FREE);
2529 sshc->actualcode = result;
2531 else
2532 state(conn, SSH_STOP);
2534 break;
2536 case SSH_SCP_DONE:
2537 if(data->set.upload)
2538 state(conn, SSH_SCP_SEND_EOF);
2539 else
2540 state(conn, SSH_SCP_CHANNEL_FREE);
2541 break;
2543 case SSH_SCP_SEND_EOF:
2544 if(sshc->ssh_channel) {
2545 rc = libssh2_channel_send_eof(sshc->ssh_channel);
2546 if(rc == LIBSSH2_ERROR_EAGAIN) {
2547 break;
2549 else if(rc) {
2550 infof(data, "Failed to send libssh2 channel EOF\n");
2553 state(conn, SSH_SCP_WAIT_EOF);
2554 break;
2556 case SSH_SCP_WAIT_EOF:
2557 if(sshc->ssh_channel) {
2558 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2559 if(rc == LIBSSH2_ERROR_EAGAIN) {
2560 break;
2562 else if(rc) {
2563 infof(data, "Failed to get channel EOF: %d\n", rc);
2566 state(conn, SSH_SCP_WAIT_CLOSE);
2567 break;
2569 case SSH_SCP_WAIT_CLOSE:
2570 if(sshc->ssh_channel) {
2571 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2572 if(rc == LIBSSH2_ERROR_EAGAIN) {
2573 break;
2575 else if(rc) {
2576 infof(data, "Channel failed to close: %d\n", rc);
2579 state(conn, SSH_SCP_CHANNEL_FREE);
2580 break;
2582 case SSH_SCP_CHANNEL_FREE:
2583 if(sshc->ssh_channel) {
2584 rc = libssh2_channel_free(sshc->ssh_channel);
2585 if(rc == LIBSSH2_ERROR_EAGAIN) {
2586 break;
2588 else if(rc < 0) {
2589 infof(data, "Failed to free libssh2 scp subsystem\n");
2591 sshc->ssh_channel = NULL;
2593 DEBUGF(infof(data, "SCP DONE phase complete\n"));
2594 #if 0 /* PREV */
2595 state(conn, SSH_SESSION_DISCONNECT);
2596 #endif
2597 state(conn, SSH_STOP);
2598 result = sshc->actualcode;
2599 break;
2601 case SSH_SESSION_DISCONNECT:
2602 /* during weird times when we've been prematurely aborted, the channel
2603 is still alive when we reach this state and we MUST kill the channel
2604 properly first */
2605 if(sshc->ssh_channel) {
2606 rc = libssh2_channel_free(sshc->ssh_channel);
2607 if(rc == LIBSSH2_ERROR_EAGAIN) {
2608 break;
2610 else if(rc < 0) {
2611 infof(data, "Failed to free libssh2 scp subsystem\n");
2613 sshc->ssh_channel = NULL;
2616 if(sshc->ssh_session) {
2617 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2618 if(rc == LIBSSH2_ERROR_EAGAIN) {
2619 break;
2621 else if(rc < 0) {
2622 infof(data, "Failed to disconnect libssh2 session\n");
2626 Curl_safefree(sshc->homedir);
2627 conn->data->state.most_recent_ftp_entrypath = NULL;
2629 state(conn, SSH_SESSION_FREE);
2630 break;
2632 case SSH_SESSION_FREE:
2633 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2634 if(sshc->kh) {
2635 libssh2_knownhost_free(sshc->kh);
2636 sshc->kh = NULL;
2638 #endif
2640 #ifdef HAVE_LIBSSH2_AGENT_API
2641 if(sshc->ssh_agent) {
2642 rc = libssh2_agent_disconnect(sshc->ssh_agent);
2643 if(rc == LIBSSH2_ERROR_EAGAIN) {
2644 break;
2646 else if(rc < 0) {
2647 infof(data, "Failed to disconnect from libssh2 agent\n");
2649 libssh2_agent_free (sshc->ssh_agent);
2650 sshc->ssh_agent = NULL;
2652 /* NB: there is no need to free identities, they are part of internal
2653 agent stuff */
2654 sshc->sshagent_identity = NULL;
2655 sshc->sshagent_prev_identity = NULL;
2657 #endif
2659 if(sshc->ssh_session) {
2660 rc = libssh2_session_free(sshc->ssh_session);
2661 if(rc == LIBSSH2_ERROR_EAGAIN) {
2662 break;
2664 else if(rc < 0) {
2665 infof(data, "Failed to free libssh2 session\n");
2667 sshc->ssh_session = NULL;
2670 /* worst-case scenario cleanup */
2672 DEBUGASSERT(sshc->ssh_session == NULL);
2673 DEBUGASSERT(sshc->ssh_channel == NULL);
2674 DEBUGASSERT(sshc->sftp_session == NULL);
2675 DEBUGASSERT(sshc->sftp_handle == NULL);
2676 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2677 DEBUGASSERT(sshc->kh == NULL);
2678 #endif
2679 #ifdef HAVE_LIBSSH2_AGENT_API
2680 DEBUGASSERT(sshc->ssh_agent == NULL);
2681 #endif
2683 Curl_safefree(sshc->rsa_pub);
2684 Curl_safefree(sshc->rsa);
2686 Curl_safefree(sshc->quote_path1);
2687 Curl_safefree(sshc->quote_path2);
2689 Curl_safefree(sshc->homedir);
2691 Curl_safefree(sshc->readdir_filename);
2692 Curl_safefree(sshc->readdir_longentry);
2693 Curl_safefree(sshc->readdir_line);
2694 Curl_safefree(sshc->readdir_linkPath);
2696 /* the code we are about to return */
2697 result = sshc->actualcode;
2699 memset(sshc, 0, sizeof(struct ssh_conn));
2701 connclose(conn, "SSH session free");
2702 sshc->state = SSH_SESSION_FREE; /* current */
2703 sshc->nextstate = SSH_NO_STATE;
2704 state(conn, SSH_STOP);
2705 break;
2707 case SSH_QUIT:
2708 /* fallthrough, just stop! */
2709 default:
2710 /* internal error */
2711 sshc->nextstate = SSH_NO_STATE;
2712 state(conn, SSH_STOP);
2713 break;
2716 } while(!rc && (sshc->state != SSH_STOP));
2718 if(rc == LIBSSH2_ERROR_EAGAIN) {
2719 /* we would block, we need to wait for the socket to be ready (in the
2720 right direction too)! */
2721 *block = TRUE;
2724 return result;
2727 /* called by the multi interface to figure out what socket(s) to wait for and
2728 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
2729 static int ssh_perform_getsock(const struct connectdata *conn,
2730 curl_socket_t *sock, /* points to numsocks
2731 number of sockets */
2732 int numsocks)
2734 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2735 int bitmap = GETSOCK_BLANK;
2736 (void)numsocks;
2738 sock[0] = conn->sock[FIRSTSOCKET];
2740 if(conn->waitfor & KEEP_RECV)
2741 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
2743 if(conn->waitfor & KEEP_SEND)
2744 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
2746 return bitmap;
2747 #else
2748 /* if we don't know the direction we can use the generic *_getsock()
2749 function even for the protocol_connect and doing states */
2750 return Curl_single_getsock(conn, sock, numsocks);
2751 #endif
2754 /* Generic function called by the multi interface to figure out what socket(s)
2755 to wait for and for what actions during the DOING and PROTOCONNECT states*/
2756 static int ssh_getsock(struct connectdata *conn,
2757 curl_socket_t *sock, /* points to numsocks number
2758 of sockets */
2759 int numsocks)
2761 #ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2762 (void)conn;
2763 (void)sock;
2764 (void)numsocks;
2765 /* if we don't know any direction we can just play along as we used to and
2766 not provide any sensible info */
2767 return GETSOCK_BLANK;
2768 #else
2769 /* if we know the direction we can use the generic *_getsock() function even
2770 for the protocol_connect and doing states */
2771 return ssh_perform_getsock(conn, sock, numsocks);
2772 #endif
2775 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2777 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
2778 * function is used to figure out in what direction and stores this info so
2779 * that the multi interface can take advantage of it. Make sure to call this
2780 * function in all cases so that when it _doesn't_ return EAGAIN we can
2781 * restore the default wait bits.
2783 static void ssh_block2waitfor(struct connectdata *conn, bool block)
2785 struct ssh_conn *sshc = &conn->proto.sshc;
2786 int dir;
2787 if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
2788 /* translate the libssh2 define bits into our own bit defines */
2789 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
2790 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
2792 else
2793 /* It didn't block or libssh2 didn't reveal in which direction, put back
2794 the original set */
2795 conn->waitfor = sshc->orig_waitfor;
2797 #else
2798 /* no libssh2 directional support so we simply don't know */
2799 #define ssh_block2waitfor(x,y) Curl_nop_stmt
2800 #endif
2802 /* called repeatedly until done from multi.c */
2803 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
2805 struct ssh_conn *sshc = &conn->proto.sshc;
2806 CURLcode result = CURLE_OK;
2807 bool block; /* we store the status and use that to provide a ssh_getsock()
2808 implementation */
2810 result = ssh_statemach_act(conn, &block);
2811 *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
2812 ssh_block2waitfor(conn, block);
2814 return result;
2817 static CURLcode ssh_block_statemach(struct connectdata *conn,
2818 bool duringconnect)
2820 struct ssh_conn *sshc = &conn->proto.sshc;
2821 CURLcode result = CURLE_OK;
2822 struct SessionHandle *data = conn->data;
2824 while((sshc->state != SSH_STOP) && !result) {
2825 bool block;
2826 long left;
2828 result = ssh_statemach_act(conn, &block);
2829 if(result)
2830 break;
2832 if(Curl_pgrsUpdate(conn))
2833 return CURLE_ABORTED_BY_CALLBACK;
2834 else {
2835 struct timeval now = Curl_tvnow();
2836 result = Curl_speedcheck(data, now);
2837 if(result)
2838 break;
2841 left = Curl_timeleft(data, NULL, duringconnect);
2842 if(left < 0) {
2843 failf(data, "Operation timed out");
2844 return CURLE_OPERATION_TIMEDOUT;
2847 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
2848 if(!result && block) {
2849 int dir = libssh2_session_block_directions(sshc->ssh_session);
2850 curl_socket_t sock = conn->sock[FIRSTSOCKET];
2851 curl_socket_t fd_read = CURL_SOCKET_BAD;
2852 curl_socket_t fd_write = CURL_SOCKET_BAD;
2853 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
2854 fd_read = sock;
2855 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
2856 fd_write = sock;
2857 /* wait for the socket to become ready */
2858 Curl_socket_ready(fd_read, fd_write,
2859 left>1000?1000:left); /* ignore result */
2861 #endif
2865 return result;
2869 * SSH setup and connection
2871 static CURLcode ssh_setup_connection(struct connectdata *conn)
2873 struct SSHPROTO *ssh;
2875 conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
2876 if(!ssh)
2877 return CURLE_OUT_OF_MEMORY;
2879 return CURLE_OK;
2882 static Curl_recv scp_recv, sftp_recv;
2883 static Curl_send scp_send, sftp_send;
2886 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
2887 * do protocol-specific actions at connect-time.
2889 static CURLcode ssh_connect(struct connectdata *conn, bool *done)
2891 #ifdef CURL_LIBSSH2_DEBUG
2892 curl_socket_t sock;
2893 #endif
2894 struct ssh_conn *ssh;
2895 CURLcode result;
2896 struct SessionHandle *data = conn->data;
2898 /* initialize per-handle data if not already */
2899 if(!data->req.protop)
2900 ssh_setup_connection(conn);
2902 /* We default to persistent connections. We set this already in this connect
2903 function to make the re-use checks properly be able to check this bit. */
2904 connkeep(conn, "SSH default");
2906 if(conn->handler->protocol & CURLPROTO_SCP) {
2907 conn->recv[FIRSTSOCKET] = scp_recv;
2908 conn->send[FIRSTSOCKET] = scp_send;
2910 else {
2911 conn->recv[FIRSTSOCKET] = sftp_recv;
2912 conn->send[FIRSTSOCKET] = sftp_send;
2914 ssh = &conn->proto.sshc;
2916 #ifdef CURL_LIBSSH2_DEBUG
2917 if(conn->user) {
2918 infof(data, "User: %s\n", conn->user);
2920 if(conn->passwd) {
2921 infof(data, "Password: %s\n", conn->passwd);
2923 sock = conn->sock[FIRSTSOCKET];
2924 #endif /* CURL_LIBSSH2_DEBUG */
2926 ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
2927 my_libssh2_free,
2928 my_libssh2_realloc, conn);
2929 if(ssh->ssh_session == NULL) {
2930 failf(data, "Failure initialising ssh session");
2931 return CURLE_FAILED_INIT;
2934 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2935 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
2936 int rc;
2937 ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
2938 if(!ssh->kh) {
2939 /* eeek. TODO: free the ssh_session! */
2940 return CURLE_FAILED_INIT;
2943 /* read all known hosts from there */
2944 rc = libssh2_knownhost_readfile(ssh->kh,
2945 data->set.str[STRING_SSH_KNOWNHOSTS],
2946 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
2947 if(rc < 0)
2948 infof(data, "Failed to read known hosts from %s\n",
2949 data->set.str[STRING_SSH_KNOWNHOSTS]);
2951 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2953 #ifdef CURL_LIBSSH2_DEBUG
2954 libssh2_trace(ssh->ssh_session, ~0);
2955 infof(data, "SSH socket: %d\n", (int)sock);
2956 #endif /* CURL_LIBSSH2_DEBUG */
2958 state(conn, SSH_INIT);
2960 result = ssh_multi_statemach(conn, done);
2962 return result;
2966 ***********************************************************************
2968 * scp_perform()
2970 * This is the actual DO function for SCP. Get a file according to
2971 * the options previously setup.
2974 static
2975 CURLcode scp_perform(struct connectdata *conn,
2976 bool *connected,
2977 bool *dophase_done)
2979 CURLcode result = CURLE_OK;
2981 DEBUGF(infof(conn->data, "DO phase starts\n"));
2983 *dophase_done = FALSE; /* not done yet */
2985 /* start the first command in the DO phase */
2986 state(conn, SSH_SCP_TRANS_INIT);
2988 /* run the state-machine */
2989 result = ssh_multi_statemach(conn, dophase_done);
2991 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
2993 if(*dophase_done) {
2994 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2997 return result;
3000 /* called from multi.c while DOing */
3001 static CURLcode scp_doing(struct connectdata *conn,
3002 bool *dophase_done)
3004 CURLcode result;
3005 result = ssh_multi_statemach(conn, dophase_done);
3007 if(*dophase_done) {
3008 DEBUGF(infof(conn->data, "DO phase is complete\n"));
3010 return result;
3014 * The DO function is generic for both protocols. There was previously two
3015 * separate ones but this way means less duplicated code.
3018 static CURLcode ssh_do(struct connectdata *conn, bool *done)
3020 CURLcode result;
3021 bool connected = 0;
3022 struct SessionHandle *data = conn->data;
3023 struct ssh_conn *sshc = &conn->proto.sshc;
3025 *done = FALSE; /* default to false */
3027 data->req.size = -1; /* make sure this is unknown at this point */
3029 sshc->actualcode = CURLE_OK; /* reset error code */
3030 sshc->secondCreateDirs =0; /* reset the create dir attempt state
3031 variable */
3033 Curl_pgrsSetUploadCounter(data, 0);
3034 Curl_pgrsSetDownloadCounter(data, 0);
3035 Curl_pgrsSetUploadSize(data, -1);
3036 Curl_pgrsSetDownloadSize(data, -1);
3038 if(conn->handler->protocol & CURLPROTO_SCP)
3039 result = scp_perform(conn, &connected, done);
3040 else
3041 result = sftp_perform(conn, &connected, done);
3043 return result;
3046 /* BLOCKING, but the function is using the state machine so the only reason
3047 this is still blocking is that the multi interface code has no support for
3048 disconnecting operations that takes a while */
3049 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
3051 CURLcode result = CURLE_OK;
3052 struct ssh_conn *ssh = &conn->proto.sshc;
3053 (void) dead_connection;
3055 Curl_safefree(conn->data->req.protop);
3057 if(ssh->ssh_session) {
3058 /* only if there's a session still around to use! */
3060 state(conn, SSH_SESSION_DISCONNECT);
3062 result = ssh_block_statemach(conn, FALSE);
3065 return result;
3068 /* generic done function for both SCP and SFTP called from their specific
3069 done functions */
3070 static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
3072 CURLcode result = CURLE_OK;
3073 struct SSHPROTO *sftp_scp = conn->data->req.protop;
3075 if(!status) {
3076 /* run the state-machine
3078 TODO: when the multi interface is used, this _really_ should be using
3079 the ssh_multi_statemach function but we have no general support for
3080 non-blocking DONE operations!
3082 result = ssh_block_statemach(conn, FALSE);
3084 else
3085 result = status;
3087 if(sftp_scp)
3088 Curl_safefree(sftp_scp->path);
3089 if(Curl_pgrsDone(conn))
3090 return CURLE_ABORTED_BY_CALLBACK;
3092 conn->data->req.keepon = 0; /* clear all bits */
3093 return result;
3097 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
3098 bool premature)
3100 (void)premature; /* not used */
3102 if(!status)
3103 state(conn, SSH_SCP_DONE);
3105 return ssh_done(conn, status);
3109 /* return number of received (decrypted) bytes */
3110 static ssize_t scp_send(struct connectdata *conn, int sockindex,
3111 const void *mem, size_t len, CURLcode *err)
3113 ssize_t nwrite;
3114 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3116 /* libssh2_channel_write() returns int! */
3117 nwrite = (ssize_t)
3118 libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
3120 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3122 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3123 *err = CURLE_AGAIN;
3124 nwrite = 0;
3126 else if(nwrite < LIBSSH2_ERROR_NONE) {
3127 *err = libssh2_session_error_to_CURLE((int)nwrite);
3128 nwrite = -1;
3131 return nwrite;
3135 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
3136 * a regular CURLcode value.
3138 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
3139 char *mem, size_t len, CURLcode *err)
3141 ssize_t nread;
3142 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3144 /* libssh2_channel_read() returns int */
3145 nread = (ssize_t)
3146 libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
3148 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3149 if(nread == LIBSSH2_ERROR_EAGAIN) {
3150 *err = CURLE_AGAIN;
3151 nread = -1;
3154 return nread;
3158 * =============== SFTP ===============
3162 ***********************************************************************
3164 * sftp_perform()
3166 * This is the actual DO function for SFTP. Get a file/directory according to
3167 * the options previously setup.
3170 static
3171 CURLcode sftp_perform(struct connectdata *conn,
3172 bool *connected,
3173 bool *dophase_done)
3175 CURLcode result = CURLE_OK;
3177 DEBUGF(infof(conn->data, "DO phase starts\n"));
3179 *dophase_done = FALSE; /* not done yet */
3181 /* start the first command in the DO phase */
3182 state(conn, SSH_SFTP_QUOTE_INIT);
3184 /* run the state-machine */
3185 result = ssh_multi_statemach(conn, dophase_done);
3187 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
3189 if(*dophase_done) {
3190 DEBUGF(infof(conn->data, "DO phase is complete\n"));
3193 return result;
3196 /* called from multi.c while DOing */
3197 static CURLcode sftp_doing(struct connectdata *conn,
3198 bool *dophase_done)
3200 CURLcode result = ssh_multi_statemach(conn, dophase_done);
3202 if(*dophase_done) {
3203 DEBUGF(infof(conn->data, "DO phase is complete\n"));
3205 return result;
3208 /* BLOCKING, but the function is using the state machine so the only reason
3209 this is still blocking is that the multi interface code has no support for
3210 disconnecting operations that takes a while */
3211 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
3213 CURLcode result = CURLE_OK;
3214 (void) dead_connection;
3216 DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
3218 Curl_safefree(conn->data->req.protop);
3220 if(conn->proto.sshc.ssh_session) {
3221 /* only if there's a session still around to use! */
3222 state(conn, SSH_SFTP_SHUTDOWN);
3223 result = ssh_block_statemach(conn, FALSE);
3226 DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
3228 return result;
3232 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
3233 bool premature)
3235 struct ssh_conn *sshc = &conn->proto.sshc;
3237 if(!status) {
3238 /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3239 errors that could happen due to open file handles during POSTQUOTE
3240 operation */
3241 if(!status && !premature && conn->data->set.postquote) {
3242 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3243 state(conn, SSH_SFTP_CLOSE);
3245 else
3246 state(conn, SSH_SFTP_CLOSE);
3248 return ssh_done(conn, status);
3251 /* return number of sent bytes */
3252 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
3253 const void *mem, size_t len, CURLcode *err)
3255 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
3256 but is changed to ssize_t in 0.15. These days we don't
3257 support libssh2 0.15*/
3258 (void)sockindex;
3260 nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
3262 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3264 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3265 *err = CURLE_AGAIN;
3266 nwrite = 0;
3268 else if(nwrite < LIBSSH2_ERROR_NONE) {
3269 *err = libssh2_session_error_to_CURLE((int)nwrite);
3270 nwrite = -1;
3273 return nwrite;
3277 * Return number of received (decrypted) bytes
3278 * or <0 on error
3280 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
3281 char *mem, size_t len, CURLcode *err)
3283 ssize_t nread;
3284 (void)sockindex;
3286 nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
3288 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3290 if(nread == LIBSSH2_ERROR_EAGAIN) {
3291 *err = CURLE_AGAIN;
3292 nread = -1;
3295 else if(nread < 0) {
3296 *err = libssh2_session_error_to_CURLE((int)nread);
3298 return nread;
3301 /* The get_pathname() function is being borrowed from OpenSSH sftp.c
3302 version 4.6p1. */
3304 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
3306 * Permission to use, copy, modify, and distribute this software for any
3307 * purpose with or without fee is hereby granted, provided that the above
3308 * copyright notice and this permission notice appear in all copies.
3310 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3311 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3312 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3313 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3314 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3315 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3316 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3318 static CURLcode
3319 get_pathname(const char **cpp, char **path)
3321 const char *cp = *cpp, *end;
3322 char quot;
3323 unsigned int i, j;
3324 static const char WHITESPACE[] = " \t\r\n";
3326 cp += strspn(cp, WHITESPACE);
3327 if(!*cp) {
3328 *cpp = cp;
3329 *path = NULL;
3330 return CURLE_QUOTE_ERROR;
3333 *path = malloc(strlen(cp) + 1);
3334 if(*path == NULL)
3335 return CURLE_OUT_OF_MEMORY;
3337 /* Check for quoted filenames */
3338 if(*cp == '\"' || *cp == '\'') {
3339 quot = *cp++;
3341 /* Search for terminating quote, unescape some chars */
3342 for(i = j = 0; i <= strlen(cp); i++) {
3343 if(cp[i] == quot) { /* Found quote */
3344 i++;
3345 (*path)[j] = '\0';
3346 break;
3348 if(cp[i] == '\0') { /* End of string */
3349 /*error("Unterminated quote");*/
3350 goto fail;
3352 if(cp[i] == '\\') { /* Escaped characters */
3353 i++;
3354 if(cp[i] != '\'' && cp[i] != '\"' &&
3355 cp[i] != '\\') {
3356 /*error("Bad escaped character '\\%c'",
3357 cp[i]);*/
3358 goto fail;
3361 (*path)[j++] = cp[i];
3364 if(j == 0) {
3365 /*error("Empty quotes");*/
3366 goto fail;
3368 *cpp = cp + i + strspn(cp + i, WHITESPACE);
3370 else {
3371 /* Read to end of filename */
3372 end = strpbrk(cp, WHITESPACE);
3373 if(end == NULL)
3374 end = strchr(cp, '\0');
3375 *cpp = end + strspn(end, WHITESPACE);
3377 memcpy(*path, cp, end - cp);
3378 (*path)[end - cp] = '\0';
3380 return CURLE_OK;
3382 fail:
3383 Curl_safefree(*path);
3384 return CURLE_QUOTE_ERROR;
3388 static const char *sftp_libssh2_strerror(int err)
3390 switch (err) {
3391 case LIBSSH2_FX_NO_SUCH_FILE:
3392 return "No such file or directory";
3394 case LIBSSH2_FX_PERMISSION_DENIED:
3395 return "Permission denied";
3397 case LIBSSH2_FX_FAILURE:
3398 return "Operation failed";
3400 case LIBSSH2_FX_BAD_MESSAGE:
3401 return "Bad message from SFTP server";
3403 case LIBSSH2_FX_NO_CONNECTION:
3404 return "Not connected to SFTP server";
3406 case LIBSSH2_FX_CONNECTION_LOST:
3407 return "Connection to SFTP server lost";
3409 case LIBSSH2_FX_OP_UNSUPPORTED:
3410 return "Operation not supported by SFTP server";
3412 case LIBSSH2_FX_INVALID_HANDLE:
3413 return "Invalid handle";
3415 case LIBSSH2_FX_NO_SUCH_PATH:
3416 return "No such file or directory";
3418 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3419 return "File already exists";
3421 case LIBSSH2_FX_WRITE_PROTECT:
3422 return "File is write protected";
3424 case LIBSSH2_FX_NO_MEDIA:
3425 return "No media";
3427 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3428 return "Disk full";
3430 case LIBSSH2_FX_QUOTA_EXCEEDED:
3431 return "User quota exceeded";
3433 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3434 return "Unknown principle";
3436 case LIBSSH2_FX_LOCK_CONFlICT:
3437 return "File lock conflict";
3439 case LIBSSH2_FX_DIR_NOT_EMPTY:
3440 return "Directory not empty";
3442 case LIBSSH2_FX_NOT_A_DIRECTORY:
3443 return "Not a directory";
3445 case LIBSSH2_FX_INVALID_FILENAME:
3446 return "Invalid filename";
3448 case LIBSSH2_FX_LINK_LOOP:
3449 return "Link points to itself";
3451 return "Unknown error in libssh2";
3454 #endif /* USE_LIBSSH2 */