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