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