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