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