VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/vssh/libssh2.c@ 106165

最後變更 在這個檔案從106165是 104083,由 vboxsync 提交於 8 月 前

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

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

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