1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2008, 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 http://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 * $Id: ssh.c,v 1.127 2008-12-28 05:49:39 gknauf Exp $
22 ***************************************************************************/
23
24 /* #define CURL_LIBSSH2_DEBUG */
25
26 #include "setup.h"
27
28 #ifdef USE_LIBSSH2
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <ctype.h>
34 #include <limits.h>
35
36 #include <libssh2.h>
37 #include <libssh2_sftp.h>
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #ifdef HAVE_FCNTL_H
44 #include <fcntl.h>
45 #endif
46
47 #ifdef HAVE_TIME_H
48 #include <time.h>
49 #endif
50
51 #ifndef WIN32
52 #ifdef HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
54 #endif
55 #ifdef HAVE_NETINET_IN_H
56 #include <netinet/in.h>
57 #endif
58 #ifdef HAVE_ARPA_INET_H
59 #include <arpa/inet.h>
60 #endif
61 #ifdef HAVE_UTSNAME_H
62 #include <sys/utsname.h>
63 #endif
64 #ifdef HAVE_NETDB_H
65 #include <netdb.h>
66 #endif
67 #ifdef VMS
68 #include <in.h>
69 #include <inet.h>
70 #endif
71 #endif /* !WIN32 */
72
73 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
74 #undef in_addr_t
75 #define in_addr_t unsigned long
76 #endif
77
78 #include <curl/curl.h>
79 #include "urldata.h"
80 #include "sendf.h"
81 #include "easyif.h" /* for Curl_convert_... prototypes */
82
83 #include "hostip.h"
84 #include "progress.h"
85 #include "transfer.h"
86 #include "escape.h"
87 #include "http.h" /* for HTTP proxy tunnel stuff */
88 #include "ssh.h"
89 #include "url.h"
90 #include "speedcheck.h"
91 #include "getinfo.h"
92
93 #include "strequal.h"
94 #include "sslgen.h"
95 #include "connect.h"
96 #include "strerror.h"
97 #include "inet_ntop.h"
98 #include "parsedate.h" /* for the week day and month names */
99 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
100 #include "strtoofft.h"
101 #include "multiif.h"
102 #include "select.h"
103
104 #define _MPRINTF_REPLACE /* use our functions only */
105 #include <curl/mprintf.h>
106
107 #include "memory.h"
108 /* The last #include file should be: */
109 #include "memdebug.h"
110
111 #ifndef PATH_MAX
112 #define PATH_MAX 1024 /* just an extra precaution since there are systems that
113 have their definition hidden well */
114 #endif
115
116 /* Local functions: */
117 static const char *sftp_libssh2_strerror(unsigned long err);
118 static LIBSSH2_ALLOC_FUNC(libssh2_malloc);
119 static LIBSSH2_REALLOC_FUNC(libssh2_realloc);
120 static LIBSSH2_FREE_FUNC(libssh2_free);
121
122 static CURLcode get_pathname(const char **cpp, char **path);
123
124 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
125 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
126 static CURLcode ssh_do(struct connectdata *conn, bool *done);
127
128 static CURLcode ssh_getworkingpath(struct connectdata *conn,
129 char *homedir, /* when SFTP is used */
130 char **path);
131
132 static CURLcode scp_done(struct connectdata *conn,
133 CURLcode, bool premature);
134 static CURLcode scp_doing(struct connectdata *conn,
135 bool *dophase_done);
136 static CURLcode scp_disconnect(struct connectdata *conn);
137
138 static CURLcode sftp_done(struct connectdata *conn,
139 CURLcode, bool premature);
140 static CURLcode sftp_doing(struct connectdata *conn,
141 bool *dophase_done);
142 static CURLcode sftp_disconnect(struct connectdata *conn);
143 static
144 CURLcode sftp_perform(struct connectdata *conn,
145 bool *connected,
146 bool *dophase_done);
147
148 static int ssh_getsock(struct connectdata *conn,
149 curl_socket_t *sock, /* points to numsocks number
150 of sockets */
151 int numsocks);
152
153 static int ssh_perform_getsock(const struct connectdata *conn,
154 curl_socket_t *sock, /* points to numsocks
155 number of sockets */
156 int numsocks);
157
158 /*
159 * SCP protocol handler.
160 */
161
162 const struct Curl_handler Curl_handler_scp = {
163 "SCP", /* scheme */
164 ZERO_NULL, /* setup_connection */
165 ssh_do, /* do_it */
166 scp_done, /* done */
167 ZERO_NULL, /* do_more */
168 ssh_connect, /* connect_it */
169 ssh_multi_statemach, /* connecting */
170 scp_doing, /* doing */
171 ssh_getsock, /* proto_getsock */
172 ssh_getsock, /* doing_getsock */
173 ssh_perform_getsock, /* perform_getsock */
174 scp_disconnect, /* disconnect */
175 PORT_SSH, /* defport */
176 PROT_SCP /* protocol */
177 };
178
179
180 /*
181 * SFTP protocol handler.
182 */
183
184 const struct Curl_handler Curl_handler_sftp = {
185 "SFTP", /* scheme */
186 ZERO_NULL, /* setup_connection */
187 ssh_do, /* do_it */
188 sftp_done, /* done */
189 ZERO_NULL, /* do_more */
190 ssh_connect, /* connect_it */
191 ssh_multi_statemach, /* connecting */
192 sftp_doing, /* doing */
193 ssh_getsock, /* proto_getsock */
194 ssh_getsock, /* doing_getsock */
195 ssh_perform_getsock, /* perform_getsock */
196 sftp_disconnect, /* disconnect */
197 PORT_SSH, /* defport */
198 PROT_SFTP /* protocol */
199 };
200
201
202 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)203 kbd_callback(const char *name, int name_len, const char *instruction,
204 int instruction_len, int num_prompts,
205 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
206 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
207 void **abstract)
208 {
209 struct connectdata *conn = (struct connectdata *)*abstract;
210
211 #ifdef CURL_LIBSSH2_DEBUG
212 fprintf(stderr, "name=%s\n", name);
213 fprintf(stderr, "name_len=%d\n", name_len);
214 fprintf(stderr, "instruction=%s\n", instruction);
215 fprintf(stderr, "instruction_len=%d\n", instruction_len);
216 fprintf(stderr, "num_prompts=%d\n", num_prompts);
217 #else
218 (void)name;
219 (void)name_len;
220 (void)instruction;
221 (void)instruction_len;
222 #endif /* CURL_LIBSSH2_DEBUG */
223 if(num_prompts == 1) {
224 responses[0].text = strdup(conn->passwd);
225 responses[0].length = strlen(conn->passwd);
226 }
227 (void)prompts;
228 (void)abstract;
229 } /* kbd_callback */
230
sftp_libssh2_error_to_CURLE(unsigned long err)231 static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
232 {
233 switch (err) {
234 case LIBSSH2_FX_OK:
235 return CURLE_OK;
236
237 case LIBSSH2_ERROR_ALLOC:
238 return CURLE_OUT_OF_MEMORY;
239
240 case LIBSSH2_FX_NO_SUCH_FILE:
241 case LIBSSH2_FX_NO_SUCH_PATH:
242 return CURLE_REMOTE_FILE_NOT_FOUND;
243
244 case LIBSSH2_FX_PERMISSION_DENIED:
245 case LIBSSH2_FX_WRITE_PROTECT:
246 case LIBSSH2_FX_LOCK_CONFlICT:
247 return CURLE_REMOTE_ACCESS_DENIED;
248
249 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
250 case LIBSSH2_FX_QUOTA_EXCEEDED:
251 return CURLE_REMOTE_DISK_FULL;
252
253 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
254 return CURLE_REMOTE_FILE_EXISTS;
255
256 case LIBSSH2_FX_DIR_NOT_EMPTY:
257 return CURLE_QUOTE_ERROR;
258
259 default:
260 break;
261 }
262
263 return CURLE_SSH;
264 }
265
libssh2_session_error_to_CURLE(int err)266 static CURLcode libssh2_session_error_to_CURLE(int err)
267 {
268 if(err == LIBSSH2_ERROR_ALLOC)
269 return CURLE_OUT_OF_MEMORY;
270
271 /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
272 error code, and possibly add a few new SSH-related one. We must however
273 not return or even depend on libssh2 errors in the public libcurl API */
274
275 return CURLE_SSH;
276 }
277
LIBSSH2_ALLOC_FUNC(libssh2_malloc)278 static LIBSSH2_ALLOC_FUNC(libssh2_malloc)
279 {
280 (void)abstract; /* arg not used */
281 return malloc(count);
282 }
283
LIBSSH2_REALLOC_FUNC(libssh2_realloc)284 static LIBSSH2_REALLOC_FUNC(libssh2_realloc)
285 {
286 (void)abstract; /* arg not used */
287 return realloc(ptr, count);
288 }
289
LIBSSH2_FREE_FUNC(libssh2_free)290 static LIBSSH2_FREE_FUNC(libssh2_free)
291 {
292 (void)abstract; /* arg not used */
293 free(ptr);
294 }
295
296 /*
297 * SSH State machine related code
298 */
299 /* This is the ONLY way to change SSH state! */
state(struct connectdata * conn,sshstate nowstate)300 static void state(struct connectdata *conn, sshstate nowstate)
301 {
302 #if defined(CURLDEBUG) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
303 /* for debug purposes */
304 static const char * const names[] = {
305 "SSH_STOP",
306 "SSH_S_STARTUP",
307 "SSH_AUTHLIST",
308 "SSH_AUTH_PKEY_INIT",
309 "SSH_AUTH_PKEY",
310 "SSH_AUTH_PASS_INIT",
311 "SSH_AUTH_PASS",
312 "SSH_AUTH_HOST_INIT",
313 "SSH_AUTH_HOST",
314 "SSH_AUTH_KEY_INIT",
315 "SSH_AUTH_KEY",
316 "SSH_AUTH_DONE",
317 "SSH_SFTP_INIT",
318 "SSH_SFTP_REALPATH",
319 "SSH_SFTP_QUOTE_INIT",
320 "SSH_SFTP_POSTQUOTE_INIT",
321 "SSH_SFTP_QUOTE",
322 "SSH_SFTP_NEXT_QUOTE",
323 "SSH_SFTP_QUOTE_STAT",
324 "SSH_SFTP_QUOTE_SETSTAT",
325 "SSH_SFTP_QUOTE_SYMLINK",
326 "SSH_SFTP_QUOTE_MKDIR",
327 "SSH_SFTP_QUOTE_RENAME",
328 "SSH_SFTP_QUOTE_RMDIR",
329 "SSH_SFTP_QUOTE_UNLINK",
330 "SSH_SFTP_TRANS_INIT",
331 "SSH_SFTP_UPLOAD_INIT",
332 "SSH_SFTP_CREATE_DIRS_INIT",
333 "SSH_SFTP_CREATE_DIRS",
334 "SSH_SFTP_CREATE_DIRS_MKDIR",
335 "SSH_SFTP_READDIR_INIT",
336 "SSH_SFTP_READDIR",
337 "SSH_SFTP_READDIR_LINK",
338 "SSH_SFTP_READDIR_BOTTOM",
339 "SSH_SFTP_READDIR_DONE",
340 "SSH_SFTP_DOWNLOAD_INIT",
341 "SSH_SFTP_DOWNLOAD_STAT",
342 "SSH_SFTP_CLOSE",
343 "SSH_SFTP_SHUTDOWN",
344 "SSH_SCP_TRANS_INIT",
345 "SSH_SCP_UPLOAD_INIT",
346 "SSH_SCP_DOWNLOAD_INIT",
347 "SSH_SCP_DONE",
348 "SSH_SCP_SEND_EOF",
349 "SSH_SCP_WAIT_EOF",
350 "SSH_SCP_WAIT_CLOSE",
351 "SSH_SCP_CHANNEL_FREE",
352 "SSH_SESSION_DISCONNECT",
353 "SSH_SESSION_FREE",
354 "QUIT"
355 };
356 #endif
357 struct ssh_conn *sshc = &conn->proto.sshc;
358
359 #if defined(CURLDEBUG) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
360 if(sshc->state != nowstate) {
361 infof(conn->data, "SFTP %p state change from %s to %s\n",
362 sshc, names[sshc->state], names[nowstate]);
363 }
364 #endif
365
366 sshc->state = nowstate;
367 }
368
369 /* figure out the path to work with in this particular request */
ssh_getworkingpath(struct connectdata * conn,char * homedir,char ** path)370 static CURLcode ssh_getworkingpath(struct connectdata *conn,
371 char *homedir, /* when SFTP is used */
372 char **path) /* returns the allocated
373 real path to work with */
374 {
375 struct SessionHandle *data = conn->data;
376 char *real_path = NULL;
377 char *working_path;
378 int working_path_len;
379
380 working_path = curl_easy_unescape(data, data->state.path, 0,
381 &working_path_len);
382 if(!working_path)
383 return CURLE_OUT_OF_MEMORY;
384
385 /* Check for /~/ , indicating relative to the user's home directory */
386 if(conn->protocol & PROT_SCP) {
387 real_path = malloc(working_path_len+1);
388 if(real_path == NULL) {
389 free(working_path);
390 return CURLE_OUT_OF_MEMORY;
391 }
392 if((working_path_len > 1) && (working_path[1] == '~'))
393 /* It is referenced to the home directory, so strip the leading '/' */
394 memcpy(real_path, working_path+1, 1 + working_path_len-1);
395 else
396 memcpy(real_path, working_path, 1 + working_path_len);
397 }
398 else if(conn->protocol & PROT_SFTP) {
399 if((working_path_len > 1) && (working_path[1] == '~')) {
400 size_t homelen = strlen(homedir);
401 real_path = malloc(homelen + working_path_len + 1);
402 if(real_path == NULL) {
403 free(working_path);
404 return CURLE_OUT_OF_MEMORY;
405 }
406 /* It is referenced to the home directory, so strip the
407 leading '/' */
408 memcpy(real_path, homedir, homelen);
409 real_path[homelen] = '/';
410 real_path[homelen+1] = '\0';
411 if(working_path_len > 3) {
412 memcpy(real_path+homelen+1, working_path + 3,
413 1 + working_path_len -3);
414 }
415 }
416 else {
417 real_path = malloc(working_path_len+1);
418 if(real_path == NULL) {
419 free(working_path);
420 return CURLE_OUT_OF_MEMORY;
421 }
422 memcpy(real_path, working_path, 1+working_path_len);
423 }
424 }
425
426 free(working_path);
427
428 /* store the pointer for the caller to receive */
429 *path = real_path;
430
431 return CURLE_OK;
432 }
433
434 /*
435 * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
436 * with 32bit size_t.
437 */
438 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
439 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
440 #else
441 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, y)
442 #endif
443
444 /*
445 * ssh_statemach_act() runs the SSH statemachine "one round" and returns. The
446 * data the pointer 'block' points to will be set to TRUE if the libssh2
447 * function returns LIBSSH2_ERROR_EAGAIN meaning it wants to be called again
448 * when the socket is ready
449 */
450
ssh_statemach_act(struct connectdata * conn,bool * block)451 static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
452 {
453 CURLcode result = CURLE_OK;
454 struct SessionHandle *data = conn->data;
455 struct SSHPROTO *sftp_scp = data->state.proto.ssh;
456 struct ssh_conn *sshc = &conn->proto.sshc;
457 curl_socket_t sock = conn->sock[FIRSTSOCKET];
458 #ifdef CURL_LIBSSH2_DEBUG
459 const char *fingerprint;
460 #endif /* CURL_LIBSSH2_DEBUG */
461 const char *host_public_key_md5;
462 int rc = LIBSSH2_ERROR_NONE, i;
463 int err;
464 *block = 0; /* we're not blocking by default */
465
466 switch(sshc->state) {
467 case SSH_S_STARTUP:
468 sshc->secondCreateDirs = 0;
469 sshc->nextstate = SSH_NO_STATE;
470 sshc->actualcode = CURLE_OK;
471
472 rc = libssh2_session_startup(sshc->ssh_session, sock);
473 if(rc == LIBSSH2_ERROR_EAGAIN) {
474 break;
475 }
476 else if(rc) {
477 failf(data, "Failure establishing ssh session");
478 state(conn, SSH_SESSION_FREE);
479 sshc->actualcode = CURLE_FAILED_INIT;
480 break;
481 }
482
483 /* Set libssh2 to non-blocking, since cURL is all non-blocking */
484 libssh2_session_set_blocking(sshc->ssh_session, 0);
485
486 #ifdef CURL_LIBSSH2_DEBUG
487 /*
488 * Before we authenticate we should check the hostkey's fingerprint
489 * against our known hosts. How that is handled (reading from file,
490 * whatever) is up to us. As for know not much is implemented, besides
491 * showing how to get the fingerprint.
492 */
493 fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
494 LIBSSH2_HOSTKEY_HASH_MD5);
495
496 /* The fingerprint points to static storage (!), don't free() it. */
497 infof(data, "Fingerprint: ");
498 for (rc = 0; rc < 16; rc++) {
499 infof(data, "%02X ", (unsigned char) fingerprint[rc]);
500 }
501 infof(data, "\n");
502 #endif /* CURL_LIBSSH2_DEBUG */
503
504 /* Before we authenticate we check the hostkey's MD5 fingerprint
505 * against a known fingerprint, if available. This implementation pulls
506 * it from the curl option.
507 */
508 if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
509 strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) {
510 char buf[33];
511 host_public_key_md5 = libssh2_hostkey_hash(sshc->ssh_session,
512 LIBSSH2_HOSTKEY_HASH_MD5);
513 for (i = 0; i < 16; i++)
514 snprintf(&buf[i*2], 3, "%02x",
515 (unsigned char) host_public_key_md5[i]);
516 if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) {
517 failf(data,
518 "Denied establishing ssh session: mismatch md5 fingerprint. "
519 "Remote %s is not equal to %s",
520 buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]);
521 state(conn, SSH_SESSION_FREE);
522 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
523 break;
524 }
525 }
526
527 state(conn, SSH_AUTHLIST);
528 break;
529
530 case SSH_AUTHLIST:
531 /* TBD - methods to check the host keys need to be done */
532
533 /*
534 * Figure out authentication methods
535 * NB: As soon as we have provided a username to an openssh server we
536 * must never change it later. Thus, always specify the correct username
537 * here, even though the libssh2 docs kind of indicate that it should be
538 * possible to get a 'generic' list (not user-specific) of authentication
539 * methods, presumably with a blank username. That won't work in my
540 * experience.
541 * So always specify it here.
542 */
543 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
544 conn->user,
545 strlen(conn->user));
546
547 if(!sshc->authlist) {
548 if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
549 LIBSSH2_ERROR_EAGAIN) {
550 rc = LIBSSH2_ERROR_EAGAIN;
551 break;
552 }
553 else {
554 state(conn, SSH_SESSION_FREE);
555 sshc->actualcode = libssh2_session_error_to_CURLE(err);
556 break;
557 }
558 }
559 infof(data, "SSH authentication methods available: %s\n", sshc->authlist);
560
561 state(conn, SSH_AUTH_PKEY_INIT);
562 break;
563
564 case SSH_AUTH_PKEY_INIT:
565 /*
566 * Check the supported auth types in the order I feel is most secure
567 * with the requested type of authentication
568 */
569 sshc->authed = FALSE;
570
571 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
572 (strstr(sshc->authlist, "publickey") != NULL)) {
573 char *home;
574
575 sshc->rsa_pub = sshc->rsa = NULL;
576
577 /* To ponder about: should really the lib be messing about with the
578 HOME environment variable etc? */
579 home = curl_getenv("HOME");
580
581 if(data->set.str[STRING_SSH_PUBLIC_KEY])
582 sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]);
583 else if(home)
584 sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
585 else
586 /* as a final resort, try current dir! */
587 sshc->rsa_pub = strdup("id_dsa.pub");
588
589 if(sshc->rsa_pub == NULL) {
590 Curl_safefree(home);
591 home = NULL;
592 state(conn, SSH_SESSION_FREE);
593 sshc->actualcode = CURLE_OUT_OF_MEMORY;
594 break;
595 }
596
597 if(data->set.str[STRING_SSH_PRIVATE_KEY])
598 sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]);
599 else if(home)
600 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
601 else
602 /* as a final resort, try current dir! */
603 sshc->rsa = strdup("id_dsa");
604
605 if(sshc->rsa == NULL) {
606 Curl_safefree(home);
607 home = NULL;
608 Curl_safefree(sshc->rsa_pub);
609 sshc->rsa_pub = NULL;
610 state(conn, SSH_SESSION_FREE);
611 sshc->actualcode = CURLE_OUT_OF_MEMORY;
612 break;
613 }
614
615 sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
616 if(!sshc->passphrase)
617 sshc->passphrase = "";
618
619 Curl_safefree(home);
620 home = NULL;
621
622 infof(data, "Using ssh public key file %s\n", sshc->rsa_pub);
623 infof(data, "Using ssh private key file %s\n", sshc->rsa);
624
625 state(conn, SSH_AUTH_PKEY);
626 }
627 else {
628 state(conn, SSH_AUTH_PASS_INIT);
629 }
630 break;
631
632 case SSH_AUTH_PKEY:
633 /* The function below checks if the files exists, no need to stat() here.
634 */
635 rc = libssh2_userauth_publickey_fromfile(sshc->ssh_session,
636 conn->user, sshc->rsa_pub,
637 sshc->rsa, sshc->passphrase);
638 if(rc == LIBSSH2_ERROR_EAGAIN) {
639 break;
640 }
641
642 Curl_safefree(sshc->rsa_pub);
643 sshc->rsa_pub = NULL;
644 Curl_safefree(sshc->rsa);
645 sshc->rsa = NULL;
646
647 if(rc == 0) {
648 sshc->authed = TRUE;
649 infof(data, "Initialized SSH public key authentication\n");
650 state(conn, SSH_AUTH_DONE);
651 }
652 else {
653 char *err_msg;
654 (void)libssh2_session_last_error(sshc->ssh_session,
655 &err_msg, NULL, 0);
656 infof(data, "SSH public key authentication failed: %s\n", err_msg);
657 state(conn, SSH_AUTH_PASS_INIT);
658 }
659 break;
660
661 case SSH_AUTH_PASS_INIT:
662 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
663 (strstr(sshc->authlist, "password") != NULL)) {
664 state(conn, SSH_AUTH_PASS);
665 }
666 else {
667 state(conn, SSH_AUTH_HOST_INIT);
668 }
669 break;
670
671 case SSH_AUTH_PASS:
672 rc = libssh2_userauth_password(sshc->ssh_session, conn->user,
673 conn->passwd);
674 if(rc == LIBSSH2_ERROR_EAGAIN) {
675 break;
676 }
677 else if(rc == 0) {
678 sshc->authed = TRUE;
679 infof(data, "Initialized password authentication\n");
680 state(conn, SSH_AUTH_DONE);
681 }
682 else {
683 state(conn, SSH_AUTH_HOST_INIT);
684 }
685 break;
686
687 case SSH_AUTH_HOST_INIT:
688 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
689 (strstr(sshc->authlist, "hostbased") != NULL)) {
690 state(conn, SSH_AUTH_HOST);
691 }
692 else {
693 state(conn, SSH_AUTH_KEY_INIT);
694 }
695 break;
696
697 case SSH_AUTH_HOST:
698 state(conn, SSH_AUTH_KEY_INIT);
699 break;
700
701 case SSH_AUTH_KEY_INIT:
702 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
703 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
704 state(conn, SSH_AUTH_KEY);
705 }
706 else {
707 state(conn, SSH_AUTH_DONE);
708 }
709 break;
710
711 case SSH_AUTH_KEY:
712 /* Authentication failed. Continue with keyboard-interactive now. */
713 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
714 conn->user,
715 strlen(conn->user),
716 &kbd_callback);
717 if(rc == LIBSSH2_ERROR_EAGAIN) {
718 break;
719 }
720 else if(rc == 0) {
721 sshc->authed = TRUE;
722 infof(data, "Initialized keyboard interactive authentication\n");
723 }
724 state(conn, SSH_AUTH_DONE);
725 break;
726
727 case SSH_AUTH_DONE:
728 if(!sshc->authed) {
729 failf(data, "Authentication failure");
730 state(conn, SSH_SESSION_FREE);
731 sshc->actualcode = CURLE_LOGIN_DENIED;
732 break;
733 }
734
735 /*
736 * At this point we have an authenticated ssh session.
737 */
738 infof(data, "Authentication complete\n");
739
740 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
741
742 conn->sockfd = sock;
743 conn->writesockfd = CURL_SOCKET_BAD;
744
745 if(conn->protocol == PROT_SFTP) {
746 state(conn, SSH_SFTP_INIT);
747 break;
748 }
749 infof(data, "SSH CONNECT phase done\n");
750 state(conn, SSH_STOP);
751 break;
752
753 case SSH_SFTP_INIT:
754 /*
755 * Start the libssh2 sftp session
756 */
757 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
758 if(!sshc->sftp_session) {
759 if(libssh2_session_last_errno(sshc->ssh_session) ==
760 LIBSSH2_ERROR_EAGAIN) {
761 rc = LIBSSH2_ERROR_EAGAIN;
762 break;
763 }
764 else {
765 char *err_msg;
766
767 (void)libssh2_session_last_error(sshc->ssh_session,
768 &err_msg, NULL, 0);
769 failf(data, "Failure initializing sftp session: %s", err_msg);
770 state(conn, SSH_SESSION_FREE);
771 sshc->actualcode = CURLE_FAILED_INIT;
772 break;
773 }
774 }
775 state(conn, SSH_SFTP_REALPATH);
776 break;
777
778 case SSH_SFTP_REALPATH:
779 {
780 char tempHome[PATH_MAX];
781
782 /*
783 * Get the "home" directory
784 */
785 rc = libssh2_sftp_realpath(sshc->sftp_session, ".",
786 tempHome, PATH_MAX-1);
787 if(rc == LIBSSH2_ERROR_EAGAIN) {
788 break;
789 }
790 else if(rc > 0) {
791 /* It seems that this string is not always NULL terminated */
792 tempHome[rc] = '\0';
793 sshc->homedir = strdup(tempHome);
794 if(!sshc->homedir) {
795 state(conn, SSH_SFTP_CLOSE);
796 sshc->actualcode = CURLE_OUT_OF_MEMORY;
797 break;
798 }
799 }
800 else {
801 /* Return the error type */
802 err = libssh2_sftp_last_error(sshc->sftp_session);
803 result = sftp_libssh2_error_to_CURLE(err);
804 sshc->actualcode = result?result:CURLE_SSH;
805 DEBUGF(infof(data, "error = %d makes libcurl = %d\n", err, result));
806 state(conn, SSH_STOP);
807 break;
808 }
809 }
810 /* This is the last step in the SFTP connect phase. Do note that while
811 we get the homedir here, we get the "workingpath" in the DO action
812 since the homedir will remain the same between request but the
813 working path will not. */
814 DEBUGF(infof(data, "SSH CONNECT phase done\n"));
815 state(conn, SSH_STOP);
816 break;
817
818 case SSH_SFTP_QUOTE_INIT:
819
820 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
821 if(result) {
822 sshc->actualcode = result;
823 state(conn, SSH_STOP);
824 break;
825 }
826
827 if(data->set.quote) {
828 infof(data, "Sending quote commands\n");
829 sshc->quote_item = data->set.quote;
830 state(conn, SSH_SFTP_QUOTE);
831 }
832 else {
833 state(conn, SSH_SFTP_TRANS_INIT);
834 }
835 break;
836
837 case SSH_SFTP_POSTQUOTE_INIT:
838 if(data->set.postquote) {
839 infof(data, "Sending quote commands\n");
840 sshc->quote_item = data->set.postquote;
841 state(conn, SSH_SFTP_QUOTE);
842 }
843 else {
844 state(conn, SSH_STOP);
845 }
846 break;
847
848 case SSH_SFTP_QUOTE:
849 /* Send any quote commands */
850 {
851 const char *cp;
852
853 /*
854 * Support some of the "FTP" commands
855 */
856 if(curl_strequal("pwd", sshc->quote_item->data)) {
857 /* output debug output if that is requested */
858 if(data->set.verbose) {
859 char tmp[PATH_MAX+1];
860
861 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
862 snprintf(tmp, PATH_MAX, "257 \"%s\" is current directory.\n",
863 sftp_scp->path);
864 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
865 }
866 state(conn, SSH_SFTP_NEXT_QUOTE);
867 break;
868 }
869 else if(sshc->quote_item->data) {
870 /*
871 * the arguments following the command must be separated from the
872 * command with a space so we can check for it unconditionally
873 */
874 cp = strchr(sshc->quote_item->data, ' ');
875 if(cp == NULL) {
876 failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
877 state(conn, SSH_SFTP_CLOSE);
878 sshc->actualcode = CURLE_QUOTE_ERROR;
879 break;
880 }
881
882 /*
883 * also, every command takes at least one argument so we get that
884 * first argument right now
885 */
886 result = get_pathname(&cp, &sshc->quote_path1);
887 if(result) {
888 if(result == CURLE_OUT_OF_MEMORY)
889 failf(data, "Out of memory");
890 else
891 failf(data, "Syntax error: Bad first parameter");
892 state(conn, SSH_SFTP_CLOSE);
893 sshc->actualcode = result;
894 break;
895 }
896
897 /*
898 * SFTP is a binary protocol, so we don't send text commands to
899 * the server. Instead, we scan for commands for commands used by
900 * OpenSSH's sftp program and call the appropriate libssh2
901 * functions.
902 */
903 if(curl_strnequal(sshc->quote_item->data, "chgrp ", 6) ||
904 curl_strnequal(sshc->quote_item->data, "chmod ", 6) ||
905 curl_strnequal(sshc->quote_item->data, "chown ", 6) ) {
906 /* attribute change */
907
908 /* sshc->quote_path1 contains the mode to set */
909 /* get the destination */
910 result = get_pathname(&cp, &sshc->quote_path2);
911 if(result) {
912 if(result == CURLE_OUT_OF_MEMORY)
913 failf(data, "Out of memory");
914 else
915 failf(data, "Syntax error in chgrp/chmod/chown: "
916 "Bad second parameter");
917 Curl_safefree(sshc->quote_path1);
918 sshc->quote_path1 = NULL;
919 state(conn, SSH_SFTP_CLOSE);
920 sshc->actualcode = result;
921 break;
922 }
923 memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
924 state(conn, SSH_SFTP_QUOTE_STAT);
925 break;
926 }
927 else if(curl_strnequal(sshc->quote_item->data, "ln ", 3) ||
928 curl_strnequal(sshc->quote_item->data, "symlink ", 8)) {
929 /* symbolic linking */
930 /* sshc->quote_path1 is the source */
931 /* get the destination */
932 result = get_pathname(&cp, &sshc->quote_path2);
933 if(result) {
934 if(result == CURLE_OUT_OF_MEMORY)
935 failf(data, "Out of memory");
936 else
937 failf(data,
938 "Syntax error in ln/symlink: Bad second parameter");
939 Curl_safefree(sshc->quote_path1);
940 sshc->quote_path1 = NULL;
941 state(conn, SSH_SFTP_CLOSE);
942 sshc->actualcode = result;
943 break;
944 }
945 state(conn, SSH_SFTP_QUOTE_SYMLINK);
946 break;
947 }
948 else if(curl_strnequal(sshc->quote_item->data, "mkdir ", 6)) {
949 /* create dir */
950 state(conn, SSH_SFTP_QUOTE_MKDIR);
951 break;
952 }
953 else if(curl_strnequal(sshc->quote_item->data, "rename ", 7)) {
954 /* rename file */
955 /* first param is the source path */
956 /* second param is the dest. path */
957 result = get_pathname(&cp, &sshc->quote_path2);
958 if(result) {
959 if(result == CURLE_OUT_OF_MEMORY)
960 failf(data, "Out of memory");
961 else
962 failf(data, "Syntax error in rename: Bad second parameter");
963 Curl_safefree(sshc->quote_path1);
964 sshc->quote_path1 = NULL;
965 state(conn, SSH_SFTP_CLOSE);
966 sshc->actualcode = result;
967 break;
968 }
969 state(conn, SSH_SFTP_QUOTE_RENAME);
970 break;
971 }
972 else if(curl_strnequal(sshc->quote_item->data, "rmdir ", 6)) {
973 /* delete dir */
974 state(conn, SSH_SFTP_QUOTE_RMDIR);
975 break;
976 }
977 else if(curl_strnequal(sshc->quote_item->data, "rm ", 3)) {
978 state(conn, SSH_SFTP_QUOTE_UNLINK);
979 break;
980 }
981
982 failf(data, "Unknown SFTP command");
983 Curl_safefree(sshc->quote_path1);
984 sshc->quote_path1 = NULL;
985 Curl_safefree(sshc->quote_path2);
986 sshc->quote_path2 = NULL;
987 state(conn, SSH_SFTP_CLOSE);
988 sshc->actualcode = CURLE_QUOTE_ERROR;
989 break;
990 }
991 }
992 if(!sshc->quote_item) {
993 state(conn, SSH_SFTP_TRANS_INIT);
994 }
995 break;
996
997 case SSH_SFTP_NEXT_QUOTE:
998 if(sshc->quote_path1) {
999 Curl_safefree(sshc->quote_path1);
1000 sshc->quote_path1 = NULL;
1001 }
1002 if(sshc->quote_path2) {
1003 Curl_safefree(sshc->quote_path2);
1004 sshc->quote_path2 = NULL;
1005 }
1006
1007 sshc->quote_item = sshc->quote_item->next;
1008
1009 if(sshc->quote_item) {
1010 state(conn, SSH_SFTP_QUOTE);
1011 }
1012 else {
1013 if(sshc->nextstate != SSH_NO_STATE) {
1014 state(conn, sshc->nextstate);
1015 sshc->nextstate = SSH_NO_STATE;
1016 }
1017 else {
1018 state(conn, SSH_SFTP_TRANS_INIT);
1019 }
1020 }
1021 break;
1022
1023 case SSH_SFTP_QUOTE_STAT:
1024 if(!curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
1025 /* Since chown and chgrp only set owner OR group but libssh2 wants to
1026 * set them both at once, we need to obtain the current ownership first.
1027 * This takes an extra protocol round trip.
1028 */
1029 rc = libssh2_sftp_stat(sshc->sftp_session, sshc->quote_path2,
1030 &sshc->quote_attrs);
1031 if(rc == LIBSSH2_ERROR_EAGAIN) {
1032 break;
1033 }
1034 else if(rc != 0) { /* get those attributes */
1035 err = libssh2_sftp_last_error(sshc->sftp_session);
1036 Curl_safefree(sshc->quote_path1);
1037 sshc->quote_path1 = NULL;
1038 Curl_safefree(sshc->quote_path2);
1039 sshc->quote_path2 = NULL;
1040 failf(data, "Attempt to get SFTP stats failed: %s",
1041 sftp_libssh2_strerror(err));
1042 state(conn, SSH_SFTP_CLOSE);
1043 sshc->actualcode = CURLE_QUOTE_ERROR;
1044 break;
1045 }
1046 }
1047
1048 /* Now set the new attributes... */
1049 if(curl_strnequal(sshc->quote_item->data, "chgrp", 5)) {
1050 sshc->quote_attrs.gid = strtol(sshc->quote_path1, NULL, 10);
1051 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1052 if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
1053 Curl_safefree(sshc->quote_path1);
1054 sshc->quote_path1 = NULL;
1055 Curl_safefree(sshc->quote_path2);
1056 sshc->quote_path2 = NULL;
1057 failf(data, "Syntax error: chgrp gid not a number");
1058 state(conn, SSH_SFTP_CLOSE);
1059 sshc->actualcode = CURLE_QUOTE_ERROR;
1060 break;
1061 }
1062 }
1063 else if(curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
1064 sshc->quote_attrs.permissions = strtol(sshc->quote_path1, NULL, 8);
1065 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1066 /* permissions are octal */
1067 if(sshc->quote_attrs.permissions == 0 &&
1068 !ISDIGIT(sshc->quote_path1[0])) {
1069 Curl_safefree(sshc->quote_path1);
1070 sshc->quote_path1 = NULL;
1071 Curl_safefree(sshc->quote_path2);
1072 sshc->quote_path2 = NULL;
1073 failf(data, "Syntax error: chmod permissions not a number");
1074 state(conn, SSH_SFTP_CLOSE);
1075 sshc->actualcode = CURLE_QUOTE_ERROR;
1076 break;
1077 }
1078 }
1079 else if(curl_strnequal(sshc->quote_item->data, "chown", 5)) {
1080 sshc->quote_attrs.uid = strtol(sshc->quote_path1, NULL, 10);
1081 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1082 if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
1083 Curl_safefree(sshc->quote_path1);
1084 sshc->quote_path1 = NULL;
1085 Curl_safefree(sshc->quote_path2);
1086 sshc->quote_path2 = NULL;
1087 failf(data, "Syntax error: chown uid not a number");
1088 state(conn, SSH_SFTP_CLOSE);
1089 sshc->actualcode = CURLE_QUOTE_ERROR;
1090 break;
1091 }
1092 }
1093
1094 /* Now send the completed structure... */
1095 state(conn, SSH_SFTP_QUOTE_SETSTAT);
1096 break;
1097
1098 case SSH_SFTP_QUOTE_SETSTAT:
1099 rc = libssh2_sftp_setstat(sshc->sftp_session, sshc->quote_path2,
1100 &sshc->quote_attrs);
1101 if(rc == LIBSSH2_ERROR_EAGAIN) {
1102 break;
1103 }
1104 else if(rc != 0) {
1105 err = libssh2_sftp_last_error(sshc->sftp_session);
1106 Curl_safefree(sshc->quote_path1);
1107 sshc->quote_path1 = NULL;
1108 Curl_safefree(sshc->quote_path2);
1109 sshc->quote_path2 = NULL;
1110 failf(data, "Attempt to set SFTP stats failed: %s",
1111 sftp_libssh2_strerror(err));
1112 state(conn, SSH_SFTP_CLOSE);
1113 sshc->actualcode = CURLE_QUOTE_ERROR;
1114 break;
1115 }
1116 state(conn, SSH_SFTP_NEXT_QUOTE);
1117 break;
1118
1119 case SSH_SFTP_QUOTE_SYMLINK:
1120 rc = libssh2_sftp_symlink(sshc->sftp_session, sshc->quote_path1,
1121 sshc->quote_path2);
1122 if(rc == LIBSSH2_ERROR_EAGAIN) {
1123 break;
1124 }
1125 else if(rc != 0) {
1126 err = libssh2_sftp_last_error(sshc->sftp_session);
1127 Curl_safefree(sshc->quote_path1);
1128 sshc->quote_path1 = NULL;
1129 Curl_safefree(sshc->quote_path2);
1130 sshc->quote_path2 = NULL;
1131 failf(data, "symlink command failed: %s",
1132 sftp_libssh2_strerror(err));
1133 state(conn, SSH_SFTP_CLOSE);
1134 sshc->actualcode = CURLE_QUOTE_ERROR;
1135 break;
1136 }
1137 state(conn, SSH_SFTP_NEXT_QUOTE);
1138 break;
1139
1140 case SSH_SFTP_QUOTE_MKDIR:
1141 rc = libssh2_sftp_mkdir(sshc->sftp_session, sshc->quote_path1, 0755);
1142 if(rc == LIBSSH2_ERROR_EAGAIN) {
1143 break;
1144 }
1145 else if(rc != 0) {
1146 err = libssh2_sftp_last_error(sshc->sftp_session);
1147 Curl_safefree(sshc->quote_path1);
1148 sshc->quote_path1 = NULL;
1149 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
1150 state(conn, SSH_SFTP_CLOSE);
1151 sshc->actualcode = CURLE_QUOTE_ERROR;
1152 break;
1153 }
1154 state(conn, SSH_SFTP_NEXT_QUOTE);
1155 break;
1156
1157 case SSH_SFTP_QUOTE_RENAME:
1158 rc = libssh2_sftp_rename(sshc->sftp_session, sshc->quote_path1,
1159 sshc->quote_path2);
1160 if(rc == LIBSSH2_ERROR_EAGAIN) {
1161 break;
1162 }
1163 else if(rc != 0) {
1164 err = libssh2_sftp_last_error(sshc->sftp_session);
1165 Curl_safefree(sshc->quote_path1);
1166 sshc->quote_path1 = NULL;
1167 Curl_safefree(sshc->quote_path2);
1168 sshc->quote_path2 = NULL;
1169 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
1170 state(conn, SSH_SFTP_CLOSE);
1171 sshc->actualcode = CURLE_QUOTE_ERROR;
1172 break;
1173 }
1174 state(conn, SSH_SFTP_NEXT_QUOTE);
1175 break;
1176
1177 case SSH_SFTP_QUOTE_RMDIR:
1178 rc = libssh2_sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
1179 if(rc == LIBSSH2_ERROR_EAGAIN) {
1180 break;
1181 }
1182 else if(rc != 0) {
1183 err = libssh2_sftp_last_error(sshc->sftp_session);
1184 Curl_safefree(sshc->quote_path1);
1185 sshc->quote_path1 = NULL;
1186 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
1187 state(conn, SSH_SFTP_CLOSE);
1188 sshc->actualcode = CURLE_QUOTE_ERROR;
1189 break;
1190 }
1191 state(conn, SSH_SFTP_NEXT_QUOTE);
1192 break;
1193
1194 case SSH_SFTP_QUOTE_UNLINK:
1195 rc = libssh2_sftp_unlink(sshc->sftp_session, sshc->quote_path1);
1196 if(rc == LIBSSH2_ERROR_EAGAIN) {
1197 break;
1198 }
1199 else if(rc != 0) {
1200 err = libssh2_sftp_last_error(sshc->sftp_session);
1201 Curl_safefree(sshc->quote_path1);
1202 sshc->quote_path1 = NULL;
1203 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
1204 state(conn, SSH_SFTP_CLOSE);
1205 sshc->actualcode = CURLE_QUOTE_ERROR;
1206 break;
1207 }
1208 state(conn, SSH_SFTP_NEXT_QUOTE);
1209 break;
1210
1211 case SSH_SFTP_TRANS_INIT:
1212 if(data->set.upload)
1213 state(conn, SSH_SFTP_UPLOAD_INIT);
1214 else {
1215 if(data->set.opt_no_body)
1216 state(conn, SSH_STOP);
1217 else if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
1218 state(conn, SSH_SFTP_READDIR_INIT);
1219 else
1220 state(conn, SSH_SFTP_DOWNLOAD_INIT);
1221 }
1222 break;
1223
1224 case SSH_SFTP_UPLOAD_INIT:
1225 {
1226 unsigned long flags;
1227 /*
1228 * NOTE!!! libssh2 requires that the destination path is a full path
1229 * that includes the destination file and name OR ends in a "/"
1230 * If this is not done the destination file will be named the
1231 * same name as the last directory in the path.
1232 */
1233
1234 if(data->state.resume_from != 0) {
1235 LIBSSH2_SFTP_ATTRIBUTES attrs;
1236 if(data->state.resume_from< 0) {
1237 rc = libssh2_sftp_stat(sshc->sftp_session, sftp_scp->path, &attrs);
1238 if(rc == LIBSSH2_ERROR_EAGAIN) {
1239 break;
1240 }
1241 else if(rc) {
1242 data->state.resume_from = 0;
1243 }
1244 else {
1245 data->state.resume_from = attrs.filesize;
1246 }
1247 }
1248 }
1249
1250 if(data->set.ftp_append)
1251 /* Try to open for append, but create if nonexisting */
1252 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
1253 else if (data->state.resume_from > 0)
1254 /* If we have restart position then open for append */
1255 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
1256 else
1257 /* Clear file before writing (normal behaviour) */
1258 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
1259
1260 sshc->sftp_handle =
1261 libssh2_sftp_open(sshc->sftp_session, sftp_scp->path,
1262 flags, data->set.new_file_perms);
1263
1264 if(!sshc->sftp_handle) {
1265 rc = libssh2_session_last_errno(sshc->ssh_session);
1266
1267 if(LIBSSH2_ERROR_EAGAIN == rc)
1268 break;
1269 else {
1270 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
1271 /* only when there was an SFTP protocol error can we extract
1272 the sftp error! */
1273 err = libssh2_sftp_last_error(sshc->sftp_session);
1274 else
1275 err = -1; /* not an sftp error at all */
1276
1277 if(sshc->secondCreateDirs) {
1278 state(conn, SSH_SFTP_CLOSE);
1279 sshc->actualcode = err>= LIBSSH2_FX_OK?
1280 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1281 failf(data, "Creating the dir/file failed: %s",
1282 sftp_libssh2_strerror(err));
1283 break;
1284 }
1285 else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
1286 (err == LIBSSH2_FX_FAILURE) ||
1287 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
1288 (data->set.ftp_create_missing_dirs &&
1289 (strlen(sftp_scp->path) > 1))) {
1290 /* try to create the path remotely */
1291 sshc->secondCreateDirs = 1;
1292 state(conn, SSH_SFTP_CREATE_DIRS_INIT);
1293 break;
1294 }
1295 state(conn, SSH_SFTP_CLOSE);
1296 sshc->actualcode = err>= LIBSSH2_FX_OK?
1297 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
1298 if(!sshc->actualcode) {
1299 /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
1300 even though libssh2_sftp_open() failed previously! We need to
1301 work around that! */
1302 sshc->actualcode = CURLE_SSH;
1303 err=-1;
1304 }
1305 failf(data, "Upload failed: %s (%d/%d)",
1306 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
1307 err, rc);
1308 break;
1309 }
1310 }
1311
1312 /* If we have restart point then we need to seek to the correct position. */
1313 if(data->state.resume_from > 0) {
1314 /* Let's read off the proper amount of bytes from the input. */
1315 if(conn->seek_func) {
1316 curl_off_t readthisamountnow = data->state.resume_from;
1317
1318 if(conn->seek_func(conn->seek_client,
1319 readthisamountnow, SEEK_SET) != 0) {
1320 failf(data, "Could not seek stream");
1321 return CURLE_FTP_COULDNT_USE_REST;
1322 }
1323 }
1324 else {
1325 curl_off_t passed=0;
1326 curl_off_t readthisamountnow;
1327 curl_off_t actuallyread;
1328 do {
1329 readthisamountnow = (data->state.resume_from - passed);
1330
1331 if(readthisamountnow > BUFSIZE)
1332 readthisamountnow = BUFSIZE;
1333
1334 actuallyread =
1335 (curl_off_t) conn->fread_func(data->state.buffer, 1,
1336 (size_t)readthisamountnow,
1337 conn->fread_in);
1338
1339 passed += actuallyread;
1340 if((actuallyread <= 0) || (actuallyread > readthisamountnow)) {
1341 /* this checks for greater-than only to make sure that the
1342 CURL_READFUNC_ABORT return code still aborts */
1343 failf(data, "Failed to read data");
1344 return CURLE_FTP_COULDNT_USE_REST;
1345 }
1346 } while(passed < data->state.resume_from);
1347 }
1348
1349 /* now, decrease the size of the read */
1350 if(data->set.infilesize>0) {
1351 data->set.infilesize -= data->state.resume_from;
1352 data->req.size = data->set.infilesize;
1353 Curl_pgrsSetUploadSize(data, data->set.infilesize);
1354 }
1355
1356 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1357 }
1358 if(data->set.infilesize>0) {
1359 data->req.size = data->set.infilesize;
1360 Curl_pgrsSetUploadSize(data, data->set.infilesize);
1361 }
1362 /* upload data */
1363 result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
1364 FIRSTSOCKET, NULL);
1365
1366 if(result) {
1367 state(conn, SSH_SFTP_CLOSE);
1368 sshc->actualcode = result;
1369 }
1370 else {
1371 /* store this original bitmask setup to use later on if we can't figure
1372 out a "real" bitmask */
1373 sshc->orig_waitfor = data->req.keepon;
1374
1375 state(conn, SSH_STOP);
1376 }
1377 break;
1378 }
1379
1380 case SSH_SFTP_CREATE_DIRS_INIT:
1381 if(strlen(sftp_scp->path) > 1) {
1382 sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
1383 state(conn, SSH_SFTP_CREATE_DIRS);
1384 }
1385 else {
1386 state(conn, SSH_SFTP_UPLOAD_INIT);
1387 }
1388 break;
1389
1390 case SSH_SFTP_CREATE_DIRS:
1391 if((sshc->slash_pos = strchr(sshc->slash_pos, '/')) != NULL) {
1392 *sshc->slash_pos = 0;
1393
1394 infof(data, "Creating directory '%s'\n", sftp_scp->path);
1395 state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
1396 break;
1397 }
1398 else {
1399 state(conn, SSH_SFTP_UPLOAD_INIT);
1400 }
1401 break;
1402
1403 case SSH_SFTP_CREATE_DIRS_MKDIR:
1404 /* 'mode' - parameter is preliminary - default to 0644 */
1405 rc = libssh2_sftp_mkdir(sshc->sftp_session, sftp_scp->path,
1406 data->set.new_directory_perms);
1407 if(rc == LIBSSH2_ERROR_EAGAIN) {
1408 break;
1409 }
1410 *sshc->slash_pos = '/';
1411 ++sshc->slash_pos;
1412 if(rc == -1) {
1413 unsigned int sftp_err = 0;
1414 /*
1415 * abort if failure wasn't that the dir already exists or the
1416 * permission was denied (creation might succeed further
1417 * down the path) - retry on unspecific FAILURE also
1418 */
1419 sftp_err = libssh2_sftp_last_error(sshc->sftp_session);
1420 if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
1421 (sftp_err != LIBSSH2_FX_FAILURE) &&
1422 (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) {
1423 result = sftp_libssh2_error_to_CURLE(sftp_err);
1424 state(conn, SSH_SFTP_CLOSE);
1425 sshc->actualcode = result?result:CURLE_SSH;
1426 break;
1427 }
1428 }
1429 state(conn, SSH_SFTP_CREATE_DIRS);
1430 break;
1431
1432 case SSH_SFTP_READDIR_INIT:
1433 /*
1434 * This is a directory that we are trying to get, so produce a
1435 * directory listing
1436 */
1437 sshc->sftp_handle = libssh2_sftp_opendir(sshc->sftp_session,
1438 sftp_scp->path);
1439 if(!sshc->sftp_handle) {
1440 if(libssh2_session_last_errno(sshc->ssh_session) ==
1441 LIBSSH2_ERROR_EAGAIN) {
1442 rc = LIBSSH2_ERROR_EAGAIN;
1443 break;
1444 }
1445 else {
1446 err = libssh2_sftp_last_error(sshc->sftp_session);
1447 failf(data, "Could not open directory for reading: %s",
1448 sftp_libssh2_strerror(err));
1449 state(conn, SSH_SFTP_CLOSE);
1450 result = sftp_libssh2_error_to_CURLE(err);
1451 sshc->actualcode = result?result:CURLE_SSH;
1452 break;
1453 }
1454 }
1455 if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
1456 state(conn, SSH_SFTP_CLOSE);
1457 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1458 break;
1459 }
1460 if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
1461 Curl_safefree(sshc->readdir_filename);
1462 sshc->readdir_filename = NULL;
1463 state(conn, SSH_SFTP_CLOSE);
1464 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1465 break;
1466 }
1467 state(conn, SSH_SFTP_READDIR);
1468 break;
1469
1470 case SSH_SFTP_READDIR:
1471 sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
1472 sshc->readdir_filename,
1473 PATH_MAX,
1474 sshc->readdir_longentry,
1475 PATH_MAX,
1476 &sshc->readdir_attrs);
1477 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
1478 rc = LIBSSH2_ERROR_EAGAIN;
1479 break;
1480 }
1481 if(sshc->readdir_len > 0) {
1482 sshc->readdir_filename[sshc->readdir_len] = '\0';
1483
1484 if(data->set.ftp_list_only) {
1485 char *tmpLine;
1486
1487 tmpLine = aprintf("%s\n", sshc->readdir_filename);
1488 if(tmpLine == NULL) {
1489 state(conn, SSH_SFTP_CLOSE);
1490 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1491 break;
1492 }
1493 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1494 tmpLine, sshc->readdir_len+1);
1495 Curl_safefree(tmpLine);
1496
1497 if(result) {
1498 state(conn, SSH_STOP);
1499 break;
1500 }
1501 /* since this counts what we send to the client, we include the newline
1502 in this counter */
1503 data->req.bytecount += sshc->readdir_len+1;
1504
1505 /* output debug output if that is requested */
1506 if(data->set.verbose) {
1507 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
1508 sshc->readdir_len, conn);
1509 }
1510 }
1511 else {
1512 sshc->readdir_currLen = strlen(sshc->readdir_longentry);
1513 sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
1514 sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
1515 if(!sshc->readdir_line) {
1516 Curl_safefree(sshc->readdir_filename);
1517 sshc->readdir_filename = NULL;
1518 Curl_safefree(sshc->readdir_longentry);
1519 sshc->readdir_longentry = NULL;
1520 state(conn, SSH_SFTP_CLOSE);
1521 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1522 break;
1523 }
1524
1525 memcpy(sshc->readdir_line, sshc->readdir_longentry,
1526 sshc->readdir_currLen);
1527 if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
1528 ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
1529 LIBSSH2_SFTP_S_IFLNK)) {
1530 sshc->readdir_linkPath = malloc(PATH_MAX + 1);
1531 if(sshc->readdir_linkPath == NULL) {
1532 Curl_safefree(sshc->readdir_filename);
1533 sshc->readdir_filename = NULL;
1534 Curl_safefree(sshc->readdir_longentry);
1535 sshc->readdir_longentry = NULL;
1536 state(conn, SSH_SFTP_CLOSE);
1537 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1538 break;
1539 }
1540
1541 snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
1542 sshc->readdir_filename);
1543 state(conn, SSH_SFTP_READDIR_LINK);
1544 break;
1545 }
1546 state(conn, SSH_SFTP_READDIR_BOTTOM);
1547 break;
1548 }
1549 }
1550 else if(sshc->readdir_len == 0) {
1551 Curl_safefree(sshc->readdir_filename);
1552 sshc->readdir_filename = NULL;
1553 Curl_safefree(sshc->readdir_longentry);
1554 sshc->readdir_longentry = NULL;
1555 state(conn, SSH_SFTP_READDIR_DONE);
1556 break;
1557 }
1558 else if(sshc->readdir_len <= 0) {
1559 err = libssh2_sftp_last_error(sshc->sftp_session);
1560 result = sftp_libssh2_error_to_CURLE(err);
1561 sshc->actualcode = result?result:CURLE_SSH;
1562 failf(data, "Could not open remote file for reading: %s :: %d",
1563 sftp_libssh2_strerror(err),
1564 libssh2_session_last_errno(sshc->ssh_session));
1565 Curl_safefree(sshc->readdir_filename);
1566 sshc->readdir_filename = NULL;
1567 Curl_safefree(sshc->readdir_longentry);
1568 sshc->readdir_longentry = NULL;
1569 state(conn, SSH_SFTP_CLOSE);
1570 break;
1571 }
1572 break;
1573
1574 case SSH_SFTP_READDIR_LINK:
1575 sshc->readdir_len = libssh2_sftp_readlink(sshc->sftp_session,
1576 sshc->readdir_linkPath,
1577 sshc->readdir_filename,
1578 PATH_MAX);
1579 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
1580 rc = LIBSSH2_ERROR_EAGAIN;
1581 break;
1582 }
1583 Curl_safefree(sshc->readdir_linkPath);
1584 sshc->readdir_linkPath = NULL;
1585 sshc->readdir_line = realloc(sshc->readdir_line,
1586 sshc->readdir_totalLen + 4 +
1587 sshc->readdir_len);
1588 if(!sshc->readdir_line) {
1589 Curl_safefree(sshc->readdir_filename);
1590 sshc->readdir_filename = NULL;
1591 Curl_safefree(sshc->readdir_longentry);
1592 sshc->readdir_longentry = NULL;
1593 state(conn, SSH_SFTP_CLOSE);
1594 sshc->actualcode = CURLE_OUT_OF_MEMORY;
1595 break;
1596 }
1597
1598 sshc->readdir_currLen += snprintf(sshc->readdir_line +
1599 sshc->readdir_currLen,
1600 sshc->readdir_totalLen -
1601 sshc->readdir_currLen,
1602 " -> %s",
1603 sshc->readdir_filename);
1604
1605 state(conn, SSH_SFTP_READDIR_BOTTOM);
1606 break;
1607
1608 case SSH_SFTP_READDIR_BOTTOM:
1609 sshc->readdir_currLen += snprintf(sshc->readdir_line +
1610 sshc->readdir_currLen,
1611 sshc->readdir_totalLen -
1612 sshc->readdir_currLen, "\n");
1613 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1614 sshc->readdir_line,
1615 sshc->readdir_currLen);
1616
1617 if(result == CURLE_OK) {
1618
1619 /* output debug output if that is requested */
1620 if(data->set.verbose) {
1621 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
1622 sshc->readdir_currLen, conn);
1623 }
1624 data->req.bytecount += sshc->readdir_currLen;
1625 }
1626 Curl_safefree(sshc->readdir_line);
1627 sshc->readdir_line = NULL;
1628 if(result) {
1629 state(conn, SSH_STOP);
1630 }
1631 else
1632 state(conn, SSH_SFTP_READDIR);
1633 break;
1634
1635 case SSH_SFTP_READDIR_DONE:
1636 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
1637 LIBSSH2_ERROR_EAGAIN) {
1638 rc = LIBSSH2_ERROR_EAGAIN;
1639 break;
1640 }
1641 sshc->sftp_handle = NULL;
1642 Curl_safefree(sshc->readdir_filename);
1643 sshc->readdir_filename = NULL;
1644 Curl_safefree(sshc->readdir_longentry);
1645 sshc->readdir_longentry = NULL;
1646
1647 /* no data to transfer */
1648 result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1649 state(conn, SSH_STOP);
1650 break;
1651
1652 case SSH_SFTP_DOWNLOAD_INIT:
1653 /*
1654 * Work on getting the specified file
1655 */
1656 sshc->sftp_handle =
1657 libssh2_sftp_open(sshc->sftp_session, sftp_scp->path,
1658 LIBSSH2_FXF_READ, data->set.new_file_perms);
1659 if(!sshc->sftp_handle) {
1660 if(libssh2_session_last_errno(sshc->ssh_session) ==
1661 LIBSSH2_ERROR_EAGAIN) {
1662 rc = LIBSSH2_ERROR_EAGAIN;
1663 break;
1664 }
1665 else {
1666 err = libssh2_sftp_last_error(sshc->sftp_session);
1667 failf(data, "Could not open remote file for reading: %s",
1668 sftp_libssh2_strerror(err));
1669 state(conn, SSH_SFTP_CLOSE);
1670 result = sftp_libssh2_error_to_CURLE(err);
1671 sshc->actualcode = result?result:CURLE_SSH;
1672 break;
1673 }
1674 }
1675 state(conn, SSH_SFTP_DOWNLOAD_STAT);
1676 break;
1677
1678 case SSH_SFTP_DOWNLOAD_STAT:
1679 {
1680 LIBSSH2_SFTP_ATTRIBUTES attrs;
1681
1682 rc = libssh2_sftp_stat(sshc->sftp_session, sftp_scp->path, &attrs);
1683 if(rc == LIBSSH2_ERROR_EAGAIN) {
1684 break;
1685 }
1686 else if(rc) {
1687 /*
1688 * libssh2_sftp_open() didn't return an error, so maybe the server
1689 * just doesn't support stat()
1690 */
1691 data->req.size = -1;
1692 data->req.maxdownload = -1;
1693 }
1694 else {
1695 curl_off_t size;
1696
1697 size = attrs.filesize;
1698 if(conn->data->state.use_range) {
1699 curl_off_t from, to;
1700 char *ptr;
1701 char *ptr2;
1702
1703 from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
1704 while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))
1705 ptr++;
1706 to=curlx_strtoofft(ptr, &ptr2, 0);
1707 if((ptr == ptr2) /* no "to" value given */
1708 || (to >= size)) {
1709 to = size - 1;
1710 }
1711 if(from < 0) {
1712 /* from is relative to end of file */
1713 from += size;
1714 }
1715 if(from >= size) {
1716 failf(data, "Offset (%"
1717 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")",
1718 from, attrs.filesize);
1719 return CURLE_BAD_DOWNLOAD_RESUME;
1720 }
1721 if(from > to) {
1722 from = to;
1723 size = 0;
1724 }
1725 else {
1726 size = to - from + 1;
1727 }
1728
1729 SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
1730 }
1731 data->req.size = size;
1732 data->req.maxdownload = size;
1733 Curl_pgrsSetDownloadSize(data, size);
1734 }
1735
1736 /* We can resume if we can seek to the resume position */
1737 if(data->state.resume_from) {
1738 if(data->state.resume_from< 0) {
1739 /* We're supposed to download the last abs(from) bytes */
1740 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
1741 failf(data, "Offset (%"
1742 FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")",
1743 data->state.resume_from, attrs.filesize);
1744 return CURLE_BAD_DOWNLOAD_RESUME;
1745 }
1746 /* download from where? */
1747 data->state.resume_from = attrs.filesize - data->state.resume_from;
1748 }
1749 else {
1750 if((curl_off_t)attrs.filesize < data->state.resume_from) {
1751 failf(data, "Offset (%" FORMAT_OFF_T
1752 ") was beyond file size (%" FORMAT_OFF_T ")",
1753 data->state.resume_from, attrs.filesize);
1754 return CURLE_BAD_DOWNLOAD_RESUME;
1755 }
1756 }
1757 /* Does a completed file need to be seeked and started or closed ? */
1758 /* Now store the number of bytes we are expected to download */
1759 data->req.size = attrs.filesize - data->state.resume_from;
1760 data->req.maxdownload = attrs.filesize - data->state.resume_from;
1761 Curl_pgrsSetDownloadSize(data,
1762 attrs.filesize - data->state.resume_from);
1763 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
1764 }
1765 }
1766 /* Setup the actual download */
1767 if(data->req.size == 0) {
1768 /* no data to transfer */
1769 result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1770 infof(data, "File already completely downloaded\n");
1771 state(conn, SSH_STOP);
1772 break;
1773 }
1774 else {
1775 result = Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
1776 FALSE, NULL, -1, NULL);
1777 }
1778 if(result) {
1779 state(conn, SSH_SFTP_CLOSE);
1780 sshc->actualcode = result;
1781 }
1782 else {
1783 state(conn, SSH_STOP);
1784 }
1785 break;
1786
1787 case SSH_SFTP_CLOSE:
1788 if(sshc->sftp_handle) {
1789 rc = libssh2_sftp_close(sshc->sftp_handle);
1790 if(rc == LIBSSH2_ERROR_EAGAIN) {
1791 break;
1792 }
1793 else if(rc < 0) {
1794 infof(data, "Failed to close libssh2 file\n");
1795 }
1796 sshc->sftp_handle = NULL;
1797 }
1798 Curl_safefree(sftp_scp->path);
1799 sftp_scp->path = NULL;
1800
1801 DEBUGF(infof(data, "SFTP DONE done\n"));
1802 #if 0 /* PREV */
1803 state(conn, SSH_SFTP_SHUTDOWN);
1804 #endif
1805 state(conn, SSH_STOP);
1806 result = sshc->actualcode;
1807 break;
1808
1809 case SSH_SFTP_SHUTDOWN:
1810 /* during times we get here due to a broken transfer and then the
1811 sftp_handle might not have been taken down so make sure that is done
1812 before we proceed */
1813
1814 if(sshc->sftp_handle) {
1815 rc = libssh2_sftp_close(sshc->sftp_handle);
1816 if(rc == LIBSSH2_ERROR_EAGAIN) {
1817 break;
1818 }
1819 else if(rc < 0) {
1820 infof(data, "Failed to close libssh2 file\n");
1821 }
1822 sshc->sftp_handle = NULL;
1823 }
1824 if(sshc->sftp_session) {
1825 rc = libssh2_sftp_shutdown(sshc->sftp_session);
1826 if(rc == LIBSSH2_ERROR_EAGAIN) {
1827 break;
1828 }
1829 else if(rc < 0) {
1830 infof(data, "Failed to stop libssh2 sftp subsystem\n");
1831 }
1832 sshc->sftp_session = NULL;
1833 }
1834
1835 Curl_safefree(sshc->homedir);
1836 sshc->homedir = NULL;
1837
1838 state(conn, SSH_SESSION_DISCONNECT);
1839 break;
1840
1841 case SSH_SCP_TRANS_INIT:
1842 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
1843 if(result) {
1844 sshc->actualcode = result;
1845 state(conn, SSH_STOP);
1846 break;
1847 }
1848
1849 if(data->set.upload) {
1850 if(data->set.infilesize < 0) {
1851 failf(data, "SCP requires a known file size for upload");
1852 sshc->actualcode = CURLE_UPLOAD_FAILED;
1853 state(conn, SSH_SCP_CHANNEL_FREE);
1854 break;
1855 }
1856 state(conn, SSH_SCP_UPLOAD_INIT);
1857 }
1858 else {
1859 state(conn, SSH_SCP_DOWNLOAD_INIT);
1860 }
1861 break;
1862
1863 case SSH_SCP_UPLOAD_INIT:
1864 /*
1865 * libssh2 requires that the destination path is a full path that
1866 * includes the destination file and name OR ends in a "/" . If this is
1867 * not done the destination file will be named the same name as the last
1868 * directory in the path.
1869 */
1870 sshc->ssh_channel =
1871 libssh2_scp_send_ex(sshc->ssh_session, sftp_scp->path,
1872 data->set.new_file_perms,
1873 data->set.infilesize, 0, 0);
1874 if(!sshc->ssh_channel) {
1875 if(libssh2_session_last_errno(sshc->ssh_session) ==
1876 LIBSSH2_ERROR_EAGAIN) {
1877 rc = LIBSSH2_ERROR_EAGAIN;
1878 break;
1879 }
1880 else {
1881 int ssh_err;
1882 char *err_msg;
1883
1884 ssh_err = libssh2_session_last_error(sshc->ssh_session,
1885 &err_msg, NULL, 0);
1886 failf(conn->data, "%s", err_msg);
1887 state(conn, SSH_SCP_CHANNEL_FREE);
1888 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
1889 break;
1890 }
1891 }
1892
1893 /* upload data */
1894 result = Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
1895 FIRSTSOCKET, NULL);
1896
1897 if(result) {
1898 state(conn, SSH_SCP_CHANNEL_FREE);
1899 sshc->actualcode = result;
1900 }
1901 else {
1902 state(conn, SSH_STOP);
1903 }
1904 break;
1905
1906 case SSH_SCP_DOWNLOAD_INIT:
1907 {
1908 /*
1909 * We must check the remote file; if it is a directory no values will
1910 * be set in sb
1911 */
1912 struct stat sb;
1913 curl_off_t bytecount;
1914
1915 /* clear the struct scp recv will fill in */
1916 memset(&sb, 0, sizeof(struct stat));
1917
1918 /* get a fresh new channel from the ssh layer */
1919 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
1920 sftp_scp->path, &sb);
1921 if(!sshc->ssh_channel) {
1922 if(libssh2_session_last_errno(sshc->ssh_session) ==
1923 LIBSSH2_ERROR_EAGAIN) {
1924 rc = LIBSSH2_ERROR_EAGAIN;
1925 break;
1926 }
1927 else {
1928 int ssh_err;
1929 char *err_msg;
1930
1931 ssh_err = libssh2_session_last_error(sshc->ssh_session,
1932 &err_msg, NULL, 0);
1933 failf(conn->data, "%s", err_msg);
1934 state(conn, SSH_SCP_CHANNEL_FREE);
1935 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
1936 break;
1937 }
1938 }
1939
1940 /* download data */
1941 bytecount = (curl_off_t)sb.st_size;
1942 data->req.maxdownload = (curl_off_t)sb.st_size;
1943 result = Curl_setup_transfer(conn, FIRSTSOCKET,
1944 bytecount, FALSE, NULL, -1, NULL);
1945
1946 if(result) {
1947 state(conn, SSH_SCP_CHANNEL_FREE);
1948 sshc->actualcode = result;
1949 }
1950 else
1951 state(conn, SSH_STOP);
1952 }
1953 break;
1954
1955 case SSH_SCP_DONE:
1956 if(data->set.upload)
1957 state(conn, SSH_SCP_SEND_EOF);
1958 else
1959 state(conn, SSH_SCP_CHANNEL_FREE);
1960 break;
1961
1962 case SSH_SCP_SEND_EOF:
1963 if(sshc->ssh_channel) {
1964 rc = libssh2_channel_send_eof(sshc->ssh_channel);
1965 if(rc == LIBSSH2_ERROR_EAGAIN) {
1966 break;
1967 }
1968 else if(rc) {
1969 infof(data, "Failed to send libssh2 channel EOF\n");
1970 }
1971 }
1972 state(conn, SSH_SCP_WAIT_EOF);
1973 break;
1974
1975 case SSH_SCP_WAIT_EOF:
1976 if(sshc->ssh_channel) {
1977 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
1978 if(rc == LIBSSH2_ERROR_EAGAIN) {
1979 break;
1980 }
1981 else if(rc) {
1982 infof(data, "Failed to get channel EOF: %d\n", rc);
1983 }
1984 }
1985 state(conn, SSH_SCP_WAIT_CLOSE);
1986 break;
1987
1988 case SSH_SCP_WAIT_CLOSE:
1989 if(sshc->ssh_channel) {
1990 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
1991 if(rc == LIBSSH2_ERROR_EAGAIN) {
1992 break;
1993 }
1994 else if(rc) {
1995 infof(data, "Channel failed to close: %d\n", rc);
1996 }
1997 }
1998 state(conn, SSH_SCP_CHANNEL_FREE);
1999 break;
2000
2001 case SSH_SCP_CHANNEL_FREE:
2002 if(sshc->ssh_channel) {
2003 rc = libssh2_channel_free(sshc->ssh_channel);
2004 if(rc == LIBSSH2_ERROR_EAGAIN) {
2005 break;
2006 }
2007 else if(rc < 0) {
2008 infof(data, "Failed to free libssh2 scp subsystem\n");
2009 }
2010 sshc->ssh_channel = NULL;
2011 }
2012 DEBUGF(infof(data, "SCP DONE phase complete\n"));
2013 #if 0 /* PREV */
2014 state(conn, SSH_SESSION_DISCONNECT);
2015 #endif
2016 state(conn, SSH_STOP);
2017 result = sshc->actualcode;
2018 break;
2019
2020 case SSH_SESSION_DISCONNECT:
2021 /* during weird times when we've been prematurely aborted, the channel
2022 is still alive when we reach this state and we MUST kill the channel
2023 properly first */
2024 if(sshc->ssh_channel) {
2025 rc = libssh2_channel_free(sshc->ssh_channel);
2026 if(rc == LIBSSH2_ERROR_EAGAIN) {
2027 break;
2028 }
2029 else if(rc < 0) {
2030 infof(data, "Failed to free libssh2 scp subsystem\n");
2031 }
2032 sshc->ssh_channel = NULL;
2033 }
2034
2035 if(sshc->ssh_session) {
2036 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2037 if(rc == LIBSSH2_ERROR_EAGAIN) {
2038 break;
2039 }
2040 else if(rc < 0) {
2041 infof(data, "Failed to disconnect libssh2 session\n");
2042 }
2043 }
2044
2045 Curl_safefree(sshc->homedir);
2046 sshc->homedir = NULL;
2047
2048 state(conn, SSH_SESSION_FREE);
2049 break;
2050
2051 case SSH_SESSION_FREE:
2052 if(sshc->ssh_session) {
2053 rc = libssh2_session_free(sshc->ssh_session);
2054 if(rc == LIBSSH2_ERROR_EAGAIN) {
2055 break;
2056 }
2057 else if(rc < 0) {
2058 infof(data, "Failed to free libssh2 session\n");
2059 }
2060 sshc->ssh_session = NULL;
2061 }
2062 sshc->nextstate = SSH_NO_STATE;
2063 state(conn, SSH_STOP);
2064 result = sshc->actualcode;
2065 break;
2066
2067 case SSH_QUIT:
2068 /* fallthrough, just stop! */
2069 default:
2070 /* internal error */
2071 sshc->nextstate = SSH_NO_STATE;
2072 state(conn, SSH_STOP);
2073 break;
2074 }
2075
2076 if(rc == LIBSSH2_ERROR_EAGAIN) {
2077 /* we would block, we need to wait for the socket to be ready (in the
2078 right direction too)! */
2079 *block = TRUE;
2080 }
2081
2082 return result;
2083 }
2084
2085 /* called by the multi interface to figure out what socket(s) to wait for and
2086 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
ssh_perform_getsock(const struct connectdata * conn,curl_socket_t * sock,int numsocks)2087 static int ssh_perform_getsock(const struct connectdata *conn,
2088 curl_socket_t *sock, /* points to numsocks
2089 number of sockets */
2090 int numsocks)
2091 {
2092 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTIONS
2093 int bitmap = GETSOCK_BLANK;
2094 (void)numsocks;
2095
2096 sock[0] = conn->sock[FIRSTSOCKET];
2097
2098 if(conn->proto.sshc.waitfor & KEEP_READ)
2099 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
2100
2101 if(conn->proto.sshc.waitfor & KEEP_WRITE)
2102 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
2103
2104 return bitmap;
2105 #else
2106 /* if we don't know the direction we can use the generic *_getsock()
2107 function even for the protocol_connect and doing states */
2108 return Curl_single_getsock(conn, sock, numsocks);
2109 #endif
2110 }
2111
2112 /* Generic function called by the multi interface to figure out what socket(s)
2113 to wait for and for what actions during the DOING and PROTOCONNECT states*/
ssh_getsock(struct connectdata * conn,curl_socket_t * sock,int numsocks)2114 static int ssh_getsock(struct connectdata *conn,
2115 curl_socket_t *sock, /* points to numsocks number
2116 of sockets */
2117 int numsocks)
2118 {
2119 #ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTIONS
2120 (void)conn;
2121 (void)sock;
2122 (void)numsocks;
2123 /* if we don't know any direction we can just play along as we used to and
2124 not provide any sensible info */
2125 return GETSOCK_BLANK;
2126 #else
2127 /* if we know the direction we can use the generic *_getsock() function even
2128 for the protocol_connect and doing states */
2129 return ssh_perform_getsock(conn, sock, numsocks);
2130 #endif
2131 }
2132
2133 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTIONS
2134 /*
2135 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
2136 * function is used to figure out in what direction and stores this info so
2137 * that the multi interface can take advantage of it. Make sure to call this
2138 * function in all cases so that when it _doesn't_ return EAGAIN we can
2139 * restore the default wait bits.
2140 */
ssh_block2waitfor(struct connectdata * conn,bool block)2141 static void ssh_block2waitfor(struct connectdata *conn, bool block)
2142 {
2143 struct ssh_conn *sshc = &conn->proto.sshc;
2144 int dir;
2145 if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
2146 /* translate the libssh2 define bits into our own bit defines */
2147 sshc->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_READ:0) |
2148 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_WRITE:0);
2149 }
2150 else
2151 /* It didn't block or libssh2 didn't reveal in which direction, put back
2152 the original set */
2153 sshc->waitfor = sshc->orig_waitfor;
2154 }
2155 #else
2156 /* no libssh2 directional support so we simply don't know */
2157 #define ssh_block2waitfor(x,y)
2158 #endif
2159
2160 /* called repeatedly until done from multi.c */
ssh_multi_statemach(struct connectdata * conn,bool * done)2161 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
2162 {
2163 struct ssh_conn *sshc = &conn->proto.sshc;
2164 CURLcode result = CURLE_OK;
2165 bool block; /* we store the status and use that to provide a ssh_getsock()
2166 implementation */
2167
2168 result = ssh_statemach_act(conn, &block);
2169 *done = (bool)(sshc->state == SSH_STOP);
2170 ssh_block2waitfor(conn, block);
2171
2172 return result;
2173 }
2174
ssh_easy_statemach(struct connectdata * conn)2175 static CURLcode ssh_easy_statemach(struct connectdata *conn)
2176 {
2177 struct ssh_conn *sshc = &conn->proto.sshc;
2178 CURLcode result = CURLE_OK;
2179
2180 while((sshc->state != SSH_STOP) && !result) {
2181 bool block;
2182 result = ssh_statemach_act(conn, &block);
2183
2184 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTIONS
2185 if((CURLE_OK == result) && block) {
2186 int dir = libssh2_session_block_directions(sshc->ssh_session);
2187 curl_socket_t sock = conn->sock[FIRSTSOCKET];
2188 curl_socket_t fd_read = CURL_SOCKET_BAD;
2189 curl_socket_t fd_write = CURL_SOCKET_BAD;
2190 if (LIBSSH2_SESSION_BLOCK_INBOUND & dir) {
2191 fd_read = sock;
2192 }
2193 if (LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) {
2194 fd_write = sock;
2195 }
2196 /* wait for the socket to become ready */
2197 Curl_socket_ready(fd_read, fd_write, 1000); /* ignore result */
2198 }
2199 #endif
2200
2201 }
2202
2203 return result;
2204 }
2205
2206 /*
2207 * SSH setup and connection
2208 */
ssh_init(struct connectdata * conn)2209 static CURLcode ssh_init(struct connectdata *conn)
2210 {
2211 struct SessionHandle *data = conn->data;
2212 struct SSHPROTO *ssh;
2213 struct ssh_conn *sshc = &conn->proto.sshc;
2214
2215 sshc->actualcode = CURLE_OK; /* reset error code */
2216 sshc->secondCreateDirs =0; /* reset the create dir attempt state variable */
2217
2218 if(data->state.proto.ssh)
2219 return CURLE_OK;
2220
2221 ssh = calloc(sizeof(struct SSHPROTO), 1);
2222 if(!ssh)
2223 return CURLE_OUT_OF_MEMORY;
2224
2225 data->state.proto.ssh = ssh;
2226
2227 return CURLE_OK;
2228 }
2229
2230 /*
2231 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
2232 * do protocol-specific actions at connect-time.
2233 */
ssh_connect(struct connectdata * conn,bool * done)2234 static CURLcode ssh_connect(struct connectdata *conn, bool *done)
2235 {
2236 #ifdef CURL_LIBSSH2_DEBUG
2237 curl_socket_t sock;
2238 #endif
2239 struct ssh_conn *ssh;
2240 CURLcode result;
2241 struct SessionHandle *data = conn->data;
2242
2243 /* We default to persistent connections. We set this already in this connect
2244 function to make the re-use checks properly be able to check this bit. */
2245 conn->bits.close = FALSE;
2246
2247 /* If there already is a protocol-specific struct allocated for this
2248 sessionhandle, deal with it */
2249 Curl_reset_reqproto(conn);
2250
2251 result = ssh_init(conn);
2252 if(result)
2253 return result;
2254
2255 ssh = &conn->proto.sshc;
2256
2257 #ifdef CURL_LIBSSH2_DEBUG
2258 if(conn->user) {
2259 infof(data, "User: %s\n", conn->user);
2260 }
2261 if(conn->passwd) {
2262 infof(data, "Password: %s\n", conn->passwd);
2263 }
2264 sock = conn->sock[FIRSTSOCKET];
2265 #endif /* CURL_LIBSSH2_DEBUG */
2266
2267 ssh->ssh_session = libssh2_session_init_ex(libssh2_malloc, libssh2_free,
2268 libssh2_realloc, conn);
2269 if(ssh->ssh_session == NULL) {
2270 failf(data, "Failure initialising ssh session");
2271 return CURLE_FAILED_INIT;
2272 }
2273
2274 #ifdef CURL_LIBSSH2_DEBUG
2275 libssh2_trace(ssh->ssh_session, ~0);
2276 infof(data, "SSH socket: %d\n", sock);
2277 #endif /* CURL_LIBSSH2_DEBUG */
2278
2279 state(conn, SSH_S_STARTUP);
2280
2281 if(data->state.used_interface == Curl_if_multi)
2282 result = ssh_multi_statemach(conn, done);
2283 else {
2284 result = ssh_easy_statemach(conn);
2285 if(!result)
2286 *done = TRUE;
2287 }
2288
2289 return result;
2290 }
2291
2292 /*
2293 ***********************************************************************
2294 *
2295 * scp_perform()
2296 *
2297 * This is the actual DO function for SCP. Get a file according to
2298 * the options previously setup.
2299 */
2300
2301 static
scp_perform(struct connectdata * conn,bool * connected,bool * dophase_done)2302 CURLcode scp_perform(struct connectdata *conn,
2303 bool *connected,
2304 bool *dophase_done)
2305 {
2306 CURLcode result = CURLE_OK;
2307
2308 DEBUGF(infof(conn->data, "DO phase starts\n"));
2309
2310 *dophase_done = FALSE; /* not done yet */
2311
2312 /* start the first command in the DO phase */
2313 state(conn, SSH_SCP_TRANS_INIT);
2314
2315 /* run the state-machine */
2316 if(conn->data->state.used_interface == Curl_if_multi) {
2317 result = ssh_multi_statemach(conn, dophase_done);
2318 }
2319 else {
2320 result = ssh_easy_statemach(conn);
2321 *dophase_done = TRUE; /* with the easy interface we are done here */
2322 }
2323 *connected = conn->bits.tcpconnect;
2324
2325 if(*dophase_done) {
2326 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2327 }
2328
2329 return result;
2330 }
2331
2332 /* called from multi.c while DOing */
scp_doing(struct connectdata * conn,bool * dophase_done)2333 static CURLcode scp_doing(struct connectdata *conn,
2334 bool *dophase_done)
2335 {
2336 CURLcode result;
2337 result = ssh_multi_statemach(conn, dophase_done);
2338
2339 if(*dophase_done) {
2340 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2341 }
2342 return result;
2343 }
2344
2345 /*
2346 * The DO function is generic for both protocols. There was previously two
2347 * separate ones but this way means less duplicated code.
2348 */
2349
ssh_do(struct connectdata * conn,bool * done)2350 static CURLcode ssh_do(struct connectdata *conn, bool *done)
2351 {
2352 CURLcode res;
2353 bool connected = 0;
2354 struct SessionHandle *data = conn->data;
2355
2356 *done = FALSE; /* default to false */
2357
2358 /*
2359 Since connections can be re-used between SessionHandles, this might be a
2360 connection already existing but on a fresh SessionHandle struct so we must
2361 make sure we have a good 'struct SSHPROTO' to play with. For new
2362 connections, the struct SSHPROTO is allocated and setup in the
2363 ssh_connect() function.
2364 */
2365 Curl_reset_reqproto(conn);
2366 res = ssh_init(conn);
2367 if(res)
2368 return res;
2369
2370 data->req.size = -1; /* make sure this is unknown at this point */
2371
2372 Curl_pgrsSetUploadCounter(data, 0);
2373 Curl_pgrsSetDownloadCounter(data, 0);
2374 Curl_pgrsSetUploadSize(data, 0);
2375 Curl_pgrsSetDownloadSize(data, 0);
2376
2377 if(conn->protocol & PROT_SCP)
2378 res = scp_perform(conn, &connected, done);
2379 else
2380 res = sftp_perform(conn, &connected, done);
2381
2382 return res;
2383 }
2384
2385 /* BLOCKING, but the function is using the state machine so the only reason this
2386 is still blocking is that the multi interface code has no support for
2387 disconnecting operations that takes a while */
scp_disconnect(struct connectdata * conn)2388 static CURLcode scp_disconnect(struct connectdata *conn)
2389 {
2390 CURLcode result = CURLE_OK;
2391
2392 Curl_safefree(conn->data->state.proto.ssh);
2393 conn->data->state.proto.ssh = NULL;
2394
2395 if(conn->proto.sshc.ssh_session) {
2396 /* only if there's a session still around to use! */
2397
2398 state(conn, SSH_SESSION_DISCONNECT);
2399
2400 result = ssh_easy_statemach(conn);
2401 }
2402
2403 return result;
2404 }
2405
2406 /* generic done function for both SCP and SFTP called from their specific
2407 done functions */
ssh_done(struct connectdata * conn,CURLcode status)2408 static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
2409 {
2410 CURLcode result = CURLE_OK;
2411 struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh;
2412
2413 if(status == CURLE_OK) {
2414 /* run the state-machine
2415
2416 TODO: when the multi interface this _really_ should be using the
2417 ssh_multi_statemach function but we have no general support for
2418 non-blocking DONE operations, not in the multi state machine and with
2419 Curl_done() invokes on several places in the code!
2420 */
2421 result = ssh_easy_statemach(conn);
2422 }
2423 else
2424 result = status;
2425
2426 Curl_safefree(sftp_scp->path);
2427 sftp_scp->path = NULL;
2428 Curl_pgrsDone(conn);
2429
2430 conn->data->req.keepon = 0; /* clear all bits */
2431 return result;
2432 }
2433
2434
scp_done(struct connectdata * conn,CURLcode status,bool premature)2435 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
2436 bool premature)
2437 {
2438 (void)premature; /* not used */
2439
2440 if(status == CURLE_OK)
2441 state(conn, SSH_SCP_DONE);
2442
2443 return ssh_done(conn, status);
2444
2445 }
2446
2447 /* return number of received (decrypted) bytes */
Curl_scp_send(struct connectdata * conn,int sockindex,const void * mem,size_t len)2448 ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
2449 const void *mem, size_t len)
2450 {
2451 ssize_t nwrite;
2452 (void)sockindex; /* we only support SCP on the fixed known primary socket */
2453
2454 /* libssh2_channel_write() returns int! */
2455 nwrite = (ssize_t)
2456 libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
2457
2458 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2459
2460 if(nwrite == LIBSSH2_ERROR_EAGAIN)
2461 return 0;
2462
2463 return nwrite;
2464 }
2465
2466 /*
2467 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
2468 * a regular CURLcode value.
2469 */
Curl_scp_recv(struct connectdata * conn,int sockindex,char * mem,size_t len)2470 ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
2471 char *mem, size_t len)
2472 {
2473 ssize_t nread;
2474 (void)sockindex; /* we only support SCP on the fixed known primary socket */
2475
2476 /* libssh2_channel_read() returns int */
2477 nread = (ssize_t)
2478 libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
2479
2480 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2481
2482 return nread;
2483 }
2484
2485 /*
2486 * =============== SFTP ===============
2487 */
2488
2489 /*
2490 ***********************************************************************
2491 *
2492 * sftp_perform()
2493 *
2494 * This is the actual DO function for SFTP. Get a file/directory according to
2495 * the options previously setup.
2496 */
2497
2498 static
sftp_perform(struct connectdata * conn,bool * connected,bool * dophase_done)2499 CURLcode sftp_perform(struct connectdata *conn,
2500 bool *connected,
2501 bool *dophase_done)
2502 {
2503 CURLcode result = CURLE_OK;
2504
2505 DEBUGF(infof(conn->data, "DO phase starts\n"));
2506
2507 *dophase_done = FALSE; /* not done yet */
2508
2509 /* start the first command in the DO phase */
2510 state(conn, SSH_SFTP_QUOTE_INIT);
2511
2512 /* run the state-machine */
2513 if(conn->data->state.used_interface == Curl_if_multi) {
2514 result = ssh_multi_statemach(conn, dophase_done);
2515 }
2516 else {
2517 result = ssh_easy_statemach(conn);
2518 *dophase_done = TRUE; /* with the easy interface we are done here */
2519 }
2520 *connected = conn->bits.tcpconnect;
2521
2522 if(*dophase_done) {
2523 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2524 }
2525
2526 return result;
2527 }
2528
2529 /* called from multi.c while DOing */
sftp_doing(struct connectdata * conn,bool * dophase_done)2530 static CURLcode sftp_doing(struct connectdata *conn,
2531 bool *dophase_done)
2532 {
2533 CURLcode result;
2534 result = ssh_multi_statemach(conn, dophase_done);
2535
2536 if(*dophase_done) {
2537 DEBUGF(infof(conn->data, "DO phase is complete\n"));
2538 }
2539 return result;
2540 }
2541
2542 /* BLOCKING, but the function is using the state machine so the only reason this
2543 is still blocking is that the multi interface code has no support for
2544 disconnecting operations that takes a while */
sftp_disconnect(struct connectdata * conn)2545 static CURLcode sftp_disconnect(struct connectdata *conn)
2546 {
2547 CURLcode result = CURLE_OK;
2548
2549 DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
2550
2551 Curl_safefree(conn->data->state.proto.ssh);
2552 conn->data->state.proto.ssh = NULL;
2553
2554 if(conn->proto.sshc.ssh_session) {
2555 /* only if there's a session still around to use! */
2556 state(conn, SSH_SFTP_SHUTDOWN);
2557 result = ssh_easy_statemach(conn);
2558 }
2559
2560 DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
2561
2562 return result;
2563
2564 }
2565
sftp_done(struct connectdata * conn,CURLcode status,bool premature)2566 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
2567 bool premature)
2568 {
2569 struct ssh_conn *sshc = &conn->proto.sshc;
2570
2571 if(status == CURLE_OK) {
2572 /* Before we shut down, see if there are any post-quote commands to send: */
2573 if(!status && !premature && conn->data->set.postquote) {
2574 sshc->nextstate = SSH_SFTP_CLOSE;
2575 state(conn, SSH_SFTP_POSTQUOTE_INIT);
2576 }
2577 else
2578 state(conn, SSH_SFTP_CLOSE);
2579 }
2580 return ssh_done(conn, status);
2581 }
2582
2583 /* return number of sent bytes */
Curl_sftp_send(struct connectdata * conn,int sockindex,const void * mem,size_t len)2584 ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
2585 const void *mem, size_t len)
2586 {
2587 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
2588 but is changed to ssize_t in 0.15. These days we don't
2589 support libssh2 0.15*/
2590 (void)sockindex;
2591
2592 nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
2593
2594 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2595
2596 if(nwrite == LIBSSH2_ERROR_EAGAIN)
2597 return 0;
2598
2599 return nwrite;
2600 }
2601
2602 /*
2603 * Return number of received (decrypted) bytes
2604 */
Curl_sftp_recv(struct connectdata * conn,int sockindex,char * mem,size_t len)2605 ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
2606 char *mem, size_t len)
2607 {
2608 ssize_t nread;
2609 (void)sockindex;
2610
2611 nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
2612
2613 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
2614
2615 return nread;
2616 }
2617
2618 /* The get_pathname() function is being borrowed from OpenSSH sftp.c
2619 version 4.6p1. */
2620 /*
2621 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
2622 *
2623 * Permission to use, copy, modify, and distribute this software for any
2624 * purpose with or without fee is hereby granted, provided that the above
2625 * copyright notice and this permission notice appear in all copies.
2626 *
2627 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
2628 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
2629 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
2630 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2631 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2632 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2633 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2634 */
2635 static CURLcode
get_pathname(const char ** cpp,char ** path)2636 get_pathname(const char **cpp, char **path)
2637 {
2638 const char *cp = *cpp, *end;
2639 char quot;
2640 unsigned int i, j;
2641 static const char WHITESPACE[] = " \t\r\n";
2642
2643 cp += strspn(cp, WHITESPACE);
2644 if(!*cp) {
2645 *cpp = cp;
2646 *path = NULL;
2647 return CURLE_QUOTE_ERROR;
2648 }
2649
2650 *path = malloc(strlen(cp) + 1);
2651 if(*path == NULL)
2652 return CURLE_OUT_OF_MEMORY;
2653
2654 /* Check for quoted filenames */
2655 if(*cp == '\"' || *cp == '\'') {
2656 quot = *cp++;
2657
2658 /* Search for terminating quote, unescape some chars */
2659 for (i = j = 0; i <= strlen(cp); i++) {
2660 if(cp[i] == quot) { /* Found quote */
2661 i++;
2662 (*path)[j] = '\0';
2663 break;
2664 }
2665 if(cp[i] == '\0') { /* End of string */
2666 /*error("Unterminated quote");*/
2667 goto fail;
2668 }
2669 if(cp[i] == '\\') { /* Escaped characters */
2670 i++;
2671 if(cp[i] != '\'' && cp[i] != '\"' &&
2672 cp[i] != '\\') {
2673 /*error("Bad escaped character '\\%c'",
2674 cp[i]);*/
2675 goto fail;
2676 }
2677 }
2678 (*path)[j++] = cp[i];
2679 }
2680
2681 if(j == 0) {
2682 /*error("Empty quotes");*/
2683 goto fail;
2684 }
2685 *cpp = cp + i + strspn(cp + i, WHITESPACE);
2686 }
2687 else {
2688 /* Read to end of filename */
2689 end = strpbrk(cp, WHITESPACE);
2690 if(end == NULL)
2691 end = strchr(cp, '\0');
2692 *cpp = end + strspn(end, WHITESPACE);
2693
2694 memcpy(*path, cp, end - cp);
2695 (*path)[end - cp] = '\0';
2696 }
2697 return CURLE_OK;
2698
2699 fail:
2700 Curl_safefree(*path);
2701 *path = NULL;
2702 return CURLE_QUOTE_ERROR;
2703 }
2704
2705
sftp_libssh2_strerror(unsigned long err)2706 static const char *sftp_libssh2_strerror(unsigned long err)
2707 {
2708 switch (err) {
2709 case LIBSSH2_FX_NO_SUCH_FILE:
2710 return "No such file or directory";
2711
2712 case LIBSSH2_FX_PERMISSION_DENIED:
2713 return "Permission denied";
2714
2715 case LIBSSH2_FX_FAILURE:
2716 return "Operation failed";
2717
2718 case LIBSSH2_FX_BAD_MESSAGE:
2719 return "Bad message from SFTP server";
2720
2721 case LIBSSH2_FX_NO_CONNECTION:
2722 return "Not connected to SFTP server";
2723
2724 case LIBSSH2_FX_CONNECTION_LOST:
2725 return "Connection to SFTP server lost";
2726
2727 case LIBSSH2_FX_OP_UNSUPPORTED:
2728 return "Operation not supported by SFTP server";
2729
2730 case LIBSSH2_FX_INVALID_HANDLE:
2731 return "Invalid handle";
2732
2733 case LIBSSH2_FX_NO_SUCH_PATH:
2734 return "No such file or directory";
2735
2736 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
2737 return "File already exists";
2738
2739 case LIBSSH2_FX_WRITE_PROTECT:
2740 return "File is write protected";
2741
2742 case LIBSSH2_FX_NO_MEDIA:
2743 return "No media";
2744
2745 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
2746 return "Disk full";
2747
2748 case LIBSSH2_FX_QUOTA_EXCEEDED:
2749 return "User quota exceeded";
2750
2751 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
2752 return "Unknown principle";
2753
2754 case LIBSSH2_FX_LOCK_CONFlICT:
2755 return "File lock conflict";
2756
2757 case LIBSSH2_FX_DIR_NOT_EMPTY:
2758 return "Directory not empty";
2759
2760 case LIBSSH2_FX_NOT_A_DIRECTORY:
2761 return "Not a directory";
2762
2763 case LIBSSH2_FX_INVALID_FILENAME:
2764 return "Invalid filename";
2765
2766 case LIBSSH2_FX_LINK_LOOP:
2767 return "Link points to itself";
2768 }
2769 return "Unknown error in libssh2";
2770 }
2771
2772 #endif /* USE_LIBSSH2 */
2773