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