source: EcnlProtoTool/trunk/curl-7.57.0/lib/ssh.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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