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