smtp: use the upload buffer size for scratch buffer malloc
[platform/upstream/curl.git] / lib / ssh-libssh.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2017 - 2018 Red Hat, Inc.
9  *
10  * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
11  *          Robert Kolcun, Andreas Schneider
12  *
13  * This software is licensed as described in the file COPYING, which
14  * you should have received as part of this distribution. The terms
15  * are also available at https://curl.haxx.se/docs/copyright.html.
16  *
17  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
18  * copies of the Software, and permit persons to whom the Software is
19  * furnished to do so, under the terms of the COPYING file.
20  *
21  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22  * KIND, either express or implied.
23  *
24  ***************************************************************************/
25
26 #include "curl_setup.h"
27
28 #ifdef USE_LIBSSH
29
30 #include <limits.h>
31
32 #include <libssh/libssh.h>
33 #include <libssh/sftp.h>
34
35 #ifdef HAVE_FCNTL_H
36 #include <fcntl.h>
37 #endif
38
39 #ifdef HAVE_NETINET_IN_H
40 #include <netinet/in.h>
41 #endif
42 #ifdef HAVE_ARPA_INET_H
43 #include <arpa/inet.h>
44 #endif
45 #ifdef HAVE_UTSNAME_H
46 #include <sys/utsname.h>
47 #endif
48 #ifdef HAVE_NETDB_H
49 #include <netdb.h>
50 #endif
51 #ifdef __VMS
52 #include <in.h>
53 #include <inet.h>
54 #endif
55
56 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
57 #undef in_addr_t
58 #define in_addr_t unsigned long
59 #endif
60
61 #include <curl/curl.h>
62 #include "urldata.h"
63 #include "sendf.h"
64 #include "hostip.h"
65 #include "progress.h"
66 #include "transfer.h"
67 #include "escape.h"
68 #include "http.h"               /* for HTTP proxy tunnel stuff */
69 #include "ssh.h"
70 #include "url.h"
71 #include "speedcheck.h"
72 #include "getinfo.h"
73 #include "strdup.h"
74 #include "strcase.h"
75 #include "vtls/vtls.h"
76 #include "connect.h"
77 #include "strerror.h"
78 #include "inet_ntop.h"
79 #include "parsedate.h"          /* for the week day and month names */
80 #include "sockaddr.h"           /* required for Curl_sockaddr_storage */
81 #include "strtoofft.h"
82 #include "multiif.h"
83 #include "select.h"
84 #include "warnless.h"
85
86 /* for permission and open flags */
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #include <unistd.h>
90 #include <fcntl.h>
91
92 /* The last 3 #include files should be in this order */
93 #include "curl_printf.h"
94 #include "curl_memory.h"
95 #include "memdebug.h"
96 #include "curl_path.h"
97
98 /* Local functions: */
99 static CURLcode myssh_connect(struct connectdata *conn, bool *done);
100 static CURLcode myssh_multi_statemach(struct connectdata *conn,
101                                       bool *done);
102 static CURLcode myssh_do_it(struct connectdata *conn, bool *done);
103
104 static CURLcode scp_done(struct connectdata *conn,
105                          CURLcode, bool premature);
106 static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done);
107 static CURLcode scp_disconnect(struct connectdata *conn,
108                                bool dead_connection);
109
110 static CURLcode sftp_done(struct connectdata *conn,
111                           CURLcode, bool premature);
112 static CURLcode sftp_doing(struct connectdata *conn,
113                            bool *dophase_done);
114 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
115 static
116 CURLcode sftp_perform(struct connectdata *conn,
117                       bool *connected,
118                       bool *dophase_done);
119
120 static void sftp_quote(struct connectdata *conn);
121 static void sftp_quote_stat(struct connectdata *conn);
122
123 static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock,
124                          int numsocks);
125
126 static int myssh_perform_getsock(const struct connectdata *conn,
127                                  curl_socket_t *sock,
128                                  int numsocks);
129
130 static CURLcode myssh_setup_connection(struct connectdata *conn);
131
132 /*
133  * SCP protocol handler.
134  */
135
136 const struct Curl_handler Curl_handler_scp = {
137   "SCP",                        /* scheme */
138   myssh_setup_connection,       /* setup_connection */
139   myssh_do_it,                  /* do_it */
140   scp_done,                     /* done */
141   ZERO_NULL,                    /* do_more */
142   myssh_connect,                /* connect_it */
143   myssh_multi_statemach,        /* connecting */
144   scp_doing,                    /* doing */
145   myssh_getsock,                /* proto_getsock */
146   myssh_getsock,                /* doing_getsock */
147   ZERO_NULL,                    /* domore_getsock */
148   myssh_perform_getsock,        /* perform_getsock */
149   scp_disconnect,               /* disconnect */
150   ZERO_NULL,                    /* readwrite */
151   ZERO_NULL,                    /* connection_check */
152   PORT_SSH,                     /* defport */
153   CURLPROTO_SCP,                /* protocol */
154   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */
155 };
156
157 /*
158  * SFTP protocol handler.
159  */
160
161 const struct Curl_handler Curl_handler_sftp = {
162   "SFTP",                               /* scheme */
163   myssh_setup_connection,               /* setup_connection */
164   myssh_do_it,                          /* do_it */
165   sftp_done,                            /* done */
166   ZERO_NULL,                            /* do_more */
167   myssh_connect,                        /* connect_it */
168   myssh_multi_statemach,                /* connecting */
169   sftp_doing,                           /* doing */
170   myssh_getsock,                        /* proto_getsock */
171   myssh_getsock,                        /* doing_getsock */
172   ZERO_NULL,                            /* domore_getsock */
173   myssh_perform_getsock,                /* perform_getsock */
174   sftp_disconnect,                      /* disconnect */
175   ZERO_NULL,                            /* readwrite */
176   ZERO_NULL,                            /* connection_check */
177   PORT_SSH,                             /* defport */
178   CURLPROTO_SFTP,                       /* protocol */
179   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
180   | PROTOPT_NOURLQUERY                  /* flags */
181 };
182
183 static CURLcode sftp_error_to_CURLE(int err)
184 {
185   switch(err) {
186     case SSH_FX_OK:
187       return CURLE_OK;
188
189     case SSH_FX_NO_SUCH_FILE:
190     case SSH_FX_NO_SUCH_PATH:
191       return CURLE_REMOTE_FILE_NOT_FOUND;
192
193     case SSH_FX_PERMISSION_DENIED:
194     case SSH_FX_WRITE_PROTECT:
195       return CURLE_REMOTE_ACCESS_DENIED;
196
197     case SSH_FX_FILE_ALREADY_EXISTS:
198       return CURLE_REMOTE_FILE_EXISTS;
199
200     default:
201       break;
202   }
203
204   return CURLE_SSH;
205 }
206
207 /*
208  * SSH State machine related code
209  */
210 /* This is the ONLY way to change SSH state! */
211 static void state(struct connectdata *conn, sshstate nowstate)
212 {
213   struct ssh_conn *sshc = &conn->proto.sshc;
214 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
215   /* for debug purposes */
216   static const char *const names[] = {
217     "SSH_STOP",
218     "SSH_INIT",
219     "SSH_S_STARTUP",
220     "SSH_HOSTKEY",
221     "SSH_AUTHLIST",
222     "SSH_AUTH_PKEY_INIT",
223     "SSH_AUTH_PKEY",
224     "SSH_AUTH_PASS_INIT",
225     "SSH_AUTH_PASS",
226     "SSH_AUTH_AGENT_INIT",
227     "SSH_AUTH_AGENT_LIST",
228     "SSH_AUTH_AGENT",
229     "SSH_AUTH_HOST_INIT",
230     "SSH_AUTH_HOST",
231     "SSH_AUTH_KEY_INIT",
232     "SSH_AUTH_KEY",
233     "SSH_AUTH_GSSAPI",
234     "SSH_AUTH_DONE",
235     "SSH_SFTP_INIT",
236     "SSH_SFTP_REALPATH",
237     "SSH_SFTP_QUOTE_INIT",
238     "SSH_SFTP_POSTQUOTE_INIT",
239     "SSH_SFTP_QUOTE",
240     "SSH_SFTP_NEXT_QUOTE",
241     "SSH_SFTP_QUOTE_STAT",
242     "SSH_SFTP_QUOTE_SETSTAT",
243     "SSH_SFTP_QUOTE_SYMLINK",
244     "SSH_SFTP_QUOTE_MKDIR",
245     "SSH_SFTP_QUOTE_RENAME",
246     "SSH_SFTP_QUOTE_RMDIR",
247     "SSH_SFTP_QUOTE_UNLINK",
248     "SSH_SFTP_QUOTE_STATVFS",
249     "SSH_SFTP_GETINFO",
250     "SSH_SFTP_FILETIME",
251     "SSH_SFTP_TRANS_INIT",
252     "SSH_SFTP_UPLOAD_INIT",
253     "SSH_SFTP_CREATE_DIRS_INIT",
254     "SSH_SFTP_CREATE_DIRS",
255     "SSH_SFTP_CREATE_DIRS_MKDIR",
256     "SSH_SFTP_READDIR_INIT",
257     "SSH_SFTP_READDIR",
258     "SSH_SFTP_READDIR_LINK",
259     "SSH_SFTP_READDIR_BOTTOM",
260     "SSH_SFTP_READDIR_DONE",
261     "SSH_SFTP_DOWNLOAD_INIT",
262     "SSH_SFTP_DOWNLOAD_STAT",
263     "SSH_SFTP_CLOSE",
264     "SSH_SFTP_SHUTDOWN",
265     "SSH_SCP_TRANS_INIT",
266     "SSH_SCP_UPLOAD_INIT",
267     "SSH_SCP_DOWNLOAD_INIT",
268     "SSH_SCP_DOWNLOAD",
269     "SSH_SCP_DONE",
270     "SSH_SCP_SEND_EOF",
271     "SSH_SCP_WAIT_EOF",
272     "SSH_SCP_WAIT_CLOSE",
273     "SSH_SCP_CHANNEL_FREE",
274     "SSH_SESSION_DISCONNECT",
275     "SSH_SESSION_FREE",
276     "QUIT"
277   };
278
279
280   if(sshc->state != nowstate) {
281     infof(conn->data, "SSH %p state change from %s to %s\n",
282           (void *) sshc, names[sshc->state], names[nowstate]);
283   }
284 #endif
285
286   sshc->state = nowstate;
287 }
288
289 /* Multiple options:
290  * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
291  *    hash (90s style auth, not sure we should have it here)
292  * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
293  *    use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
294  *    is returned by it.
295  * 3. none of the above. We only accept if it is present on known hosts.
296  *
297  * Returns SSH_OK or SSH_ERROR.
298  */
299 static int myssh_is_known(struct connectdata *conn)
300 {
301   int rc;
302   struct Curl_easy *data = conn->data;
303   struct ssh_conn *sshc = &conn->proto.sshc;
304   ssh_key pubkey;
305   size_t hlen;
306   unsigned char *hash = NULL;
307   char *base64 = NULL;
308   int vstate;
309   enum curl_khmatch keymatch;
310   struct curl_khkey foundkey;
311   curl_sshkeycallback func =
312     data->set.ssh_keyfunc;
313
314   rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
315   if(rc != SSH_OK)
316     return rc;
317
318   if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
319     rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
320                                 &hash, &hlen);
321     if(rc != SSH_OK)
322       goto cleanup;
323
324     if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) ||
325        memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) {
326       rc = SSH_ERROR;
327       goto cleanup;
328     }
329
330     rc = SSH_OK;
331     goto cleanup;
332   }
333
334   if(data->set.ssl.primary.verifyhost != TRUE) {
335     rc = SSH_OK;
336     goto cleanup;
337   }
338
339   vstate = ssh_is_server_known(sshc->ssh_session);
340   switch(vstate) {
341     case SSH_SERVER_KNOWN_OK:
342       keymatch = CURLKHMATCH_OK;
343       break;
344     case SSH_SERVER_FILE_NOT_FOUND:
345       /* fallthrough */
346     case SSH_SERVER_NOT_KNOWN:
347       keymatch = CURLKHMATCH_MISSING;
348       break;
349   default:
350       keymatch = CURLKHMATCH_MISMATCH;
351       break;
352   }
353
354   if(func) { /* use callback to determine action */
355     rc = ssh_pki_export_pubkey_base64(pubkey, &base64);
356     if(rc != SSH_OK)
357       goto cleanup;
358
359     foundkey.key = base64;
360     foundkey.len = strlen(base64);
361
362     switch(ssh_key_type(pubkey)) {
363       case SSH_KEYTYPE_RSA:
364         foundkey.keytype = CURLKHTYPE_RSA;
365         break;
366       case SSH_KEYTYPE_RSA1:
367         foundkey.keytype = CURLKHTYPE_RSA1;
368         break;
369       case SSH_KEYTYPE_ECDSA:
370         foundkey.keytype = CURLKHTYPE_ECDSA;
371         break;
372 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
373       case SSH_KEYTYPE_ED25519:
374         foundkey.keytype = CURLKHTYPE_ED25519;
375         break;
376 #endif
377       case SSH_KEYTYPE_DSS:
378         foundkey.keytype = CURLKHTYPE_DSS;
379         break;
380       default:
381         rc = SSH_ERROR;
382         goto cleanup;
383     }
384
385     /* we don't have anything equivalent to knownkey. Always NULL */
386     Curl_set_in_callback(data, true);
387     rc = func(data, NULL, &foundkey, /* from the remote host */
388               keymatch, data->set.ssh_keyfunc_userp);
389     Curl_set_in_callback(data, false);
390
391     switch(rc) {
392       case CURLKHSTAT_FINE_ADD_TO_FILE:
393         rc = ssh_write_knownhost(sshc->ssh_session);
394         if(rc != SSH_OK) {
395           goto cleanup;
396         }
397         break;
398       case CURLKHSTAT_FINE:
399         break;
400       default: /* REJECT/DEFER */
401         rc = SSH_ERROR;
402         goto cleanup;
403     }
404   }
405   else {
406     if(keymatch != CURLKHMATCH_OK) {
407       rc = SSH_ERROR;
408       goto cleanup;
409     }
410   }
411   rc = SSH_OK;
412
413 cleanup:
414   if(hash)
415     ssh_clean_pubkey_hash(&hash);
416   ssh_key_free(pubkey);
417   return rc;
418 }
419
420 #define MOVE_TO_ERROR_STATE(_r) { \
421   state(conn, SSH_SESSION_FREE); \
422   sshc->actualcode = _r; \
423   rc = SSH_ERROR; \
424   break; \
425 }
426
427 #define MOVE_TO_SFTP_CLOSE_STATE() { \
428   state(conn, SSH_SFTP_CLOSE); \
429   sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
430   rc = SSH_ERROR; \
431   break; \
432 }
433
434 #define MOVE_TO_LAST_AUTH \
435   if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
436     rc = SSH_OK; \
437     state(conn, SSH_AUTH_PASS_INIT); \
438     break; \
439   } \
440   else { \
441     MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
442   }
443
444 #define MOVE_TO_TERTIARY_AUTH \
445   if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
446     rc = SSH_OK; \
447     state(conn, SSH_AUTH_KEY_INIT); \
448     break; \
449   } \
450   else { \
451     MOVE_TO_LAST_AUTH; \
452   }
453
454 #define MOVE_TO_SECONDARY_AUTH \
455   if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
456     rc = SSH_OK; \
457     state(conn, SSH_AUTH_GSSAPI); \
458     break; \
459   } \
460   else { \
461     MOVE_TO_TERTIARY_AUTH; \
462   }
463
464 static
465 int myssh_auth_interactive(struct connectdata *conn)
466 {
467   int rc;
468   struct ssh_conn *sshc = &conn->proto.sshc;
469   int nprompts;
470
471 restart:
472   switch(sshc->kbd_state) {
473     case 0:
474       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
475       if(rc == SSH_AUTH_AGAIN)
476         return SSH_AGAIN;
477
478       if(rc != SSH_AUTH_INFO)
479         return SSH_ERROR;
480
481       nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
482       if(nprompts == SSH_ERROR || nprompts != 1)
483         return SSH_ERROR;
484
485       rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd);
486       if(rc < 0)
487         return SSH_ERROR;
488
489     /* fallthrough */
490     case 1:
491       sshc->kbd_state = 1;
492
493       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
494       if(rc == SSH_AUTH_AGAIN)
495         return SSH_AGAIN;
496       else if(rc == SSH_AUTH_SUCCESS)
497         rc = SSH_OK;
498       else if(rc == SSH_AUTH_INFO) {
499         nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
500         if(nprompts != 0)
501           return SSH_ERROR;
502
503         sshc->kbd_state = 2;
504         goto restart;
505       }
506       else
507         rc = SSH_ERROR;
508       break;
509     case 2:
510       sshc->kbd_state = 2;
511
512       rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
513       if(rc == SSH_AUTH_AGAIN)
514         return SSH_AGAIN;
515       else if(rc == SSH_AUTH_SUCCESS)
516         rc = SSH_OK;
517       else
518         rc = SSH_ERROR;
519
520       break;
521     default:
522       return SSH_ERROR;
523   }
524
525   sshc->kbd_state = 0;
526   return rc;
527 }
528
529 /*
530  * ssh_statemach_act() runs the SSH state machine as far as it can without
531  * blocking and without reaching the end.  The data the pointer 'block' points
532  * to will be set to TRUE if the libssh function returns SSH_AGAIN
533  * meaning it wants to be called again when the socket is ready
534  */
535 static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
536 {
537   CURLcode result = CURLE_OK;
538   struct Curl_easy *data = conn->data;
539   struct SSHPROTO *protop = data->req.protop;
540   struct ssh_conn *sshc = &conn->proto.sshc;
541   int rc = SSH_NO_ERROR, err;
542   char *new_readdir_line;
543   int seekerr = CURL_SEEKFUNC_OK;
544   const char *err_msg;
545   *block = 0;                   /* we're not blocking by default */
546
547   do {
548
549     switch(sshc->state) {
550     case SSH_INIT:
551       sshc->secondCreateDirs = 0;
552       sshc->nextstate = SSH_NO_STATE;
553       sshc->actualcode = CURLE_OK;
554
555 #if 0
556       ssh_set_log_level(SSH_LOG_PROTOCOL);
557 #endif
558
559       /* Set libssh to non-blocking, since everything internally is
560          non-blocking */
561       ssh_set_blocking(sshc->ssh_session, 0);
562
563       state(conn, SSH_S_STARTUP);
564       /* fall-through */
565
566     case SSH_S_STARTUP:
567       rc = ssh_connect(sshc->ssh_session);
568       if(rc == SSH_AGAIN)
569         break;
570
571       if(rc != SSH_OK) {
572         failf(data, "Failure establishing ssh session");
573         MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
574       }
575
576       state(conn, SSH_HOSTKEY);
577
578       /* fall-through */
579     case SSH_HOSTKEY:
580
581       rc = myssh_is_known(conn);
582       if(rc != SSH_OK) {
583         MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
584       }
585
586       state(conn, SSH_AUTHLIST);
587       /* fall through */
588     case SSH_AUTHLIST:{
589         sshc->authed = FALSE;
590
591         rc = ssh_userauth_none(sshc->ssh_session, NULL);
592         if(rc == SSH_AUTH_AGAIN) {
593           rc = SSH_AGAIN;
594           break;
595         }
596
597         if(rc == SSH_AUTH_SUCCESS) {
598           sshc->authed = TRUE;
599           infof(data, "Authenticated with none\n");
600           state(conn, SSH_AUTH_DONE);
601           break;
602         }
603         else if(rc == SSH_AUTH_ERROR) {
604           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
605         }
606
607         sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
608         if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
609           state(conn, SSH_AUTH_PKEY_INIT);
610         }
611         else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
612           state(conn, SSH_AUTH_GSSAPI);
613         }
614         else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
615           state(conn, SSH_AUTH_KEY_INIT);
616         }
617         else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
618           state(conn, SSH_AUTH_PASS_INIT);
619         }
620         else {                  /* unsupported authentication method */
621           MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
622         }
623
624         break;
625       }
626     case SSH_AUTH_PKEY_INIT:
627       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
628         MOVE_TO_SECONDARY_AUTH;
629       }
630
631       /* Two choices, (1) private key was given on CMD,
632        * (2) use the "default" keys. */
633       if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
634         if(sshc->pubkey && !data->set.ssl.key_passwd) {
635           rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
636                                           sshc->pubkey);
637           if(rc == SSH_AUTH_AGAIN) {
638             rc = SSH_AGAIN;
639             break;
640           }
641
642           if(rc != SSH_OK) {
643             MOVE_TO_SECONDARY_AUTH;
644           }
645         }
646
647         rc = ssh_pki_import_privkey_file(data->
648                                          set.str[STRING_SSH_PRIVATE_KEY],
649                                          data->set.ssl.key_passwd, NULL,
650                                          NULL, &sshc->privkey);
651         if(rc != SSH_OK) {
652           failf(data, "Could not load private key file %s",
653                 data->set.str[STRING_SSH_PRIVATE_KEY]);
654           break;
655         }
656
657         state(conn, SSH_AUTH_PKEY);
658         break;
659
660       }
661       else {
662         infof(data, "Authentication using SSH public key file\n");
663
664         rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
665                                          data->set.ssl.key_passwd);
666         if(rc == SSH_AUTH_AGAIN) {
667           rc = SSH_AGAIN;
668           break;
669         }
670         if(rc == SSH_AUTH_SUCCESS) {
671           rc = SSH_OK;
672           sshc->authed = TRUE;
673           infof(data, "Completed public key authentication\n");
674           state(conn, SSH_AUTH_DONE);
675           break;
676         }
677
678         MOVE_TO_SECONDARY_AUTH;
679       }
680       break;
681     case SSH_AUTH_PKEY:
682       rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
683       if(rc == SSH_AUTH_AGAIN) {
684         rc = SSH_AGAIN;
685         break;
686       }
687
688       if(rc == SSH_AUTH_SUCCESS) {
689         sshc->authed = TRUE;
690         infof(data, "Completed public key authentication\n");
691         state(conn, SSH_AUTH_DONE);
692         break;
693       }
694       else {
695         infof(data, "Failed public key authentication (rc: %d)\n", rc);
696         MOVE_TO_SECONDARY_AUTH;
697       }
698       break;
699
700     case SSH_AUTH_GSSAPI:
701       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
702         MOVE_TO_TERTIARY_AUTH;
703       }
704
705       rc = ssh_userauth_gssapi(sshc->ssh_session);
706       if(rc == SSH_AUTH_AGAIN) {
707         rc = SSH_AGAIN;
708         break;
709       }
710
711       if(rc == SSH_AUTH_SUCCESS) {
712         rc = SSH_OK;
713         sshc->authed = TRUE;
714         infof(data, "Completed gssapi authentication\n");
715         state(conn, SSH_AUTH_DONE);
716         break;
717       }
718
719       MOVE_TO_TERTIARY_AUTH;
720       break;
721
722     case SSH_AUTH_KEY_INIT:
723       if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
724         state(conn, SSH_AUTH_KEY);
725       }
726       else {
727         MOVE_TO_LAST_AUTH;
728       }
729       break;
730
731     case SSH_AUTH_KEY:
732
733       /* Authentication failed. Continue with keyboard-interactive now. */
734       rc = myssh_auth_interactive(conn);
735       if(rc == SSH_AGAIN) {
736         break;
737       }
738       if(rc == SSH_OK) {
739         sshc->authed = TRUE;
740         infof(data, "completed keyboard interactive authentication\n");
741       }
742       state(conn, SSH_AUTH_DONE);
743       break;
744
745     case SSH_AUTH_PASS_INIT:
746       if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
747         /* Host key authentication is intentionally not implemented */
748         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
749       }
750       state(conn, SSH_AUTH_PASS);
751       /* fall through */
752
753     case SSH_AUTH_PASS:
754       rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
755       if(rc == SSH_AUTH_AGAIN) {
756         rc = SSH_AGAIN;
757         break;
758       }
759
760       if(rc == SSH_AUTH_SUCCESS) {
761         sshc->authed = TRUE;
762         infof(data, "Completed password authentication\n");
763         state(conn, SSH_AUTH_DONE);
764       }
765       else {
766         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
767       }
768       break;
769
770     case SSH_AUTH_DONE:
771       if(!sshc->authed) {
772         failf(data, "Authentication failure");
773         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
774         break;
775       }
776
777       /*
778        * At this point we have an authenticated ssh session.
779        */
780       infof(data, "Authentication complete\n");
781
782       Curl_pgrsTime(conn->data, TIMER_APPCONNECT);      /* SSH is connected */
783
784       conn->sockfd = ssh_get_fd(sshc->ssh_session);
785       conn->writesockfd = CURL_SOCKET_BAD;
786
787       if(conn->handler->protocol == CURLPROTO_SFTP) {
788         state(conn, SSH_SFTP_INIT);
789         break;
790       }
791       infof(data, "SSH CONNECT phase done\n");
792       state(conn, SSH_STOP);
793       break;
794
795     case SSH_SFTP_INIT:
796       ssh_set_blocking(sshc->ssh_session, 1);
797
798       sshc->sftp_session = sftp_new(sshc->ssh_session);
799       if(!sshc->sftp_session) {
800         failf(data, "Failure initializing sftp session: %s",
801               ssh_get_error(sshc->ssh_session));
802         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
803         break;
804       }
805
806       rc = sftp_init(sshc->sftp_session);
807       if(rc != SSH_OK) {
808         rc = sftp_get_error(sshc->sftp_session);
809         failf(data, "Failure initializing sftp session: %s",
810               ssh_get_error(sshc->ssh_session));
811         MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
812         break;
813       }
814       state(conn, SSH_SFTP_REALPATH);
815       /* fall through */
816     case SSH_SFTP_REALPATH:
817       /*
818        * Get the "home" directory
819        */
820       sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
821       if(sshc->homedir == NULL) {
822         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
823       }
824       conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
825
826       /* This is the last step in the SFTP connect phase. Do note that while
827          we get the homedir here, we get the "workingpath" in the DO action
828          since the homedir will remain the same between request but the
829          working path will not. */
830       DEBUGF(infof(data, "SSH CONNECT phase done\n"));
831       state(conn, SSH_STOP);
832       break;
833
834     case SSH_SFTP_QUOTE_INIT:
835
836       result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
837       if(result) {
838         sshc->actualcode = result;
839         state(conn, SSH_STOP);
840         break;
841       }
842
843       if(data->set.quote) {
844         infof(data, "Sending quote commands\n");
845         sshc->quote_item = data->set.quote;
846         state(conn, SSH_SFTP_QUOTE);
847       }
848       else {
849         state(conn, SSH_SFTP_GETINFO);
850       }
851       break;
852
853     case SSH_SFTP_POSTQUOTE_INIT:
854       if(data->set.postquote) {
855         infof(data, "Sending quote commands\n");
856         sshc->quote_item = data->set.postquote;
857         state(conn, SSH_SFTP_QUOTE);
858       }
859       else {
860         state(conn, SSH_STOP);
861       }
862       break;
863
864     case SSH_SFTP_QUOTE:
865       /* Send any quote commands */
866       sftp_quote(conn);
867       break;
868
869     case SSH_SFTP_NEXT_QUOTE:
870       Curl_safefree(sshc->quote_path1);
871       Curl_safefree(sshc->quote_path2);
872
873       sshc->quote_item = sshc->quote_item->next;
874
875       if(sshc->quote_item) {
876         state(conn, SSH_SFTP_QUOTE);
877       }
878       else {
879         if(sshc->nextstate != SSH_NO_STATE) {
880           state(conn, sshc->nextstate);
881           sshc->nextstate = SSH_NO_STATE;
882         }
883         else {
884           state(conn, SSH_SFTP_GETINFO);
885         }
886       }
887       break;
888
889     case SSH_SFTP_QUOTE_STAT:
890       sftp_quote_stat(conn);
891       break;
892
893     case SSH_SFTP_QUOTE_SETSTAT:
894       rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
895                         sshc->quote_attrs);
896       if(rc != 0 && !sshc->acceptfail) {
897         Curl_safefree(sshc->quote_path1);
898         Curl_safefree(sshc->quote_path2);
899         failf(data, "Attempt to set SFTP stats failed: %s",
900               ssh_get_error(sshc->ssh_session));
901         state(conn, SSH_SFTP_CLOSE);
902         sshc->nextstate = SSH_NO_STATE;
903         sshc->actualcode = CURLE_QUOTE_ERROR;
904         /* sshc->actualcode = sftp_error_to_CURLE(err);
905          * we do not send the actual error; we return
906          * the error the libssh2 backend is returning */
907         break;
908       }
909       state(conn, SSH_SFTP_NEXT_QUOTE);
910       break;
911
912     case SSH_SFTP_QUOTE_SYMLINK:
913       rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
914                         sshc->quote_path1);
915       if(rc != 0 && !sshc->acceptfail) {
916         Curl_safefree(sshc->quote_path1);
917         Curl_safefree(sshc->quote_path2);
918         failf(data, "symlink command failed: %s",
919               ssh_get_error(sshc->ssh_session));
920         state(conn, SSH_SFTP_CLOSE);
921         sshc->nextstate = SSH_NO_STATE;
922         sshc->actualcode = CURLE_QUOTE_ERROR;
923         break;
924       }
925       state(conn, SSH_SFTP_NEXT_QUOTE);
926       break;
927
928     case SSH_SFTP_QUOTE_MKDIR:
929       rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
930                       (mode_t)data->set.new_directory_perms);
931       if(rc != 0 && !sshc->acceptfail) {
932         Curl_safefree(sshc->quote_path1);
933         failf(data, "mkdir command failed: %s",
934               ssh_get_error(sshc->ssh_session));
935         state(conn, SSH_SFTP_CLOSE);
936         sshc->nextstate = SSH_NO_STATE;
937         sshc->actualcode = CURLE_QUOTE_ERROR;
938         break;
939       }
940       state(conn, SSH_SFTP_NEXT_QUOTE);
941       break;
942
943     case SSH_SFTP_QUOTE_RENAME:
944       rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
945                        sshc->quote_path2);
946       if(rc != 0 && !sshc->acceptfail) {
947         Curl_safefree(sshc->quote_path1);
948         Curl_safefree(sshc->quote_path2);
949         failf(data, "rename command failed: %s",
950               ssh_get_error(sshc->ssh_session));
951         state(conn, SSH_SFTP_CLOSE);
952         sshc->nextstate = SSH_NO_STATE;
953         sshc->actualcode = CURLE_QUOTE_ERROR;
954         break;
955       }
956       state(conn, SSH_SFTP_NEXT_QUOTE);
957       break;
958
959     case SSH_SFTP_QUOTE_RMDIR:
960       rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
961       if(rc != 0 && !sshc->acceptfail) {
962         Curl_safefree(sshc->quote_path1);
963         failf(data, "rmdir command failed: %s",
964               ssh_get_error(sshc->ssh_session));
965         state(conn, SSH_SFTP_CLOSE);
966         sshc->nextstate = SSH_NO_STATE;
967         sshc->actualcode = CURLE_QUOTE_ERROR;
968         break;
969       }
970       state(conn, SSH_SFTP_NEXT_QUOTE);
971       break;
972
973     case SSH_SFTP_QUOTE_UNLINK:
974       rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
975       if(rc != 0 && !sshc->acceptfail) {
976         Curl_safefree(sshc->quote_path1);
977         failf(data, "rm command failed: %s",
978               ssh_get_error(sshc->ssh_session));
979         state(conn, SSH_SFTP_CLOSE);
980         sshc->nextstate = SSH_NO_STATE;
981         sshc->actualcode = CURLE_QUOTE_ERROR;
982         break;
983       }
984       state(conn, SSH_SFTP_NEXT_QUOTE);
985       break;
986
987     case SSH_SFTP_QUOTE_STATVFS:
988     {
989       sftp_statvfs_t statvfs;
990
991       statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
992       if(!statvfs && !sshc->acceptfail) {
993         Curl_safefree(sshc->quote_path1);
994         failf(data, "statvfs command failed: %s",
995               ssh_get_error(sshc->ssh_session));
996         state(conn, SSH_SFTP_CLOSE);
997         sshc->nextstate = SSH_NO_STATE;
998         sshc->actualcode = CURLE_QUOTE_ERROR;
999         break;
1000       }
1001       else if(statvfs) {
1002         char *tmp = aprintf("statvfs:\n"
1003                             "f_bsize: %llu\n" "f_frsize: %llu\n"
1004                             "f_blocks: %llu\n" "f_bfree: %llu\n"
1005                             "f_bavail: %llu\n" "f_files: %llu\n"
1006                             "f_ffree: %llu\n" "f_favail: %llu\n"
1007                             "f_fsid: %llu\n" "f_flag: %llu\n"
1008                             "f_namemax: %llu\n",
1009                             statvfs->f_bsize, statvfs->f_frsize,
1010                             statvfs->f_blocks, statvfs->f_bfree,
1011                             statvfs->f_bavail, statvfs->f_files,
1012                             statvfs->f_ffree, statvfs->f_favail,
1013                             statvfs->f_fsid, statvfs->f_flag,
1014                             statvfs->f_namemax);
1015         sftp_statvfs_free(statvfs);
1016
1017         if(!tmp) {
1018           result = CURLE_OUT_OF_MEMORY;
1019           state(conn, SSH_SFTP_CLOSE);
1020           sshc->nextstate = SSH_NO_STATE;
1021           break;
1022         }
1023
1024         result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
1025         free(tmp);
1026         if(result) {
1027           state(conn, SSH_SFTP_CLOSE);
1028           sshc->nextstate = SSH_NO_STATE;
1029           sshc->actualcode = result;
1030         }
1031       }
1032       state(conn, SSH_SFTP_NEXT_QUOTE);
1033       break;
1034     }
1035
1036     case SSH_SFTP_GETINFO:
1037       if(data->set.get_filetime) {
1038         state(conn, SSH_SFTP_FILETIME);
1039       }
1040       else {
1041         state(conn, SSH_SFTP_TRANS_INIT);
1042       }
1043       break;
1044
1045     case SSH_SFTP_FILETIME:
1046     {
1047       sftp_attributes attrs;
1048
1049       attrs = sftp_stat(sshc->sftp_session, protop->path);
1050       if(attrs != 0) {
1051         data->info.filetime = attrs->mtime;
1052         sftp_attributes_free(attrs);
1053       }
1054
1055       state(conn, SSH_SFTP_TRANS_INIT);
1056       break;
1057     }
1058
1059     case SSH_SFTP_TRANS_INIT:
1060       if(data->set.upload)
1061         state(conn, SSH_SFTP_UPLOAD_INIT);
1062       else {
1063         if(protop->path[strlen(protop->path)-1] == '/')
1064           state(conn, SSH_SFTP_READDIR_INIT);
1065         else
1066           state(conn, SSH_SFTP_DOWNLOAD_INIT);
1067       }
1068       break;
1069
1070     case SSH_SFTP_UPLOAD_INIT:
1071     {
1072       int flags;
1073
1074       if(data->state.resume_from != 0) {
1075         sftp_attributes attrs;
1076
1077         if(data->state.resume_from < 0) {
1078           attrs = sftp_stat(sshc->sftp_session, protop->path);
1079           if(attrs != 0) {
1080             curl_off_t size = attrs->size;
1081             if(size < 0) {
1082               failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
1083               MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
1084             }
1085             data->state.resume_from = attrs->size;
1086
1087             sftp_attributes_free(attrs);
1088           }
1089           else {
1090             data->state.resume_from = 0;
1091           }
1092         }
1093       }
1094
1095       if(data->set.ftp_append)
1096         /* Try to open for append, but create if nonexisting */
1097         flags = O_WRONLY|O_CREAT|O_APPEND;
1098       else if(data->state.resume_from > 0)
1099         /* If we have restart position then open for append */
1100         flags = O_WRONLY|O_APPEND;
1101       else
1102         /* Clear file before writing (normal behaviour) */
1103         flags = O_WRONLY|O_APPEND|O_CREAT|O_TRUNC;
1104
1105       if(sshc->sftp_file)
1106         sftp_close(sshc->sftp_file);
1107       sshc->sftp_file =
1108         sftp_open(sshc->sftp_session, protop->path,
1109                   flags, (mode_t)data->set.new_file_perms);
1110       if(!sshc->sftp_file) {
1111         err = sftp_get_error(sshc->sftp_session);
1112
1113         if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
1114              err == SSH_FX_NO_SUCH_PATH)) &&
1115              (data->set.ftp_create_missing_dirs &&
1116              (strlen(protop->path) > 1))) {
1117                /* try to create the path remotely */
1118                rc = 0;
1119                sshc->secondCreateDirs = 1;
1120                state(conn, SSH_SFTP_CREATE_DIRS_INIT);
1121                break;
1122         }
1123         else {
1124           MOVE_TO_SFTP_CLOSE_STATE();
1125         }
1126       }
1127
1128       /* If we have a restart point then we need to seek to the correct
1129          position. */
1130       if(data->state.resume_from > 0) {
1131         /* Let's read off the proper amount of bytes from the input. */
1132         if(conn->seek_func) {
1133           Curl_set_in_callback(data, true);
1134           seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1135                                     SEEK_SET);
1136           Curl_set_in_callback(data, false);
1137         }
1138
1139         if(seekerr != CURL_SEEKFUNC_OK) {
1140           curl_off_t passed = 0;
1141
1142           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1143             failf(data, "Could not seek stream");
1144             return CURLE_FTP_COULDNT_USE_REST;
1145           }
1146           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
1147           do {
1148             size_t readthisamountnow =
1149               (data->state.resume_from - passed > data->set.buffer_size) ?
1150               (size_t)data->set.buffer_size :
1151               curlx_sotouz(data->state.resume_from - passed);
1152
1153             size_t actuallyread =
1154               data->state.fread_func(data->state.buffer, 1,
1155                                      readthisamountnow, data->state.in);
1156
1157             passed += actuallyread;
1158             if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1159               /* this checks for greater-than only to make sure that the
1160                  CURL_READFUNC_ABORT return code still aborts */
1161               failf(data, "Failed to read data");
1162               MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
1163             }
1164           } while(passed < data->state.resume_from);
1165         }
1166
1167         /* now, decrease the size of the read */
1168         if(data->state.infilesize > 0) {
1169           data->state.infilesize -= data->state.resume_from;
1170           data->req.size = data->state.infilesize;
1171           Curl_pgrsSetUploadSize(data, data->state.infilesize);
1172         }
1173
1174         rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
1175         if(rc != 0) {
1176           MOVE_TO_SFTP_CLOSE_STATE();
1177         }
1178       }
1179       if(data->state.infilesize > 0) {
1180         data->req.size = data->state.infilesize;
1181         Curl_pgrsSetUploadSize(data, data->state.infilesize);
1182       }
1183       /* upload data */
1184       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
1185
1186       /* not set by Curl_setup_transfer to preserve keepon bits */
1187       conn->sockfd = conn->writesockfd;
1188
1189       /* store this original bitmask setup to use later on if we can't
1190          figure out a "real" bitmask */
1191       sshc->orig_waitfor = data->req.keepon;
1192
1193       /* we want to use the _sending_ function even when the socket turns
1194          out readable as the underlying libssh sftp send function will deal
1195          with both accordingly */
1196       conn->cselect_bits = CURL_CSELECT_OUT;
1197
1198       /* since we don't really wait for anything at this point, we want the
1199          state machine to move on as soon as possible so we set a very short
1200          timeout here */
1201       Curl_expire(data, 0, EXPIRE_RUN_NOW);
1202
1203       state(conn, SSH_STOP);
1204       break;
1205     }
1206
1207     case SSH_SFTP_CREATE_DIRS_INIT:
1208       if(strlen(protop->path) > 1) {
1209         sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
1210         state(conn, SSH_SFTP_CREATE_DIRS);
1211       }
1212       else {
1213         state(conn, SSH_SFTP_UPLOAD_INIT);
1214       }
1215       break;
1216
1217     case SSH_SFTP_CREATE_DIRS:
1218       sshc->slash_pos = strchr(sshc->slash_pos, '/');
1219       if(sshc->slash_pos) {
1220         *sshc->slash_pos = 0;
1221
1222         infof(data, "Creating directory '%s'\n", protop->path);
1223         state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
1224         break;
1225       }
1226       state(conn, SSH_SFTP_UPLOAD_INIT);
1227       break;
1228
1229     case SSH_SFTP_CREATE_DIRS_MKDIR:
1230       /* 'mode' - parameter is preliminary - default to 0644 */
1231       rc = sftp_mkdir(sshc->sftp_session, protop->path,
1232                       (mode_t)data->set.new_directory_perms);
1233       *sshc->slash_pos = '/';
1234       ++sshc->slash_pos;
1235       if(rc < 0) {
1236         /*
1237          * Abort if failure wasn't that the dir already exists or the
1238          * permission was denied (creation might succeed further down the
1239          * path) - retry on unspecific FAILURE also
1240          */
1241         err = sftp_get_error(sshc->sftp_session);
1242         if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
1243            (err != SSH_FX_FAILURE) &&
1244            (err != SSH_FX_PERMISSION_DENIED)) {
1245           MOVE_TO_SFTP_CLOSE_STATE();
1246         }
1247         rc = 0; /* clear rc and continue */
1248       }
1249       state(conn, SSH_SFTP_CREATE_DIRS);
1250       break;
1251
1252     case SSH_SFTP_READDIR_INIT:
1253       Curl_pgrsSetDownloadSize(data, -1);
1254       if(data->set.opt_no_body) {
1255         state(conn, SSH_STOP);
1256         break;
1257       }
1258
1259       /*
1260        * This is a directory that we are trying to get, so produce a directory
1261        * listing
1262        */
1263       sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
1264                                     protop->path);
1265       if(!sshc->sftp_dir) {
1266         failf(data, "Could not open directory for reading: %s",
1267               ssh_get_error(sshc->ssh_session));
1268         MOVE_TO_SFTP_CLOSE_STATE();
1269       }
1270       state(conn, SSH_SFTP_READDIR);
1271       break;
1272
1273     case SSH_SFTP_READDIR:
1274
1275       if(sshc->readdir_attrs)
1276         sftp_attributes_free(sshc->readdir_attrs);
1277
1278       sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
1279       if(sshc->readdir_attrs) {
1280         sshc->readdir_filename = sshc->readdir_attrs->name;
1281         sshc->readdir_longentry = sshc->readdir_attrs->longname;
1282         sshc->readdir_len = (int)strlen(sshc->readdir_filename);
1283
1284         if(data->set.ftp_list_only) {
1285           char *tmpLine;
1286
1287           tmpLine = aprintf("%s\n", sshc->readdir_filename);
1288           if(tmpLine == NULL) {
1289             state(conn, SSH_SFTP_CLOSE);
1290             sshc->actualcode = CURLE_OUT_OF_MEMORY;
1291             break;
1292           }
1293           result = Curl_client_write(conn, CLIENTWRITE_BODY,
1294                                      tmpLine, sshc->readdir_len + 1);
1295           free(tmpLine);
1296
1297           if(result) {
1298             state(conn, SSH_STOP);
1299             break;
1300           }
1301           /* since this counts what we send to the client, we include the
1302              newline in this counter */
1303           data->req.bytecount += sshc->readdir_len + 1;
1304
1305           /* output debug output if that is requested */
1306           if(data->set.verbose) {
1307             Curl_debug(data, CURLINFO_DATA_OUT,
1308                        (char *)sshc->readdir_filename,
1309                        sshc->readdir_len, conn);
1310           }
1311         }
1312         else {
1313           sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
1314           sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
1315           sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
1316           if(!sshc->readdir_line) {
1317             state(conn, SSH_SFTP_CLOSE);
1318             sshc->actualcode = CURLE_OUT_OF_MEMORY;
1319             break;
1320           }
1321
1322           memcpy(sshc->readdir_line, sshc->readdir_longentry,
1323                  sshc->readdir_currLen);
1324           if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
1325              ((sshc->readdir_attrs->permissions & S_IFMT) ==
1326               S_IFLNK)) {
1327             sshc->readdir_linkPath = malloc(PATH_MAX + 1);
1328             if(sshc->readdir_linkPath == NULL) {
1329               state(conn, SSH_SFTP_CLOSE);
1330               sshc->actualcode = CURLE_OUT_OF_MEMORY;
1331               break;
1332             }
1333
1334             snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
1335                      sshc->readdir_filename);
1336
1337             state(conn, SSH_SFTP_READDIR_LINK);
1338             break;
1339           }
1340           state(conn, SSH_SFTP_READDIR_BOTTOM);
1341           break;
1342         }
1343       }
1344       else if(sshc->readdir_attrs == NULL && sftp_dir_eof(sshc->sftp_dir)) {
1345         state(conn, SSH_SFTP_READDIR_DONE);
1346         break;
1347       }
1348       else {
1349         failf(data, "Could not open remote file for reading: %s",
1350               ssh_get_error(sshc->ssh_session));
1351         MOVE_TO_SFTP_CLOSE_STATE();
1352         break;
1353       }
1354       break;
1355
1356     case SSH_SFTP_READDIR_LINK:
1357       if(sshc->readdir_link_attrs)
1358         sftp_attributes_free(sshc->readdir_link_attrs);
1359
1360       sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session,
1361                                             sshc->readdir_linkPath);
1362       if(sshc->readdir_link_attrs == 0) {
1363         failf(data, "Could not read symlink for reading: %s",
1364               ssh_get_error(sshc->ssh_session));
1365         MOVE_TO_SFTP_CLOSE_STATE();
1366       }
1367
1368       if(sshc->readdir_link_attrs->name == NULL) {
1369         sshc->readdir_tmp = sftp_readlink(sshc->sftp_session,
1370                                           sshc->readdir_linkPath);
1371         if(sshc->readdir_filename == NULL)
1372           sshc->readdir_len = 0;
1373         else
1374           sshc->readdir_len = (int)strlen(sshc->readdir_tmp);
1375         sshc->readdir_longentry = NULL;
1376         sshc->readdir_filename = sshc->readdir_tmp;
1377       }
1378       else {
1379         sshc->readdir_len = (int)strlen(sshc->readdir_link_attrs->name);
1380         sshc->readdir_filename = sshc->readdir_link_attrs->name;
1381         sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
1382       }
1383
1384       Curl_safefree(sshc->readdir_linkPath);
1385
1386       /* get room for the filename and extra output */
1387       sshc->readdir_totalLen += 4 + sshc->readdir_len;
1388       new_readdir_line = Curl_saferealloc(sshc->readdir_line,
1389                                           sshc->readdir_totalLen);
1390       if(!new_readdir_line) {
1391         sshc->readdir_line = NULL;
1392         state(conn, SSH_SFTP_CLOSE);
1393         sshc->actualcode = CURLE_OUT_OF_MEMORY;
1394         break;
1395       }
1396       sshc->readdir_line = new_readdir_line;
1397
1398       sshc->readdir_currLen += snprintf(sshc->readdir_line +
1399                                         sshc->readdir_currLen,
1400                                         sshc->readdir_totalLen -
1401                                         sshc->readdir_currLen,
1402                                         " -> %s",
1403                                         sshc->readdir_filename);
1404
1405       sftp_attributes_free(sshc->readdir_link_attrs);
1406       sshc->readdir_link_attrs = NULL;
1407       sshc->readdir_filename = NULL;
1408       sshc->readdir_longentry = NULL;
1409
1410       state(conn, SSH_SFTP_READDIR_BOTTOM);
1411       /* fall through */
1412     case SSH_SFTP_READDIR_BOTTOM:
1413       sshc->readdir_currLen += snprintf(sshc->readdir_line +
1414                                         sshc->readdir_currLen,
1415                                         sshc->readdir_totalLen -
1416                                         sshc->readdir_currLen, "\n");
1417       result = Curl_client_write(conn, CLIENTWRITE_BODY,
1418                                  sshc->readdir_line,
1419                                  sshc->readdir_currLen);
1420
1421       if(!result) {
1422
1423         /* output debug output if that is requested */
1424         if(data->set.verbose) {
1425           Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
1426                      sshc->readdir_currLen, conn);
1427         }
1428         data->req.bytecount += sshc->readdir_currLen;
1429       }
1430       Curl_safefree(sshc->readdir_line);
1431       ssh_string_free_char(sshc->readdir_tmp);
1432       sshc->readdir_tmp = NULL;
1433
1434       if(result) {
1435         state(conn, SSH_STOP);
1436       }
1437       else
1438         state(conn, SSH_SFTP_READDIR);
1439       break;
1440
1441     case SSH_SFTP_READDIR_DONE:
1442       sftp_closedir(sshc->sftp_dir);
1443       sshc->sftp_dir = NULL;
1444
1445       /* no data to transfer */
1446       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1447       state(conn, SSH_STOP);
1448       break;
1449
1450     case SSH_SFTP_DOWNLOAD_INIT:
1451       /*
1452        * Work on getting the specified file
1453        */
1454       if(sshc->sftp_file)
1455         sftp_close(sshc->sftp_file);
1456
1457       sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
1458                                   O_RDONLY, (mode_t)data->set.new_file_perms);
1459       if(!sshc->sftp_file) {
1460         failf(data, "Could not open remote file for reading: %s",
1461               ssh_get_error(sshc->ssh_session));
1462
1463         MOVE_TO_SFTP_CLOSE_STATE();
1464       }
1465
1466       state(conn, SSH_SFTP_DOWNLOAD_STAT);
1467       break;
1468
1469     case SSH_SFTP_DOWNLOAD_STAT:
1470     {
1471       sftp_attributes attrs;
1472       curl_off_t size;
1473
1474       attrs = sftp_fstat(sshc->sftp_file);
1475       if(!attrs ||
1476               !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
1477               (attrs->size == 0)) {
1478         /*
1479          * sftp_fstat didn't return an error, so maybe the server
1480          * just doesn't support stat()
1481          * OR the server doesn't return a file size with a stat()
1482          * OR file size is 0
1483          */
1484         data->req.size = -1;
1485         data->req.maxdownload = -1;
1486         Curl_pgrsSetDownloadSize(data, -1);
1487         size = 0;
1488       }
1489       else {
1490         size = attrs->size;
1491
1492         sftp_attributes_free(attrs);
1493
1494         if(size < 0) {
1495           failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
1496           return CURLE_BAD_DOWNLOAD_RESUME;
1497         }
1498         if(conn->data->state.use_range) {
1499           curl_off_t from, to;
1500           char *ptr;
1501           char *ptr2;
1502           CURLofft to_t;
1503           CURLofft from_t;
1504
1505           from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
1506           if(from_t == CURL_OFFT_FLOW) {
1507             return CURLE_RANGE_ERROR;
1508           }
1509           while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
1510             ptr++;
1511           to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
1512           if(to_t == CURL_OFFT_FLOW) {
1513             return CURLE_RANGE_ERROR;
1514           }
1515           if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
1516              || (to >= size)) {
1517             to = size - 1;
1518           }
1519           if(from_t) {
1520             /* from is relative to end of file */
1521             from = size - to;
1522             to = size - 1;
1523           }
1524           if(from > size) {
1525             failf(data, "Offset (%"
1526                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
1527                   CURL_FORMAT_CURL_OFF_T ")", from, size);
1528             return CURLE_BAD_DOWNLOAD_RESUME;
1529           }
1530           if(from > to) {
1531             from = to;
1532             size = 0;
1533           }
1534           else {
1535             size = to - from + 1;
1536           }
1537
1538           rc = sftp_seek64(sshc->sftp_file, from);
1539           if(rc != 0) {
1540             MOVE_TO_SFTP_CLOSE_STATE();
1541           }
1542         }
1543         data->req.size = size;
1544         data->req.maxdownload = size;
1545         Curl_pgrsSetDownloadSize(data, size);
1546       }
1547
1548       /* We can resume if we can seek to the resume position */
1549       if(data->state.resume_from) {
1550         if(data->state.resume_from < 0) {
1551           /* We're supposed to download the last abs(from) bytes */
1552           if((curl_off_t)size < -data->state.resume_from) {
1553             failf(data, "Offset (%"
1554                   CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
1555                   CURL_FORMAT_CURL_OFF_T ")",
1556                   data->state.resume_from, size);
1557             return CURLE_BAD_DOWNLOAD_RESUME;
1558           }
1559           /* download from where? */
1560           data->state.resume_from += size;
1561         }
1562         else {
1563           if((curl_off_t)size < data->state.resume_from) {
1564             failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
1565                   ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
1566                   data->state.resume_from, size);
1567             return CURLE_BAD_DOWNLOAD_RESUME;
1568           }
1569         }
1570         /* Does a completed file need to be seeked and started or closed ? */
1571         /* Now store the number of bytes we are expected to download */
1572         data->req.size = size - data->state.resume_from;
1573         data->req.maxdownload = size - data->state.resume_from;
1574         Curl_pgrsSetDownloadSize(data,
1575                                  size - data->state.resume_from);
1576
1577         rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
1578         if(rc != 0) {
1579           MOVE_TO_SFTP_CLOSE_STATE();
1580         }
1581       }
1582     }
1583
1584     /* Setup the actual download */
1585     if(data->req.size == 0) {
1586       /* no data to transfer */
1587       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1588       infof(data, "File already completely downloaded\n");
1589       state(conn, SSH_STOP);
1590       break;
1591     }
1592     Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
1593                         FALSE, NULL, -1, NULL);
1594
1595     /* not set by Curl_setup_transfer to preserve keepon bits */
1596     conn->writesockfd = conn->sockfd;
1597
1598     /* we want to use the _receiving_ function even when the socket turns
1599        out writableable as the underlying libssh recv function will deal
1600        with both accordingly */
1601     conn->cselect_bits = CURL_CSELECT_IN;
1602
1603     if(result) {
1604       /* this should never occur; the close state should be entered
1605          at the time the error occurs */
1606       state(conn, SSH_SFTP_CLOSE);
1607       sshc->actualcode = result;
1608     }
1609     else {
1610       sshc->sftp_recv_state = 0;
1611       state(conn, SSH_STOP);
1612     }
1613     break;
1614
1615     case SSH_SFTP_CLOSE:
1616       if(sshc->sftp_file) {
1617         sftp_close(sshc->sftp_file);
1618         sshc->sftp_file = NULL;
1619       }
1620       Curl_safefree(protop->path);
1621
1622       DEBUGF(infof(data, "SFTP DONE done\n"));
1623
1624       /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
1625          After nextstate is executed, the control should come back to
1626          SSH_SFTP_CLOSE to pass the correct result back  */
1627       if(sshc->nextstate != SSH_NO_STATE &&
1628          sshc->nextstate != SSH_SFTP_CLOSE) {
1629         state(conn, sshc->nextstate);
1630         sshc->nextstate = SSH_SFTP_CLOSE;
1631       }
1632       else {
1633         state(conn, SSH_STOP);
1634         result = sshc->actualcode;
1635       }
1636       break;
1637
1638     case SSH_SFTP_SHUTDOWN:
1639       /* during times we get here due to a broken transfer and then the
1640          sftp_handle might not have been taken down so make sure that is done
1641          before we proceed */
1642
1643       if(sshc->sftp_file) {
1644         sftp_close(sshc->sftp_file);
1645         sshc->sftp_file = NULL;
1646       }
1647
1648       if(sshc->sftp_session) {
1649         sftp_free(sshc->sftp_session);
1650         sshc->sftp_session = NULL;
1651       }
1652
1653       Curl_safefree(sshc->homedir);
1654       conn->data->state.most_recent_ftp_entrypath = NULL;
1655
1656       state(conn, SSH_SESSION_DISCONNECT);
1657       break;
1658
1659
1660     case SSH_SCP_TRANS_INIT:
1661       result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
1662       if(result) {
1663         sshc->actualcode = result;
1664         state(conn, SSH_STOP);
1665         break;
1666       }
1667
1668       /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
1669       ssh_set_blocking(sshc->ssh_session, 1);
1670
1671       if(data->set.upload) {
1672         if(data->state.infilesize < 0) {
1673           failf(data, "SCP requires a known file size for upload");
1674           sshc->actualcode = CURLE_UPLOAD_FAILED;
1675           MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1676         }
1677
1678         sshc->scp_session =
1679           ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
1680         state(conn, SSH_SCP_UPLOAD_INIT);
1681       }
1682       else {
1683         sshc->scp_session =
1684           ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
1685         state(conn, SSH_SCP_DOWNLOAD_INIT);
1686       }
1687
1688       if(!sshc->scp_session) {
1689         err_msg = ssh_get_error(sshc->ssh_session);
1690         failf(conn->data, "%s", err_msg);
1691         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1692       }
1693
1694       break;
1695
1696     case SSH_SCP_UPLOAD_INIT:
1697
1698       rc = ssh_scp_init(sshc->scp_session);
1699       if(rc != SSH_OK) {
1700         err_msg = ssh_get_error(sshc->ssh_session);
1701         failf(conn->data, "%s", err_msg);
1702         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1703       }
1704
1705       rc = ssh_scp_push_file(sshc->scp_session, protop->path,
1706                              data->state.infilesize,
1707                              (int)data->set.new_file_perms);
1708       if(rc != SSH_OK) {
1709         err_msg = ssh_get_error(sshc->ssh_session);
1710         failf(conn->data, "%s", err_msg);
1711         MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
1712       }
1713
1714       /* upload data */
1715       Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
1716                           FIRSTSOCKET, NULL);
1717
1718       /* not set by Curl_setup_transfer to preserve keepon bits */
1719       conn->sockfd = conn->writesockfd;
1720
1721       /* store this original bitmask setup to use later on if we can't
1722          figure out a "real" bitmask */
1723       sshc->orig_waitfor = data->req.keepon;
1724
1725       /* we want to use the _sending_ function even when the socket turns
1726          out readable as the underlying libssh scp send function will deal
1727          with both accordingly */
1728       conn->cselect_bits = CURL_CSELECT_OUT;
1729
1730       state(conn, SSH_STOP);
1731
1732       break;
1733
1734     case SSH_SCP_DOWNLOAD_INIT:
1735
1736       rc = ssh_scp_init(sshc->scp_session);
1737       if(rc != SSH_OK) {
1738         err_msg = ssh_get_error(sshc->ssh_session);
1739         failf(conn->data, "%s", err_msg);
1740         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
1741       }
1742       state(conn, SSH_SCP_DOWNLOAD);
1743       /* fall through */
1744
1745     case SSH_SCP_DOWNLOAD:{
1746         curl_off_t bytecount;
1747
1748         rc = ssh_scp_pull_request(sshc->scp_session);
1749         if(rc != SSH_SCP_REQUEST_NEWFILE) {
1750           err_msg = ssh_get_error(sshc->ssh_session);
1751           failf(conn->data, "%s", err_msg);
1752           MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
1753           break;
1754         }
1755
1756         /* download data */
1757         bytecount = ssh_scp_request_get_size(sshc->scp_session);
1758         data->req.maxdownload = (curl_off_t) bytecount;
1759         Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1,
1760                             NULL);
1761
1762         /* not set by Curl_setup_transfer to preserve keepon bits */
1763         conn->writesockfd = conn->sockfd;
1764
1765         /* we want to use the _receiving_ function even when the socket turns
1766            out writableable as the underlying libssh recv function will deal
1767            with both accordingly */
1768         conn->cselect_bits = CURL_CSELECT_IN;
1769
1770         state(conn, SSH_STOP);
1771         break;
1772       }
1773     case SSH_SCP_DONE:
1774       if(data->set.upload)
1775         state(conn, SSH_SCP_SEND_EOF);
1776       else
1777         state(conn, SSH_SCP_CHANNEL_FREE);
1778       break;
1779
1780     case SSH_SCP_SEND_EOF:
1781       if(sshc->scp_session) {
1782         rc = ssh_scp_close(sshc->scp_session);
1783         if(rc == SSH_AGAIN) {
1784           /* Currently the ssh_scp_close handles waiting for EOF in
1785            * blocking way.
1786            */
1787           break;
1788         }
1789         if(rc != SSH_OK) {
1790           infof(data, "Failed to close libssh scp channel: %s\n",
1791                 ssh_get_error(sshc->ssh_session));
1792         }
1793       }
1794
1795       state(conn, SSH_SCP_CHANNEL_FREE);
1796       break;
1797
1798     case SSH_SCP_CHANNEL_FREE:
1799       if(sshc->scp_session) {
1800         ssh_scp_free(sshc->scp_session);
1801         sshc->scp_session = NULL;
1802       }
1803       DEBUGF(infof(data, "SCP DONE phase complete\n"));
1804
1805       ssh_set_blocking(sshc->ssh_session, 0);
1806
1807       state(conn, SSH_SESSION_DISCONNECT);
1808       /* fall through */
1809
1810     case SSH_SESSION_DISCONNECT:
1811       /* during weird times when we've been prematurely aborted, the channel
1812          is still alive when we reach this state and we MUST kill the channel
1813          properly first */
1814       if(sshc->scp_session) {
1815         ssh_scp_free(sshc->scp_session);
1816         sshc->scp_session = NULL;
1817       }
1818
1819       ssh_disconnect(sshc->ssh_session);
1820
1821       Curl_safefree(sshc->homedir);
1822       conn->data->state.most_recent_ftp_entrypath = NULL;
1823
1824       state(conn, SSH_SESSION_FREE);
1825       /* fall through */
1826     case SSH_SESSION_FREE:
1827       if(sshc->ssh_session) {
1828         ssh_free(sshc->ssh_session);
1829         sshc->ssh_session = NULL;
1830       }
1831
1832       /* worst-case scenario cleanup */
1833
1834       DEBUGASSERT(sshc->ssh_session == NULL);
1835       DEBUGASSERT(sshc->scp_session == NULL);
1836
1837       if(sshc->readdir_tmp) {
1838         ssh_string_free_char(sshc->readdir_tmp);
1839         sshc->readdir_tmp = NULL;
1840       }
1841
1842       if(sshc->quote_attrs)
1843         sftp_attributes_free(sshc->quote_attrs);
1844
1845       if(sshc->readdir_attrs)
1846         sftp_attributes_free(sshc->readdir_attrs);
1847
1848       if(sshc->readdir_link_attrs)
1849         sftp_attributes_free(sshc->readdir_link_attrs);
1850
1851       if(sshc->privkey)
1852         ssh_key_free(sshc->privkey);
1853       if(sshc->pubkey)
1854         ssh_key_free(sshc->pubkey);
1855
1856       Curl_safefree(sshc->rsa_pub);
1857       Curl_safefree(sshc->rsa);
1858
1859       Curl_safefree(sshc->quote_path1);
1860       Curl_safefree(sshc->quote_path2);
1861
1862       Curl_safefree(sshc->homedir);
1863
1864       Curl_safefree(sshc->readdir_line);
1865       Curl_safefree(sshc->readdir_linkPath);
1866
1867       /* the code we are about to return */
1868       result = sshc->actualcode;
1869
1870       memset(sshc, 0, sizeof(struct ssh_conn));
1871
1872       connclose(conn, "SSH session free");
1873       sshc->state = SSH_SESSION_FREE;   /* current */
1874       sshc->nextstate = SSH_NO_STATE;
1875       state(conn, SSH_STOP);
1876       break;
1877
1878     case SSH_QUIT:
1879       /* fallthrough, just stop! */
1880     default:
1881       /* internal error */
1882       sshc->nextstate = SSH_NO_STATE;
1883       state(conn, SSH_STOP);
1884       break;
1885
1886     }
1887   } while(!rc && (sshc->state != SSH_STOP));
1888
1889
1890   if(rc == SSH_AGAIN) {
1891     /* we would block, we need to wait for the socket to be ready (in the
1892        right direction too)! */
1893     *block = TRUE;
1894   }
1895
1896   return result;
1897 }
1898
1899
1900 /* called by the multi interface to figure out what socket(s) to wait for and
1901    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
1902 static int myssh_perform_getsock(const struct connectdata *conn,
1903                                  curl_socket_t *sock,  /* points to numsocks
1904                                                           number of sockets */
1905                                  int numsocks)
1906 {
1907   int bitmap = GETSOCK_BLANK;
1908   (void) numsocks;
1909
1910   sock[0] = conn->sock[FIRSTSOCKET];
1911
1912   if(conn->waitfor & KEEP_RECV)
1913     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
1914
1915   if(conn->waitfor & KEEP_SEND)
1916     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
1917
1918   return bitmap;
1919 }
1920
1921 /* Generic function called by the multi interface to figure out what socket(s)
1922    to wait for and for what actions during the DOING and PROTOCONNECT states*/
1923 static int myssh_getsock(struct connectdata *conn,
1924                          curl_socket_t *sock,  /* points to numsocks
1925                                                    number of sockets */
1926                          int numsocks)
1927 {
1928   /* if we know the direction we can use the generic *_getsock() function even
1929      for the protocol_connect and doing states */
1930   return myssh_perform_getsock(conn, sock, numsocks);
1931 }
1932
1933 static void myssh_block2waitfor(struct connectdata *conn, bool block)
1934 {
1935   struct ssh_conn *sshc = &conn->proto.sshc;
1936   int dir;
1937
1938   /* If it didn't block, or nothing was returned by ssh_get_poll_flags
1939    * have the original set */
1940   conn->waitfor = sshc->orig_waitfor;
1941
1942   if(block) {
1943     dir = ssh_get_poll_flags(sshc->ssh_session);
1944     if(dir & SSH_READ_PENDING) {
1945       /* translate the libssh define bits into our own bit defines */
1946       conn->waitfor = KEEP_RECV;
1947     }
1948     else if(dir & SSH_WRITE_PENDING) {
1949       conn->waitfor = KEEP_SEND;
1950     }
1951   }
1952 }
1953
1954 /* called repeatedly until done from multi.c */
1955 static CURLcode myssh_multi_statemach(struct connectdata *conn,
1956                                       bool *done)
1957 {
1958   struct ssh_conn *sshc = &conn->proto.sshc;
1959   CURLcode result = CURLE_OK;
1960   bool block;    /* we store the status and use that to provide a ssh_getsock()
1961                     implementation */
1962
1963   result = myssh_statemach_act(conn, &block);
1964   *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
1965   myssh_block2waitfor(conn, block);
1966
1967   return result;
1968 }
1969
1970 static CURLcode myssh_block_statemach(struct connectdata *conn,
1971                                       bool disconnect)
1972 {
1973   struct ssh_conn *sshc = &conn->proto.sshc;
1974   CURLcode result = CURLE_OK;
1975   struct Curl_easy *data = conn->data;
1976
1977   while((sshc->state != SSH_STOP) && !result) {
1978     bool block;
1979     timediff_t left = 1000;
1980     struct curltime now = Curl_now();
1981
1982     result = myssh_statemach_act(conn, &block);
1983     if(result)
1984       break;
1985
1986     if(!disconnect) {
1987       if(Curl_pgrsUpdate(conn))
1988         return CURLE_ABORTED_BY_CALLBACK;
1989
1990       result = Curl_speedcheck(data, now);
1991       if(result)
1992         break;
1993
1994       left = Curl_timeleft(data, NULL, FALSE);
1995       if(left < 0) {
1996         failf(data, "Operation timed out");
1997         return CURLE_OPERATION_TIMEDOUT;
1998       }
1999     }
2000
2001     if(!result && block) {
2002       curl_socket_t sock = conn->sock[FIRSTSOCKET];
2003       curl_socket_t fd_read = CURL_SOCKET_BAD;
2004       fd_read = sock;
2005       /* wait for the socket to become ready */
2006       (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD,
2007                                CURL_SOCKET_BAD, left > 1000 ? 1000 : left);
2008     }
2009
2010   }
2011
2012   return result;
2013 }
2014
2015 /*
2016  * SSH setup connection
2017  */
2018 static CURLcode myssh_setup_connection(struct connectdata *conn)
2019 {
2020   struct SSHPROTO *ssh;
2021
2022   conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
2023   if(!ssh)
2024     return CURLE_OUT_OF_MEMORY;
2025
2026   return CURLE_OK;
2027 }
2028
2029 static Curl_recv scp_recv, sftp_recv;
2030 static Curl_send scp_send, sftp_send;
2031
2032 /*
2033  * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
2034  * do protocol-specific actions at connect-time.
2035  */
2036 static CURLcode myssh_connect(struct connectdata *conn, bool *done)
2037 {
2038   struct ssh_conn *ssh;
2039   CURLcode result;
2040   struct Curl_easy *data = conn->data;
2041   int rc;
2042
2043   /* initialize per-handle data if not already */
2044   if(!data->req.protop)
2045     myssh_setup_connection(conn);
2046
2047   /* We default to persistent connections. We set this already in this connect
2048      function to make the re-use checks properly be able to check this bit. */
2049   connkeep(conn, "SSH default");
2050
2051   if(conn->handler->protocol & CURLPROTO_SCP) {
2052     conn->recv[FIRSTSOCKET] = scp_recv;
2053     conn->send[FIRSTSOCKET] = scp_send;
2054   }
2055   else {
2056     conn->recv[FIRSTSOCKET] = sftp_recv;
2057     conn->send[FIRSTSOCKET] = sftp_send;
2058   }
2059
2060   ssh = &conn->proto.sshc;
2061
2062   ssh->ssh_session = ssh_new();
2063   if(ssh->ssh_session == NULL) {
2064     failf(data, "Failure initialising ssh session");
2065     return CURLE_FAILED_INIT;
2066   }
2067
2068   if(conn->user) {
2069     infof(data, "User: %s\n", conn->user);
2070     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
2071   }
2072
2073   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
2074     infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]);
2075     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
2076                     data->set.str[STRING_SSH_KNOWNHOSTS]);
2077   }
2078
2079   ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
2080   if(conn->remote_port)
2081     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT,
2082                     &conn->remote_port);
2083
2084   if(data->set.ssh_compression) {
2085     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION,
2086                     "zlib,zlib@openssh.com,none");
2087   }
2088
2089   ssh->privkey = NULL;
2090   ssh->pubkey = NULL;
2091
2092   if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
2093     rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
2094                                     &ssh->pubkey);
2095     if(rc != SSH_OK) {
2096       failf(data, "Could not load public key file");
2097       /* ignore */
2098     }
2099   }
2100
2101   /* we do not verify here, we do it at the state machine,
2102    * after connection */
2103
2104   state(conn, SSH_INIT);
2105
2106   result = myssh_multi_statemach(conn, done);
2107
2108   return result;
2109 }
2110
2111 /* called from multi.c while DOing */
2112 static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
2113 {
2114   CURLcode result;
2115
2116   result = myssh_multi_statemach(conn, dophase_done);
2117
2118   if(*dophase_done) {
2119     DEBUGF(infof(conn->data, "DO phase is complete\n"));
2120   }
2121   return result;
2122 }
2123
2124 /*
2125  ***********************************************************************
2126  *
2127  * scp_perform()
2128  *
2129  * This is the actual DO function for SCP. Get a file according to
2130  * the options previously setup.
2131  */
2132
2133 static
2134 CURLcode scp_perform(struct connectdata *conn,
2135                      bool *connected, bool *dophase_done)
2136 {
2137   CURLcode result = CURLE_OK;
2138
2139   DEBUGF(infof(conn->data, "DO phase starts\n"));
2140
2141   *dophase_done = FALSE;        /* not done yet */
2142
2143   /* start the first command in the DO phase */
2144   state(conn, SSH_SCP_TRANS_INIT);
2145
2146   result = myssh_multi_statemach(conn, dophase_done);
2147
2148   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
2149
2150   if(*dophase_done) {
2151     DEBUGF(infof(conn->data, "DO phase is complete\n"));
2152   }
2153
2154   return result;
2155 }
2156
2157 static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
2158 {
2159   CURLcode result;
2160   bool connected = 0;
2161   struct Curl_easy *data = conn->data;
2162   struct ssh_conn *sshc = &conn->proto.sshc;
2163
2164   *done = FALSE;                /* default to false */
2165
2166   data->req.size = -1;          /* make sure this is unknown at this point */
2167
2168   sshc->actualcode = CURLE_OK;  /* reset error code */
2169   sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
2170                                    variable */
2171
2172   Curl_pgrsSetUploadCounter(data, 0);
2173   Curl_pgrsSetDownloadCounter(data, 0);
2174   Curl_pgrsSetUploadSize(data, -1);
2175   Curl_pgrsSetDownloadSize(data, -1);
2176
2177   if(conn->handler->protocol & CURLPROTO_SCP)
2178     result = scp_perform(conn, &connected, done);
2179   else
2180     result = sftp_perform(conn, &connected, done);
2181
2182   return result;
2183 }
2184
2185 /* BLOCKING, but the function is using the state machine so the only reason
2186    this is still blocking is that the multi interface code has no support for
2187    disconnecting operations that takes a while */
2188 static CURLcode scp_disconnect(struct connectdata *conn,
2189                                bool dead_connection)
2190 {
2191   CURLcode result = CURLE_OK;
2192   struct ssh_conn *ssh = &conn->proto.sshc;
2193   (void) dead_connection;
2194
2195   if(ssh->ssh_session) {
2196     /* only if there's a session still around to use! */
2197
2198     state(conn, SSH_SESSION_DISCONNECT);
2199
2200     result = myssh_block_statemach(conn, TRUE);
2201   }
2202
2203   return result;
2204 }
2205
2206 /* generic done function for both SCP and SFTP called from their specific
2207    done functions */
2208 static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
2209 {
2210   CURLcode result = CURLE_OK;
2211   struct SSHPROTO *protop = conn->data->req.protop;
2212
2213   if(!status) {
2214     /* run the state-machine
2215
2216        TODO: when the multi interface is used, this _really_ should be using
2217        the ssh_multi_statemach function but we have no general support for
2218        non-blocking DONE operations!
2219      */
2220     result = myssh_block_statemach(conn, FALSE);
2221   }
2222   else
2223     result = status;
2224
2225   if(protop)
2226     Curl_safefree(protop->path);
2227   if(Curl_pgrsDone(conn))
2228     return CURLE_ABORTED_BY_CALLBACK;
2229
2230   conn->data->req.keepon = 0;   /* clear all bits */
2231   return result;
2232 }
2233
2234
2235 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
2236                          bool premature)
2237 {
2238   (void) premature;             /* not used */
2239
2240   if(!status)
2241     state(conn, SSH_SCP_DONE);
2242
2243   return myssh_done(conn, status);
2244
2245 }
2246
2247 static ssize_t scp_send(struct connectdata *conn, int sockindex,
2248                         const void *mem, size_t len, CURLcode *err)
2249 {
2250   int rc;
2251   (void) sockindex; /* we only support SCP on the fixed known primary socket */
2252   (void) err;
2253
2254   rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);
2255
2256 #if 0
2257   /* The following code is misleading, mostly added as wishful thinking
2258    * that libssh at some point will implement non-blocking ssh_scp_write/read.
2259    * Currently rc can only be number of bytes read or SSH_ERROR. */
2260   myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE);
2261
2262   if(rc == SSH_AGAIN) {
2263     *err = CURLE_AGAIN;
2264     return 0;
2265   }
2266   else
2267 #endif
2268   if(rc != SSH_OK) {
2269     *err = CURLE_SSH;
2270     return -1;
2271   }
2272
2273   return len;
2274 }
2275
2276 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
2277                         char *mem, size_t len, CURLcode *err)
2278 {
2279   ssize_t nread;
2280   (void) err;
2281   (void) sockindex; /* we only support SCP on the fixed known primary socket */
2282
2283   /* libssh returns int */
2284   nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);
2285
2286 #if 0
2287   /* The following code is misleading, mostly added as wishful thinking
2288    * that libssh at some point will implement non-blocking ssh_scp_write/read.
2289    * Currently rc can only be SSH_OK or SSH_ERROR. */
2290
2291   myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE);
2292   if(nread == SSH_AGAIN) {
2293     *err = CURLE_AGAIN;
2294     nread = -1;
2295   }
2296 #endif
2297
2298   return nread;
2299 }
2300
2301 /*
2302  * =============== SFTP ===============
2303  */
2304
2305 /*
2306  ***********************************************************************
2307  *
2308  * sftp_perform()
2309  *
2310  * This is the actual DO function for SFTP. Get a file/directory according to
2311  * the options previously setup.
2312  */
2313
2314 static
2315 CURLcode sftp_perform(struct connectdata *conn,
2316                       bool *connected,
2317                       bool *dophase_done)
2318 {
2319   CURLcode result = CURLE_OK;
2320
2321   DEBUGF(infof(conn->data, "DO phase starts\n"));
2322
2323   *dophase_done = FALSE; /* not done yet */
2324
2325   /* start the first command in the DO phase */
2326   state(conn, SSH_SFTP_QUOTE_INIT);
2327
2328   /* run the state-machine */
2329   result = myssh_multi_statemach(conn, dophase_done);
2330
2331   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
2332
2333   if(*dophase_done) {
2334     DEBUGF(infof(conn->data, "DO phase is complete\n"));
2335   }
2336
2337   return result;
2338 }
2339
2340 /* called from multi.c while DOing */
2341 static CURLcode sftp_doing(struct connectdata *conn,
2342                            bool *dophase_done)
2343 {
2344   CURLcode result = myssh_multi_statemach(conn, dophase_done);
2345   if(*dophase_done) {
2346     DEBUGF(infof(conn->data, "DO phase is complete\n"));
2347   }
2348   return result;
2349 }
2350
2351 /* BLOCKING, but the function is using the state machine so the only reason
2352    this is still blocking is that the multi interface code has no support for
2353    disconnecting operations that takes a while */
2354 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
2355 {
2356   CURLcode result = CURLE_OK;
2357   (void) dead_connection;
2358
2359   DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
2360
2361   if(conn->proto.sshc.ssh_session) {
2362     /* only if there's a session still around to use! */
2363     state(conn, SSH_SFTP_SHUTDOWN);
2364     result = myssh_block_statemach(conn, TRUE);
2365   }
2366
2367   DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
2368
2369   return result;
2370
2371 }
2372
2373 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
2374                                bool premature)
2375 {
2376   struct ssh_conn *sshc = &conn->proto.sshc;
2377
2378   if(!status) {
2379     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
2380        errors that could happen due to open file handles during POSTQUOTE
2381        operation */
2382     if(!status && !premature && conn->data->set.postquote) {
2383       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
2384       state(conn, SSH_SFTP_CLOSE);
2385     }
2386     else
2387       state(conn, SSH_SFTP_CLOSE);
2388   }
2389   return myssh_done(conn, status);
2390 }
2391
2392 /* return number of sent bytes */
2393 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
2394                          const void *mem, size_t len, CURLcode *err)
2395 {
2396   ssize_t nwrite;
2397   (void)sockindex;
2398
2399   nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
2400
2401   myssh_block2waitfor(conn, FALSE);
2402
2403 #if 0 /* not returned by libssh on write */
2404   if(nwrite == SSH_AGAIN) {
2405     *err = CURLE_AGAIN;
2406     nwrite = 0;
2407   }
2408   else
2409 #endif
2410   if(nwrite < 0) {
2411     *err = CURLE_SSH;
2412     nwrite = -1;
2413   }
2414
2415   return nwrite;
2416 }
2417
2418 /*
2419  * Return number of received (decrypted) bytes
2420  * or <0 on error
2421  */
2422 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
2423                          char *mem, size_t len, CURLcode *err)
2424 {
2425   ssize_t nread;
2426   (void)sockindex;
2427
2428   if(len >= (size_t)1<<32)
2429     len = (size_t)(1<<31)-1;
2430
2431   switch(conn->proto.sshc.sftp_recv_state) {
2432     case 0:
2433       conn->proto.sshc.sftp_file_index =
2434             sftp_async_read_begin(conn->proto.sshc.sftp_file,
2435                                   (uint32_t)len);
2436       if(conn->proto.sshc.sftp_file_index < 0) {
2437         *err = CURLE_RECV_ERROR;
2438         return -1;
2439       }
2440
2441       /* fall-through */
2442     case 1:
2443       conn->proto.sshc.sftp_recv_state = 1;
2444
2445       nread = sftp_async_read(conn->proto.sshc.sftp_file,
2446                               mem, (uint32_t)len,
2447                               conn->proto.sshc.sftp_file_index);
2448
2449       myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE);
2450
2451       if(nread == SSH_AGAIN) {
2452         *err = CURLE_AGAIN;
2453         return -1;
2454       }
2455       else if(nread < 0) {
2456         *err = CURLE_RECV_ERROR;
2457         return -1;
2458       }
2459
2460       conn->proto.sshc.sftp_recv_state = 0;
2461       return nread;
2462
2463     default:
2464       /* we never reach here */
2465       return -1;
2466   }
2467 }
2468
2469 static void sftp_quote(struct connectdata *conn)
2470 {
2471   const char *cp;
2472   struct Curl_easy *data = conn->data;
2473   struct SSHPROTO *protop = data->req.protop;
2474   struct ssh_conn *sshc = &conn->proto.sshc;
2475   CURLcode result;
2476
2477   /*
2478    * Support some of the "FTP" commands
2479    */
2480   char *cmd = sshc->quote_item->data;
2481   sshc->acceptfail = FALSE;
2482
2483   /* if a command starts with an asterisk, which a legal SFTP command never
2484      can, the command will be allowed to fail without it causing any
2485      aborts or cancels etc. It will cause libcurl to act as if the command
2486      is successful, whatever the server reponds. */
2487
2488   if(cmd[0] == '*') {
2489     cmd++;
2490     sshc->acceptfail = TRUE;
2491   }
2492
2493   if(strcasecompare("pwd", cmd)) {
2494     /* output debug output if that is requested */
2495     char *tmp = aprintf("257 \"%s\" is current directory.\n",
2496                         protop->path);
2497     if(!tmp) {
2498       sshc->actualcode = CURLE_OUT_OF_MEMORY;
2499       state(conn, SSH_SFTP_CLOSE);
2500       sshc->nextstate = SSH_NO_STATE;
2501       return;
2502     }
2503     if(data->set.verbose) {
2504       Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4, conn);
2505       Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
2506     }
2507     /* this sends an FTP-like "header" to the header callback so that the
2508        current directory can be read very similar to how it is read when
2509        using ordinary FTP. */
2510     result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
2511     free(tmp);
2512     if(result) {
2513       state(conn, SSH_SFTP_CLOSE);
2514       sshc->nextstate = SSH_NO_STATE;
2515       sshc->actualcode = result;
2516     }
2517     else
2518       state(conn, SSH_SFTP_NEXT_QUOTE);
2519     return;
2520   }
2521
2522   /*
2523    * the arguments following the command must be separated from the
2524    * command with a space so we can check for it unconditionally
2525    */
2526   cp = strchr(cmd, ' ');
2527   if(cp == NULL) {
2528     failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
2529     state(conn, SSH_SFTP_CLOSE);
2530     sshc->nextstate = SSH_NO_STATE;
2531     sshc->actualcode = CURLE_QUOTE_ERROR;
2532     return;
2533   }
2534
2535   /*
2536    * also, every command takes at least one argument so we get that
2537    * first argument right now
2538    */
2539   result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
2540   if(result) {
2541     if(result == CURLE_OUT_OF_MEMORY)
2542       failf(data, "Out of memory");
2543     else
2544       failf(data, "Syntax error: Bad first parameter");
2545     state(conn, SSH_SFTP_CLOSE);
2546     sshc->nextstate = SSH_NO_STATE;
2547     sshc->actualcode = result;
2548     return;
2549   }
2550
2551   /*
2552    * SFTP is a binary protocol, so we don't send text commands
2553    * to the server. Instead, we scan for commands used by
2554    * OpenSSH's sftp program and call the appropriate libssh
2555    * functions.
2556    */
2557   if(strncasecompare(cmd, "chgrp ", 6) ||
2558      strncasecompare(cmd, "chmod ", 6) ||
2559      strncasecompare(cmd, "chown ", 6)) {
2560     /* attribute change */
2561
2562     /* sshc->quote_path1 contains the mode to set */
2563     /* get the destination */
2564     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
2565     if(result) {
2566       if(result == CURLE_OUT_OF_MEMORY)
2567         failf(data, "Out of memory");
2568       else
2569         failf(data, "Syntax error in chgrp/chmod/chown: "
2570               "Bad second parameter");
2571       Curl_safefree(sshc->quote_path1);
2572       state(conn, SSH_SFTP_CLOSE);
2573       sshc->nextstate = SSH_NO_STATE;
2574       sshc->actualcode = result;
2575       return;
2576     }
2577     sshc->quote_attrs = NULL;
2578     state(conn, SSH_SFTP_QUOTE_STAT);
2579     return;
2580   }
2581   if(strncasecompare(cmd, "ln ", 3) ||
2582      strncasecompare(cmd, "symlink ", 8)) {
2583     /* symbolic linking */
2584     /* sshc->quote_path1 is the source */
2585     /* get the destination */
2586     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
2587     if(result) {
2588       if(result == CURLE_OUT_OF_MEMORY)
2589         failf(data, "Out of memory");
2590       else
2591         failf(data, "Syntax error in ln/symlink: Bad second parameter");
2592       Curl_safefree(sshc->quote_path1);
2593       state(conn, SSH_SFTP_CLOSE);
2594       sshc->nextstate = SSH_NO_STATE;
2595       sshc->actualcode = result;
2596       return;
2597     }
2598     state(conn, SSH_SFTP_QUOTE_SYMLINK);
2599     return;
2600   }
2601   else if(strncasecompare(cmd, "mkdir ", 6)) {
2602     /* create dir */
2603     state(conn, SSH_SFTP_QUOTE_MKDIR);
2604     return;
2605   }
2606   else if(strncasecompare(cmd, "rename ", 7)) {
2607     /* rename file */
2608     /* first param is the source path */
2609     /* second param is the dest. path */
2610     result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
2611     if(result) {
2612       if(result == CURLE_OUT_OF_MEMORY)
2613         failf(data, "Out of memory");
2614       else
2615         failf(data, "Syntax error in rename: Bad second parameter");
2616       Curl_safefree(sshc->quote_path1);
2617       state(conn, SSH_SFTP_CLOSE);
2618       sshc->nextstate = SSH_NO_STATE;
2619       sshc->actualcode = result;
2620       return;
2621     }
2622     state(conn, SSH_SFTP_QUOTE_RENAME);
2623     return;
2624   }
2625   else if(strncasecompare(cmd, "rmdir ", 6)) {
2626     /* delete dir */
2627     state(conn, SSH_SFTP_QUOTE_RMDIR);
2628     return;
2629   }
2630   else if(strncasecompare(cmd, "rm ", 3)) {
2631     state(conn, SSH_SFTP_QUOTE_UNLINK);
2632     return;
2633   }
2634 #ifdef HAS_STATVFS_SUPPORT
2635   else if(strncasecompare(cmd, "statvfs ", 8)) {
2636     state(conn, SSH_SFTP_QUOTE_STATVFS);
2637     return;
2638   }
2639 #endif
2640
2641   failf(data, "Unknown SFTP command");
2642   Curl_safefree(sshc->quote_path1);
2643   Curl_safefree(sshc->quote_path2);
2644   state(conn, SSH_SFTP_CLOSE);
2645   sshc->nextstate = SSH_NO_STATE;
2646   sshc->actualcode = CURLE_QUOTE_ERROR;
2647 }
2648
2649 static void sftp_quote_stat(struct connectdata *conn)
2650 {
2651   struct Curl_easy *data = conn->data;
2652   struct ssh_conn *sshc = &conn->proto.sshc;
2653   char *cmd = sshc->quote_item->data;
2654   sshc->acceptfail = FALSE;
2655
2656   /* if a command starts with an asterisk, which a legal SFTP command never
2657      can, the command will be allowed to fail without it causing any
2658      aborts or cancels etc. It will cause libcurl to act as if the command
2659      is successful, whatever the server reponds. */
2660
2661   if(cmd[0] == '*') {
2662     cmd++;
2663     sshc->acceptfail = TRUE;
2664   }
2665
2666   /* We read the file attributes, store them in sshc->quote_attrs
2667    * and modify them accordingly to command. Then we switch to
2668    * QUOTE_SETSTAT state to write new ones.
2669    */
2670
2671   if(sshc->quote_attrs)
2672     sftp_attributes_free(sshc->quote_attrs);
2673   sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
2674   if(sshc->quote_attrs == NULL) {
2675     Curl_safefree(sshc->quote_path1);
2676     Curl_safefree(sshc->quote_path2);
2677     failf(data, "Attempt to get SFTP stats failed: %d",
2678           sftp_get_error(sshc->sftp_session));
2679     state(conn, SSH_SFTP_CLOSE);
2680     sshc->nextstate = SSH_NO_STATE;
2681     sshc->actualcode = CURLE_QUOTE_ERROR;
2682     return;
2683   }
2684
2685   /* Now set the new attributes... */
2686   if(strncasecompare(cmd, "chgrp", 5)) {
2687     sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
2688     if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
2689         !sshc->acceptfail) {
2690       Curl_safefree(sshc->quote_path1);
2691       Curl_safefree(sshc->quote_path2);
2692       failf(data, "Syntax error: chgrp gid not a number");
2693       state(conn, SSH_SFTP_CLOSE);
2694       sshc->nextstate = SSH_NO_STATE;
2695       sshc->actualcode = CURLE_QUOTE_ERROR;
2696       return;
2697     }
2698     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
2699   }
2700   else if(strncasecompare(cmd, "chmod", 5)) {
2701     mode_t perms;
2702     perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
2703     /* permissions are octal */
2704     if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
2705       Curl_safefree(sshc->quote_path1);
2706       Curl_safefree(sshc->quote_path2);
2707       failf(data, "Syntax error: chmod permissions not a number");
2708       state(conn, SSH_SFTP_CLOSE);
2709       sshc->nextstate = SSH_NO_STATE;
2710       sshc->actualcode = CURLE_QUOTE_ERROR;
2711       return;
2712     }
2713     sshc->quote_attrs->permissions = perms;
2714     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
2715   }
2716   else if(strncasecompare(cmd, "chown", 5)) {
2717     sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
2718     if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
2719         !sshc->acceptfail) {
2720       Curl_safefree(sshc->quote_path1);
2721       Curl_safefree(sshc->quote_path2);
2722       failf(data, "Syntax error: chown uid not a number");
2723       state(conn, SSH_SFTP_CLOSE);
2724       sshc->nextstate = SSH_NO_STATE;
2725       sshc->actualcode = CURLE_QUOTE_ERROR;
2726       return;
2727     }
2728     sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
2729   }
2730
2731   /* Now send the completed structure... */
2732   state(conn, SSH_SFTP_QUOTE_SETSTAT);
2733   return;
2734 }
2735
2736
2737 #endif                          /* USE_LIBSSH */