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