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