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(CURL * easy,const struct curl_khkey * knownkey,const struct curl_khkey * foundkey,enum curl_khmatch match,void * clientp)392 static int sshkeycallback(CURL *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
sftp_quote(struct Curl_easy * data,struct ssh_conn * sshc,struct SSHPROTO * sshp)962 static CURLcode sftp_quote(struct Curl_easy *data,
963 struct ssh_conn *sshc,
964 struct SSHPROTO *sshp)
965 {
966 const char *cp;
967 CURLcode result = CURLE_OK;
968
969 /*
970 * Support some of the "FTP" commands
971 *
972 * 'sshc->quote_item' is already verified to be non-NULL before it
973 * switched to this state.
974 */
975 char *cmd = sshc->quote_item->data;
976 sshc->acceptfail = FALSE;
977
978 /* if a command starts with an asterisk, which a legal SFTP command never
979 can, the command will be allowed to fail without it causing any
980 aborts or cancels etc. It will cause libcurl to act as if the command
981 is successful, whatever the server responds. */
982
983 if(cmd[0] == '*') {
984 cmd++;
985 sshc->acceptfail = TRUE;
986 }
987
988 if(strcasecompare("pwd", cmd)) {
989 /* output debug output if that is requested */
990 char *tmp = aprintf("257 \"%s\" is current directory.\n", sshp->path);
991 if(!tmp)
992 return CURLE_OUT_OF_MEMORY;
993 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
994 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
995
996 /* this sends an FTP-like "header" to the header callback so that the
997 current directory can be read very similar to how it is read when
998 using ordinary FTP. */
999 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1000 free(tmp);
1001 if(!result)
1002 state(data, SSH_SFTP_NEXT_QUOTE);
1003 return result;
1004 }
1005
1006 /*
1007 * the arguments following the command must be separated from the
1008 * command with a space so we can check for it unconditionally
1009 */
1010 cp = strchr(cmd, ' ');
1011 if(!cp) {
1012 failf(data, "Syntax error command '%s', missing parameter", cmd);
1013 return result;
1014 }
1015
1016 /*
1017 * also, every command takes at least one argument so we get that
1018 * first argument right now
1019 */
1020 result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
1021 if(result) {
1022 if(result != CURLE_OUT_OF_MEMORY)
1023 failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
1024 return result;
1025 }
1026
1027 /*
1028 * SFTP is a binary protocol, so we do not send text commands to the server.
1029 * Instead, we scan for commands used by OpenSSH's sftp program and call the
1030 * appropriate libssh2 functions.
1031 */
1032 if(strncasecompare(cmd, "chgrp ", 6) ||
1033 strncasecompare(cmd, "chmod ", 6) ||
1034 strncasecompare(cmd, "chown ", 6) ||
1035 strncasecompare(cmd, "atime ", 6) ||
1036 strncasecompare(cmd, "mtime ", 6)) {
1037 /* attribute change */
1038
1039 /* sshc->quote_path1 contains the mode to set */
1040 /* get the destination */
1041 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1042 if(result) {
1043 if(result != CURLE_OUT_OF_MEMORY)
1044 failf(data, "Syntax error in %s: Bad second parameter", cmd);
1045 Curl_safefree(sshc->quote_path1);
1046 return result;
1047 }
1048 memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1049 state(data, SSH_SFTP_QUOTE_STAT);
1050 return result;
1051 }
1052 if(strncasecompare(cmd, "ln ", 3) ||
1053 strncasecompare(cmd, "symlink ", 8)) {
1054 /* symbolic linking */
1055 /* sshc->quote_path1 is the source */
1056 /* get the destination */
1057 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1058 if(result) {
1059 if(result != CURLE_OUT_OF_MEMORY)
1060 failf(data, "Syntax error in ln/symlink: Bad second parameter");
1061 Curl_safefree(sshc->quote_path1);
1062 return result;
1063 }
1064 state(data, SSH_SFTP_QUOTE_SYMLINK);
1065 return result;
1066 }
1067 else if(strncasecompare(cmd, "mkdir ", 6)) {
1068 /* create dir */
1069 state(data, SSH_SFTP_QUOTE_MKDIR);
1070 return result;
1071 }
1072 else if(strncasecompare(cmd, "rename ", 7)) {
1073 /* rename file */
1074 /* first param is the source path */
1075 /* second param is the dest. path */
1076 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
1077 if(result) {
1078 if(result != CURLE_OUT_OF_MEMORY)
1079 failf(data, "Syntax error in rename: Bad second parameter");
1080 Curl_safefree(sshc->quote_path1);
1081 return result;
1082 }
1083 state(data, SSH_SFTP_QUOTE_RENAME);
1084 return result;
1085 }
1086 else if(strncasecompare(cmd, "rmdir ", 6)) {
1087 /* delete dir */
1088 state(data, SSH_SFTP_QUOTE_RMDIR);
1089 return result;
1090 }
1091 else if(strncasecompare(cmd, "rm ", 3)) {
1092 state(data, SSH_SFTP_QUOTE_UNLINK);
1093 return result;
1094 }
1095 #ifdef HAS_STATVFS_SUPPORT
1096 else if(strncasecompare(cmd, "statvfs ", 8)) {
1097 state(data, SSH_SFTP_QUOTE_STATVFS);
1098 return result;
1099 }
1100 #endif
1101
1102 failf(data, "Unknown SFTP command");
1103 Curl_safefree(sshc->quote_path1);
1104 Curl_safefree(sshc->quote_path2);
1105 return CURLE_QUOTE_ERROR;
1106 }
1107
1108 static CURLcode
sftp_upload_init(struct Curl_easy * data,struct ssh_conn * sshc,struct SSHPROTO * sshp,bool * blockp)1109 sftp_upload_init(struct Curl_easy *data,
1110 struct ssh_conn *sshc,
1111 struct SSHPROTO *sshp,
1112 bool *blockp)
1113 {
1114 unsigned long flags;
1115
1116 /*
1117 * NOTE!!! libssh2 requires that the destination path is a full path
1118 * that includes the destination file and name OR ends in a "/"
1119 * If this is not done the destination file will be named the
1120 * same name as the last directory in the path.
1121 */
1122
1123 if(data->state.resume_from) {
1124 LIBSSH2_SFTP_ATTRIBUTES attrs;
1125 if(data->state.resume_from < 0) {
1126 int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
1127 curlx_uztoui(strlen(sshp->path)),
1128 LIBSSH2_SFTP_STAT, &attrs);
1129 if(rc == LIBSSH2_ERROR_EAGAIN) {
1130 *blockp = TRUE;
1131 return CURLE_OK;
1132 }
1133 if(rc) {
1134 data->state.resume_from = 0;
1135 }
1136 else {
1137 curl_off_t size = attrs.filesize;
1138 if(size < 0) {
1139 failf(data, "Bad file size (%" FMT_OFF_T ")", size);
1140 return CURLE_BAD_DOWNLOAD_RESUME;
1141 }
1142 data->state.resume_from = attrs.filesize;
1143 }
1144 }
1145 }
1146
1147 if(data->set.remote_append)
1148 /* Try to open for append, but create if nonexisting */
1149 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
1150 else if(data->state.resume_from > 0)
1151 /* If we have restart position then open for append */
1152 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
1153 else
1154 /* Clear file before writing (normal behavior) */
1155 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
1156
1157 sshc->sftp_handle =
1158 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
1159 curlx_uztoui(strlen(sshp->path)),
1160 flags, (long)data->set.new_file_perms,
1161 LIBSSH2_SFTP_OPENFILE);
1162
1163 if(!sshc->sftp_handle) {
1164 unsigned long sftperr;
1165 int rc = libssh2_session_last_errno(sshc->ssh_session);
1166
1167 if(LIBSSH2_ERROR_EAGAIN == rc) {
1168 *blockp = TRUE;
1169 return CURLE_OK;
1170 }
1171
1172 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
1173 /* only when there was an SFTP protocol error can we extract
1174 the sftp error! */
1175 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1176 else
1177 sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
1178
1179 if(sshc->secondCreateDirs) {
1180 state(data, SSH_SFTP_CLOSE);
1181 sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
1182 sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
1183 failf(data, "Creating the dir/file failed: %s",
1184 sftp_libssh2_strerror(sftperr));
1185 return CURLE_OK;
1186 }
1187 if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
1188 (sftperr == LIBSSH2_FX_FAILURE) ||
1189 (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
1190 (data->set.ftp_create_missing_dirs &&
1191 (strlen(sshp->path) > 1))) {
1192 /* try to create the path remotely */
1193 sshc->secondCreateDirs = 1;
1194 state(data, SSH_SFTP_CREATE_DIRS_INIT);
1195 return CURLE_OK;
1196 }
1197 state(data, SSH_SFTP_CLOSE);
1198 sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
1199 sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
1200 if(!sshc->actualcode) {
1201 /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
1202 even though libssh2_sftp_open() failed previously! We need to
1203 work around that! */
1204 sshc->actualcode = CURLE_SSH;
1205 sftperr = LIBSSH2_FX_OK;
1206 }
1207 failf(data, "Upload failed: %s (%lu/%d)",
1208 sftperr != LIBSSH2_FX_OK ?
1209 sftp_libssh2_strerror(sftperr) : "ssh error",
1210 sftperr, rc);
1211 return sshc->actualcode;
1212 }
1213
1214 /* If we have a restart point then we need to seek to the correct
1215 position. */
1216 if(data->state.resume_from > 0) {
1217 int seekerr = CURL_SEEKFUNC_OK;
1218 /* Let's read off the proper amount of bytes from the input. */
1219 if(data->set.seek_func) {
1220 Curl_set_in_callback(data, TRUE);
1221 seekerr = data->set.seek_func(data->set.seek_client,
1222 data->state.resume_from, SEEK_SET);
1223 Curl_set_in_callback(data, FALSE);
1224 }
1225
1226 if(seekerr != CURL_SEEKFUNC_OK) {
1227 curl_off_t passed = 0;
1228
1229 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1230 failf(data, "Could not seek stream");
1231 return CURLE_FTP_COULDNT_USE_REST;
1232 }
1233 /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
1234 do {
1235 char scratch[4*1024];
1236 size_t readthisamountnow =
1237 (data->state.resume_from - passed >
1238 (curl_off_t)sizeof(scratch)) ?
1239 sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
1240
1241 size_t actuallyread;
1242 Curl_set_in_callback(data, TRUE);
1243 actuallyread = data->state.fread_func(scratch, 1,
1244 readthisamountnow,
1245 data->state.in);
1246 Curl_set_in_callback(data, FALSE);
1247
1248 passed += actuallyread;
1249 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1250 /* this checks for greater-than only to make sure that the
1251 CURL_READFUNC_ABORT return code still aborts */
1252 failf(data, "Failed to read data");
1253 return CURLE_FTP_COULDNT_USE_REST;
1254 }
1255 } while(passed < data->state.resume_from);
1256 }
1257
1258 /* now, decrease the size of the read */
1259 if(data->state.infilesize > 0) {
1260 data->state.infilesize -= data->state.resume_from;
1261 data->req.size = data->state.infilesize;
1262 Curl_pgrsSetUploadSize(data, data->state.infilesize);
1263 }
1264
1265 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1266 }
1267 if(data->state.infilesize > 0) {
1268 data->req.size = data->state.infilesize;
1269 Curl_pgrsSetUploadSize(data, data->state.infilesize);
1270 }
1271 /* upload data */
1272 Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
1273
1274 /* not set by Curl_xfer_setup to preserve keepon bits */
1275 data->conn->sockfd = data->conn->writesockfd;
1276
1277 /* store this original bitmask setup to use later on if we cannot
1278 figure out a "real" bitmask */
1279 sshc->orig_waitfor = data->req.keepon;
1280
1281 /* we want to use the _sending_ function even when the socket turns
1282 out readable as the underlying libssh2 sftp send function will deal
1283 with both accordingly */
1284 data->state.select_bits = CURL_CSELECT_OUT;
1285
1286 /* since we do not really wait for anything at this point, we want the
1287 state machine to move on as soon as possible so we set a very short
1288 timeout here */
1289 Curl_expire(data, 0, EXPIRE_RUN_NOW);
1290
1291 state(data, SSH_STOP);
1292 return CURLE_OK;
1293 }
1294
1295 static CURLcode
sftp_pkey_init(struct Curl_easy * data,struct ssh_conn * sshc)1296 sftp_pkey_init(struct Curl_easy *data,
1297 struct ssh_conn *sshc)
1298 {
1299 /*
1300 * Check the supported auth types in the order I feel is most secure
1301 * with the requested type of authentication
1302 */
1303 sshc->authed = FALSE;
1304
1305 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
1306 (strstr(sshc->authlist, "publickey") != NULL)) {
1307 bool out_of_memory = FALSE;
1308
1309 sshc->rsa_pub = sshc->rsa = NULL;
1310
1311 if(data->set.str[STRING_SSH_PRIVATE_KEY])
1312 sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
1313 else {
1314 /* To ponder about: should really the lib be messing about with the
1315 HOME environment variable etc? */
1316 char *home = curl_getenv("HOME");
1317 struct_stat sbuf;
1318
1319 /* If no private key file is specified, try some common paths. */
1320 if(home) {
1321 /* Try ~/.ssh first. */
1322 sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
1323 if(!sshc->rsa)
1324 out_of_memory = TRUE;
1325 else if(stat(sshc->rsa, &sbuf)) {
1326 Curl_safefree(sshc->rsa);
1327 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
1328 if(!sshc->rsa)
1329 out_of_memory = TRUE;
1330 else if(stat(sshc->rsa, &sbuf)) {
1331 Curl_safefree(sshc->rsa);
1332 }
1333 }
1334 free(home);
1335 }
1336 if(!out_of_memory && !sshc->rsa) {
1337 /* Nothing found; try the current dir. */
1338 sshc->rsa = strdup("id_rsa");
1339 if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
1340 Curl_safefree(sshc->rsa);
1341 sshc->rsa = strdup("id_dsa");
1342 if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
1343 Curl_safefree(sshc->rsa);
1344 /* Out of guesses. Set to the empty string to avoid
1345 * surprising info messages. */
1346 sshc->rsa = strdup("");
1347 }
1348 }
1349 }
1350 }
1351
1352 /*
1353 * Unless the user explicitly specifies a public key file, let
1354 * libssh2 extract the public key from the private key file.
1355 * This is done by simply passing sshc->rsa_pub = NULL.
1356 */
1357 if(data->set.str[STRING_SSH_PUBLIC_KEY]
1358 /* treat empty string the same way as NULL */
1359 && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
1360 sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
1361 if(!sshc->rsa_pub)
1362 out_of_memory = TRUE;
1363 }
1364
1365 if(out_of_memory || !sshc->rsa) {
1366 Curl_safefree(sshc->rsa);
1367 Curl_safefree(sshc->rsa_pub);
1368 state(data, SSH_SESSION_FREE);
1369 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1370 return CURLE_OUT_OF_MEMORY;
1371 }
1372
1373 sshc->passphrase = data->set.ssl.key_passwd;
1374 if(!sshc->passphrase)
1375 sshc->passphrase = "";
1376
1377 if(sshc->rsa_pub)
1378 infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
1379 infof(data, "Using SSH private key file '%s'", sshc->rsa);
1380
1381 state(data, SSH_AUTH_PKEY);
1382 }
1383 else {
1384 state(data, SSH_AUTH_PASS_INIT);
1385 }
1386 return CURLE_OK;
1387 }
1388
1389 static CURLcode
sftp_quote_stat(struct Curl_easy * data,struct ssh_conn * sshc,struct SSHPROTO * sshp,bool * blockp)1390 sftp_quote_stat(struct Curl_easy *data,
1391 struct ssh_conn *sshc,
1392 struct SSHPROTO *sshp,
1393 bool *blockp)
1394 {
1395 char *cmd = sshc->quote_item->data;
1396 sshc->acceptfail = FALSE;
1397
1398 /* if a command starts with an asterisk, which a legal SFTP command never
1399 can, the command will be allowed to fail without it causing any aborts or
1400 cancels etc. It will cause libcurl to act as if the command is
1401 successful, whatever the server responds. */
1402
1403 if(cmd[0] == '*') {
1404 cmd++;
1405 sshc->acceptfail = TRUE;
1406 }
1407
1408 if(!strncasecompare(cmd, "chmod", 5)) {
1409 /* Since chown and chgrp only set owner OR group but libssh2 wants to set
1410 * them both at once, we need to obtain the current ownership first. This
1411 * takes an extra protocol round trip.
1412 */
1413 int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1414 curlx_uztoui(strlen(sshc->quote_path2)),
1415 LIBSSH2_SFTP_STAT,
1416 &sshp->quote_attrs);
1417 if(rc == LIBSSH2_ERROR_EAGAIN) {
1418 *blockp = TRUE;
1419 return CURLE_OK;
1420 }
1421 if(rc && !sshc->acceptfail) { /* get those attributes */
1422 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1423 failf(data, "Attempt to get SFTP stats failed: %s",
1424 sftp_libssh2_strerror(sftperr));
1425 goto fail;
1426 }
1427 }
1428
1429 /* Now set the new attributes... */
1430 if(strncasecompare(cmd, "chgrp", 5)) {
1431 sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
1432 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1433 if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1434 !sshc->acceptfail) {
1435 failf(data, "Syntax error: chgrp gid not a number");
1436 goto fail;
1437 }
1438 }
1439 else if(strncasecompare(cmd, "chmod", 5)) {
1440 sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
1441 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1442 /* permissions are octal */
1443 if(sshp->quote_attrs.permissions == 0 &&
1444 !ISDIGIT(sshc->quote_path1[0])) {
1445 failf(data, "Syntax error: chmod permissions not a number");
1446 goto fail;
1447 }
1448 }
1449 else if(strncasecompare(cmd, "chown", 5)) {
1450 sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
1451 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1452 if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
1453 !sshc->acceptfail) {
1454 failf(data, "Syntax error: chown uid not a number");
1455 goto fail;
1456 }
1457 }
1458 else if(strncasecompare(cmd, "atime", 5) ||
1459 strncasecompare(cmd, "mtime", 5)) {
1460 time_t date = Curl_getdate_capped(sshc->quote_path1);
1461 bool fail = FALSE;
1462
1463 if(date == -1) {
1464 failf(data, "incorrect date format for %.*s", 5, cmd);
1465 fail = TRUE;
1466 }
1467 #if SIZEOF_TIME_T > SIZEOF_LONG
1468 if(date > 0xffffffff) {
1469 /* if 'long' cannot old >32-bit, this date cannot be sent */
1470 failf(data, "date overflow");
1471 fail = TRUE;
1472 }
1473 #endif
1474 if(fail)
1475 goto fail;
1476 if(strncasecompare(cmd, "atime", 5))
1477 sshp->quote_attrs.atime = (unsigned long)date;
1478 else /* mtime */
1479 sshp->quote_attrs.mtime = (unsigned long)date;
1480
1481 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
1482 }
1483
1484 /* Now send the completed structure... */
1485 state(data, SSH_SFTP_QUOTE_SETSTAT);
1486 return CURLE_OK;
1487 fail:
1488 Curl_safefree(sshc->quote_path1);
1489 Curl_safefree(sshc->quote_path2);
1490 return CURLE_QUOTE_ERROR;
1491 }
1492
1493 static CURLcode
sftp_download_stat(struct Curl_easy * data,struct ssh_conn * sshc,struct SSHPROTO * sshp,bool * blockp)1494 sftp_download_stat(struct Curl_easy *data,
1495 struct ssh_conn *sshc,
1496 struct SSHPROTO *sshp,
1497 bool *blockp)
1498 {
1499 LIBSSH2_SFTP_ATTRIBUTES attrs;
1500 int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
1501 curlx_uztoui(strlen(sshp->path)),
1502 LIBSSH2_SFTP_STAT, &attrs);
1503 if(rc == LIBSSH2_ERROR_EAGAIN) {
1504 *blockp = TRUE;
1505 return CURLE_OK;
1506 }
1507 if(rc ||
1508 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
1509 (attrs.filesize == 0)) {
1510 /*
1511 * libssh2_sftp_open() did not return an error, so maybe the server
1512 * just does not support stat()
1513 * OR the server does not return a file size with a stat()
1514 * OR file size is 0
1515 */
1516 data->req.size = -1;
1517 data->req.maxdownload = -1;
1518 Curl_pgrsSetDownloadSize(data, -1);
1519 }
1520 else {
1521 curl_off_t size = attrs.filesize;
1522
1523 if(size < 0) {
1524 failf(data, "Bad file size (%" FMT_OFF_T ")", size);
1525 return CURLE_BAD_DOWNLOAD_RESUME;
1526 }
1527 if(data->state.use_range) {
1528 curl_off_t from, to;
1529 char *ptr;
1530 char *ptr2;
1531 CURLofft to_t;
1532 CURLofft from_t;
1533
1534 from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
1535 if(from_t == CURL_OFFT_FLOW)
1536 return CURLE_RANGE_ERROR;
1537 while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
1538 ptr++;
1539 to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
1540 if(to_t == CURL_OFFT_FLOW)
1541 return CURLE_RANGE_ERROR;
1542 if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
1543 || (to >= size)) {
1544 to = size - 1;
1545 }
1546 if(from_t) {
1547 /* from is relative to end of file */
1548 from = size - to;
1549 to = size - 1;
1550 }
1551 if(from > size) {
1552 failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
1553 FMT_OFF_T ")", from, (curl_off_t)attrs.filesize);
1554 return CURLE_BAD_DOWNLOAD_RESUME;
1555 }
1556 if(from > to) {
1557 from = to;
1558 size = 0;
1559 }
1560 else {
1561 if((to - from) == CURL_OFF_T_MAX)
1562 return CURLE_RANGE_ERROR;
1563 size = to - from + 1;
1564 }
1565
1566 SFTP_SEEK(sshc->sftp_handle, from);
1567 }
1568 data->req.size = size;
1569 data->req.maxdownload = size;
1570 Curl_pgrsSetDownloadSize(data, size);
1571 }
1572
1573 /* We can resume if we can seek to the resume position */
1574 if(data->state.resume_from) {
1575 if(data->state.resume_from < 0) {
1576 /* We are supposed to download the last abs(from) bytes */
1577 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
1578 failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
1579 FMT_OFF_T ")",
1580 data->state.resume_from, (curl_off_t)attrs.filesize);
1581 return CURLE_BAD_DOWNLOAD_RESUME;
1582 }
1583 /* download from where? */
1584 data->state.resume_from += attrs.filesize;
1585 }
1586 else {
1587 if((curl_off_t)attrs.filesize < data->state.resume_from) {
1588 failf(data, "Offset (%" FMT_OFF_T
1589 ") was beyond file size (%" FMT_OFF_T ")",
1590 data->state.resume_from, (curl_off_t)attrs.filesize);
1591 return CURLE_BAD_DOWNLOAD_RESUME;
1592 }
1593 }
1594 /* Now store the number of bytes we are expected to download */
1595 data->req.size = attrs.filesize - data->state.resume_from;
1596 data->req.maxdownload = attrs.filesize - data->state.resume_from;
1597 Curl_pgrsSetDownloadSize(data,
1598 attrs.filesize - data->state.resume_from);
1599 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1600 }
1601
1602 /* Setup the actual download */
1603 if(data->req.size == 0) {
1604 /* no data to transfer */
1605 Curl_xfer_setup_nop(data);
1606 infof(data, "File already completely downloaded");
1607 state(data, SSH_STOP);
1608 return CURLE_OK;
1609 }
1610 Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
1611
1612 /* not set by Curl_xfer_setup to preserve keepon bits */
1613 data->conn->writesockfd = data->conn->sockfd;
1614
1615 /* we want to use the _receiving_ function even when the socket turns
1616 out writableable as the underlying libssh2 recv function will deal
1617 with both accordingly */
1618 data->state.select_bits = CURL_CSELECT_IN;
1619 state(data, SSH_STOP);
1620
1621 return CURLE_OK;
1622 }
1623
sftp_readdir(struct Curl_easy * data,struct ssh_conn * sshc,struct SSHPROTO * sshp,bool * blockp)1624 static CURLcode sftp_readdir(struct Curl_easy *data,
1625 struct ssh_conn *sshc,
1626 struct SSHPROTO *sshp,
1627 bool *blockp)
1628 {
1629 CURLcode result = CURLE_OK;
1630 int rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
1631 sshp->readdir_filename, CURL_PATH_MAX,
1632 sshp->readdir_longentry, CURL_PATH_MAX,
1633 &sshp->readdir_attrs);
1634 if(rc == LIBSSH2_ERROR_EAGAIN) {
1635 *blockp = TRUE;
1636 return result;
1637 }
1638 if(rc > 0) {
1639 size_t readdir_len = (size_t) rc;
1640 sshp->readdir_filename[readdir_len] = '\0';
1641
1642 if(data->set.list_only) {
1643 result = Curl_client_write(data, CLIENTWRITE_BODY,
1644 sshp->readdir_filename,
1645 readdir_len);
1646 if(!result)
1647 result = Curl_client_write(data, CLIENTWRITE_BODY,
1648 (char *)"\n", 1);
1649 if(result)
1650 return result;
1651 }
1652 else {
1653 result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
1654
1655 if(!result) {
1656 if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
1657 ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
1658 LIBSSH2_SFTP_S_IFLNK)) {
1659 Curl_dyn_init(&sshp->readdir_link, CURL_PATH_MAX);
1660 result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
1661 sshp->readdir_filename);
1662 state(data, SSH_SFTP_READDIR_LINK);
1663 }
1664 else {
1665 state(data, SSH_SFTP_READDIR_BOTTOM);
1666 }
1667 }
1668 return result;
1669 }
1670 }
1671 else if(rc == 0) {
1672 state(data, SSH_SFTP_READDIR_DONE);
1673 }
1674 else if(rc < 0) {
1675 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1676 result = sftp_libssh2_error_to_CURLE(sftperr);
1677 sshc->actualcode = result ? result : CURLE_SSH;
1678 failf(data, "Could not open remote file for reading: %s :: %d",
1679 sftp_libssh2_strerror(sftperr),
1680 libssh2_session_last_errno(sshc->ssh_session));
1681 state(data, SSH_SFTP_CLOSE);
1682 }
1683 return result;
1684 }
1685 /*
1686 * ssh_statemachine() runs the SSH state machine as far as it can without
1687 * blocking and without reaching the end. The data the pointer 'block' points
1688 * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
1689 * meaning it wants to be called again when the socket is ready
1690 */
1691
ssh_statemachine(struct Curl_easy * data,bool * block)1692 static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
1693 {
1694 CURLcode result = CURLE_OK;
1695 struct connectdata *conn = data->conn;
1696 struct SSHPROTO *sshp = data->req.p.ssh;
1697 struct ssh_conn *sshc = &conn->proto.sshc;
1698
1699 int rc = LIBSSH2_ERROR_NONE;
1700 *block = 0; /* we are not blocking by default */
1701
1702 do {
1703 switch(sshc->state) {
1704 case SSH_INIT:
1705 sshc->secondCreateDirs = 0;
1706 sshc->nextstate = SSH_NO_STATE;
1707 sshc->actualcode = CURLE_OK;
1708
1709 /* Set libssh2 to non-blocking, since everything internally is
1710 non-blocking */
1711 libssh2_session_set_blocking(sshc->ssh_session, 0);
1712
1713 result = ssh_force_knownhost_key_type(data);
1714 if(result) {
1715 state(data, SSH_SESSION_FREE);
1716 sshc->actualcode = result;
1717 break;
1718 }
1719
1720 state(data, SSH_S_STARTUP);
1721 FALLTHROUGH();
1722
1723 case SSH_S_STARTUP:
1724 rc = session_startup(sshc->ssh_session, conn->sock[FIRSTSOCKET]);
1725 if(rc == LIBSSH2_ERROR_EAGAIN) {
1726 break;
1727 }
1728 if(rc) {
1729 char *err_msg = NULL;
1730 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
1731 failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
1732
1733 state(data, SSH_SESSION_FREE);
1734 sshc->actualcode = CURLE_FAILED_INIT;
1735 break;
1736 }
1737
1738 state(data, SSH_HOSTKEY);
1739
1740 FALLTHROUGH();
1741 case SSH_HOSTKEY:
1742 /*
1743 * Before we authenticate we should check the hostkey's fingerprint
1744 * against our known hosts. How that is handled (reading from file,
1745 * whatever) is up to us.
1746 */
1747 result = ssh_check_fingerprint(data);
1748 if(!result)
1749 state(data, SSH_AUTHLIST);
1750 /* ssh_check_fingerprint sets state appropriately on error */
1751 break;
1752
1753 case SSH_AUTHLIST:
1754 /*
1755 * Figure out authentication methods
1756 * NB: As soon as we have provided a username to an openssh server we
1757 * must never change it later. Thus, always specify the correct username
1758 * here, even though the libssh2 docs kind of indicate that it should be
1759 * possible to get a 'generic' list (not user-specific) of authentication
1760 * methods, presumably with a blank username. That will not work in my
1761 * experience.
1762 * So always specify it here.
1763 */
1764 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
1765 conn->user,
1766 curlx_uztoui(strlen(conn->user)));
1767
1768 if(!sshc->authlist) {
1769 if(libssh2_userauth_authenticated(sshc->ssh_session)) {
1770 sshc->authed = TRUE;
1771 infof(data, "SSH user accepted with no authentication");
1772 state(data, SSH_AUTH_DONE);
1773 break;
1774 }
1775 rc = libssh2_session_last_errno(sshc->ssh_session);
1776 if(rc == LIBSSH2_ERROR_EAGAIN)
1777 rc = LIBSSH2_ERROR_EAGAIN;
1778 else {
1779 state(data, SSH_SESSION_FREE);
1780 sshc->actualcode = libssh2_session_error_to_CURLE(rc);
1781 }
1782 break;
1783 }
1784 infof(data, "SSH authentication methods available: %s",
1785 sshc->authlist);
1786
1787 state(data, SSH_AUTH_PKEY_INIT);
1788 break;
1789
1790 case SSH_AUTH_PKEY_INIT:
1791 result = sftp_pkey_init(data, sshc);
1792 break;
1793
1794 case SSH_AUTH_PKEY:
1795 /* The function below checks if the files exists, no need to stat() here.
1796 */
1797 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
1798 conn->user,
1799 curlx_uztoui(
1800 strlen(conn->user)),
1801 sshc->rsa_pub,
1802 sshc->rsa, sshc->passphrase);
1803 if(rc == LIBSSH2_ERROR_EAGAIN) {
1804 break;
1805 }
1806
1807 Curl_safefree(sshc->rsa_pub);
1808 Curl_safefree(sshc->rsa);
1809
1810 if(rc == 0) {
1811 sshc->authed = TRUE;
1812 infof(data, "Initialized SSH public key authentication");
1813 state(data, SSH_AUTH_DONE);
1814 }
1815 else {
1816 char *err_msg = NULL;
1817 char unknown[] = "Reason unknown (-1)";
1818 if(rc == -1) {
1819 /* No error message has been set and the last set error message, if
1820 any, is from a previous error so ignore it. #11837 */
1821 err_msg = unknown;
1822 }
1823 else {
1824 (void)libssh2_session_last_error(sshc->ssh_session,
1825 &err_msg, NULL, 0);
1826 }
1827 infof(data, "SSH public key authentication failed: %s", err_msg);
1828 state(data, SSH_AUTH_PASS_INIT);
1829 rc = 0; /* clear rc and continue */
1830 }
1831 break;
1832
1833 case SSH_AUTH_PASS_INIT:
1834 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
1835 (strstr(sshc->authlist, "password") != NULL)) {
1836 state(data, SSH_AUTH_PASS);
1837 }
1838 else {
1839 state(data, SSH_AUTH_HOST_INIT);
1840 rc = 0; /* clear rc and continue */
1841 }
1842 break;
1843
1844 case SSH_AUTH_PASS:
1845 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
1846 curlx_uztoui(strlen(conn->user)),
1847 conn->passwd,
1848 curlx_uztoui(strlen(conn->passwd)),
1849 NULL);
1850 if(rc == LIBSSH2_ERROR_EAGAIN) {
1851 break;
1852 }
1853 if(rc == 0) {
1854 sshc->authed = TRUE;
1855 infof(data, "Initialized password authentication");
1856 state(data, SSH_AUTH_DONE);
1857 }
1858 else {
1859 state(data, SSH_AUTH_HOST_INIT);
1860 rc = 0; /* clear rc and continue */
1861 }
1862 break;
1863
1864 case SSH_AUTH_HOST_INIT:
1865 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
1866 (strstr(sshc->authlist, "hostbased") != NULL)) {
1867 state(data, SSH_AUTH_HOST);
1868 }
1869 else {
1870 state(data, SSH_AUTH_AGENT_INIT);
1871 }
1872 break;
1873
1874 case SSH_AUTH_HOST:
1875 state(data, SSH_AUTH_AGENT_INIT);
1876 break;
1877
1878 case SSH_AUTH_AGENT_INIT:
1879 #ifdef HAVE_LIBSSH2_AGENT_API
1880 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
1881 && (strstr(sshc->authlist, "publickey") != NULL)) {
1882
1883 /* Connect to the ssh-agent */
1884 /* The agent could be shared by a curl thread i believe
1885 but nothing obvious as keys can be added/removed at any time */
1886 if(!sshc->ssh_agent) {
1887 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
1888 if(!sshc->ssh_agent) {
1889 infof(data, "Could not create agent object");
1890
1891 state(data, SSH_AUTH_KEY_INIT);
1892 break;
1893 }
1894 }
1895
1896 rc = libssh2_agent_connect(sshc->ssh_agent);
1897 if(rc == LIBSSH2_ERROR_EAGAIN)
1898 break;
1899 if(rc < 0) {
1900 infof(data, "Failure connecting to agent");
1901 state(data, SSH_AUTH_KEY_INIT);
1902 rc = 0; /* clear rc and continue */
1903 }
1904 else {
1905 state(data, SSH_AUTH_AGENT_LIST);
1906 }
1907 }
1908 else
1909 #endif /* HAVE_LIBSSH2_AGENT_API */
1910 state(data, SSH_AUTH_KEY_INIT);
1911 break;
1912
1913 case SSH_AUTH_AGENT_LIST:
1914 #ifdef HAVE_LIBSSH2_AGENT_API
1915 rc = libssh2_agent_list_identities(sshc->ssh_agent);
1916
1917 if(rc == LIBSSH2_ERROR_EAGAIN)
1918 break;
1919 if(rc < 0) {
1920 infof(data, "Failure requesting identities to agent");
1921 state(data, SSH_AUTH_KEY_INIT);
1922 rc = 0; /* clear rc and continue */
1923 }
1924 else {
1925 state(data, SSH_AUTH_AGENT);
1926 sshc->sshagent_prev_identity = NULL;
1927 }
1928 #endif
1929 break;
1930
1931 case SSH_AUTH_AGENT:
1932 #ifdef HAVE_LIBSSH2_AGENT_API
1933 /* as prev_identity evolves only after an identity user auth finished we
1934 can safely request it again as long as EAGAIN is returned here or by
1935 libssh2_agent_userauth */
1936 rc = libssh2_agent_get_identity(sshc->ssh_agent,
1937 &sshc->sshagent_identity,
1938 sshc->sshagent_prev_identity);
1939 if(rc == LIBSSH2_ERROR_EAGAIN)
1940 break;
1941
1942 if(rc == 0) {
1943 rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
1944 sshc->sshagent_identity);
1945
1946 if(rc < 0) {
1947 if(rc != LIBSSH2_ERROR_EAGAIN) {
1948 /* tried and failed? go to next identity */
1949 sshc->sshagent_prev_identity = sshc->sshagent_identity;
1950 }
1951 break;
1952 }
1953 }
1954
1955 if(rc < 0)
1956 infof(data, "Failure requesting identities to agent");
1957 else if(rc == 1)
1958 infof(data, "No identity would match");
1959
1960 if(rc == LIBSSH2_ERROR_NONE) {
1961 sshc->authed = TRUE;
1962 infof(data, "Agent based authentication successful");
1963 state(data, SSH_AUTH_DONE);
1964 }
1965 else {
1966 state(data, SSH_AUTH_KEY_INIT);
1967 rc = 0; /* clear rc and continue */
1968 }
1969 #endif
1970 break;
1971
1972 case SSH_AUTH_KEY_INIT:
1973 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
1974 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
1975 state(data, SSH_AUTH_KEY);
1976 }
1977 else {
1978 state(data, SSH_AUTH_DONE);
1979 }
1980 break;
1981
1982 case SSH_AUTH_KEY:
1983 /* Authentication failed. Continue with keyboard-interactive now. */
1984 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
1985 conn->user,
1986 curlx_uztoui(
1987 strlen(conn->user)),
1988 &kbd_callback);
1989 if(rc == LIBSSH2_ERROR_EAGAIN) {
1990 break;
1991 }
1992 if(rc == 0) {
1993 sshc->authed = TRUE;
1994 infof(data, "Initialized keyboard interactive authentication");
1995 }
1996 state(data, SSH_AUTH_DONE);
1997 break;
1998
1999 case SSH_AUTH_DONE:
2000 if(!sshc->authed) {
2001 failf(data, "Authentication failure");
2002 state(data, SSH_SESSION_FREE);
2003 sshc->actualcode = CURLE_LOGIN_DENIED;
2004 break;
2005 }
2006
2007 /*
2008 * At this point we have an authenticated ssh session.
2009 */
2010 infof(data, "Authentication complete");
2011
2012 Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
2013
2014 conn->sockfd = conn->sock[FIRSTSOCKET];
2015 conn->writesockfd = CURL_SOCKET_BAD;
2016
2017 if(conn->handler->protocol == CURLPROTO_SFTP) {
2018 state(data, SSH_SFTP_INIT);
2019 break;
2020 }
2021 infof(data, "SSH CONNECT phase done");
2022 state(data, SSH_STOP);
2023 break;
2024
2025 case SSH_SFTP_INIT:
2026 /*
2027 * Start the libssh2 sftp session
2028 */
2029 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
2030 if(!sshc->sftp_session) {
2031 char *err_msg = NULL;
2032 if(libssh2_session_last_errno(sshc->ssh_session) ==
2033 LIBSSH2_ERROR_EAGAIN) {
2034 rc = LIBSSH2_ERROR_EAGAIN;
2035 break;
2036 }
2037
2038 (void)libssh2_session_last_error(sshc->ssh_session,
2039 &err_msg, NULL, 0);
2040 failf(data, "Failure initializing sftp session: %s", err_msg);
2041 state(data, SSH_SESSION_FREE);
2042 sshc->actualcode = CURLE_FAILED_INIT;
2043 break;
2044 }
2045 state(data, SSH_SFTP_REALPATH);
2046 break;
2047
2048 case SSH_SFTP_REALPATH:
2049 /*
2050 * Get the "home" directory
2051 */
2052 rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
2053 sshp->readdir_filename, CURL_PATH_MAX);
2054 if(rc == LIBSSH2_ERROR_EAGAIN) {
2055 break;
2056 }
2057 if(rc > 0) {
2058 /* It seems that this string is not always NULL terminated */
2059 sshp->readdir_filename[rc] = '\0';
2060 sshc->homedir = strdup(sshp->readdir_filename);
2061 if(!sshc->homedir) {
2062 state(data, SSH_SFTP_CLOSE);
2063 sshc->actualcode = CURLE_OUT_OF_MEMORY;
2064 break;
2065 }
2066 data->state.most_recent_ftp_entrypath = sshc->homedir;
2067 }
2068 else {
2069 /* Return the error type */
2070 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2071 if(sftperr)
2072 result = sftp_libssh2_error_to_CURLE(sftperr);
2073 else
2074 /* in this case, the error was not in the SFTP level but for example
2075 a time-out or similar */
2076 result = CURLE_SSH;
2077 sshc->actualcode = result;
2078 DEBUGF(infof(data, "error = %lu makes libcurl = %d",
2079 sftperr, (int)result));
2080 state(data, SSH_STOP);
2081 break;
2082 }
2083
2084 /* This is the last step in the SFTP connect phase. Do note that while
2085 we get the homedir here, we get the "workingpath" in the DO action
2086 since the homedir will remain the same between request but the
2087 working path will not. */
2088 DEBUGF(infof(data, "SSH CONNECT phase done"));
2089 state(data, SSH_STOP);
2090 break;
2091
2092 case SSH_SFTP_QUOTE_INIT:
2093
2094 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
2095 if(result) {
2096 sshc->actualcode = result;
2097 state(data, SSH_STOP);
2098 break;
2099 }
2100
2101 if(data->set.quote) {
2102 infof(data, "Sending quote commands");
2103 sshc->quote_item = data->set.quote;
2104 state(data, SSH_SFTP_QUOTE);
2105 }
2106 else {
2107 state(data, SSH_SFTP_GETINFO);
2108 }
2109 break;
2110
2111 case SSH_SFTP_POSTQUOTE_INIT:
2112 if(data->set.postquote) {
2113 infof(data, "Sending quote commands");
2114 sshc->quote_item = data->set.postquote;
2115 state(data, SSH_SFTP_QUOTE);
2116 }
2117 else {
2118 state(data, SSH_STOP);
2119 }
2120 break;
2121
2122 case SSH_SFTP_QUOTE:
2123 /* Send quote commands */
2124 result = sftp_quote(data, sshc, sshp);
2125 if(result) {
2126 state(data, SSH_SFTP_CLOSE);
2127 sshc->nextstate = SSH_NO_STATE;
2128 sshc->actualcode = result;
2129 }
2130 break;
2131
2132 case SSH_SFTP_NEXT_QUOTE:
2133 Curl_safefree(sshc->quote_path1);
2134 Curl_safefree(sshc->quote_path2);
2135
2136 sshc->quote_item = sshc->quote_item->next;
2137
2138 if(sshc->quote_item) {
2139 state(data, SSH_SFTP_QUOTE);
2140 }
2141 else {
2142 if(sshc->nextstate != SSH_NO_STATE) {
2143 state(data, sshc->nextstate);
2144 sshc->nextstate = SSH_NO_STATE;
2145 }
2146 else {
2147 state(data, SSH_SFTP_GETINFO);
2148 }
2149 }
2150 break;
2151
2152 case SSH_SFTP_QUOTE_STAT:
2153 result = sftp_quote_stat(data, sshc, sshp, block);
2154 if(result) {
2155 state(data, SSH_SFTP_CLOSE);
2156 sshc->nextstate = SSH_NO_STATE;
2157 sshc->actualcode = result;
2158 }
2159 break;
2160
2161 case SSH_SFTP_QUOTE_SETSTAT:
2162 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
2163 curlx_uztoui(strlen(sshc->quote_path2)),
2164 LIBSSH2_SFTP_SETSTAT,
2165 &sshp->quote_attrs);
2166 if(rc == LIBSSH2_ERROR_EAGAIN) {
2167 break;
2168 }
2169 if(rc && !sshc->acceptfail) {
2170 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2171 Curl_safefree(sshc->quote_path1);
2172 Curl_safefree(sshc->quote_path2);
2173 failf(data, "Attempt to set SFTP stats failed: %s",
2174 sftp_libssh2_strerror(sftperr));
2175 state(data, SSH_SFTP_CLOSE);
2176 sshc->nextstate = SSH_NO_STATE;
2177 sshc->actualcode = CURLE_QUOTE_ERROR;
2178 break;
2179 }
2180 state(data, SSH_SFTP_NEXT_QUOTE);
2181 break;
2182
2183 case SSH_SFTP_QUOTE_SYMLINK:
2184 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
2185 curlx_uztoui(strlen(sshc->quote_path1)),
2186 sshc->quote_path2,
2187 curlx_uztoui(strlen(sshc->quote_path2)),
2188 LIBSSH2_SFTP_SYMLINK);
2189 if(rc == LIBSSH2_ERROR_EAGAIN) {
2190 break;
2191 }
2192 if(rc && !sshc->acceptfail) {
2193 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2194 Curl_safefree(sshc->quote_path1);
2195 Curl_safefree(sshc->quote_path2);
2196 failf(data, "symlink command failed: %s",
2197 sftp_libssh2_strerror(sftperr));
2198 state(data, SSH_SFTP_CLOSE);
2199 sshc->nextstate = SSH_NO_STATE;
2200 sshc->actualcode = CURLE_QUOTE_ERROR;
2201 break;
2202 }
2203 state(data, SSH_SFTP_NEXT_QUOTE);
2204 break;
2205
2206 case SSH_SFTP_QUOTE_MKDIR:
2207 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
2208 curlx_uztoui(strlen(sshc->quote_path1)),
2209 (long)data->set.new_directory_perms);
2210 if(rc == LIBSSH2_ERROR_EAGAIN) {
2211 break;
2212 }
2213 if(rc && !sshc->acceptfail) {
2214 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2215 Curl_safefree(sshc->quote_path1);
2216 failf(data, "mkdir command failed: %s",
2217 sftp_libssh2_strerror(sftperr));
2218 state(data, SSH_SFTP_CLOSE);
2219 sshc->nextstate = SSH_NO_STATE;
2220 sshc->actualcode = CURLE_QUOTE_ERROR;
2221 break;
2222 }
2223 state(data, SSH_SFTP_NEXT_QUOTE);
2224 break;
2225
2226 case SSH_SFTP_QUOTE_RENAME:
2227 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
2228 curlx_uztoui(strlen(sshc->quote_path1)),
2229 sshc->quote_path2,
2230 curlx_uztoui(strlen(sshc->quote_path2)),
2231 LIBSSH2_SFTP_RENAME_OVERWRITE |
2232 LIBSSH2_SFTP_RENAME_ATOMIC |
2233 LIBSSH2_SFTP_RENAME_NATIVE);
2234
2235 if(rc == LIBSSH2_ERROR_EAGAIN) {
2236 break;
2237 }
2238 if(rc && !sshc->acceptfail) {
2239 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2240 Curl_safefree(sshc->quote_path1);
2241 Curl_safefree(sshc->quote_path2);
2242 failf(data, "rename command failed: %s",
2243 sftp_libssh2_strerror(sftperr));
2244 state(data, SSH_SFTP_CLOSE);
2245 sshc->nextstate = SSH_NO_STATE;
2246 sshc->actualcode = CURLE_QUOTE_ERROR;
2247 break;
2248 }
2249 state(data, SSH_SFTP_NEXT_QUOTE);
2250 break;
2251
2252 case SSH_SFTP_QUOTE_RMDIR:
2253 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
2254 curlx_uztoui(strlen(sshc->quote_path1)));
2255 if(rc == LIBSSH2_ERROR_EAGAIN) {
2256 break;
2257 }
2258 if(rc && !sshc->acceptfail) {
2259 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2260 Curl_safefree(sshc->quote_path1);
2261 failf(data, "rmdir command failed: %s",
2262 sftp_libssh2_strerror(sftperr));
2263 state(data, SSH_SFTP_CLOSE);
2264 sshc->nextstate = SSH_NO_STATE;
2265 sshc->actualcode = CURLE_QUOTE_ERROR;
2266 break;
2267 }
2268 state(data, SSH_SFTP_NEXT_QUOTE);
2269 break;
2270
2271 case SSH_SFTP_QUOTE_UNLINK:
2272 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
2273 curlx_uztoui(strlen(sshc->quote_path1)));
2274 if(rc == LIBSSH2_ERROR_EAGAIN) {
2275 break;
2276 }
2277 if(rc && !sshc->acceptfail) {
2278 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2279 Curl_safefree(sshc->quote_path1);
2280 failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
2281 state(data, SSH_SFTP_CLOSE);
2282 sshc->nextstate = SSH_NO_STATE;
2283 sshc->actualcode = CURLE_QUOTE_ERROR;
2284 break;
2285 }
2286 state(data, SSH_SFTP_NEXT_QUOTE);
2287 break;
2288
2289 #ifdef HAS_STATVFS_SUPPORT
2290 case SSH_SFTP_QUOTE_STATVFS:
2291 {
2292 LIBSSH2_SFTP_STATVFS statvfs;
2293 rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
2294 curlx_uztoui(strlen(sshc->quote_path1)),
2295 &statvfs);
2296
2297 if(rc == LIBSSH2_ERROR_EAGAIN) {
2298 break;
2299 }
2300 if(rc && !sshc->acceptfail) {
2301 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2302 Curl_safefree(sshc->quote_path1);
2303 failf(data, "statvfs command failed: %s",
2304 sftp_libssh2_strerror(sftperr));
2305 state(data, SSH_SFTP_CLOSE);
2306 sshc->nextstate = SSH_NO_STATE;
2307 sshc->actualcode = CURLE_QUOTE_ERROR;
2308 break;
2309 }
2310 else if(rc == 0) {
2311 #ifdef _MSC_VER
2312 #define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
2313 #else
2314 #define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
2315 #endif
2316 char *tmp = aprintf("statvfs:\n"
2317 "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2318 "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2319 "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2320 "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2321 "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2322 "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2323 "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2324 "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2325 "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2326 "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2327 "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
2328 statvfs.f_bsize, statvfs.f_frsize,
2329 statvfs.f_blocks, statvfs.f_bfree,
2330 statvfs.f_bavail, statvfs.f_files,
2331 statvfs.f_ffree, statvfs.f_favail,
2332 statvfs.f_fsid, statvfs.f_flag,
2333 statvfs.f_namemax);
2334 if(!tmp) {
2335 result = CURLE_OUT_OF_MEMORY;
2336 state(data, SSH_SFTP_CLOSE);
2337 sshc->nextstate = SSH_NO_STATE;
2338 break;
2339 }
2340
2341 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
2342 free(tmp);
2343 if(result) {
2344 state(data, SSH_SFTP_CLOSE);
2345 sshc->nextstate = SSH_NO_STATE;
2346 sshc->actualcode = result;
2347 }
2348 }
2349 state(data, SSH_SFTP_NEXT_QUOTE);
2350 break;
2351 }
2352 #endif
2353 case SSH_SFTP_GETINFO:
2354 {
2355 if(data->set.get_filetime) {
2356 state(data, SSH_SFTP_FILETIME);
2357 }
2358 else {
2359 state(data, SSH_SFTP_TRANS_INIT);
2360 }
2361 break;
2362 }
2363
2364 case SSH_SFTP_FILETIME:
2365 {
2366 LIBSSH2_SFTP_ATTRIBUTES attrs;
2367
2368 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2369 curlx_uztoui(strlen(sshp->path)),
2370 LIBSSH2_SFTP_STAT, &attrs);
2371 if(rc == LIBSSH2_ERROR_EAGAIN) {
2372 break;
2373 }
2374 if(rc == 0) {
2375 data->info.filetime = (time_t)attrs.mtime;
2376 }
2377
2378 state(data, SSH_SFTP_TRANS_INIT);
2379 break;
2380 }
2381
2382 case SSH_SFTP_TRANS_INIT:
2383 if(data->state.upload)
2384 state(data, SSH_SFTP_UPLOAD_INIT);
2385 else {
2386 if(sshp->path[strlen(sshp->path)-1] == '/')
2387 state(data, SSH_SFTP_READDIR_INIT);
2388 else
2389 state(data, SSH_SFTP_DOWNLOAD_INIT);
2390 }
2391 break;
2392
2393 case SSH_SFTP_UPLOAD_INIT:
2394 result = sftp_upload_init(data, sshc, sshp, block);
2395 if(result) {
2396 state(data, SSH_SFTP_CLOSE);
2397 sshc->nextstate = SSH_NO_STATE;
2398 sshc->actualcode = result;
2399 }
2400 break;
2401
2402 case SSH_SFTP_CREATE_DIRS_INIT:
2403 if(strlen(sshp->path) > 1) {
2404 sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
2405 state(data, SSH_SFTP_CREATE_DIRS);
2406 }
2407 else {
2408 state(data, SSH_SFTP_UPLOAD_INIT);
2409 }
2410 break;
2411
2412 case SSH_SFTP_CREATE_DIRS:
2413 sshc->slash_pos = strchr(sshc->slash_pos, '/');
2414 if(sshc->slash_pos) {
2415 *sshc->slash_pos = 0;
2416
2417 infof(data, "Creating directory '%s'", sshp->path);
2418 state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
2419 break;
2420 }
2421 state(data, SSH_SFTP_UPLOAD_INIT);
2422 break;
2423
2424 case SSH_SFTP_CREATE_DIRS_MKDIR:
2425 /* 'mode' - parameter is preliminary - default to 0644 */
2426 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
2427 curlx_uztoui(strlen(sshp->path)),
2428 (long)data->set.new_directory_perms);
2429 if(rc == LIBSSH2_ERROR_EAGAIN) {
2430 break;
2431 }
2432 *sshc->slash_pos = '/';
2433 ++sshc->slash_pos;
2434 if(rc < 0) {
2435 /*
2436 * Abort if failure was not that the dir already exists or the
2437 * permission was denied (creation might succeed further down the
2438 * path) - retry on unspecific FAILURE also
2439 */
2440 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2441 if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
2442 (sftperr != LIBSSH2_FX_FAILURE) &&
2443 (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
2444 result = sftp_libssh2_error_to_CURLE(sftperr);
2445 state(data, SSH_SFTP_CLOSE);
2446 sshc->actualcode = result ? result : CURLE_SSH;
2447 break;
2448 }
2449 rc = 0; /* clear rc and continue */
2450 }
2451 state(data, SSH_SFTP_CREATE_DIRS);
2452 break;
2453
2454 case SSH_SFTP_READDIR_INIT:
2455 Curl_pgrsSetDownloadSize(data, -1);
2456 if(data->req.no_body) {
2457 state(data, SSH_STOP);
2458 break;
2459 }
2460
2461 /*
2462 * This is a directory that we are trying to get, so produce a directory
2463 * listing
2464 */
2465 sshc->sftp_handle =
2466 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2467 curlx_uztoui(strlen(sshp->path)),
2468 0, 0, LIBSSH2_SFTP_OPENDIR);
2469 if(!sshc->sftp_handle) {
2470 unsigned long sftperr;
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 directory 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 Curl_dyn_init(&sshp->readdir, CURL_PATH_MAX * 2);
2485 state(data, SSH_SFTP_READDIR);
2486 break;
2487
2488 case SSH_SFTP_READDIR:
2489 result = sftp_readdir(data, sshc, sshp, block);
2490 if(result) {
2491 sshc->actualcode = result;
2492 state(data, SSH_SFTP_CLOSE);
2493 }
2494 break;
2495
2496 case SSH_SFTP_READDIR_LINK:
2497 rc =
2498 libssh2_sftp_symlink_ex(sshc->sftp_session,
2499 Curl_dyn_ptr(&sshp->readdir_link),
2500 (unsigned int)
2501 Curl_dyn_len(&sshp->readdir_link),
2502 sshp->readdir_filename,
2503 CURL_PATH_MAX, LIBSSH2_SFTP_READLINK);
2504 if(rc == LIBSSH2_ERROR_EAGAIN) {
2505 break;
2506 }
2507 Curl_dyn_free(&sshp->readdir_link);
2508
2509 /* append filename and extra output */
2510 result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
2511
2512 if(result) {
2513 state(data, SSH_SFTP_CLOSE);
2514 sshc->actualcode = result;
2515 break;
2516 }
2517
2518 state(data, SSH_SFTP_READDIR_BOTTOM);
2519 break;
2520
2521 case SSH_SFTP_READDIR_BOTTOM:
2522 result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
2523 if(!result)
2524 result = Curl_client_write(data, CLIENTWRITE_BODY,
2525 Curl_dyn_ptr(&sshp->readdir),
2526 Curl_dyn_len(&sshp->readdir));
2527
2528 if(result) {
2529 Curl_dyn_free(&sshp->readdir);
2530 state(data, SSH_STOP);
2531 }
2532 else {
2533 Curl_dyn_reset(&sshp->readdir);
2534 state(data, SSH_SFTP_READDIR);
2535 }
2536 break;
2537
2538 case SSH_SFTP_READDIR_DONE:
2539 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2540 LIBSSH2_ERROR_EAGAIN) {
2541 rc = LIBSSH2_ERROR_EAGAIN;
2542 break;
2543 }
2544 sshc->sftp_handle = NULL;
2545
2546 /* no data to transfer */
2547 Curl_xfer_setup_nop(data);
2548 state(data, SSH_STOP);
2549 break;
2550
2551 case SSH_SFTP_DOWNLOAD_INIT:
2552 /*
2553 * Work on getting the specified file
2554 */
2555 sshc->sftp_handle =
2556 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2557 curlx_uztoui(strlen(sshp->path)),
2558 LIBSSH2_FXF_READ, (long)data->set.new_file_perms,
2559 LIBSSH2_SFTP_OPENFILE);
2560 if(!sshc->sftp_handle) {
2561 unsigned long sftperr;
2562 if(libssh2_session_last_errno(sshc->ssh_session) ==
2563 LIBSSH2_ERROR_EAGAIN) {
2564 rc = LIBSSH2_ERROR_EAGAIN;
2565 break;
2566 }
2567 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2568 failf(data, "Could not open remote file for reading: %s",
2569 sftp_libssh2_strerror(sftperr));
2570 state(data, SSH_SFTP_CLOSE);
2571 result = sftp_libssh2_error_to_CURLE(sftperr);
2572 sshc->actualcode = result ? result : CURLE_SSH;
2573 break;
2574 }
2575 state(data, SSH_SFTP_DOWNLOAD_STAT);
2576 break;
2577
2578 case SSH_SFTP_DOWNLOAD_STAT:
2579 result = sftp_download_stat(data, sshc, sshp, block);
2580 if(result) {
2581 state(data, SSH_SFTP_CLOSE);
2582 sshc->nextstate = SSH_NO_STATE;
2583 sshc->actualcode = result;
2584 }
2585 break;
2586
2587 case SSH_SFTP_CLOSE:
2588 if(sshc->sftp_handle) {
2589 rc = libssh2_sftp_close(sshc->sftp_handle);
2590 if(rc == LIBSSH2_ERROR_EAGAIN) {
2591 break;
2592 }
2593 if(rc < 0) {
2594 char *err_msg = NULL;
2595 (void)libssh2_session_last_error(sshc->ssh_session,
2596 &err_msg, NULL, 0);
2597 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2598 }
2599 sshc->sftp_handle = NULL;
2600 }
2601
2602 Curl_safefree(sshp->path);
2603
2604 DEBUGF(infof(data, "SFTP DONE done"));
2605
2606 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2607 After nextstate is executed, the control should come back to
2608 SSH_SFTP_CLOSE to pass the correct result back */
2609 if(sshc->nextstate != SSH_NO_STATE &&
2610 sshc->nextstate != SSH_SFTP_CLOSE) {
2611 state(data, sshc->nextstate);
2612 sshc->nextstate = SSH_SFTP_CLOSE;
2613 }
2614 else {
2615 state(data, SSH_STOP);
2616 result = sshc->actualcode;
2617 }
2618 break;
2619
2620 case SSH_SFTP_SHUTDOWN:
2621 /* during times we get here due to a broken transfer and then the
2622 sftp_handle might not have been taken down so make sure that is done
2623 before we proceed */
2624
2625 if(sshc->sftp_handle) {
2626 rc = libssh2_sftp_close(sshc->sftp_handle);
2627 if(rc == LIBSSH2_ERROR_EAGAIN) {
2628 break;
2629 }
2630 if(rc < 0) {
2631 char *err_msg = NULL;
2632 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
2633 NULL, 0);
2634 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2635 }
2636 sshc->sftp_handle = NULL;
2637 }
2638 if(sshc->sftp_session) {
2639 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2640 if(rc == LIBSSH2_ERROR_EAGAIN) {
2641 break;
2642 }
2643 if(rc < 0) {
2644 infof(data, "Failed to stop libssh2 sftp subsystem");
2645 }
2646 sshc->sftp_session = NULL;
2647 }
2648
2649 Curl_safefree(sshc->homedir);
2650 data->state.most_recent_ftp_entrypath = NULL;
2651
2652 state(data, SSH_SESSION_DISCONNECT);
2653 break;
2654
2655 case SSH_SCP_TRANS_INIT:
2656 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
2657 if(result) {
2658 sshc->actualcode = result;
2659 state(data, SSH_STOP);
2660 break;
2661 }
2662
2663 if(data->state.upload) {
2664 if(data->state.infilesize < 0) {
2665 failf(data, "SCP requires a known file size for upload");
2666 sshc->actualcode = CURLE_UPLOAD_FAILED;
2667 state(data, SSH_SCP_CHANNEL_FREE);
2668 break;
2669 }
2670 state(data, SSH_SCP_UPLOAD_INIT);
2671 }
2672 else {
2673 state(data, SSH_SCP_DOWNLOAD_INIT);
2674 }
2675 break;
2676
2677 case SSH_SCP_UPLOAD_INIT:
2678 /*
2679 * libssh2 requires that the destination path is a full path that
2680 * includes the destination file and name OR ends in a "/" . If this is
2681 * not done the destination file will be named the same name as the last
2682 * directory in the path.
2683 */
2684 sshc->ssh_channel =
2685 SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
2686 data->state.infilesize);
2687 if(!sshc->ssh_channel) {
2688 int ssh_err;
2689 char *err_msg = NULL;
2690
2691 if(libssh2_session_last_errno(sshc->ssh_session) ==
2692 LIBSSH2_ERROR_EAGAIN) {
2693 rc = LIBSSH2_ERROR_EAGAIN;
2694 break;
2695 }
2696
2697 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2698 &err_msg, NULL, 0));
2699 failf(data, "%s", err_msg);
2700 state(data, SSH_SCP_CHANNEL_FREE);
2701 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2702 /* Map generic errors to upload failed */
2703 if(sshc->actualcode == CURLE_SSH ||
2704 sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
2705 sshc->actualcode = CURLE_UPLOAD_FAILED;
2706 break;
2707 }
2708
2709 /* upload data */
2710 data->req.size = data->state.infilesize;
2711 Curl_pgrsSetUploadSize(data, data->state.infilesize);
2712 Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
2713
2714 /* not set by Curl_xfer_setup to preserve keepon bits */
2715 conn->sockfd = conn->writesockfd;
2716
2717 if(result) {
2718 state(data, SSH_SCP_CHANNEL_FREE);
2719 sshc->actualcode = result;
2720 }
2721 else {
2722 /* store this original bitmask setup to use later on if we cannot
2723 figure out a "real" bitmask */
2724 sshc->orig_waitfor = data->req.keepon;
2725
2726 /* we want to use the _sending_ function even when the socket turns
2727 out readable as the underlying libssh2 scp send function will deal
2728 with both accordingly */
2729 data->state.select_bits = CURL_CSELECT_OUT;
2730
2731 state(data, SSH_STOP);
2732 }
2733 break;
2734
2735 case SSH_SCP_DOWNLOAD_INIT:
2736 {
2737 curl_off_t bytecount;
2738
2739 /*
2740 * We must check the remote file; if it is a directory no values will
2741 * be set in sb
2742 */
2743
2744 /*
2745 * If support for >2GB files exists, use it.
2746 */
2747
2748 /* get a fresh new channel from the ssh layer */
2749 #if LIBSSH2_VERSION_NUM < 0x010700
2750 struct stat sb;
2751 memset(&sb, 0, sizeof(struct stat));
2752 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
2753 sshp->path, &sb);
2754 #else
2755 libssh2_struct_stat sb;
2756 memset(&sb, 0, sizeof(libssh2_struct_stat));
2757 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
2758 sshp->path, &sb);
2759 #endif
2760
2761 if(!sshc->ssh_channel) {
2762 int ssh_err;
2763 char *err_msg = NULL;
2764
2765 if(libssh2_session_last_errno(sshc->ssh_session) ==
2766 LIBSSH2_ERROR_EAGAIN) {
2767 rc = LIBSSH2_ERROR_EAGAIN;
2768 break;
2769 }
2770
2771
2772 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
2773 &err_msg, NULL, 0));
2774 failf(data, "%s", err_msg);
2775 state(data, SSH_SCP_CHANNEL_FREE);
2776 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
2777 break;
2778 }
2779
2780 /* download data */
2781 bytecount = (curl_off_t)sb.st_size;
2782 data->req.maxdownload = (curl_off_t)sb.st_size;
2783 Curl_xfer_setup1(data, CURL_XFER_RECV, bytecount, FALSE);
2784
2785 /* not set by Curl_xfer_setup to preserve keepon bits */
2786 conn->writesockfd = conn->sockfd;
2787
2788 /* we want to use the _receiving_ function even when the socket turns
2789 out writableable as the underlying libssh2 recv function will deal
2790 with both accordingly */
2791 data->state.select_bits = CURL_CSELECT_IN;
2792
2793 if(result) {
2794 state(data, SSH_SCP_CHANNEL_FREE);
2795 sshc->actualcode = result;
2796 }
2797 else
2798 state(data, SSH_STOP);
2799 }
2800 break;
2801
2802 case SSH_SCP_DONE:
2803 if(data->state.upload)
2804 state(data, SSH_SCP_SEND_EOF);
2805 else
2806 state(data, SSH_SCP_CHANNEL_FREE);
2807 break;
2808
2809 case SSH_SCP_SEND_EOF:
2810 if(sshc->ssh_channel) {
2811 rc = libssh2_channel_send_eof(sshc->ssh_channel);
2812 if(rc == LIBSSH2_ERROR_EAGAIN) {
2813 break;
2814 }
2815 if(rc) {
2816 char *err_msg = NULL;
2817 (void)libssh2_session_last_error(sshc->ssh_session,
2818 &err_msg, NULL, 0);
2819 infof(data, "Failed to send libssh2 channel EOF: %d %s",
2820 rc, err_msg);
2821 }
2822 }
2823 state(data, SSH_SCP_WAIT_EOF);
2824 break;
2825
2826 case SSH_SCP_WAIT_EOF:
2827 if(sshc->ssh_channel) {
2828 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2829 if(rc == LIBSSH2_ERROR_EAGAIN) {
2830 break;
2831 }
2832 if(rc) {
2833 char *err_msg = NULL;
2834 (void)libssh2_session_last_error(sshc->ssh_session,
2835 &err_msg, NULL, 0);
2836 infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
2837 }
2838 }
2839 state(data, SSH_SCP_WAIT_CLOSE);
2840 break;
2841
2842 case SSH_SCP_WAIT_CLOSE:
2843 if(sshc->ssh_channel) {
2844 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
2845 if(rc == LIBSSH2_ERROR_EAGAIN) {
2846 break;
2847 }
2848 if(rc) {
2849 char *err_msg = NULL;
2850 (void)libssh2_session_last_error(sshc->ssh_session,
2851 &err_msg, NULL, 0);
2852 infof(data, "Channel failed to close: %d %s", rc, err_msg);
2853 }
2854 }
2855 state(data, SSH_SCP_CHANNEL_FREE);
2856 break;
2857
2858 case SSH_SCP_CHANNEL_FREE:
2859 if(sshc->ssh_channel) {
2860 rc = libssh2_channel_free(sshc->ssh_channel);
2861 if(rc == LIBSSH2_ERROR_EAGAIN) {
2862 break;
2863 }
2864 if(rc < 0) {
2865 char *err_msg = NULL;
2866 (void)libssh2_session_last_error(sshc->ssh_session,
2867 &err_msg, NULL, 0);
2868 infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2869 rc, err_msg);
2870 }
2871 sshc->ssh_channel = NULL;
2872 }
2873 DEBUGF(infof(data, "SCP DONE phase complete"));
2874 #if 0 /* PREV */
2875 state(data, SSH_SESSION_DISCONNECT);
2876 #endif
2877 state(data, SSH_STOP);
2878 result = sshc->actualcode;
2879 break;
2880
2881 case SSH_SESSION_DISCONNECT:
2882 /* during weird times when we have been prematurely aborted, the channel
2883 is still alive when we reach this state and we MUST kill the channel
2884 properly first */
2885 if(sshc->ssh_channel) {
2886 rc = libssh2_channel_free(sshc->ssh_channel);
2887 if(rc == LIBSSH2_ERROR_EAGAIN) {
2888 break;
2889 }
2890 if(rc < 0) {
2891 char *err_msg = NULL;
2892 (void)libssh2_session_last_error(sshc->ssh_session,
2893 &err_msg, NULL, 0);
2894 infof(data, "Failed to free libssh2 scp subsystem: %d %s",
2895 rc, err_msg);
2896 }
2897 sshc->ssh_channel = NULL;
2898 }
2899
2900 if(sshc->ssh_session) {
2901 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2902 if(rc == LIBSSH2_ERROR_EAGAIN) {
2903 break;
2904 }
2905 if(rc < 0) {
2906 char *err_msg = NULL;
2907 (void)libssh2_session_last_error(sshc->ssh_session,
2908 &err_msg, NULL, 0);
2909 infof(data, "Failed to disconnect libssh2 session: %d %s",
2910 rc, err_msg);
2911 }
2912 }
2913
2914 Curl_safefree(sshc->homedir);
2915 data->state.most_recent_ftp_entrypath = NULL;
2916
2917 state(data, SSH_SESSION_FREE);
2918 break;
2919
2920 case SSH_SESSION_FREE:
2921 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2922 if(sshc->kh) {
2923 libssh2_knownhost_free(sshc->kh);
2924 sshc->kh = NULL;
2925 }
2926 #endif
2927
2928 #ifdef HAVE_LIBSSH2_AGENT_API
2929 if(sshc->ssh_agent) {
2930 rc = libssh2_agent_disconnect(sshc->ssh_agent);
2931 if(rc == LIBSSH2_ERROR_EAGAIN) {
2932 break;
2933 }
2934 if(rc < 0) {
2935 char *err_msg = NULL;
2936 (void)libssh2_session_last_error(sshc->ssh_session,
2937 &err_msg, NULL, 0);
2938 infof(data, "Failed to disconnect from libssh2 agent: %d %s",
2939 rc, err_msg);
2940 }
2941 libssh2_agent_free(sshc->ssh_agent);
2942 sshc->ssh_agent = NULL;
2943
2944 /* NB: there is no need to free identities, they are part of internal
2945 agent stuff */
2946 sshc->sshagent_identity = NULL;
2947 sshc->sshagent_prev_identity = NULL;
2948 }
2949 #endif
2950
2951 if(sshc->ssh_session) {
2952 rc = libssh2_session_free(sshc->ssh_session);
2953 if(rc == LIBSSH2_ERROR_EAGAIN) {
2954 break;
2955 }
2956 if(rc < 0) {
2957 char *err_msg = NULL;
2958 (void)libssh2_session_last_error(sshc->ssh_session,
2959 &err_msg, NULL, 0);
2960 infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
2961 }
2962 sshc->ssh_session = NULL;
2963 }
2964
2965 /* worst-case scenario cleanup */
2966
2967 DEBUGASSERT(sshc->ssh_session == NULL);
2968 DEBUGASSERT(sshc->ssh_channel == NULL);
2969 DEBUGASSERT(sshc->sftp_session == NULL);
2970 DEBUGASSERT(sshc->sftp_handle == NULL);
2971 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2972 DEBUGASSERT(sshc->kh == NULL);
2973 #endif
2974 #ifdef HAVE_LIBSSH2_AGENT_API
2975 DEBUGASSERT(sshc->ssh_agent == NULL);
2976 #endif
2977
2978 Curl_safefree(sshc->rsa_pub);
2979 Curl_safefree(sshc->rsa);
2980 Curl_safefree(sshc->quote_path1);
2981 Curl_safefree(sshc->quote_path2);
2982 Curl_safefree(sshc->homedir);
2983
2984 /* the code we are about to return */
2985 result = sshc->actualcode;
2986
2987 memset(sshc, 0, sizeof(struct ssh_conn));
2988
2989 connclose(conn, "SSH session free");
2990 sshc->state = SSH_SESSION_FREE; /* current */
2991 sshc->nextstate = SSH_NO_STATE;
2992 state(data, SSH_STOP);
2993 break;
2994
2995 case SSH_QUIT:
2996 default:
2997 /* internal error */
2998 sshc->nextstate = SSH_NO_STATE;
2999 state(data, SSH_STOP);
3000 break;
3001 }
3002
3003 } while(!rc && (sshc->state != SSH_STOP));
3004
3005 if(rc == LIBSSH2_ERROR_EAGAIN) {
3006 /* we would block, we need to wait for the socket to be ready (in the
3007 right direction too)! */
3008 *block = TRUE;
3009 }
3010
3011 return result;
3012 }
3013
3014 /* called by the multi interface to figure out what socket(s) to wait for and
3015 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
ssh_getsock(struct Curl_easy * data,struct connectdata * conn,curl_socket_t * sock)3016 static int ssh_getsock(struct Curl_easy *data,
3017 struct connectdata *conn,
3018 curl_socket_t *sock)
3019 {
3020 int bitmap = GETSOCK_BLANK;
3021 (void)data;
3022
3023 sock[0] = conn->sock[FIRSTSOCKET];
3024
3025 if(conn->waitfor & KEEP_RECV)
3026 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
3027
3028 if(conn->waitfor & KEEP_SEND)
3029 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
3030
3031 return bitmap;
3032 }
3033
3034 /*
3035 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
3036 * function is used to figure out in what direction and stores this info so
3037 * that the multi interface can take advantage of it. Make sure to call this
3038 * function in all cases so that when it _does not_ return EAGAIN we can
3039 * restore the default wait bits.
3040 */
ssh_block2waitfor(struct Curl_easy * data,bool block)3041 static void ssh_block2waitfor(struct Curl_easy *data, bool block)
3042 {
3043 struct connectdata *conn = data->conn;
3044 struct ssh_conn *sshc = &conn->proto.sshc;
3045 int dir = 0;
3046 if(block) {
3047 dir = libssh2_session_block_directions(sshc->ssh_session);
3048 if(dir) {
3049 /* translate the libssh2 define bits into our own bit defines */
3050 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND) ? KEEP_RECV : 0) |
3051 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND) ? KEEP_SEND : 0);
3052 }
3053 }
3054 if(!dir)
3055 /* It did not block or libssh2 did not reveal in which direction, put back
3056 the original set */
3057 conn->waitfor = sshc->orig_waitfor;
3058 }
3059
3060 /* called repeatedly until done from multi.c */
ssh_multi_statemach(struct Curl_easy * data,bool * done)3061 static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
3062 {
3063 struct connectdata *conn = data->conn;
3064 struct ssh_conn *sshc = &conn->proto.sshc;
3065 CURLcode result = CURLE_OK;
3066 bool block; /* we store the status and use that to provide a ssh_getsock()
3067 implementation */
3068 do {
3069 result = ssh_statemachine(data, &block);
3070 *done = (sshc->state == SSH_STOP);
3071 /* if there is no error, it is not done and it did not EWOULDBLOCK, then
3072 try again */
3073 } while(!result && !*done && !block);
3074 ssh_block2waitfor(data, block);
3075
3076 return result;
3077 }
3078
ssh_block_statemach(struct Curl_easy * data,struct connectdata * conn,bool disconnect)3079 static CURLcode ssh_block_statemach(struct Curl_easy *data,
3080 struct connectdata *conn,
3081 bool disconnect)
3082 {
3083 struct ssh_conn *sshc = &conn->proto.sshc;
3084 CURLcode result = CURLE_OK;
3085 struct curltime dis = Curl_now();
3086
3087 while((sshc->state != SSH_STOP) && !result) {
3088 bool block;
3089 timediff_t left = 1000;
3090 struct curltime now = Curl_now();
3091
3092 result = ssh_statemachine(data, &block);
3093 if(result)
3094 break;
3095
3096 if(!disconnect) {
3097 if(Curl_pgrsUpdate(data))
3098 return CURLE_ABORTED_BY_CALLBACK;
3099
3100 result = Curl_speedcheck(data, now);
3101 if(result)
3102 break;
3103
3104 left = Curl_timeleft(data, NULL, FALSE);
3105 if(left < 0) {
3106 failf(data, "Operation timed out");
3107 return CURLE_OPERATION_TIMEDOUT;
3108 }
3109 }
3110 else if(Curl_timediff(now, dis) > 1000) {
3111 /* disconnect timeout */
3112 failf(data, "Disconnect timed out");
3113 result = CURLE_OK;
3114 break;
3115 }
3116
3117 if(block) {
3118 int dir = libssh2_session_block_directions(sshc->ssh_session);
3119 curl_socket_t sock = conn->sock[FIRSTSOCKET];
3120 curl_socket_t fd_read = CURL_SOCKET_BAD;
3121 curl_socket_t fd_write = CURL_SOCKET_BAD;
3122 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
3123 fd_read = sock;
3124 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
3125 fd_write = sock;
3126 /* wait for the socket to become ready */
3127 (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
3128 left > 1000 ? 1000 : left);
3129 }
3130 }
3131
3132 return result;
3133 }
3134
3135 /*
3136 * SSH setup and connection
3137 */
ssh_setup_connection(struct Curl_easy * data,struct connectdata * conn)3138 static CURLcode ssh_setup_connection(struct Curl_easy *data,
3139 struct connectdata *conn)
3140 {
3141 struct SSHPROTO *ssh;
3142 (void)conn;
3143
3144 data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
3145 if(!ssh)
3146 return CURLE_OUT_OF_MEMORY;
3147
3148 return CURLE_OK;
3149 }
3150
3151 static Curl_recv scp_recv, sftp_recv;
3152 static Curl_send scp_send, sftp_send;
3153
3154 #ifndef CURL_DISABLE_PROXY
ssh_tls_recv(libssh2_socket_t sock,void * buffer,size_t length,int flags,void ** abstract)3155 static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
3156 size_t length, int flags, void **abstract)
3157 {
3158 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3159 ssize_t nread;
3160 CURLcode result;
3161 struct connectdata *conn = data->conn;
3162 Curl_recv *backup = conn->recv[0];
3163 struct ssh_conn *ssh = &conn->proto.sshc;
3164 int socknum = Curl_conn_sockindex(data, sock);
3165 (void)flags;
3166
3167 /* swap in the TLS reader function for this call only, and then swap back
3168 the SSH one again */
3169 conn->recv[0] = ssh->tls_recv;
3170 result = Curl_conn_recv(data, socknum, buffer, length, &nread);
3171 conn->recv[0] = backup;
3172 if(result == CURLE_AGAIN)
3173 return -EAGAIN; /* magic return code for libssh2 */
3174 else if(result)
3175 return -1; /* generic error */
3176 Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
3177 return nread;
3178 }
3179
ssh_tls_send(libssh2_socket_t sock,const void * buffer,size_t length,int flags,void ** abstract)3180 static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
3181 size_t length, int flags, void **abstract)
3182 {
3183 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3184 size_t nwrite;
3185 CURLcode result;
3186 struct connectdata *conn = data->conn;
3187 Curl_send *backup = conn->send[0];
3188 struct ssh_conn *ssh = &conn->proto.sshc;
3189 int socknum = Curl_conn_sockindex(data, sock);
3190 (void)flags;
3191
3192 /* swap in the TLS writer function for this call only, and then swap back
3193 the SSH one again */
3194 conn->send[0] = ssh->tls_send;
3195 result = Curl_conn_send(data, socknum, buffer, length, FALSE, &nwrite);
3196 conn->send[0] = backup;
3197 if(result == CURLE_AGAIN)
3198 return -EAGAIN; /* magic return code for libssh2 */
3199 else if(result)
3200 return -1; /* error */
3201 Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, nwrite);
3202 return (ssize_t)nwrite;
3203 }
3204 #endif
3205
3206 /*
3207 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
3208 * do protocol-specific actions at connect-time.
3209 */
ssh_connect(struct Curl_easy * data,bool * done)3210 static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
3211 {
3212 #ifdef CURL_LIBSSH2_DEBUG
3213 curl_socket_t sock;
3214 #endif
3215 struct ssh_conn *sshc;
3216 CURLcode result;
3217 struct connectdata *conn = data->conn;
3218
3219 /* initialize per-handle data if not already */
3220 if(!data->req.p.ssh) {
3221 result = ssh_setup_connection(data, conn);
3222 if(result)
3223 return result;
3224 }
3225
3226 /* We default to persistent connections. We set this already in this connect
3227 function to make the reuse checks properly be able to check this bit. */
3228 connkeep(conn, "SSH default");
3229
3230 sshc = &conn->proto.sshc;
3231
3232 #ifdef CURL_LIBSSH2_DEBUG
3233 if(conn->user) {
3234 infof(data, "User: %s", conn->user);
3235 }
3236 if(conn->passwd) {
3237 infof(data, "Password: %s", conn->passwd);
3238 }
3239 sock = conn->sock[FIRSTSOCKET];
3240 #endif /* CURL_LIBSSH2_DEBUG */
3241
3242 /* libcurl MUST to set custom memory functions so that the kbd_callback
3243 function's memory allocations can be properly freed */
3244 sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
3245 my_libssh2_free,
3246 my_libssh2_realloc, data);
3247
3248 if(!sshc->ssh_session) {
3249 failf(data, "Failure initialising ssh session");
3250 return CURLE_FAILED_INIT;
3251 }
3252
3253 /* Set the packet read timeout if the libssh2 version supports it */
3254 #if LIBSSH2_VERSION_NUM >= 0x010B00
3255 if(data->set.server_response_timeout > 0) {
3256 libssh2_session_set_read_timeout(sshc->ssh_session,
3257 (long)(data->set.server_response_timeout / 1000));
3258 }
3259 #endif
3260
3261 #ifndef CURL_DISABLE_PROXY
3262 if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
3263 /*
3264 Setup libssh2 callbacks to make it read/write TLS from the socket.
3265
3266 ssize_t
3267 recvcb(libssh2_socket_t sock, void *buffer, size_t length,
3268 int flags, void **abstract);
3269
3270 ssize_t
3271 sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
3272 int flags, void **abstract);
3273
3274 */
3275 #if LIBSSH2_VERSION_NUM >= 0x010b01
3276 infof(data, "Uses HTTPS proxy");
3277 libssh2_session_callback_set2(sshc->ssh_session,
3278 LIBSSH2_CALLBACK_RECV,
3279 (libssh2_cb_generic *)ssh_tls_recv);
3280 libssh2_session_callback_set2(sshc->ssh_session,
3281 LIBSSH2_CALLBACK_SEND,
3282 (libssh2_cb_generic *)ssh_tls_send);
3283 #else
3284 /*
3285 * This crazy union dance is here to avoid assigning a void pointer a
3286 * function pointer as it is invalid C. The problem is of course that
3287 * libssh2 has such an API...
3288 */
3289 union receive {
3290 void *recvp;
3291 ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
3292 };
3293 union transfer {
3294 void *sendp;
3295 ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
3296 };
3297 union receive sshrecv;
3298 union transfer sshsend;
3299
3300 sshrecv.recvptr = ssh_tls_recv;
3301 sshsend.sendptr = ssh_tls_send;
3302
3303 infof(data, "Uses HTTPS proxy");
3304 libssh2_session_callback_set(sshc->ssh_session,
3305 LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
3306 libssh2_session_callback_set(sshc->ssh_session,
3307 LIBSSH2_CALLBACK_SEND, sshsend.sendp);
3308 #endif
3309
3310 /* Store the underlying TLS recv/send function pointers to be used when
3311 reading from the proxy */
3312 sshc->tls_recv = conn->recv[FIRSTSOCKET];
3313 sshc->tls_send = conn->send[FIRSTSOCKET];
3314 }
3315
3316 #endif /* CURL_DISABLE_PROXY */
3317 if(conn->handler->protocol & CURLPROTO_SCP) {
3318 conn->recv[FIRSTSOCKET] = scp_recv;
3319 conn->send[FIRSTSOCKET] = scp_send;
3320 }
3321 else {
3322 conn->recv[FIRSTSOCKET] = sftp_recv;
3323 conn->send[FIRSTSOCKET] = sftp_send;
3324 }
3325
3326 if(data->set.ssh_compression) {
3327 #if LIBSSH2_VERSION_NUM >= 0x010208
3328 if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
3329 #endif
3330 infof(data, "Failed to enable compression for ssh session");
3331 }
3332
3333 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
3334 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
3335 int rc;
3336 sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
3337 if(!sshc->kh) {
3338 libssh2_session_free(sshc->ssh_session);
3339 sshc->ssh_session = NULL;
3340 return CURLE_FAILED_INIT;
3341 }
3342
3343 /* read all known hosts from there */
3344 rc = libssh2_knownhost_readfile(sshc->kh,
3345 data->set.str[STRING_SSH_KNOWNHOSTS],
3346 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
3347 if(rc < 0)
3348 infof(data, "Failed to read known hosts from %s",
3349 data->set.str[STRING_SSH_KNOWNHOSTS]);
3350 }
3351 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
3352
3353 #ifdef CURL_LIBSSH2_DEBUG
3354 libssh2_trace(sshc->ssh_session, ~0);
3355 infof(data, "SSH socket: %d", (int)sock);
3356 #endif /* CURL_LIBSSH2_DEBUG */
3357
3358 state(data, SSH_INIT);
3359
3360 result = ssh_multi_statemach(data, done);
3361
3362 return result;
3363 }
3364
3365 /*
3366 ***********************************************************************
3367 *
3368 * scp_perform()
3369 *
3370 * This is the actual DO function for SCP. Get a file according to
3371 * the options previously setup.
3372 */
3373
3374 static
scp_perform(struct Curl_easy * data,bool * connected,bool * dophase_done)3375 CURLcode scp_perform(struct Curl_easy *data,
3376 bool *connected,
3377 bool *dophase_done)
3378 {
3379 CURLcode result = CURLE_OK;
3380
3381 DEBUGF(infof(data, "DO phase starts"));
3382
3383 *dophase_done = FALSE; /* not done yet */
3384
3385 /* start the first command in the DO phase */
3386 state(data, SSH_SCP_TRANS_INIT);
3387
3388 /* run the state-machine */
3389 result = ssh_multi_statemach(data, dophase_done);
3390
3391 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3392
3393 if(*dophase_done) {
3394 DEBUGF(infof(data, "DO phase is complete"));
3395 }
3396
3397 return result;
3398 }
3399
3400 /* called from multi.c while DOing */
scp_doing(struct Curl_easy * data,bool * dophase_done)3401 static CURLcode scp_doing(struct Curl_easy *data,
3402 bool *dophase_done)
3403 {
3404 CURLcode result;
3405 result = ssh_multi_statemach(data, dophase_done);
3406
3407 if(*dophase_done) {
3408 DEBUGF(infof(data, "DO phase is complete"));
3409 }
3410 return result;
3411 }
3412
3413 /*
3414 * The DO function is generic for both protocols. There was previously two
3415 * separate ones but this way means less duplicated code.
3416 */
3417
ssh_do(struct Curl_easy * data,bool * done)3418 static CURLcode ssh_do(struct Curl_easy *data, bool *done)
3419 {
3420 CURLcode result;
3421 bool connected = FALSE;
3422 struct connectdata *conn = data->conn;
3423 struct ssh_conn *sshc = &conn->proto.sshc;
3424
3425 *done = FALSE; /* default to false */
3426
3427 data->req.size = -1; /* make sure this is unknown at this point */
3428
3429 sshc->actualcode = CURLE_OK; /* reset error code */
3430 sshc->secondCreateDirs = 0; /* reset the create dir attempt state
3431 variable */
3432
3433 Curl_pgrsSetUploadCounter(data, 0);
3434 Curl_pgrsSetDownloadCounter(data, 0);
3435 Curl_pgrsSetUploadSize(data, -1);
3436 Curl_pgrsSetDownloadSize(data, -1);
3437
3438 if(conn->handler->protocol & CURLPROTO_SCP)
3439 result = scp_perform(data, &connected, done);
3440 else
3441 result = sftp_perform(data, &connected, done);
3442
3443 return result;
3444 }
3445
3446 /* BLOCKING, but the function is using the state machine so the only reason
3447 this is still blocking is that the multi interface code has no support for
3448 disconnecting operations that takes a while */
scp_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)3449 static CURLcode scp_disconnect(struct Curl_easy *data,
3450 struct connectdata *conn,
3451 bool dead_connection)
3452 {
3453 CURLcode result = CURLE_OK;
3454 struct ssh_conn *sshc = &conn->proto.sshc;
3455 (void) dead_connection;
3456
3457 if(sshc->ssh_session) {
3458 /* only if there is a session still around to use! */
3459 state(data, SSH_SESSION_DISCONNECT);
3460 result = ssh_block_statemach(data, conn, TRUE);
3461 }
3462
3463 return result;
3464 }
3465
3466 /* generic done function for both SCP and SFTP called from their specific
3467 done functions */
ssh_done(struct Curl_easy * data,CURLcode status)3468 static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
3469 {
3470 CURLcode result = CURLE_OK;
3471 struct SSHPROTO *sshp = data->req.p.ssh;
3472 struct connectdata *conn = data->conn;
3473
3474 if(!status)
3475 /* run the state-machine */
3476 result = ssh_block_statemach(data, conn, FALSE);
3477 else
3478 result = status;
3479
3480 Curl_safefree(sshp->path);
3481 Curl_dyn_free(&sshp->readdir);
3482
3483 if(Curl_pgrsDone(data))
3484 return CURLE_ABORTED_BY_CALLBACK;
3485
3486 data->req.keepon = 0; /* clear all bits */
3487 return result;
3488 }
3489
3490
scp_done(struct Curl_easy * data,CURLcode status,bool premature)3491 static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
3492 bool premature)
3493 {
3494 (void)premature; /* not used */
3495
3496 if(!status)
3497 state(data, SSH_SCP_DONE);
3498
3499 return ssh_done(data, status);
3500
3501 }
3502
scp_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,bool eos,CURLcode * err)3503 static ssize_t scp_send(struct Curl_easy *data, int sockindex,
3504 const void *mem, size_t len, bool eos, CURLcode *err)
3505 {
3506 ssize_t nwrite;
3507 struct connectdata *conn = data->conn;
3508 struct ssh_conn *sshc = &conn->proto.sshc;
3509 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3510 (void)eos;
3511
3512 /* libssh2_channel_write() returns int! */
3513 nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
3514
3515 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN));
3516
3517 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3518 *err = CURLE_AGAIN;
3519 nwrite = 0;
3520 }
3521 else if(nwrite < LIBSSH2_ERROR_NONE) {
3522 *err = libssh2_session_error_to_CURLE((int)nwrite);
3523 nwrite = -1;
3524 }
3525
3526 return nwrite;
3527 }
3528
scp_recv(struct Curl_easy * data,int sockindex,char * mem,size_t len,CURLcode * err)3529 static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
3530 char *mem, size_t len, CURLcode *err)
3531 {
3532 ssize_t nread;
3533 struct connectdata *conn = data->conn;
3534 struct ssh_conn *sshc = &conn->proto.sshc;
3535 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3536
3537 /* libssh2_channel_read() returns int */
3538 nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
3539
3540 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN));
3541 if(nread == LIBSSH2_ERROR_EAGAIN) {
3542 *err = CURLE_AGAIN;
3543 nread = -1;
3544 }
3545
3546 return nread;
3547 }
3548
3549 /*
3550 * =============== SFTP ===============
3551 */
3552
3553 /*
3554 ***********************************************************************
3555 *
3556 * sftp_perform()
3557 *
3558 * This is the actual DO function for SFTP. Get a file/directory according to
3559 * the options previously setup.
3560 */
3561
3562 static
sftp_perform(struct Curl_easy * data,bool * connected,bool * dophase_done)3563 CURLcode sftp_perform(struct Curl_easy *data,
3564 bool *connected,
3565 bool *dophase_done)
3566 {
3567 CURLcode result = CURLE_OK;
3568
3569 DEBUGF(infof(data, "DO phase starts"));
3570
3571 *dophase_done = FALSE; /* not done yet */
3572
3573 /* start the first command in the DO phase */
3574 state(data, SSH_SFTP_QUOTE_INIT);
3575
3576 /* run the state-machine */
3577 result = ssh_multi_statemach(data, dophase_done);
3578
3579 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3580
3581 if(*dophase_done) {
3582 DEBUGF(infof(data, "DO phase is complete"));
3583 }
3584
3585 return result;
3586 }
3587
3588 /* called from multi.c while DOing */
sftp_doing(struct Curl_easy * data,bool * dophase_done)3589 static CURLcode sftp_doing(struct Curl_easy *data,
3590 bool *dophase_done)
3591 {
3592 CURLcode result = ssh_multi_statemach(data, dophase_done);
3593
3594 if(*dophase_done) {
3595 DEBUGF(infof(data, "DO phase is complete"));
3596 }
3597 return result;
3598 }
3599
3600 /* BLOCKING, but the function is using the state machine so the only reason
3601 this is still blocking is that the multi interface code has no support for
3602 disconnecting operations that takes a while */
sftp_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)3603 static CURLcode sftp_disconnect(struct Curl_easy *data,
3604 struct connectdata *conn, bool dead_connection)
3605 {
3606 CURLcode result = CURLE_OK;
3607 struct ssh_conn *sshc = &conn->proto.sshc;
3608 (void) dead_connection;
3609
3610 DEBUGF(infof(data, "SSH DISCONNECT starts now"));
3611
3612 if(sshc->ssh_session) {
3613 /* only if there is a session still around to use! */
3614 state(data, SSH_SFTP_SHUTDOWN);
3615 result = ssh_block_statemach(data, conn, TRUE);
3616 }
3617
3618 DEBUGF(infof(data, "SSH DISCONNECT is done"));
3619
3620 return result;
3621
3622 }
3623
sftp_done(struct Curl_easy * data,CURLcode status,bool premature)3624 static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
3625 bool premature)
3626 {
3627 struct connectdata *conn = data->conn;
3628 struct ssh_conn *sshc = &conn->proto.sshc;
3629
3630 if(!status) {
3631 /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3632 errors that could happen due to open file handles during POSTQUOTE
3633 operation */
3634 if(!premature && data->set.postquote && !conn->bits.retry)
3635 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3636 state(data, SSH_SFTP_CLOSE);
3637 }
3638 return ssh_done(data, status);
3639 }
3640
3641 /* return number of sent bytes */
sftp_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,bool eos,CURLcode * err)3642 static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
3643 const void *mem, size_t len, bool eos, CURLcode *err)
3644 {
3645 ssize_t nwrite;
3646 struct connectdata *conn = data->conn;
3647 struct ssh_conn *sshc = &conn->proto.sshc;
3648 (void)sockindex;
3649 (void)eos;
3650
3651 nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
3652
3653 ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN));
3654
3655 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
3656 *err = CURLE_AGAIN;
3657 nwrite = 0;
3658 }
3659 else if(nwrite < LIBSSH2_ERROR_NONE) {
3660 *err = libssh2_session_error_to_CURLE((int)nwrite);
3661 nwrite = -1;
3662 }
3663
3664 return nwrite;
3665 }
3666
3667 /*
3668 * Return number of received (decrypted) bytes
3669 * or <0 on error
3670 */
sftp_recv(struct Curl_easy * data,int sockindex,char * mem,size_t len,CURLcode * err)3671 static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
3672 char *mem, size_t len, CURLcode *err)
3673 {
3674 ssize_t nread;
3675 struct connectdata *conn = data->conn;
3676 struct ssh_conn *sshc = &conn->proto.sshc;
3677 (void)sockindex;
3678
3679 nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
3680
3681 ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN));
3682
3683 if(nread == LIBSSH2_ERROR_EAGAIN) {
3684 *err = CURLE_AGAIN;
3685 nread = -1;
3686
3687 }
3688 else if(nread < 0) {
3689 *err = libssh2_session_error_to_CURLE((int)nread);
3690 }
3691 return nread;
3692 }
3693
sftp_libssh2_strerror(unsigned long err)3694 static const char *sftp_libssh2_strerror(unsigned long err)
3695 {
3696 switch(err) {
3697 case LIBSSH2_FX_NO_SUCH_FILE:
3698 return "No such file or directory";
3699
3700 case LIBSSH2_FX_PERMISSION_DENIED:
3701 return "Permission denied";
3702
3703 case LIBSSH2_FX_FAILURE:
3704 return "Operation failed";
3705
3706 case LIBSSH2_FX_BAD_MESSAGE:
3707 return "Bad message from SFTP server";
3708
3709 case LIBSSH2_FX_NO_CONNECTION:
3710 return "Not connected to SFTP server";
3711
3712 case LIBSSH2_FX_CONNECTION_LOST:
3713 return "Connection to SFTP server lost";
3714
3715 case LIBSSH2_FX_OP_UNSUPPORTED:
3716 return "Operation not supported by SFTP server";
3717
3718 case LIBSSH2_FX_INVALID_HANDLE:
3719 return "Invalid handle";
3720
3721 case LIBSSH2_FX_NO_SUCH_PATH:
3722 return "No such file or directory";
3723
3724 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
3725 return "File already exists";
3726
3727 case LIBSSH2_FX_WRITE_PROTECT:
3728 return "File is write protected";
3729
3730 case LIBSSH2_FX_NO_MEDIA:
3731 return "No media";
3732
3733 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
3734 return "Disk full";
3735
3736 case LIBSSH2_FX_QUOTA_EXCEEDED:
3737 return "User quota exceeded";
3738
3739 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
3740 return "Unknown principle";
3741
3742 case LIBSSH2_FX_LOCK_CONFlICT:
3743 return "File lock conflict";
3744
3745 case LIBSSH2_FX_DIR_NOT_EMPTY:
3746 return "Directory not empty";
3747
3748 case LIBSSH2_FX_NOT_A_DIRECTORY:
3749 return "Not a directory";
3750
3751 case LIBSSH2_FX_INVALID_FILENAME:
3752 return "Invalid filename";
3753
3754 case LIBSSH2_FX_LINK_LOOP:
3755 return "Link points to itself";
3756 }
3757 return "Unknown error in libssh2";
3758 }
3759
Curl_ssh_init(void)3760 CURLcode Curl_ssh_init(void)
3761 {
3762 #ifdef HAVE_LIBSSH2_INIT
3763 if(libssh2_init(0)) {
3764 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
3765 return CURLE_FAILED_INIT;
3766 }
3767 #endif
3768 return CURLE_OK;
3769 }
3770
Curl_ssh_cleanup(void)3771 void Curl_ssh_cleanup(void)
3772 {
3773 #ifdef HAVE_LIBSSH2_EXIT
3774 (void)libssh2_exit();
3775 #endif
3776 }
3777
Curl_ssh_version(char * buffer,size_t buflen)3778 void Curl_ssh_version(char *buffer, size_t buflen)
3779 {
3780 (void)msnprintf(buffer, buflen, "libssh2/%s", CURL_LIBSSH2_VERSION);
3781 }
3782
3783 /* The SSH session is associated with the *CONNECTION* but the callback user
3784 * pointer is an easy handle pointer. This function allows us to reassign the
3785 * user pointer to the *CURRENT* (new) easy handle.
3786 */
ssh_attach(struct Curl_easy * data,struct connectdata * conn)3787 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
3788 {
3789 DEBUGASSERT(data);
3790 DEBUGASSERT(conn);
3791 if(conn->handler->protocol & PROTO_FAMILY_SSH) {
3792 struct ssh_conn *sshc = &conn->proto.sshc;
3793 if(sshc->ssh_session) {
3794 /* only re-attach if the session already exists */
3795 void **abstract = libssh2_session_abstract(sshc->ssh_session);
3796 *abstract = data;
3797 }
3798 }
3799 }
3800 #endif /* USE_LIBSSH2 */
3801