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