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