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_int64_t)d, 0, 0)
426 #endif
427
428 /*
429 * libssh2 1.2.8 fixed the problem with 32-bit 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 enum curl_khtype convert_ssh2_keytype(int sshkeytype)
437 {
438 enum curl_khtype 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 enum curl_khtype keytype = convert_ssh2_keytype(sshkeytype);
784 Curl_set_in_callback(data, true);
785 rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp,
786 (int)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 (long)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 = (time_t)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, (long)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_setup1(data, CURL_XFER_SEND, -1, FALSE);
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 (long)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 (unsigned int)
2406 Curl_dyn_len(&sshp->readdir_link),
2407 sshp->readdir_filename,
2408 PATH_MAX, LIBSSH2_SFTP_READLINK);
2409 if(rc == LIBSSH2_ERROR_EAGAIN) {
2410 break;
2411 }
2412 Curl_dyn_free(&sshp->readdir_link);
2413
2414 /* append filename and extra output */
2415 result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
2416
2417 if(result) {
2418 Curl_safefree(sshp->readdir_filename);
2419 Curl_safefree(sshp->readdir_longentry);
2420 state(data, SSH_SFTP_CLOSE);
2421 sshc->actualcode = result;
2422 break;
2423 }
2424
2425 state(data, SSH_SFTP_READDIR_BOTTOM);
2426 break;
2427
2428 case SSH_SFTP_READDIR_BOTTOM:
2429 result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
2430 if(!result)
2431 result = Curl_client_write(data, CLIENTWRITE_BODY,
2432 Curl_dyn_ptr(&sshp->readdir),
2433 Curl_dyn_len(&sshp->readdir));
2434
2435 if(result) {
2436 Curl_dyn_free(&sshp->readdir);
2437 state(data, SSH_STOP);
2438 }
2439 else {
2440 Curl_dyn_reset(&sshp->readdir);
2441 state(data, SSH_SFTP_READDIR);
2442 }
2443 break;
2444
2445 case SSH_SFTP_READDIR_DONE:
2446 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2447 LIBSSH2_ERROR_EAGAIN) {
2448 rc = LIBSSH2_ERROR_EAGAIN;
2449 break;
2450 }
2451 sshc->sftp_handle = NULL;
2452 Curl_safefree(sshp->readdir_filename);
2453 Curl_safefree(sshp->readdir_longentry);
2454
2455 /* no data to transfer */
2456 Curl_xfer_setup_nop(data);
2457 state(data, SSH_STOP);
2458 break;
2459
2460 case SSH_SFTP_DOWNLOAD_INIT:
2461 /*
2462 * Work on getting the specified file
2463 */
2464 sshc->sftp_handle =
2465 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2466 curlx_uztoui(strlen(sshp->path)),
2467 LIBSSH2_FXF_READ, (long)data->set.new_file_perms,
2468 LIBSSH2_SFTP_OPENFILE);
2469 if(!sshc->sftp_handle) {
2470 if(libssh2_session_last_errno(sshc->ssh_session) ==
2471 LIBSSH2_ERROR_EAGAIN) {
2472 rc = LIBSSH2_ERROR_EAGAIN;
2473 break;
2474 }
2475 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2476 failf(data, "Could not open remote file for reading: %s",
2477 sftp_libssh2_strerror(sftperr));
2478 state(data, SSH_SFTP_CLOSE);
2479 result = sftp_libssh2_error_to_CURLE(sftperr);
2480 sshc->actualcode = result?result:CURLE_SSH;
2481 break;
2482 }
2483 state(data, SSH_SFTP_DOWNLOAD_STAT);
2484 break;
2485
2486 case SSH_SFTP_DOWNLOAD_STAT:
2487 {
2488 LIBSSH2_SFTP_ATTRIBUTES attrs;
2489
2490 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2491 curlx_uztoui(strlen(sshp->path)),
2492 LIBSSH2_SFTP_STAT, &attrs);
2493 if(rc == LIBSSH2_ERROR_EAGAIN) {
2494 break;
2495 }
2496 if(rc ||
2497 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
2498 (attrs.filesize == 0)) {
2499 /*
2500 * libssh2_sftp_open() didn't return an error, so maybe the server
2501 * just doesn't support stat()
2502 * OR the server doesn't return a file size with a stat()
2503 * OR file size is 0
2504 */
2505 data->req.size = -1;
2506 data->req.maxdownload = -1;
2507 Curl_pgrsSetDownloadSize(data, -1);
2508 }
2509 else {
2510 curl_off_t size = attrs.filesize;
2511
2512 if(size < 0) {
2513 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
2514 return CURLE_BAD_DOWNLOAD_RESUME;
2515 }
2516 if(data->state.use_range) {
2517 curl_off_t from, to;
2518 char *ptr;
2519 char *ptr2;
2520 CURLofft to_t;
2521 CURLofft from_t;
2522
2523 from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
2524 if(from_t == CURL_OFFT_FLOW)
2525 return CURLE_RANGE_ERROR;
2526 while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
2527 ptr++;
2528 to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
2529 if(to_t == CURL_OFFT_FLOW)
2530 return CURLE_RANGE_ERROR;
2531 if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
2532 || (to >= size)) {
2533 to = size - 1;
2534 }
2535 if(from_t) {
2536 /* from is relative to end of file */
2537 from = size - to;
2538 to = size - 1;
2539 }
2540 if(from > size) {
2541 failf(data, "Offset (%"
2542 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
2543 CURL_FORMAT_CURL_OFF_T ")", from,
2544 (curl_off_t)attrs.filesize);
2545 return CURLE_BAD_DOWNLOAD_RESUME;
2546 }
2547 if(from > to) {
2548 from = to;
2549 size = 0;
2550 }
2551 else {
2552 if((to - from) == CURL_OFF_T_MAX)
2553 return CURLE_RANGE_ERROR;
2554 size = to - from + 1;
2555 }
2556
2557 SFTP_SEEK(sshc->sftp_handle, from);
2558 }
2559 data->req.size = size;
2560 data->req.maxdownload = size;
2561 Curl_pgrsSetDownloadSize(data, size);
2562 }
2563
2564 /* We can resume if we can seek to the resume position */
2565 if(data->state.resume_from) {
2566 if(data->state.resume_from < 0) {
2567 /* We're supposed to download the last abs(from) bytes */
2568 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
2569 failf(data, "Offset (%"
2570 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
2571 CURL_FORMAT_CURL_OFF_T ")",
2572 data->state.resume_from, (curl_off_t)attrs.filesize);
2573 return CURLE_BAD_DOWNLOAD_RESUME;
2574 }
2575 /* download from where? */
2576 data->state.resume_from += attrs.filesize;
2577 }
2578 else {
2579 if((curl_off_t)attrs.filesize < data->state.resume_from) {
2580 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2581 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
2582 data->state.resume_from, (curl_off_t)attrs.filesize);
2583 return CURLE_BAD_DOWNLOAD_RESUME;
2584 }
2585 }
2586 /* Now store the number of bytes we are expected to download */
2587 data->req.size = attrs.filesize - data->state.resume_from;
2588 data->req.maxdownload = attrs.filesize - data->state.resume_from;
2589 Curl_pgrsSetDownloadSize(data,
2590 attrs.filesize - data->state.resume_from);
2591 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
2592 }
2593 }
2594
2595 /* Setup the actual download */
2596 if(data->req.size == 0) {
2597 /* no data to transfer */
2598 Curl_xfer_setup_nop(data);
2599 infof(data, "File already completely downloaded");
2600 state(data, SSH_STOP);
2601 break;
2602 }
2603 Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
2604
2605 /* not set by Curl_xfer_setup to preserve keepon bits */
2606 conn->writesockfd = conn->sockfd;
2607
2608 /* we want to use the _receiving_ function even when the socket turns
2609 out writableable as the underlying libssh2 recv function will deal
2610 with both accordingly */
2611 data->state.select_bits = CURL_CSELECT_IN;
2612
2613 if(result) {
2614 /* this should never occur; the close state should be entered
2615 at the time the error occurs */
2616 state(data, SSH_SFTP_CLOSE);
2617 sshc->actualcode = result;
2618 }
2619 else {
2620 state(data, SSH_STOP);
2621 }
2622 break;
2623
2624 case SSH_SFTP_CLOSE:
2625 if(sshc->sftp_handle) {
2626 rc = libssh2_sftp_close(sshc->sftp_handle);
2627 if(rc == LIBSSH2_ERROR_EAGAIN) {
2628 break;
2629 }
2630 if(rc < 0) {
2631 char *err_msg = NULL;
2632 (void)libssh2_session_last_error(sshc->ssh_session,
2633 &err_msg, NULL, 0);
2634 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2635 }
2636 sshc->sftp_handle = NULL;
2637 }
2638
2639 Curl_safefree(sshp->path);
2640
2641 DEBUGF(infof(data, "SFTP DONE done"));
2642
2643 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2644 After nextstate is executed, the control should come back to
2645 SSH_SFTP_CLOSE to pass the correct result back */
2646 if(sshc->nextstate != SSH_NO_STATE &&
2647 sshc->nextstate != SSH_SFTP_CLOSE) {
2648 state(data, sshc->nextstate);
2649 sshc->nextstate = SSH_SFTP_CLOSE;
2650 }
2651 else {
2652 state(data, SSH_STOP);
2653 result = sshc->actualcode;
2654 }
2655 break;
2656
2657 case SSH_SFTP_SHUTDOWN:
2658 /* during times we get here due to a broken transfer and then the
2659 sftp_handle might not have been taken down so make sure that is done
2660 before we proceed */
2661
2662 if(sshc->sftp_handle) {
2663 rc = libssh2_sftp_close(sshc->sftp_handle);
2664 if(rc == LIBSSH2_ERROR_EAGAIN) {
2665 break;
2666 }
2667 if(rc < 0) {
2668 char *err_msg = NULL;
2669 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
2670 NULL, 0);
2671 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2672 }
2673 sshc->sftp_handle = NULL;
2674 }
2675 if(sshc->sftp_session) {
2676 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2677 if(rc == LIBSSH2_ERROR_EAGAIN) {
2678 break;
2679 }
2680 if(rc < 0) {
2681 infof(data, "Failed to stop libssh2 sftp subsystem");
2682 }
2683 sshc->sftp_session = NULL;
2684 }
2685
2686 Curl_safefree(sshc->homedir);
2687 data->state.most_recent_ftp_entrypath = NULL;
2688
2689 state(data, SSH_SESSION_DISCONNECT);
2690 break;
2691
2692 case SSH_SCP_TRANS_INIT:
2693 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
2694 if(result) {
2695 sshc->actualcode = result;
2696 state(data, SSH_STOP);
2697 break;
2698 }
2699
2700 if(data->state.upload) {
2701 if(data->state.infilesize < 0) {
2702 failf(data, "SCP requires a known file size for upload");
2703 sshc->actualcode = CURLE_UPLOAD_FAILED;
2704 state(data, SSH_SCP_CHANNEL_FREE);
2705 break;
2706 }
2707 state(data, SSH_SCP_UPLOAD_INIT);
2708 }
2709 else {
2710 state(data, SSH_SCP_DOWNLOAD_INIT);
2711 }
2712 break;
2713
2714 case SSH_SCP_UPLOAD_INIT:
2715 /*
2716 * libssh2 requires that the destination path is a full path that
2717 * includes the destination file and name OR ends in a "/" . If this is
2718 * not done the destination file will be named the same name as the last
2719 * directory in the path.
2720 */
2721 sshc->ssh_channel =
2722 SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
2723 data->state.infilesize);
2724 if(!sshc->ssh_channel) {
2725 int ssh_err;
2726 char *err_msg = NULL;
2727
2728 if(libssh2_session_last_errno(sshc->ssh_session) ==
2729 LIBSSH2_ERROR_EAGAIN) {
2730 rc = LIBSSH2_ERROR_EAGAIN;
2731 break;
2732 }
2733
2734 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2735 &err_msg, NULL, 0));
2736 failf(data, "%s", err_msg);
2737 state(data, SSH_SCP_CHANNEL_FREE);
2738 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2739 /* Map generic errors to upload failed */
2740 if(sshc->actualcode == CURLE_SSH ||
2741 sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
2742 sshc->actualcode = CURLE_UPLOAD_FAILED;
2743 break;
2744 }
2745
2746 /* upload data */
2747 data->req.size = data->state.infilesize;
2748 Curl_pgrsSetUploadSize(data, data->state.infilesize);
2749 Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
2750
2751 /* not set by Curl_xfer_setup to preserve keepon bits */
2752 conn->sockfd = conn->writesockfd;
2753
2754 if(result) {
2755 state(data, SSH_SCP_CHANNEL_FREE);
2756 sshc->actualcode = result;
2757 }
2758 else {
2759 /* store this original bitmask setup to use later on if we can't
2760 figure out a "real" bitmask */
2761 sshc->orig_waitfor = data->req.keepon;
2762
2763 /* we want to use the _sending_ function even when the socket turns
2764 out readable as the underlying libssh2 scp send function will deal
2765 with both accordingly */
2766 data->state.select_bits = CURL_CSELECT_OUT;
2767
2768 state(data, SSH_STOP);
2769 }
2770 break;
2771
2772 case SSH_SCP_DOWNLOAD_INIT:
2773 {
2774 curl_off_t bytecount;
2775
2776 /*
2777 * We must check the remote file; if it is a directory no values will
2778 * be set in sb
2779 */
2780
2781 /*
2782 * If support for >2GB files exists, use it.
2783 */
2784
2785 /* get a fresh new channel from the ssh layer */
2786 #if LIBSSH2_VERSION_NUM < 0x010700
2787 struct stat sb;
2788 memset(&sb, 0, sizeof(struct stat));
2789 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2790 sshp->path, &sb);
2791 #else
2792 libssh2_struct_stat sb;
2793 memset(&sb, 0, sizeof(libssh2_struct_stat));
2794 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
2795 sshp->path, &sb);
2796 #endif
2797
2798 if(!sshc->ssh_channel) {
2799 int ssh_err;
2800 char *err_msg = NULL;
2801
2802 if(libssh2_session_last_errno(sshc->ssh_session) ==
2803 LIBSSH2_ERROR_EAGAIN) {
2804 rc = LIBSSH2_ERROR_EAGAIN;
2805 break;
2806 }
2807
2808
2809 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2810 &err_msg, NULL, 0));
2811 failf(data, "%s", err_msg);
2812 state(data, SSH_SCP_CHANNEL_FREE);
2813 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2814 break;
2815 }
2816
2817 /* download data */
2818 bytecount = (curl_off_t)sb.st_size;
2819 data->req.maxdownload = (curl_off_t)sb.st_size;
2820 Curl_xfer_setup1(data, CURL_XFER_RECV, bytecount, FALSE);
2821
2822 /* not set by Curl_xfer_setup to preserve keepon bits */
2823 conn->writesockfd = conn->sockfd;
2824
2825 /* we want to use the _receiving_ function even when the socket turns
2826 out writableable as the underlying libssh2 recv function will deal
2827 with both accordingly */
2828 data->state.select_bits = CURL_CSELECT_IN;
2829
2830 if(result) {
2831 state(data, SSH_SCP_CHANNEL_FREE);
2832 sshc->actualcode = result;
2833 }
2834 else
2835 state(data, SSH_STOP);
2836 }
2837 break;
2838
2839 case SSH_SCP_DONE:
2840 if(data->state.upload)
2841 state(data, SSH_SCP_SEND_EOF);
2842 else
2843 state(data, SSH_SCP_CHANNEL_FREE);
2844 break;
2845
2846 case SSH_SCP_SEND_EOF:
2847 if(sshc->ssh_channel) {
2848 rc = libssh2_channel_send_eof(sshc->ssh_channel);
2849 if(rc == LIBSSH2_ERROR_EAGAIN) {
2850 break;
2851 }
2852 if(rc) {
2853 char *err_msg = NULL;
2854 (void)libssh2_session_last_error(sshc->ssh_session,
2855 &err_msg, NULL, 0);
2856 infof(data, "Failed to send libssh2 channel EOF: %d %s",
2857 rc, err_msg);
2858 }
2859 }
2860 state(data, SSH_SCP_WAIT_EOF);
2861 break;
2862
2863 case SSH_SCP_WAIT_EOF:
2864 if(sshc->ssh_channel) {
2865 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2866 if(rc == LIBSSH2_ERROR_EAGAIN) {
2867 break;
2868 }
2869 if(rc) {
2870 char *err_msg = NULL;
2871 (void)libssh2_session_last_error(sshc->ssh_session,
2872 &err_msg, NULL, 0);
2873 infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
2874 }
2875 }
2876 state(data, SSH_SCP_WAIT_CLOSE);
2877 break;
2878
2879 case SSH_SCP_WAIT_CLOSE:
2880 if(sshc->ssh_channel) {
2881 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2882 if(rc == LIBSSH2_ERROR_EAGAIN) {
2883 break;
2884 }
2885 if(rc) {
2886 char *err_msg = NULL;
2887 (void)libssh2_session_last_error(sshc->ssh_session,
2888 &err_msg, NULL, 0);
2889 infof(data, "Channel failed to close: %d %s", rc, err_msg);
2890 }
2891 }
2892 state(data, SSH_SCP_CHANNEL_FREE);
2893 break;
2894
2895 case SSH_SCP_CHANNEL_FREE:
2896 if(sshc->ssh_channel) {
2897 rc = libssh2_channel_free(sshc->ssh_channel);
2898 if(rc == LIBSSH2_ERROR_EAGAIN) {
2899 break;
2900 }
2901 if(rc < 0) {
2902 char *err_msg = NULL;
2903 (void)libssh2_session_last_error(sshc->ssh_session,
2904 &err_msg, NULL, 0);
2905 infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2906 rc, err_msg);
2907 }
2908 sshc->ssh_channel = NULL;
2909 }
2910 DEBUGF(infof(data, "SCP DONE phase complete"));
2911 #if 0 /* PREV */
2912 state(data, SSH_SESSION_DISCONNECT);
2913 #endif
2914 state(data, SSH_STOP);
2915 result = sshc->actualcode;
2916 break;
2917
2918 case SSH_SESSION_DISCONNECT:
2919 /* during weird times when we've been prematurely aborted, the channel
2920 is still alive when we reach this state and we MUST kill the channel
2921 properly first */
2922 if(sshc->ssh_channel) {
2923 rc = libssh2_channel_free(sshc->ssh_channel);
2924 if(rc == LIBSSH2_ERROR_EAGAIN) {
2925 break;
2926 }
2927 if(rc < 0) {
2928 char *err_msg = NULL;
2929 (void)libssh2_session_last_error(sshc->ssh_session,
2930 &err_msg, NULL, 0);
2931 infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2932 rc, err_msg);
2933 }
2934 sshc->ssh_channel = NULL;
2935 }
2936
2937 if(sshc->ssh_session) {
2938 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2939 if(rc == LIBSSH2_ERROR_EAGAIN) {
2940 break;
2941 }
2942 if(rc < 0) {
2943 char *err_msg = NULL;
2944 (void)libssh2_session_last_error(sshc->ssh_session,
2945 &err_msg, NULL, 0);
2946 infof(data, "Failed to disconnect libssh2 session: %d %s",
2947 rc, err_msg);
2948 }
2949 }
2950
2951 Curl_safefree(sshc->homedir);
2952 data->state.most_recent_ftp_entrypath = NULL;
2953
2954 state(data, SSH_SESSION_FREE);
2955 break;
2956
2957 case SSH_SESSION_FREE:
2958 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2959 if(sshc->kh) {
2960 libssh2_knownhost_free(sshc->kh);
2961 sshc->kh = NULL;
2962 }
2963 #endif
2964
2965 #ifdef HAVE_LIBSSH2_AGENT_API
2966 if(sshc->ssh_agent) {
2967 rc = libssh2_agent_disconnect(sshc->ssh_agent);
2968 if(rc == LIBSSH2_ERROR_EAGAIN) {
2969 break;
2970 }
2971 if(rc < 0) {
2972 char *err_msg = NULL;
2973 (void)libssh2_session_last_error(sshc->ssh_session,
2974 &err_msg, NULL, 0);
2975 infof(data, "Failed to disconnect from libssh2 agent: %d %s",
2976 rc, err_msg);
2977 }
2978 libssh2_agent_free(sshc->ssh_agent);
2979 sshc->ssh_agent = NULL;
2980
2981 /* NB: there is no need to free identities, they are part of internal
2982 agent stuff */
2983 sshc->sshagent_identity = NULL;
2984 sshc->sshagent_prev_identity = NULL;
2985 }
2986 #endif
2987
2988 if(sshc->ssh_session) {
2989 rc = libssh2_session_free(sshc->ssh_session);
2990 if(rc == LIBSSH2_ERROR_EAGAIN) {
2991 break;
2992 }
2993 if(rc < 0) {
2994 char *err_msg = NULL;
2995 (void)libssh2_session_last_error(sshc->ssh_session,
2996 &err_msg, NULL, 0);
2997 infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
2998 }
2999 sshc->ssh_session = NULL;
3000 }
3001
3002 /* worst-case scenario cleanup */
3003
3004 DEBUGASSERT(sshc->ssh_session == NULL);
3005 DEBUGASSERT(sshc->ssh_channel == NULL);
3006 DEBUGASSERT(sshc->sftp_session == NULL);
3007 DEBUGASSERT(sshc->sftp_handle == NULL);
3008 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
3009 DEBUGASSERT(sshc->kh == NULL);
3010 #endif
3011 #ifdef HAVE_LIBSSH2_AGENT_API
3012 DEBUGASSERT(sshc->ssh_agent == NULL);
3013 #endif
3014
3015 Curl_safefree(sshc->rsa_pub);
3016 Curl_safefree(sshc->rsa);
3017 Curl_safefree(sshc->quote_path1);
3018 Curl_safefree(sshc->quote_path2);
3019 Curl_safefree(sshc->homedir);
3020
3021 /* the code we are about to return */
3022 result = sshc->actualcode;
3023
3024 memset(sshc, 0, sizeof(struct ssh_conn));
3025
3026 connclose(conn, "SSH session free");
3027 sshc->state = SSH_SESSION_FREE; /* current */
3028 sshc->nextstate = SSH_NO_STATE;
3029 state(data, SSH_STOP);
3030 break;
3031
3032 case SSH_QUIT:
3033 default:
3034 /* internal error */
3035 sshc->nextstate = SSH_NO_STATE;
3036 state(data, SSH_STOP);
3037 break;
3038 }
3039
3040 } while(!rc && (sshc->state != SSH_STOP));
3041
3042 if(rc == LIBSSH2_ERROR_EAGAIN) {
3043 /* we would block, we need to wait for the socket to be ready (in the
3044 right direction too)! */
3045 *block = TRUE;
3046 }
3047
3048 return result;
3049 }
3050
3051 /* called by the multi interface to figure out what socket(s) to wait for and
3052 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
ssh_getsock(struct Curl_easy * data,struct connectdata * conn,curl_socket_t * sock)3053 static int ssh_getsock(struct Curl_easy *data,
3054 struct connectdata *conn,
3055 curl_socket_t *sock)
3056 {
3057 int bitmap = GETSOCK_BLANK;
3058 (void)data;
3059
3060 sock[0] = conn->sock[FIRSTSOCKET];
3061
3062 if(conn->waitfor & KEEP_RECV)
3063 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
3064
3065 if(conn->waitfor & KEEP_SEND)
3066 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
3067
3068 return bitmap;
3069 }
3070
3071 /*
3072 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
3073 * function is used to figure out in what direction and stores this info so
3074 * that the multi interface can take advantage of it. Make sure to call this
3075 * function in all cases so that when it _doesn't_ return EAGAIN we can
3076 * restore the default wait bits.
3077 */
ssh_block2waitfor(struct Curl_easy * data,bool block)3078 static void ssh_block2waitfor(struct Curl_easy *data, bool block)
3079 {
3080 struct connectdata *conn = data->conn;
3081 struct ssh_conn *sshc = &conn->proto.sshc;
3082 int dir = 0;
3083 if(block) {
3084 dir = libssh2_session_block_directions(sshc->ssh_session);
3085 if(dir) {
3086 /* translate the libssh2 define bits into our own bit defines */
3087 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
3088 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
3089 }
3090 }
3091 if(!dir)
3092 /* It didn't block or libssh2 didn't reveal in which direction, put back
3093 the original set */
3094 conn->waitfor = sshc->orig_waitfor;
3095 }
3096
3097 /* called repeatedly until done from multi.c */
ssh_multi_statemach(struct Curl_easy * data,bool * done)3098 static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
3099 {
3100 struct connectdata *conn = data->conn;
3101 struct ssh_conn *sshc = &conn->proto.sshc;
3102 CURLcode result = CURLE_OK;
3103 bool block; /* we store the status and use that to provide a ssh_getsock()
3104 implementation */
3105 do {
3106 result = ssh_statemach_act(data, &block);
3107 *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
3108 /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
3109 try again */
3110 } while(!result && !*done && !block);
3111 ssh_block2waitfor(data, block);
3112
3113 return result;
3114 }
3115
ssh_block_statemach(struct Curl_easy * data,struct connectdata * conn,bool disconnect)3116 static CURLcode ssh_block_statemach(struct Curl_easy *data,
3117 struct connectdata *conn,
3118 bool disconnect)
3119 {
3120 struct ssh_conn *sshc = &conn->proto.sshc;
3121 CURLcode result = CURLE_OK;
3122 struct curltime dis = Curl_now();
3123
3124 while((sshc->state != SSH_STOP) && !result) {
3125 bool block;
3126 timediff_t left = 1000;
3127 struct curltime now = Curl_now();
3128
3129 result = ssh_statemach_act(data, &block);
3130 if(result)
3131 break;
3132
3133 if(!disconnect) {
3134 if(Curl_pgrsUpdate(data))
3135 return CURLE_ABORTED_BY_CALLBACK;
3136
3137 result = Curl_speedcheck(data, now);
3138 if(result)
3139 break;
3140
3141 left = Curl_timeleft(data, NULL, FALSE);
3142 if(left < 0) {
3143 failf(data, "Operation timed out");
3144 return CURLE_OPERATION_TIMEDOUT;
3145 }
3146 }
3147 else if(Curl_timediff(now, dis) > 1000) {
3148 /* disconnect timeout */
3149 failf(data, "Disconnect timed out");
3150 result = CURLE_OK;
3151 break;
3152 }
3153
3154 if(block) {
3155 int dir = libssh2_session_block_directions(sshc->ssh_session);
3156 curl_socket_t sock = conn->sock[FIRSTSOCKET];
3157 curl_socket_t fd_read = CURL_SOCKET_BAD;
3158 curl_socket_t fd_write = CURL_SOCKET_BAD;
3159 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
3160 fd_read = sock;
3161 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
3162 fd_write = sock;
3163 /* wait for the socket to become ready */
3164 (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
3165 left>1000?1000:left);
3166 }
3167 }
3168
3169 return result;
3170 }
3171
3172 /*
3173 * SSH setup and connection
3174 */
ssh_setup_connection(struct Curl_easy * data,struct connectdata * conn)3175 static CURLcode ssh_setup_connection(struct Curl_easy *data,
3176 struct connectdata *conn)
3177 {
3178 struct SSHPROTO *ssh;
3179 (void)conn;
3180
3181 data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
3182 if(!ssh)
3183 return CURLE_OUT_OF_MEMORY;
3184
3185 return CURLE_OK;
3186 }
3187
3188 static Curl_recv scp_recv, sftp_recv;
3189 static Curl_send scp_send, sftp_send;
3190
3191 #ifndef CURL_DISABLE_PROXY
ssh_tls_recv(libssh2_socket_t sock,void * buffer,size_t length,int flags,void ** abstract)3192 static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
3193 size_t length, int flags, void **abstract)
3194 {
3195 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3196 ssize_t nread;
3197 CURLcode result;
3198 struct connectdata *conn = data->conn;
3199 Curl_recv *backup = conn->recv[0];
3200 struct ssh_conn *ssh = &conn->proto.sshc;
3201 int socknum = Curl_conn_sockindex(data, sock);
3202 (void)flags;
3203
3204 /* swap in the TLS reader function for this call only, and then swap back
3205 the SSH one again */
3206 conn->recv[0] = ssh->tls_recv;
3207 result = Curl_conn_recv(data, socknum, buffer, length, &nread);
3208 conn->recv[0] = backup;
3209 if(result == CURLE_AGAIN)
3210 return -EAGAIN; /* magic return code for libssh2 */
3211 else if(result)
3212 return -1; /* generic error */
3213 Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
3214 return nread;
3215 }
3216
ssh_tls_send(libssh2_socket_t sock,const void * buffer,size_t length,int flags,void ** abstract)3217 static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
3218 size_t length, int flags, void **abstract)
3219 {
3220 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3221 size_t nwrite;
3222 CURLcode result;
3223 struct connectdata *conn = data->conn;
3224 Curl_send *backup = conn->send[0];
3225 struct ssh_conn *ssh = &conn->proto.sshc;
3226 int socknum = Curl_conn_sockindex(data, sock);
3227 (void)flags;
3228
3229 /* swap in the TLS writer function for this call only, and then swap back
3230 the SSH one again */
3231 conn->send[0] = ssh->tls_send;
3232 result = Curl_conn_send(data, socknum, buffer, length, &nwrite);
3233 conn->send[0] = backup;
3234 if(result == CURLE_AGAIN)
3235 return -EAGAIN; /* magic return code for libssh2 */
3236 else if(result)
3237 return -1; /* error */
3238 Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, nwrite);
3239 return (ssize_t)nwrite;
3240 }
3241 #endif
3242
3243 /*
3244 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
3245 * do protocol-specific actions at connect-time.
3246 */
ssh_connect(struct Curl_easy * data,bool * done)3247 static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
3248 {
3249 #ifdef CURL_LIBSSH2_DEBUG
3250 curl_socket_t sock;
3251 #endif
3252 struct ssh_conn *sshc;
3253 CURLcode result;
3254 struct connectdata *conn = data->conn;
3255
3256 /* initialize per-handle data if not already */
3257 if(!data->req.p.ssh) {
3258 result = ssh_setup_connection(data, conn);
3259 if(result)
3260 return result;
3261 }
3262
3263 /* We default to persistent connections. We set this already in this connect
3264 function to make the reuse checks properly be able to check this bit. */
3265 connkeep(conn, "SSH default");
3266
3267 sshc = &conn->proto.sshc;
3268
3269 #ifdef CURL_LIBSSH2_DEBUG
3270 if(conn->user) {
3271 infof(data, "User: %s", conn->user);
3272 }
3273 if(conn->passwd) {
3274 infof(data, "Password: %s", conn->passwd);
3275 }
3276 sock = conn->sock[FIRSTSOCKET];
3277 #endif /* CURL_LIBSSH2_DEBUG */
3278
3279 /* libcurl MUST to set custom memory functions so that the kbd_callback
3280 function's memory allocations can be properly freed */
3281 sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
3282 my_libssh2_free,
3283 my_libssh2_realloc, data);
3284
3285 if(!sshc->ssh_session) {
3286 failf(data, "Failure initialising ssh session");
3287 return CURLE_FAILED_INIT;
3288 }
3289
3290 /* Set the packet read timeout if the libssh2 version supports it */
3291 #if LIBSSH2_VERSION_NUM >= 0x010B00
3292 if(data->set.server_response_timeout > 0) {
3293 libssh2_session_set_read_timeout(sshc->ssh_session,
3294 (long)(data->set.server_response_timeout / 1000));
3295 }
3296 #endif
3297
3298 #ifndef CURL_DISABLE_PROXY
3299 if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
3300 /*
3301 Setup libssh2 callbacks to make it read/write TLS from the socket.
3302
3303 ssize_t
3304 recvcb(libssh2_socket_t sock, void *buffer, size_t length,
3305 int flags, void **abstract);
3306
3307 ssize_t
3308 sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
3309 int flags, void **abstract);
3310
3311 */
3312 #if LIBSSH2_VERSION_NUM >= 0x010b01
3313 infof(data, "Uses HTTPS proxy");
3314 libssh2_session_callback_set2(sshc->ssh_session,
3315 LIBSSH2_CALLBACK_RECV,
3316 (libssh2_cb_generic *)ssh_tls_recv);
3317 libssh2_session_callback_set2(sshc->ssh_session,
3318 LIBSSH2_CALLBACK_SEND,
3319 (libssh2_cb_generic *)ssh_tls_send);
3320 #else
3321 /*
3322 * This crazy union dance is here to avoid assigning a void pointer a
3323 * function pointer as it is invalid C. The problem is of course that
3324 * libssh2 has such an API...
3325 */
3326 union receive {
3327 void *recvp;
3328 ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
3329 };
3330 union transfer {
3331 void *sendp;
3332 ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
3333 };
3334 union receive sshrecv;
3335 union transfer sshsend;
3336
3337 sshrecv.recvptr = ssh_tls_recv;
3338 sshsend.sendptr = ssh_tls_send;
3339
3340 infof(data, "Uses HTTPS proxy");
3341 libssh2_session_callback_set(sshc->ssh_session,
3342 LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
3343 libssh2_session_callback_set(sshc->ssh_session,
3344 LIBSSH2_CALLBACK_SEND, sshsend.sendp);
3345 #endif
3346
3347 /* Store the underlying TLS recv/send function pointers to be used when
3348 reading from the proxy */
3349 sshc->tls_recv = conn->recv[FIRSTSOCKET];
3350 sshc->tls_send = conn->send[FIRSTSOCKET];
3351 }
3352
3353 #endif /* CURL_DISABLE_PROXY */
3354 if(conn->handler->protocol & CURLPROTO_SCP) {
3355 conn->recv[FIRSTSOCKET] = scp_recv;
3356 conn->send[FIRSTSOCKET] = scp_send;
3357 }
3358 else {
3359 conn->recv[FIRSTSOCKET] = sftp_recv;
3360 conn->send[FIRSTSOCKET] = sftp_send;
3361 }
3362
3363 if(data->set.ssh_compression) {
3364 #if LIBSSH2_VERSION_NUM >= 0x010208
3365 if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
3366 #endif
3367 infof(data, "Failed to enable compression for ssh session");
3368 }
3369
3370 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
3371 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
3372 int rc;
3373 sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
3374 if(!sshc->kh) {
3375 libssh2_session_free(sshc->ssh_session);
3376 sshc->ssh_session = NULL;
3377 return CURLE_FAILED_INIT;
3378 }
3379
3380 /* read all known hosts from there */
3381 rc = libssh2_knownhost_readfile(sshc->kh,
3382 data->set.str[STRING_SSH_KNOWNHOSTS],
3383 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
3384 if(rc < 0)
3385 infof(data, "Failed to read known hosts from %s",
3386 data->set.str[STRING_SSH_KNOWNHOSTS]);
3387 }
3388 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
3389
3390 #ifdef CURL_LIBSSH2_DEBUG
3391 libssh2_trace(sshc->ssh_session, ~0);
3392 infof(data, "SSH socket: %d", (int)sock);
3393 #endif /* CURL_LIBSSH2_DEBUG */
3394
3395 state(data, SSH_INIT);
3396
3397 result = ssh_multi_statemach(data, done);
3398
3399 return result;
3400 }
3401
3402 /*
3403 ***********************************************************************
3404 *
3405 * scp_perform()
3406 *
3407 * This is the actual DO function for SCP. Get a file according to
3408 * the options previously setup.
3409 */
3410
3411 static
scp_perform(struct Curl_easy * data,bool * connected,bool * dophase_done)3412 CURLcode scp_perform(struct Curl_easy *data,
3413 bool *connected,
3414 bool *dophase_done)
3415 {
3416 CURLcode result = CURLE_OK;
3417
3418 DEBUGF(infof(data, "DO phase starts"));
3419
3420 *dophase_done = FALSE; /* not done yet */
3421
3422 /* start the first command in the DO phase */
3423 state(data, SSH_SCP_TRANS_INIT);
3424
3425 /* run the state-machine */
3426 result = ssh_multi_statemach(data, dophase_done);
3427
3428 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3429
3430 if(*dophase_done) {
3431 DEBUGF(infof(data, "DO phase is complete"));
3432 }
3433
3434 return result;
3435 }
3436
3437 /* called from multi.c while DOing */
scp_doing(struct Curl_easy * data,bool * dophase_done)3438 static CURLcode scp_doing(struct Curl_easy *data,
3439 bool *dophase_done)
3440 {
3441 CURLcode result;
3442 result = ssh_multi_statemach(data, dophase_done);
3443
3444 if(*dophase_done) {
3445 DEBUGF(infof(data, "DO phase is complete"));
3446 }
3447 return result;
3448 }
3449
3450 /*
3451 * The DO function is generic for both protocols. There was previously two
3452 * separate ones but this way means less duplicated code.
3453 */
3454
ssh_do(struct Curl_easy * data,bool * done)3455 static CURLcode ssh_do(struct Curl_easy *data, bool *done)
3456 {
3457 CURLcode result;
3458 bool connected = 0;
3459 struct connectdata *conn = data->conn;
3460 struct ssh_conn *sshc = &conn->proto.sshc;
3461
3462 *done = FALSE; /* default to false */
3463
3464 data->req.size = -1; /* make sure this is unknown at this point */
3465
3466 sshc->actualcode = CURLE_OK; /* reset error code */
3467 sshc->secondCreateDirs = 0; /* reset the create dir attempt state
3468 variable */
3469
3470 Curl_pgrsSetUploadCounter(data, 0);
3471 Curl_pgrsSetDownloadCounter(data, 0);
3472 Curl_pgrsSetUploadSize(data, -1);
3473 Curl_pgrsSetDownloadSize(data, -1);
3474
3475 if(conn->handler->protocol & CURLPROTO_SCP)
3476 result = scp_perform(data, &connected, done);
3477 else
3478 result = sftp_perform(data, &connected, done);
3479
3480 return result;
3481 }
3482
3483 /* BLOCKING, but the function is using the state machine so the only reason
3484 this is still blocking is that the multi interface code has no support for
3485 disconnecting operations that takes a while */
scp_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)3486 static CURLcode scp_disconnect(struct Curl_easy *data,
3487 struct connectdata *conn,
3488 bool dead_connection)
3489 {
3490 CURLcode result = CURLE_OK;
3491 struct ssh_conn *sshc = &conn->proto.sshc;
3492 (void) dead_connection;
3493
3494 if(sshc->ssh_session) {
3495 /* only if there's a session still around to use! */
3496 state(data, SSH_SESSION_DISCONNECT);
3497 result = ssh_block_statemach(data, conn, TRUE);
3498 }
3499
3500 return result;
3501 }
3502
3503 /* generic done function for both SCP and SFTP called from their specific
3504 done functions */
ssh_done(struct Curl_easy * data,CURLcode status)3505 static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
3506 {
3507 CURLcode result = CURLE_OK;
3508 struct SSHPROTO *sshp = data->req.p.ssh;
3509 struct connectdata *conn = data->conn;
3510
3511 if(!status)
3512 /* run the state-machine */
3513 result = ssh_block_statemach(data, conn, FALSE);
3514 else
3515 result = status;
3516
3517 Curl_safefree(sshp->path);
3518 Curl_safefree(sshp->readdir_filename);
3519 Curl_safefree(sshp->readdir_longentry);
3520 Curl_dyn_free(&sshp->readdir);
3521
3522 if(Curl_pgrsDone(data))
3523 return CURLE_ABORTED_BY_CALLBACK;
3524
3525 data->req.keepon = 0; /* clear all bits */
3526 return result;
3527 }
3528
3529
scp_done(struct Curl_easy * data,CURLcode status,bool premature)3530 static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
3531 bool premature)
3532 {
3533 (void)premature; /* not used */
3534
3535 if(!status)
3536 state(data, SSH_SCP_DONE);
3537
3538 return ssh_done(data, status);
3539
3540 }
3541
scp_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,CURLcode * err)3542 static ssize_t scp_send(struct Curl_easy *data, int sockindex,
3543 const void *mem, size_t len, CURLcode *err)
3544 {
3545 ssize_t nwrite;
3546 struct connectdata *conn = data->conn;
3547 struct ssh_conn *sshc = &conn->proto.sshc;
3548 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3549
3550 /* libssh2_channel_write() returns int! */
3551 nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
3552
3553 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3554
3555 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3556 *err = CURLE_AGAIN;
3557 nwrite = 0;
3558 }
3559 else if(nwrite < LIBSSH2_ERROR_NONE) {
3560 *err = libssh2_session_error_to_CURLE((int)nwrite);
3561 nwrite = -1;
3562 }
3563
3564 return nwrite;
3565 }
3566
scp_recv(struct Curl_easy * data,int sockindex,char * mem,size_t len,CURLcode * err)3567 static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
3568 char *mem, size_t len, CURLcode *err)
3569 {
3570 ssize_t nread;
3571 struct connectdata *conn = data->conn;
3572 struct ssh_conn *sshc = &conn->proto.sshc;
3573 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3574
3575 /* libssh2_channel_read() returns int */
3576 nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
3577
3578 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3579 if(nread == LIBSSH2_ERROR_EAGAIN) {
3580 *err = CURLE_AGAIN;
3581 nread = -1;
3582 }
3583
3584 return nread;
3585 }
3586
3587 /*
3588 * =============== SFTP ===============
3589 */
3590
3591 /*
3592 ***********************************************************************
3593 *
3594 * sftp_perform()
3595 *
3596 * This is the actual DO function for SFTP. Get a file/directory according to
3597 * the options previously setup.
3598 */
3599
3600 static
sftp_perform(struct Curl_easy * data,bool * connected,bool * dophase_done)3601 CURLcode sftp_perform(struct Curl_easy *data,
3602 bool *connected,
3603 bool *dophase_done)
3604 {
3605 CURLcode result = CURLE_OK;
3606
3607 DEBUGF(infof(data, "DO phase starts"));
3608
3609 *dophase_done = FALSE; /* not done yet */
3610
3611 /* start the first command in the DO phase */
3612 state(data, SSH_SFTP_QUOTE_INIT);
3613
3614 /* run the state-machine */
3615 result = ssh_multi_statemach(data, dophase_done);
3616
3617 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3618
3619 if(*dophase_done) {
3620 DEBUGF(infof(data, "DO phase is complete"));
3621 }
3622
3623 return result;
3624 }
3625
3626 /* called from multi.c while DOing */
sftp_doing(struct Curl_easy * data,bool * dophase_done)3627 static CURLcode sftp_doing(struct Curl_easy *data,
3628 bool *dophase_done)
3629 {
3630 CURLcode result = ssh_multi_statemach(data, dophase_done);
3631
3632 if(*dophase_done) {
3633 DEBUGF(infof(data, "DO phase is complete"));
3634 }
3635 return result;
3636 }
3637
3638 /* BLOCKING, but the function is using the state machine so the only reason
3639 this is still blocking is that the multi interface code has no support for
3640 disconnecting operations that takes a while */
sftp_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)3641 static CURLcode sftp_disconnect(struct Curl_easy *data,
3642 struct connectdata *conn, bool dead_connection)
3643 {
3644 CURLcode result = CURLE_OK;
3645 struct ssh_conn *sshc = &conn->proto.sshc;
3646 (void) dead_connection;
3647
3648 DEBUGF(infof(data, "SSH DISCONNECT starts now"));
3649
3650 if(sshc->ssh_session) {
3651 /* only if there's a session still around to use! */
3652 state(data, SSH_SFTP_SHUTDOWN);
3653 result = ssh_block_statemach(data, conn, TRUE);
3654 }
3655
3656 DEBUGF(infof(data, "SSH DISCONNECT is done"));
3657
3658 return result;
3659
3660 }
3661
sftp_done(struct Curl_easy * data,CURLcode status,bool premature)3662 static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
3663 bool premature)
3664 {
3665 struct connectdata *conn = data->conn;
3666 struct ssh_conn *sshc = &conn->proto.sshc;
3667
3668 if(!status) {
3669 /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3670 errors that could happen due to open file handles during POSTQUOTE
3671 operation */
3672 if(!premature && data->set.postquote && !conn->bits.retry)
3673 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3674 state(data, SSH_SFTP_CLOSE);
3675 }
3676 return ssh_done(data, status);
3677 }
3678
3679 /* return number of sent bytes */
sftp_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,CURLcode * err)3680 static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
3681 const void *mem, size_t len, CURLcode *err)
3682 {
3683 ssize_t nwrite;
3684 struct connectdata *conn = data->conn;
3685 struct ssh_conn *sshc = &conn->proto.sshc;
3686 (void)sockindex;
3687
3688 nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
3689
3690 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3691
3692 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3693 *err = CURLE_AGAIN;
3694 nwrite = 0;
3695 }
3696 else if(nwrite < LIBSSH2_ERROR_NONE) {
3697 *err = libssh2_session_error_to_CURLE((int)nwrite);
3698 nwrite = -1;
3699 }
3700
3701 return nwrite;
3702 }
3703
3704 /*
3705 * Return number of received (decrypted) bytes
3706 * or <0 on error
3707 */
sftp_recv(struct Curl_easy * data,int sockindex,char * mem,size_t len,CURLcode * err)3708 static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
3709 char *mem, size_t len, CURLcode *err)
3710 {
3711 ssize_t nread;
3712 struct connectdata *conn = data->conn;
3713 struct ssh_conn *sshc = &conn->proto.sshc;
3714 (void)sockindex;
3715
3716 nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
3717
3718 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
3719
3720 if(nread == LIBSSH2_ERROR_EAGAIN) {
3721 *err = CURLE_AGAIN;
3722 nread = -1;
3723
3724 }
3725 else if(nread < 0) {
3726 *err = libssh2_session_error_to_CURLE((int)nread);
3727 }
3728 return nread;
3729 }
3730
sftp_libssh2_strerror(unsigned long err)3731 static const char *sftp_libssh2_strerror(unsigned long err)
3732 {
3733 switch(err) {
3734 case LIBSSH2_FX_NO_SUCH_FILE:
3735 return "No such file or directory";
3736
3737 case LIBSSH2_FX_PERMISSION_DENIED:
3738 return "Permission denied";
3739
3740 case LIBSSH2_FX_FAILURE:
3741 return "Operation failed";
3742
3743 case LIBSSH2_FX_BAD_MESSAGE:
3744 return "Bad message from SFTP server";
3745
3746 case LIBSSH2_FX_NO_CONNECTION:
3747 return "Not connected to SFTP server";
3748
3749 case LIBSSH2_FX_CONNECTION_LOST:
3750 return "Connection to SFTP server lost";
3751
3752 case LIBSSH2_FX_OP_UNSUPPORTED:
3753 return "Operation not supported by SFTP server";
3754
3755 case LIBSSH2_FX_INVALID_HANDLE:
3756 return "Invalid handle";
3757
3758 case LIBSSH2_FX_NO_SUCH_PATH:
3759 return "No such file or directory";
3760
3761 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3762 return "File already exists";
3763
3764 case LIBSSH2_FX_WRITE_PROTECT:
3765 return "File is write protected";
3766
3767 case LIBSSH2_FX_NO_MEDIA:
3768 return "No media";
3769
3770 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3771 return "Disk full";
3772
3773 case LIBSSH2_FX_QUOTA_EXCEEDED:
3774 return "User quota exceeded";
3775
3776 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3777 return "Unknown principle";
3778
3779 case LIBSSH2_FX_LOCK_CONFlICT:
3780 return "File lock conflict";
3781
3782 case LIBSSH2_FX_DIR_NOT_EMPTY:
3783 return "Directory not empty";
3784
3785 case LIBSSH2_FX_NOT_A_DIRECTORY:
3786 return "Not a directory";
3787
3788 case LIBSSH2_FX_INVALID_FILENAME:
3789 return "Invalid filename";
3790
3791 case LIBSSH2_FX_LINK_LOOP:
3792 return "Link points to itself";
3793 }
3794 return "Unknown error in libssh2";
3795 }
3796
Curl_ssh_init(void)3797 CURLcode Curl_ssh_init(void)
3798 {
3799 #ifdef HAVE_LIBSSH2_INIT
3800 if(libssh2_init(0)) {
3801 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
3802 return CURLE_FAILED_INIT;
3803 }
3804 #endif
3805 return CURLE_OK;
3806 }
3807
Curl_ssh_cleanup(void)3808 void Curl_ssh_cleanup(void)
3809 {
3810 #ifdef HAVE_LIBSSH2_EXIT
3811 (void)libssh2_exit();
3812 #endif
3813 }
3814
Curl_ssh_version(char * buffer,size_t buflen)3815 void Curl_ssh_version(char *buffer, size_t buflen)
3816 {
3817 (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION);
3818 }
3819
3820 /* The SSH session is associated with the *CONNECTION* but the callback user
3821 * pointer is an easy handle pointer. This function allows us to reassign the
3822 * user pointer to the *CURRENT* (new) easy handle.
3823 */
ssh_attach(struct Curl_easy * data,struct connectdata * conn)3824 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
3825 {
3826 DEBUGASSERT(data);
3827 DEBUGASSERT(conn);
3828 if(conn->handler->protocol & PROTO_FAMILY_SSH) {
3829 struct ssh_conn *sshc = &conn->proto.sshc;
3830 if(sshc->ssh_session) {
3831 /* only re-attach if the session already exists */
3832 void **abstract = libssh2_session_abstract(sshc->ssh_session);
3833 *abstract = data;
3834 }
3835 }
3836 }
3837 #endif /* USE_LIBSSH2 */
3838