VirtualBox

source: vbox/trunk/src/libs/curl-7.64.0/lib/ssh.c@ 95219

Last change on this file since 95219 was 85671, checked in by vboxsync, 4 years ago

Export out internal curl copy to make it a lot simpler to build VBox (OSE) on Windows. bugref:9814

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette