source: UsbWattMeter/trunk/curl-7.47.1/lib/ssh.c@ 164

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

TOPPERS/ECNLサンプルアプリ「USB充電器電力計」を追加

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