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