1 /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
2  * Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
3  * Copyright (c) 2009-2014 by Daniel Stenberg
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms,
7  * with or without modification, are permitted provided
8  * that the following conditions are met:
9  *
10  *   Redistributions of source code must retain the above
11  *   copyright notice, this list of conditions and the
12  *   following disclaimer.
13  *
14  *   Redistributions in binary form must reproduce the above
15  *   copyright notice, this list of conditions and the following
16  *   disclaimer in the documentation and/or other materials
17  *   provided with the distribution.
18  *
19  *   Neither the name of the copyright holder nor the names
20  *   of any other contributors may be used to endorse or
21  *   promote products derived from this software without
22  *   specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37  * OF SUCH DAMAGE.
38  */
39 
40 #include <assert.h>
41 
42 #include "libssh2_priv.h"
43 #include "libssh2_sftp.h"
44 #include "channel.h"
45 #include "session.h"
46 #include "sftp.h"
47 
48 /* Note: Version 6 was documented at the time of writing
49  * However it was marked as "DO NOT IMPLEMENT" due to pending changes
50  *
51  * This release of libssh2 implements Version 5 with automatic downgrade
52  * based on server's declaration
53  */
54 
55 /* SFTP packet types */
56 #define SSH_FXP_INIT                            1
57 #define SSH_FXP_VERSION                         2
58 #define SSH_FXP_OPEN                            3
59 #define SSH_FXP_CLOSE                           4
60 #define SSH_FXP_READ                            5
61 #define SSH_FXP_WRITE                           6
62 #define SSH_FXP_LSTAT                           7
63 #define SSH_FXP_FSTAT                           8
64 #define SSH_FXP_SETSTAT                         9
65 #define SSH_FXP_FSETSTAT                        10
66 #define SSH_FXP_OPENDIR                         11
67 #define SSH_FXP_READDIR                         12
68 #define SSH_FXP_REMOVE                          13
69 #define SSH_FXP_MKDIR                           14
70 #define SSH_FXP_RMDIR                           15
71 #define SSH_FXP_REALPATH                        16
72 #define SSH_FXP_STAT                            17
73 #define SSH_FXP_RENAME                          18
74 #define SSH_FXP_READLINK                        19
75 #define SSH_FXP_SYMLINK                         20
76 #define SSH_FXP_STATUS                          101
77 #define SSH_FXP_HANDLE                          102
78 #define SSH_FXP_DATA                            103
79 #define SSH_FXP_NAME                            104
80 #define SSH_FXP_ATTRS                           105
81 #define SSH_FXP_EXTENDED                        200
82 #define SSH_FXP_EXTENDED_REPLY                  201
83 
84 /* S_IFREG */
85 #define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE        0100000
86 /* S_IFDIR */
87 #define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR         0040000
88 
89 #define SSH_FXE_STATVFS_ST_RDONLY               0x00000001
90 #define SSH_FXE_STATVFS_ST_NOSUID               0x00000002
91 
92 /* This is the maximum packet length to accept, as larger than this indicate
93    some kind of server problem. */
94 #define LIBSSH2_SFTP_PACKET_MAXLEN  80000
95 
96 static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
97                            uint32_t request_id, unsigned char **data,
98                            size_t *data_len);
99 static void sftp_packet_flush(LIBSSH2_SFTP *sftp);
100 
101 /* sftp_attrsize
102  * Size that attr with this flagset will occupy when turned into a bin struct
103  */
sftp_attrsize(unsigned long flags)104 static int sftp_attrsize(unsigned long flags)
105 {
106     return (4 +                                 /* flags(4) */
107             ((flags & LIBSSH2_SFTP_ATTR_SIZE) ? 8 : 0) +
108             ((flags & LIBSSH2_SFTP_ATTR_UIDGID) ? 8 : 0) +
109             ((flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) ? 4 : 0) +
110             ((flags & LIBSSH2_SFTP_ATTR_ACMODTIME) ? 8 : 0));
111     /* atime + mtime as u32 */
112 }
113 
114 /* _libssh2_store_u64
115  */
_libssh2_store_u64(unsigned char ** ptr,libssh2_uint64_t value)116 static void _libssh2_store_u64(unsigned char **ptr, libssh2_uint64_t value)
117 {
118     uint32_t msl = (uint32_t)(value >> 32);
119     unsigned char *buf = *ptr;
120 
121     buf[0] = (unsigned char)((msl >> 24) & 0xFF);
122     buf[1] = (unsigned char)((msl >> 16) & 0xFF);
123     buf[2] = (unsigned char)((msl >> 8)  & 0xFF);
124     buf[3] = (unsigned char)( msl        & 0xFF);
125 
126     buf[4] = (unsigned char)((value >> 24) & 0xFF);
127     buf[5] = (unsigned char)((value >> 16) & 0xFF);
128     buf[6] = (unsigned char)((value >> 8)  & 0xFF);
129     buf[7] = (unsigned char)( value        & 0xFF);
130 
131     *ptr += 8;
132 }
133 
134 /*
135  * Search list of zombied FXP_READ request IDs.
136  *
137  * Returns NULL if ID not in list.
138  */
139 static struct sftp_zombie_requests *
find_zombie_request(LIBSSH2_SFTP * sftp,uint32_t request_id)140 find_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
141 {
142     struct sftp_zombie_requests *zombie =
143         _libssh2_list_first(&sftp->zombie_requests);
144 
145     while(zombie) {
146         if(zombie->request_id == request_id)
147             break;
148         else
149             zombie = _libssh2_list_next(&zombie->node);
150     }
151 
152     return zombie;
153 }
154 
155 static void
remove_zombie_request(LIBSSH2_SFTP * sftp,uint32_t request_id)156 remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
157 {
158     LIBSSH2_SESSION *session = sftp->channel->session;
159 
160     struct sftp_zombie_requests *zombie = find_zombie_request(sftp,
161                                                               request_id);
162     if(zombie) {
163         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
164                        "Removing request ID %ld from the list of zombie requests",
165                        request_id);
166 
167         _libssh2_list_remove(&zombie->node);
168         LIBSSH2_FREE(session, zombie);
169     }
170 }
171 
172 static int
add_zombie_request(LIBSSH2_SFTP * sftp,uint32_t request_id)173 add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
174 {
175     LIBSSH2_SESSION *session = sftp->channel->session;
176 
177     struct sftp_zombie_requests *zombie;
178 
179     _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
180                    "Marking request ID %ld as a zombie request", request_id);
181 
182     zombie = LIBSSH2_ALLOC(sftp->channel->session,
183                            sizeof(struct sftp_zombie_requests));
184     if (!zombie)
185         return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
186                               "malloc fail for zombie request  ID");
187     else {
188         zombie->request_id = request_id;
189         _libssh2_list_add(&sftp->zombie_requests, &zombie->node);
190         return LIBSSH2_ERROR_NONE;
191     }
192 }
193 
194 /*
195  * sftp_packet_add
196  *
197  * Add a packet to the SFTP packet brigade
198  */
199 static int
sftp_packet_add(LIBSSH2_SFTP * sftp,unsigned char * data,size_t data_len)200 sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
201                 size_t data_len)
202 {
203     LIBSSH2_SESSION *session = sftp->channel->session;
204     LIBSSH2_SFTP_PACKET *packet;
205     uint32_t request_id;
206 
207     _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
208                    "Received packet type %d (len %d)",
209                    (int) data[0], data_len);
210 
211     /*
212      * Experience shows that if we mess up EAGAIN handling somewhere or
213      * otherwise get out of sync with the channel, this is where we first get
214      * a wrong byte and if so we need to bail out at once to aid tracking the
215      * problem better.
216      */
217 
218     switch(data[0]) {
219     case SSH_FXP_INIT:
220     case SSH_FXP_VERSION:
221     case SSH_FXP_OPEN:
222     case SSH_FXP_CLOSE:
223     case SSH_FXP_READ:
224     case SSH_FXP_WRITE:
225     case SSH_FXP_LSTAT:
226     case SSH_FXP_FSTAT:
227     case SSH_FXP_SETSTAT:
228     case SSH_FXP_FSETSTAT:
229     case SSH_FXP_OPENDIR:
230     case SSH_FXP_READDIR:
231     case SSH_FXP_REMOVE:
232     case SSH_FXP_MKDIR:
233     case SSH_FXP_RMDIR:
234     case SSH_FXP_REALPATH:
235     case SSH_FXP_STAT:
236     case SSH_FXP_RENAME:
237     case SSH_FXP_READLINK:
238     case SSH_FXP_SYMLINK:
239     case SSH_FXP_STATUS:
240     case SSH_FXP_HANDLE:
241     case SSH_FXP_DATA:
242     case SSH_FXP_NAME:
243     case SSH_FXP_ATTRS:
244     case SSH_FXP_EXTENDED:
245     case SSH_FXP_EXTENDED_REPLY:
246         break;
247     default:
248         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
249                               "Out of sync with the world");
250     }
251 
252     request_id = _libssh2_ntohu32(&data[1]);
253 
254     _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet id %d",
255                    request_id);
256 
257     /* Don't add the packet if it answers a request we've given up on. */
258     if((data[0] == SSH_FXP_STATUS || data[0] == SSH_FXP_DATA)
259        && find_zombie_request(sftp, request_id)) {
260 
261         /* If we get here, the file ended before the response arrived. We
262            are no longer interested in the request so we discard it */
263 
264         LIBSSH2_FREE(session, data);
265 
266         remove_zombie_request(sftp, request_id);
267         return LIBSSH2_ERROR_NONE;
268     }
269 
270     packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET));
271     if (!packet) {
272         return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
273                               "Unable to allocate datablock for SFTP packet");
274     }
275 
276     packet->data = data;
277     packet->data_len = data_len;
278     packet->request_id = request_id;
279 
280     _libssh2_list_add(&sftp->packets, &packet->node);
281 
282     return LIBSSH2_ERROR_NONE;
283 }
284 
285 /*
286  * sftp_packet_read
287  *
288  * Frame an SFTP packet off the channel
289  */
290 static int
sftp_packet_read(LIBSSH2_SFTP * sftp)291 sftp_packet_read(LIBSSH2_SFTP *sftp)
292 {
293     LIBSSH2_CHANNEL *channel = sftp->channel;
294     LIBSSH2_SESSION *session = channel->session;
295     unsigned char *packet = NULL;
296     ssize_t rc;
297     unsigned long recv_window;
298     int packet_type;
299 
300     _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet");
301 
302     switch(sftp->packet_state) {
303     case libssh2_NB_state_sent: /* EAGAIN from window adjusting */
304         sftp->packet_state = libssh2_NB_state_idle;
305 
306         packet = sftp->partial_packet;
307         goto window_adjust;
308 
309     case libssh2_NB_state_sent1: /* EAGAIN from channel read */
310         sftp->packet_state = libssh2_NB_state_idle;
311 
312         packet = sftp->partial_packet;
313 
314         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
315                        "partial read cont, len: %lu", sftp->partial_len);
316         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
317                        "partial read cont, already recvd: %lu",
318                        sftp->partial_received);
319         /* fall-through */
320     default:
321         if(!packet) {
322             /* only do this if there's not already a packet buffer allocated
323                to use */
324 
325             /* each packet starts with a 32 bit length field */
326             rc = _libssh2_channel_read(channel, 0,
327                                        (char *)&sftp->partial_size[
328                                            sftp->partial_size_len],
329                                        4 - sftp->partial_size_len);
330             if (rc == LIBSSH2_ERROR_EAGAIN)
331                 return rc;
332             else if (rc < 0)
333                 return _libssh2_error(session, rc, "channel read");
334 
335             sftp->partial_size_len += rc;
336 
337             if(4 != sftp->partial_size_len)
338                 /* we got a short read for the length part */
339                 return LIBSSH2_ERROR_EAGAIN;
340 
341             sftp->partial_len = _libssh2_ntohu32(sftp->partial_size);
342             /* make sure we don't proceed if the packet size is unreasonably
343                large */
344             if (sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN)
345                 return _libssh2_error(session,
346                                       LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
347                                       "SFTP packet too large");
348 
349             _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
350                            "Data begin - Packet Length: %lu",
351                            sftp->partial_len);
352             packet = LIBSSH2_ALLOC(session, sftp->partial_len);
353             if (!packet)
354                 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
355                                       "Unable to allocate SFTP packet");
356             sftp->partial_size_len = 0;
357             sftp->partial_received = 0; /* how much of the packet already
358                                            received */
359             sftp->partial_packet = packet;
360 
361           window_adjust:
362             recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
363 
364             if(sftp->partial_len > recv_window) {
365                 /* ask for twice the data amount we need at once */
366                 rc = _libssh2_channel_receive_window_adjust(channel,
367                                                             sftp->partial_len*2,
368                                                             1, NULL);
369                 /* store the state so that we continue with the correct
370                    operation at next invoke */
371                 sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN)?
372                     libssh2_NB_state_sent:
373                     libssh2_NB_state_idle;
374 
375                 if(rc == LIBSSH2_ERROR_EAGAIN)
376                     return rc;
377             }
378         }
379 
380         /* Read as much of the packet as we can */
381         while (sftp->partial_len > sftp->partial_received) {
382             rc = _libssh2_channel_read(channel, 0,
383                                        (char *)&packet[sftp->partial_received],
384                                        sftp->partial_len -
385                                        sftp->partial_received);
386 
387             if (rc == LIBSSH2_ERROR_EAGAIN) {
388                 /*
389                  * We received EAGAIN, save what we have and return EAGAIN to
390                  * the caller. Set 'partial_packet' so that this function
391                  * knows how to continue on the next invoke.
392                  */
393                 sftp->packet_state = libssh2_NB_state_sent1;
394                 return rc;
395             }
396             else if (rc < 0) {
397                 LIBSSH2_FREE(session, packet);
398                 sftp->partial_packet = NULL;
399                 return _libssh2_error(session, rc,
400                                       "Error waiting for SFTP packet");
401             }
402             sftp->partial_received += rc;
403         }
404 
405         sftp->partial_packet = NULL;
406 
407         /* sftp_packet_add takes ownership of the packet and might free it
408            so we take a copy of the packet type before we call it. */
409         packet_type = packet[0];
410         rc = sftp_packet_add(sftp, packet, sftp->partial_len);
411         if (rc) {
412             LIBSSH2_FREE(session, packet);
413             return rc;
414         }
415         else {
416             return packet_type;
417         }
418     }
419     /* WON'T REACH */
420 }
421 /*
422  * sftp_packetlist_flush
423  *
424  * Remove all pending packets in the packet_list and the corresponding one(s)
425  * in the SFTP packet brigade.
426  */
sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE * handle)427 static void sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE *handle)
428 {
429     struct sftp_pipeline_chunk *chunk;
430     LIBSSH2_SFTP *sftp = handle->sftp;
431     LIBSSH2_SESSION *session = sftp->channel->session;
432 
433     /* remove pending packets, if any */
434     chunk = _libssh2_list_first(&handle->packet_list);
435     while(chunk) {
436         unsigned char *data;
437         size_t data_len;
438         int rc;
439         struct sftp_pipeline_chunk *next = _libssh2_list_next(&chunk->node);
440 
441         rc = sftp_packet_ask(sftp, SSH_FXP_STATUS,
442                              chunk->request_id, &data, &data_len);
443         if(rc)
444             rc = sftp_packet_ask(sftp, SSH_FXP_DATA,
445                                  chunk->request_id, &data, &data_len);
446 
447         if(!rc)
448             /* we found a packet, free it */
449             LIBSSH2_FREE(session, data);
450         else if(chunk->sent)
451             /* there was no incoming packet for this request, mark this
452                request as a zombie if it ever sent the request */
453             add_zombie_request(sftp, chunk->request_id);
454 
455         _libssh2_list_remove(&chunk->node);
456         LIBSSH2_FREE(session, chunk);
457         chunk = next;
458     }
459 }
460 
461 
462 /*
463  * sftp_packet_ask()
464  *
465  * Checks if there's a matching SFTP packet available.
466  */
467 static int
sftp_packet_ask(LIBSSH2_SFTP * sftp,unsigned char packet_type,uint32_t request_id,unsigned char ** data,size_t * data_len)468 sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
469                 uint32_t request_id, unsigned char **data,
470                 size_t *data_len)
471 {
472     LIBSSH2_SESSION *session = sftp->channel->session;
473     LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets);
474 
475     if(!packet)
476         return -1;
477 
478     /* Special consideration when getting VERSION packet */
479 
480     while (packet) {
481         if((packet->data[0] == packet_type) &&
482            ((packet_type == SSH_FXP_VERSION) ||
483             (packet->request_id == request_id))) {
484 
485             /* Match! Fetch the data */
486             *data = packet->data;
487             *data_len = packet->data_len;
488 
489             /* unlink and free this struct */
490             _libssh2_list_remove(&packet->node);
491             LIBSSH2_FREE(session, packet);
492 
493             return 0;
494         }
495         /* check next struct in the list */
496         packet = _libssh2_list_next(&packet->node);
497     }
498     return -1;
499 }
500 
501 /* sftp_packet_require
502  * A la libssh2_packet_require
503  */
504 static int
sftp_packet_require(LIBSSH2_SFTP * sftp,unsigned char packet_type,uint32_t request_id,unsigned char ** data,size_t * data_len)505 sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
506                     uint32_t request_id, unsigned char **data,
507                     size_t *data_len)
508 {
509     LIBSSH2_SESSION *session = sftp->channel->session;
510     int rc;
511 
512     _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld",
513                    (int) packet_type, request_id);
514 
515     if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) {
516         /* The right packet was available in the packet brigade */
517         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
518                        (int) packet_type);
519         return LIBSSH2_ERROR_NONE;
520     }
521 
522     while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
523         rc = sftp_packet_read(sftp);
524         if (rc < 0)
525             return rc;
526 
527         /* data was read, check the queue again */
528         if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) {
529             /* The right packet was available in the packet brigade */
530             _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
531                            (int) packet_type);
532             return LIBSSH2_ERROR_NONE;
533         }
534     }
535 
536     /* Only reached if the socket died */
537     return LIBSSH2_ERROR_SOCKET_DISCONNECT;
538 }
539 
540 /* sftp_packet_requirev
541  * Require one of N possible responses
542  */
543 static int
sftp_packet_requirev(LIBSSH2_SFTP * sftp,int num_valid_responses,const unsigned char * valid_responses,uint32_t request_id,unsigned char ** data,size_t * data_len)544 sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
545                      const unsigned char *valid_responses,
546                      uint32_t request_id, unsigned char **data,
547                      size_t *data_len)
548 {
549     int i;
550     int rc;
551 
552     /* If no timeout is active, start a new one */
553     if (sftp->requirev_start == 0)
554         sftp->requirev_start = time(NULL);
555 
556     while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
557         for(i = 0; i < num_valid_responses; i++) {
558             if (sftp_packet_ask(sftp, valid_responses[i], request_id,
559                                 data, data_len) == 0) {
560                 /*
561                  * Set to zero before all returns to say
562                  * the timeout is not active
563                  */
564                 sftp->requirev_start = 0;
565                 return LIBSSH2_ERROR_NONE;
566             }
567         }
568 
569         rc = sftp_packet_read(sftp);
570         if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
571             sftp->requirev_start = 0;
572             return rc;
573         } else if (rc <= 0) {
574             /* prevent busy-looping */
575             long left =
576                 LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start);
577 
578             if (left <= 0) {
579                 sftp->requirev_start = 0;
580                 return LIBSSH2_ERROR_TIMEOUT;
581             }
582             else if (rc == LIBSSH2_ERROR_EAGAIN) {
583                 return rc;
584             }
585         }
586     }
587 
588     sftp->requirev_start = 0;
589 
590     /* Only reached if the socket died */
591     return LIBSSH2_ERROR_SOCKET_DISCONNECT;
592 }
593 
594 /* sftp_attr2bin
595  * Populate attributes into an SFTP block
596  */
597 static ssize_t
sftp_attr2bin(unsigned char * p,const LIBSSH2_SFTP_ATTRIBUTES * attrs)598 sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
599 {
600     unsigned char *s = p;
601     uint32_t flag_mask =
602         LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID |
603         LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
604 
605     /* TODO: When we add SFTP4+ functionality flag_mask can get additional
606        bits */
607 
608     if (!attrs) {
609         _libssh2_htonu32(s, 0);
610         return 4;
611     }
612 
613     _libssh2_store_u32(&s, attrs->flags & flag_mask);
614 
615     if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
616         _libssh2_store_u64(&s, attrs->filesize);
617     }
618 
619     if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
620         _libssh2_store_u32(&s, attrs->uid);
621         _libssh2_store_u32(&s, attrs->gid);
622     }
623 
624     if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
625         _libssh2_store_u32(&s, attrs->permissions);
626     }
627 
628     if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
629         _libssh2_store_u32(&s, attrs->atime);
630         _libssh2_store_u32(&s, attrs->mtime);
631     }
632 
633     return (s - p);
634 }
635 
636 /* sftp_bin2attr
637  */
638 static int
sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs,const unsigned char * p)639 sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p)
640 {
641     const unsigned char *s = p;
642 
643     memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
644     attrs->flags = _libssh2_ntohu32(s);
645     s += 4;
646 
647     if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
648         attrs->filesize = _libssh2_ntohu64(s);
649         s += 8;
650     }
651 
652     if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
653         attrs->uid = _libssh2_ntohu32(s);
654         s += 4;
655         attrs->gid = _libssh2_ntohu32(s);
656         s += 4;
657     }
658 
659     if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
660         attrs->permissions = _libssh2_ntohu32(s);
661         s += 4;
662     }
663 
664     if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
665         attrs->atime = _libssh2_ntohu32(s);
666         s += 4;
667         attrs->mtime = _libssh2_ntohu32(s);
668         s += 4;
669     }
670 
671     return (s - p);
672 }
673 
674 /* ************
675  * SFTP API *
676  ************ */
677 
678 LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor);
679 
680 /* libssh2_sftp_dtor
681  * Shutdown an SFTP stream when the channel closes
682  */
LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)683 LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
684 {
685     LIBSSH2_SFTP *sftp = (LIBSSH2_SFTP *) (*channel_abstract);
686 
687     (void) session_abstract;
688     (void) channel;
689 
690     /* Free the partial packet storage for sftp_packet_read */
691     if (sftp->partial_packet) {
692         LIBSSH2_FREE(session, sftp->partial_packet);
693     }
694 
695     /* Free the packet storage for _libssh2_sftp_packet_readdir */
696     if (sftp->readdir_packet) {
697         LIBSSH2_FREE(session, sftp->readdir_packet);
698     }
699 
700     LIBSSH2_FREE(session, sftp);
701 }
702 
703 /*
704  * sftp_init
705  *
706  * Startup an SFTP session
707  */
sftp_init(LIBSSH2_SESSION * session)708 static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
709 {
710     unsigned char *data, *s;
711     size_t data_len;
712     ssize_t rc;
713     LIBSSH2_SFTP *sftp_handle;
714 
715     if (session->sftpInit_state == libssh2_NB_state_idle) {
716         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
717                        "Initializing SFTP subsystem");
718 
719         /*
720          * The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the
721          * session struct are only to be used during the setup phase. As soon
722          * as the SFTP session is created they are cleared and can thus be
723          * re-used again to allow any amount of SFTP handles per sessions.
724          *
725          * Note that you MUST NOT try to call libssh2_sftp_init() again to get
726          * another handle until the previous call has finished and either
727          * successfully made a handle or failed and returned error (not
728          * including *EAGAIN).
729          */
730 
731         assert(session->sftpInit_sftp == NULL);
732         session->sftpInit_sftp = NULL;
733         session->sftpInit_state = libssh2_NB_state_created;
734     }
735 
736     sftp_handle = session->sftpInit_sftp;
737 
738     if (session->sftpInit_state == libssh2_NB_state_created) {
739         session->sftpInit_channel =
740             _libssh2_channel_open(session, "session", sizeof("session") - 1,
741                                   LIBSSH2_CHANNEL_WINDOW_DEFAULT,
742                                   LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
743         if (!session->sftpInit_channel) {
744             if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
745                 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
746                                "Would block starting up channel");
747             }
748             else {
749                 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
750                                "Unable to startup channel");
751                 session->sftpInit_state = libssh2_NB_state_idle;
752             }
753             return NULL;
754         }
755 
756         session->sftpInit_state = libssh2_NB_state_sent;
757     }
758 
759     if (session->sftpInit_state == libssh2_NB_state_sent) {
760         int ret = _libssh2_channel_process_startup(session->sftpInit_channel,
761                                                    "subsystem",
762                                                    sizeof("subsystem") - 1, "sftp",
763                                                    strlen("sftp"));
764         if (ret == LIBSSH2_ERROR_EAGAIN) {
765             _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
766                            "Would block to request SFTP subsystem");
767             return NULL;
768         } else if (ret) {
769             _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
770                            "Unable to request SFTP subsystem");
771             goto sftp_init_error;
772         }
773 
774         session->sftpInit_state = libssh2_NB_state_sent1;
775     }
776 
777     if (session->sftpInit_state == libssh2_NB_state_sent1) {
778         rc = _libssh2_channel_extended_data(session->sftpInit_channel,
779                                             LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
780         if (rc == LIBSSH2_ERROR_EAGAIN) {
781             _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
782                            "Would block requesting handle extended data");
783             return NULL;
784         }
785 
786         sftp_handle =
787             session->sftpInit_sftp =
788             LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP));
789         if (!sftp_handle) {
790             _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
791                            "Unable to allocate a new SFTP structure");
792             goto sftp_init_error;
793         }
794         sftp_handle->channel = session->sftpInit_channel;
795         sftp_handle->request_id = 0;
796 
797         _libssh2_htonu32(session->sftpInit_buffer, 5);
798         session->sftpInit_buffer[4] = SSH_FXP_INIT;
799         _libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
800         session->sftpInit_sent = 0; /* nothing's sent yet */
801 
802         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
803                        "Sending FXP_INIT packet advertising version %d support",
804                        (int) LIBSSH2_SFTP_VERSION);
805 
806         session->sftpInit_state = libssh2_NB_state_sent2;
807     }
808 
809     if (session->sftpInit_state == libssh2_NB_state_sent2) {
810         /* sent off what's left of the init buffer to send */
811         rc = _libssh2_channel_write(session->sftpInit_channel, 0,
812                                     session->sftpInit_buffer +
813                                     session->sftpInit_sent,
814                                     9 - session->sftpInit_sent);
815         if (rc == LIBSSH2_ERROR_EAGAIN) {
816             _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
817                            "Would block sending SSH_FXP_INIT");
818             return NULL;
819         }
820         else if(rc < 0) {
821             _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
822                            "Unable to send SSH_FXP_INIT");
823             goto sftp_init_error;
824         }
825         else {
826             /* add up the number of bytes sent */
827             session->sftpInit_sent += rc;
828 
829             if(session->sftpInit_sent == 9)
830                 /* move on */
831                 session->sftpInit_state = libssh2_NB_state_sent3;
832 
833             /* if less than 9, we remain in this state to send more later on */
834         }
835     }
836 
837     rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
838                              0, &data, &data_len);
839     if (rc == LIBSSH2_ERROR_EAGAIN) {
840          _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
841                         "Would block receiving SSH_FXP_VERSION");
842          return NULL;
843     }
844     else if (rc) {
845         _libssh2_error(session, rc,
846                        "Timeout waiting for response from SFTP subsystem");
847         goto sftp_init_error;
848     }
849     if (data_len < 5) {
850         _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
851                        "Invalid SSH_FXP_VERSION response");
852         LIBSSH2_FREE(session, data);
853         goto sftp_init_error;
854     }
855 
856     s = data + 1;
857     sftp_handle->version = _libssh2_ntohu32(s);
858     s += 4;
859     if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
860         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
861                        "Truncating remote SFTP version from %lu",
862                        sftp_handle->version);
863         sftp_handle->version = LIBSSH2_SFTP_VERSION;
864     }
865     _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
866                    "Enabling SFTP version %lu compatibility",
867                    sftp_handle->version);
868     while (s < (data + data_len)) {
869         size_t extname_len, extdata_len;
870 
871         extname_len = _libssh2_ntohu32(s);
872         s += 4;
873         /* the extension name starts here */
874         s += extname_len;
875 
876         extdata_len = _libssh2_ntohu32(s);
877         s += 4;
878 
879         /* TODO: Actually process extensions */
880         s += extdata_len;
881 
882     }
883     LIBSSH2_FREE(session, data);
884 
885     /* Make sure that when the channel gets closed, the SFTP service is shut
886        down too */
887     sftp_handle->channel->abstract = sftp_handle;
888     sftp_handle->channel->close_cb = libssh2_sftp_dtor;
889 
890     session->sftpInit_state = libssh2_NB_state_idle;
891 
892     /* clear the sftp and channel pointers in this session struct now */
893     session->sftpInit_sftp = NULL;
894     session->sftpInit_channel = NULL;
895 
896     _libssh2_list_init(&sftp_handle->sftp_handles);
897 
898     return sftp_handle;
899 
900   sftp_init_error:
901     while (_libssh2_channel_free(session->sftpInit_channel) ==
902            LIBSSH2_ERROR_EAGAIN);
903     session->sftpInit_channel = NULL;
904     if (session->sftpInit_sftp) {
905         LIBSSH2_FREE(session, session->sftpInit_sftp);
906         session->sftpInit_sftp = NULL;
907     }
908     session->sftpInit_state = libssh2_NB_state_idle;
909     return NULL;
910 }
911 
912 /*
913  * libssh2_sftp_init
914  *
915  * Startup an SFTP session
916  */
libssh2_sftp_init(LIBSSH2_SESSION * session)917 LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session)
918 {
919     LIBSSH2_SFTP *ptr;
920 
921     if(!session)
922         return NULL;
923 
924     if(!(session->state & LIBSSH2_STATE_AUTHENTICATED)) {
925         _libssh2_error(session, LIBSSH2_ERROR_INVAL,
926                        "session not authenticated yet");
927         return NULL;
928     }
929 
930     BLOCK_ADJUST_ERRNO(ptr, session, sftp_init(session));
931     return ptr;
932 }
933 
934 /*
935  * sftp_shutdown
936  *
937  * Shuts down the SFTP subsystem
938  */
939 static int
sftp_shutdown(LIBSSH2_SFTP * sftp)940 sftp_shutdown(LIBSSH2_SFTP *sftp)
941 {
942     int rc;
943     LIBSSH2_SESSION *session = sftp->channel->session;
944     /*
945      * Make sure all memory used in the state variables are free
946      */
947     if (sftp->partial_packet) {
948         LIBSSH2_FREE(session, sftp->partial_packet);
949         sftp->partial_packet = NULL;
950     }
951     if (sftp->open_packet) {
952         LIBSSH2_FREE(session, sftp->open_packet);
953         sftp->open_packet = NULL;
954     }
955     if (sftp->readdir_packet) {
956         LIBSSH2_FREE(session, sftp->readdir_packet);
957         sftp->readdir_packet = NULL;
958     }
959     if (sftp->fstat_packet) {
960         LIBSSH2_FREE(session, sftp->fstat_packet);
961         sftp->fstat_packet = NULL;
962     }
963     if (sftp->unlink_packet) {
964         LIBSSH2_FREE(session, sftp->unlink_packet);
965         sftp->unlink_packet = NULL;
966     }
967     if (sftp->rename_packet) {
968         LIBSSH2_FREE(session, sftp->rename_packet);
969         sftp->rename_packet = NULL;
970     }
971     if (sftp->fstatvfs_packet) {
972         LIBSSH2_FREE(session, sftp->fstatvfs_packet);
973         sftp->fstatvfs_packet = NULL;
974     }
975     if (sftp->statvfs_packet) {
976         LIBSSH2_FREE(session, sftp->statvfs_packet);
977         sftp->statvfs_packet = NULL;
978     }
979     if (sftp->mkdir_packet) {
980         LIBSSH2_FREE(session, sftp->mkdir_packet);
981         sftp->mkdir_packet = NULL;
982     }
983     if (sftp->rmdir_packet) {
984         LIBSSH2_FREE(session, sftp->rmdir_packet);
985         sftp->rmdir_packet = NULL;
986     }
987     if (sftp->stat_packet) {
988         LIBSSH2_FREE(session, sftp->stat_packet);
989         sftp->stat_packet = NULL;
990     }
991     if (sftp->symlink_packet) {
992         LIBSSH2_FREE(session, sftp->symlink_packet);
993         sftp->symlink_packet = NULL;
994     }
995     if (sftp->fsync_packet) {
996         LIBSSH2_FREE(session, sftp->fsync_packet);
997         sftp->fsync_packet = NULL;
998     }
999 
1000     sftp_packet_flush(sftp);
1001 
1002     /* TODO: We should consider walking over the sftp_handles list and kill
1003      * any remaining sftp handles ... */
1004 
1005     rc = _libssh2_channel_free(sftp->channel);
1006 
1007     return rc;
1008 }
1009 
1010 /* libssh2_sftp_shutdown
1011  * Shutsdown the SFTP subsystem
1012  */
1013 LIBSSH2_API int
libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)1014 libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
1015 {
1016     int rc;
1017     if(!sftp)
1018         return LIBSSH2_ERROR_BAD_USE;
1019     BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp));
1020     return rc;
1021 }
1022 
1023 /* *******************************
1024  * SFTP File and Directory Ops *
1025  ******************************* */
1026 
1027 /* sftp_open
1028  */
1029 static LIBSSH2_SFTP_HANDLE *
sftp_open(LIBSSH2_SFTP * sftp,const char * filename,size_t filename_len,uint32_t flags,long mode,int open_type)1030 sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
1031           size_t filename_len, uint32_t flags, long mode,
1032           int open_type)
1033 {
1034     LIBSSH2_CHANNEL *channel = sftp->channel;
1035     LIBSSH2_SESSION *session = channel->session;
1036     LIBSSH2_SFTP_HANDLE *fp;
1037     LIBSSH2_SFTP_ATTRIBUTES attrs = {
1038         LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
1039     };
1040     unsigned char *s;
1041     ssize_t rc;
1042     int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0;
1043 
1044     if (sftp->open_state == libssh2_NB_state_idle) {
1045         /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
1046            flags(4) */
1047         sftp->open_packet_len = filename_len + 13 +
1048             (open_file? (4 + sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0);
1049 
1050         /* surprise! this starts out with nothing sent */
1051         sftp->open_packet_sent = 0;
1052         s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
1053         if (!sftp->open_packet) {
1054             _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1055                            "Unable to allocate memory for FXP_OPEN or "
1056                            "FXP_OPENDIR packet");
1057             return NULL;
1058         }
1059         /* Filetype in SFTP 3 and earlier */
1060         attrs.permissions = mode |
1061             (open_file ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE :
1062              LIBSSH2_SFTP_ATTR_PFILETYPE_DIR);
1063 
1064         _libssh2_store_u32(&s, sftp->open_packet_len - 4);
1065         *(s++) = open_file? SSH_FXP_OPEN : SSH_FXP_OPENDIR;
1066         sftp->open_request_id = sftp->request_id++;
1067         _libssh2_store_u32(&s, sftp->open_request_id);
1068         _libssh2_store_str(&s, filename, filename_len);
1069 
1070         if (open_file) {
1071             _libssh2_store_u32(&s, flags);
1072             s += sftp_attr2bin(s, &attrs);
1073         }
1074 
1075         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request",
1076                        open_file? "file" : "directory");
1077 
1078         sftp->open_state = libssh2_NB_state_created;
1079     }
1080 
1081     if (sftp->open_state == libssh2_NB_state_created) {
1082         rc = _libssh2_channel_write(channel, 0, sftp->open_packet+
1083                                     sftp->open_packet_sent,
1084                                     sftp->open_packet_len -
1085                                     sftp->open_packet_sent);
1086         if (rc == LIBSSH2_ERROR_EAGAIN) {
1087             _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
1088                            "Would block sending FXP_OPEN or FXP_OPENDIR command");
1089             return NULL;
1090         }
1091         else if(rc < 0) {
1092             _libssh2_error(session, rc, "Unable to send FXP_OPEN*");
1093             LIBSSH2_FREE(session, sftp->open_packet);
1094             sftp->open_packet = NULL;
1095             sftp->open_state = libssh2_NB_state_idle;
1096             return NULL;
1097         }
1098 
1099         /* bump the sent counter and remain in this state until the whole
1100            data is off */
1101         sftp->open_packet_sent += rc;
1102 
1103         if(sftp->open_packet_len == sftp->open_packet_sent) {
1104             LIBSSH2_FREE(session, sftp->open_packet);
1105             sftp->open_packet = NULL;
1106 
1107             sftp->open_state = libssh2_NB_state_sent;
1108         }
1109     }
1110 
1111     if (sftp->open_state == libssh2_NB_state_sent) {
1112         size_t data_len;
1113         unsigned char *data;
1114         static const unsigned char fopen_responses[2] =
1115             { SSH_FXP_HANDLE, SSH_FXP_STATUS };
1116         rc = sftp_packet_requirev(sftp, 2, fopen_responses,
1117                                   sftp->open_request_id, &data,
1118                                   &data_len);
1119         if (rc == LIBSSH2_ERROR_EAGAIN) {
1120             _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
1121                            "Would block waiting for status message");
1122             return NULL;
1123         }
1124         sftp->open_state = libssh2_NB_state_idle;
1125         if (rc) {
1126             _libssh2_error(session, rc, "Timeout waiting for status message");
1127             return NULL;
1128         }
1129 
1130         /* OPEN can basically get STATUS or HANDLE back, where HANDLE implies
1131            a fine response while STATUS means error. It seems though that at
1132            times we get an SSH_FX_OK back in a STATUS, followed the "real"
1133            HANDLE so we need to properly deal with that. */
1134         if (data[0] == SSH_FXP_STATUS) {
1135             int badness = 1;
1136 
1137             if(data_len < 9) {
1138                 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1139                                "Too small FXP_STATUS");
1140                 LIBSSH2_FREE(session, data);
1141                 return NULL;
1142             }
1143 
1144             sftp->last_errno = _libssh2_ntohu32(data + 5);
1145 
1146             if(LIBSSH2_FX_OK == sftp->last_errno) {
1147                 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!");
1148 
1149                 LIBSSH2_FREE(session, data);
1150 
1151                 /* silly situation, but check for a HANDLE */
1152                 rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
1153                                          sftp->open_request_id, &data,
1154                                          &data_len);
1155                 if(rc == LIBSSH2_ERROR_EAGAIN) {
1156                     /* go back to sent state and wait for something else */
1157                     sftp->open_state = libssh2_NB_state_sent;
1158                     return NULL;
1159                 }
1160                 else if(!rc)
1161                     /* we got the handle so this is not a bad situation */
1162                     badness = 0;
1163             }
1164 
1165             if(badness) {
1166                 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1167                                "Failed opening remote file");
1168                 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d",
1169                                sftp->last_errno);
1170                 LIBSSH2_FREE(session, data);
1171                 return NULL;
1172             }
1173         }
1174 
1175         if(data_len < 10) {
1176             _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1177                            "Too small FXP_HANDLE");
1178             LIBSSH2_FREE(session, data);
1179             return NULL;
1180         }
1181 
1182         fp = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
1183         if (!fp) {
1184             _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1185                            "Unable to allocate new SFTP handle structure");
1186             LIBSSH2_FREE(session, data);
1187             return NULL;
1188         }
1189         fp->handle_type = open_file ? LIBSSH2_SFTP_HANDLE_FILE :
1190             LIBSSH2_SFTP_HANDLE_DIR;
1191 
1192         fp->handle_len = _libssh2_ntohu32(data + 5);
1193         if (fp->handle_len > SFTP_HANDLE_MAXLEN)
1194             /* SFTP doesn't allow handles longer than 256 characters */
1195             fp->handle_len = SFTP_HANDLE_MAXLEN;
1196 
1197         if(fp->handle_len > (data_len - 9))
1198             /* do not reach beyond the end of the data we got */
1199             fp->handle_len = data_len - 9;
1200 
1201         memcpy(fp->handle, data + 9, fp->handle_len);
1202 
1203         LIBSSH2_FREE(session, data);
1204 
1205         /* add this file handle to the list kept in the sftp session */
1206         _libssh2_list_add(&sftp->sftp_handles, &fp->node);
1207 
1208         fp->sftp = sftp; /* point to the parent struct */
1209 
1210         fp->u.file.offset = 0;
1211         fp->u.file.offset_sent = 0;
1212 
1213         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful");
1214         return fp;
1215     }
1216     return NULL;
1217 }
1218 
1219 /* libssh2_sftp_open_ex
1220  */
1221 LIBSSH2_API LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp,const char * filename,unsigned int filename_len,unsigned long flags,long mode,int open_type)1222 libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename,
1223                      unsigned int filename_len, unsigned long flags, long mode,
1224                      int open_type)
1225 {
1226     LIBSSH2_SFTP_HANDLE *hnd;
1227 
1228     if(!sftp)
1229         return NULL;
1230 
1231     BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session,
1232                        sftp_open(sftp, filename, filename_len, flags, mode,
1233                                  open_type));
1234     return hnd;
1235 }
1236 
1237 /*
1238  * sftp_read
1239  *
1240  * Read from an SFTP file handle
1241  *
1242  */
sftp_read(LIBSSH2_SFTP_HANDLE * handle,char * buffer,size_t buffer_size)1243 static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
1244                          size_t buffer_size)
1245 {
1246     LIBSSH2_SFTP *sftp = handle->sftp;
1247     LIBSSH2_CHANNEL *channel = sftp->channel;
1248     LIBSSH2_SESSION *session = channel->session;
1249     size_t count = 0;
1250     struct sftp_pipeline_chunk *chunk;
1251     struct sftp_pipeline_chunk *next;
1252     ssize_t rc;
1253     struct _libssh2_sftp_handle_file_data *filep =
1254         &handle->u.file;
1255     size_t bytes_in_buffer = 0;
1256     char *sliding_bufferp = buffer;
1257 
1258     /* This function can be interrupted in three different places where it
1259        might need to wait for data from the network.  It returns EAGAIN to
1260        allow non-blocking clients to do other work but these client are
1261        expected to call this function again (possibly many times) to finish
1262        the operation.
1263 
1264        The tricky part is that if we previously aborted a sftp_read due to
1265        EAGAIN, we must continue at the same spot to continue the previously
1266        interrupted operation.  This is done using a state machine to record
1267        what phase of execution we were at.  The state is stored in
1268        sftp->read_state.
1269 
1270        libssh2_NB_state_idle: The first phase is where we prepare multiple
1271        FXP_READ packets to do optimistic read-ahead.  We send off as many as
1272        possible in the second phase without waiting for a response to each
1273        one; this is the key to fast reads. But we may have to adjust the
1274        channel window size to do this which may interrupt this function while
1275        waiting.  The state machine saves the phase as libssh2_NB_state_idle so
1276        it returns here on the next call.
1277 
1278        libssh2_NB_state_sent: The second phase is where we send the FXP_READ
1279        packets.  Writing them to the channel can be interrupted with EAGAIN
1280        but the state machine ensures we skip the first phase on the next call
1281        and resume sending.
1282 
1283        libssh2_NB_state_sent2: In the third phase (indicated by ) we read the
1284        data from the responses that have arrived so far.  Reading can be
1285        interrupted with EAGAIN but the state machine ensures we skip the first
1286        and second phases on the next call and resume sending.
1287     */
1288 
1289     switch (sftp->read_state) {
1290     case libssh2_NB_state_idle:
1291 
1292         /* Some data may already have been read from the server in the
1293            previous call but didn't fit in the buffer at the time.  If so, we
1294            return that now as we can't risk being interrupted later with data
1295            partially written to the buffer. */
1296         if(filep->data_left) {
1297             size_t copy = MIN(buffer_size, filep->data_left);
1298 
1299             memcpy(buffer, &filep->data[ filep->data_len - filep->data_left],
1300                    copy);
1301 
1302             filep->data_left -= copy;
1303             filep->offset += copy;
1304 
1305             if(!filep->data_left) {
1306                 LIBSSH2_FREE(session, filep->data);
1307                 filep->data = NULL;
1308             }
1309 
1310             return copy;
1311         }
1312 
1313         if (filep->eof) {
1314             return 0;
1315         } else {
1316             /* We allow a number of bytes being requested at any given time
1317                without having been acked - until we reach EOF. */
1318 
1319             /* Number of bytes asked for that haven't been acked yet */
1320             size_t already = (size_t)(filep->offset_sent - filep->offset);
1321 
1322             size_t max_read_ahead = buffer_size*4;
1323             unsigned long recv_window;
1324 
1325             if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*4)
1326                 max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*4;
1327 
1328             /* if the buffer_size passed in now is smaller than what has
1329                already been sent, we risk getting count become a very large
1330                number */
1331             if(max_read_ahead > already)
1332                 count = max_read_ahead - already;
1333 
1334             /* 'count' is how much more data to ask for, and 'already' is how
1335                much data that already has been asked for but not yet returned.
1336                Specificly, 'count' means how much data that have or will be
1337                asked for by the nodes that are already added to the linked
1338                list. Some of those read requests may not actually have been
1339                sent off successfully yet.
1340 
1341                If 'already' is very large it should be perfectly fine to have
1342                count set to 0 as then we don't have to ask for more data
1343                (right now).
1344 
1345                buffer_size*4 is just picked more or less out of the air. The
1346                idea is that when reading SFTP from a remote server, we send
1347                away multiple read requests guessing that the client will read
1348                more than only this 'buffer_size' amount of memory. So we ask
1349                for maximum buffer_size*4 amount of data so that we can return
1350                them very fast in subsequent calls.
1351             */
1352 
1353             recv_window = libssh2_channel_window_read_ex(sftp->channel,
1354                                                          NULL, NULL);
1355             if(max_read_ahead > recv_window) {
1356                 /* more data will be asked for than what the window currently
1357                    allows, expand it! */
1358 
1359                 rc = _libssh2_channel_receive_window_adjust(sftp->channel,
1360                                                             max_read_ahead*8,
1361                                                             1, NULL);
1362                 /* if this returns EAGAIN, we will get back to this function
1363                    at next call */
1364                 assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left);
1365                 assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof);
1366                 if (rc)
1367                     return rc;
1368             }
1369         }
1370 
1371         while(count > 0) {
1372             unsigned char *s;
1373 
1374             /* 25 = packet_len(4) + packet_type(1) + request_id(4) +
1375                handle_len(4) + offset(8) + count(4) */
1376             uint32_t packet_len = (uint32_t)handle->handle_len + 25;
1377             uint32_t request_id;
1378 
1379             uint32_t size = count;
1380             if (size < buffer_size)
1381                 size = buffer_size;
1382             if (size > MAX_SFTP_READ_SIZE)
1383                 size = MAX_SFTP_READ_SIZE;
1384 
1385             chunk = LIBSSH2_ALLOC(session, packet_len +
1386                                   sizeof(struct sftp_pipeline_chunk));
1387             if (!chunk)
1388                 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1389                                       "malloc fail for FXP_WRITE");
1390 
1391             chunk->offset = filep->offset_sent;
1392             chunk->len = size;
1393             chunk->lefttosend = packet_len;
1394             chunk->sent = 0;
1395 
1396             s = chunk->packet;
1397 
1398             _libssh2_store_u32(&s, packet_len - 4);
1399             *s++ = SSH_FXP_READ;
1400             request_id = sftp->request_id++;
1401             chunk->request_id = request_id;
1402             _libssh2_store_u32(&s, request_id);
1403             _libssh2_store_str(&s, handle->handle, handle->handle_len);
1404             _libssh2_store_u64(&s, filep->offset_sent);
1405             filep->offset_sent += size; /* advance offset at once */
1406             _libssh2_store_u32(&s, size);
1407 
1408             /* add this new entry LAST in the list */
1409             _libssh2_list_add(&handle->packet_list, &chunk->node);
1410             count -= MIN(size,count); /* deduct the size we used, as we might
1411                                        * have to create more packets */
1412             _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1413                            "read request id %d sent (offset: %d, size: %d)",
1414                            request_id, (int)chunk->offset, (int)chunk->len);
1415         }
1416 
1417     case libssh2_NB_state_sent:
1418 
1419         sftp->read_state = libssh2_NB_state_idle;
1420 
1421         /* move through the READ packets that haven't been sent and send as
1422            many as possible - remember that we don't block */
1423         chunk = _libssh2_list_first(&handle->packet_list);
1424 
1425         while(chunk) {
1426             if(chunk->lefttosend) {
1427 
1428                 rc = _libssh2_channel_write(channel, 0,
1429                                             &chunk->packet[chunk->sent],
1430                                             chunk->lefttosend);
1431                 if(rc < 0) {
1432                     sftp->read_state = libssh2_NB_state_sent;
1433                     return rc;
1434                 }
1435 
1436                 /* remember where to continue sending the next time */
1437                 chunk->lefttosend -= rc;
1438                 chunk->sent += rc;
1439 
1440                 if(chunk->lefttosend) {
1441                     /* We still have data left to send for this chunk.
1442                      * If there is at least one completely sent chunk,
1443                      * we can get out of this loop and start reading.  */
1444                     if (chunk != _libssh2_list_first(&handle->packet_list)) {
1445                         break;
1446                     } else {
1447                         continue;
1448                     }
1449                 }
1450             }
1451 
1452             /* move on to the next chunk with data to send */
1453             chunk = _libssh2_list_next(&chunk->node);
1454         }
1455 
1456     case libssh2_NB_state_sent2:
1457 
1458         sftp->read_state = libssh2_NB_state_idle;
1459 
1460         /*
1461          * Count all ACKed packets and act on the contents of them.
1462          */
1463         chunk = _libssh2_list_first(&handle->packet_list);
1464 
1465         while(chunk) {
1466             unsigned char *data;
1467             size_t data_len;
1468             uint32_t rc32;
1469             static const unsigned char read_responses[2] = {
1470                 SSH_FXP_DATA, SSH_FXP_STATUS
1471             };
1472 
1473             if(chunk->lefttosend) {
1474                 /* if the chunk still has data left to send, we shouldn't wait
1475                    for an ACK for it just yet */
1476                 if (bytes_in_buffer > 0) {
1477                     return bytes_in_buffer;
1478                 } else {
1479                     /* we should never reach this point */
1480                     return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1481                                           "sftp_read() internal error");
1482                 }
1483             }
1484 
1485             rc = sftp_packet_requirev(sftp, 2, read_responses,
1486                                       chunk->request_id, &data, &data_len);
1487 
1488             if (rc==LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) {
1489                 /* do not return EAGAIN if we have already
1490                  * written data into the buffer */
1491                 return bytes_in_buffer;
1492             }
1493 
1494             if (rc < 0) {
1495                 sftp->read_state = libssh2_NB_state_sent2;
1496                 return rc;
1497             }
1498 
1499             /*
1500              * We get DATA or STATUS back. STATUS can be error, or it is
1501              * FX_EOF when we reach the end of the file.
1502              */
1503 
1504             switch (data[0]) {
1505             case SSH_FXP_STATUS:
1506                 /* remove the chunk we just processed */
1507 
1508                 _libssh2_list_remove(&chunk->node);
1509                 LIBSSH2_FREE(session, chunk);
1510 
1511                 /* we must remove all outstanding READ requests, as either we
1512                    got an error or we're at end of file */
1513                 sftp_packetlist_flush(handle);
1514 
1515                 rc32 = _libssh2_ntohu32(data + 5);
1516                 LIBSSH2_FREE(session, data);
1517 
1518                 if (rc32 == LIBSSH2_FX_EOF) {
1519                     filep->eof = TRUE;
1520                     return bytes_in_buffer;
1521                 }
1522                 else {
1523                     sftp->last_errno = rc32;
1524                     return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1525                                           "SFTP READ error");
1526                 }
1527                 break;
1528 
1529             case SSH_FXP_DATA:
1530                 if (chunk->offset != filep->offset) {
1531                     /* This could happen if the server returns less bytes than
1532                        requested, which shouldn't happen for normal files. See:
1533                        https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
1534                        #section-6.4
1535                     */
1536                     return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1537                                           "Read Packet At Unexpected Offset");
1538                 }
1539 
1540                 rc32 = _libssh2_ntohu32(data + 5);
1541                 if (rc32 > (data_len - 9))
1542                     return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1543                                           "SFTP Protocol badness");
1544 
1545                 if(rc32 > chunk->len) {
1546                     /* A chunk larger than we requested was returned to us.
1547                        This is a protocol violation and we don't know how to
1548                        deal with it. Bail out! */
1549                     return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1550                                           "FXP_READ response too big");
1551                 }
1552 
1553                 if(rc32 != chunk->len) {
1554                     /* a short read does not imply end of file, but we must
1555                        adjust the offset_sent since it was advanced with a
1556                        full chunk->len before */
1557                     filep->offset_sent -= (chunk->len - rc32);
1558                 }
1559 
1560                 if((bytes_in_buffer + rc32) > buffer_size) {
1561                     /* figure out the overlap amount */
1562                     filep->data_left = (bytes_in_buffer + rc32) - buffer_size;
1563 
1564                     /* getting the full packet would overflow the buffer, so
1565                        only get the correct amount and keep the remainder */
1566                     rc32 = (uint32_t)buffer_size - bytes_in_buffer;
1567 
1568                     /* store data to keep for next call */
1569                     filep->data = data;
1570                     filep->data_len = data_len;
1571                 }
1572                 else
1573                     filep->data_len = 0;
1574 
1575                 /* copy the received data from the received FXP_DATA packet to
1576                    the buffer at the correct index */
1577                 memcpy(sliding_bufferp, data + 9, rc32);
1578                 filep->offset += rc32;
1579                 bytes_in_buffer += rc32;
1580                 sliding_bufferp += rc32;
1581 
1582                 if(filep->data_len == 0)
1583                     /* free the allocated data if not stored to keep */
1584                     LIBSSH2_FREE(session, data);
1585 
1586                 /* remove the chunk we just processed keeping track of the
1587                  * next one in case we need it */
1588                 next = _libssh2_list_next(&chunk->node);
1589                 _libssh2_list_remove(&chunk->node);
1590                 LIBSSH2_FREE(session, chunk);
1591 
1592                 /* check if we have space left in the buffer
1593                  * and either continue to the next chunk or stop
1594                  */
1595                 if (bytes_in_buffer < buffer_size) {
1596                     chunk = next;
1597                 } else {
1598                     chunk = NULL;
1599                 }
1600 
1601                 break;
1602             default:
1603                 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1604                                       "SFTP Protocol badness: unrecognised "
1605                                       "read request response");
1606             }
1607         }
1608 
1609         if (bytes_in_buffer > 0)
1610             return bytes_in_buffer;
1611 
1612         break;
1613 
1614     default:
1615         assert(!"State machine error; unrecognised read state");
1616     }
1617 
1618     /* we should never reach this point */
1619     return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1620                           "sftp_read() internal error");
1621 }
1622 
1623 /* libssh2_sftp_read
1624  * Read from an SFTP file handle
1625  */
1626 LIBSSH2_API ssize_t
libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * hnd,char * buffer,size_t buffer_maxlen)1627 libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
1628                   size_t buffer_maxlen)
1629 {
1630     ssize_t rc;
1631     if(!hnd)
1632         return LIBSSH2_ERROR_BAD_USE;
1633     BLOCK_ADJUST(rc, hnd->sftp->channel->session,
1634                  sftp_read(hnd, buffer, buffer_maxlen));
1635     return rc;
1636 }
1637 
1638 /* sftp_readdir
1639  * Read from an SFTP directory handle
1640  */
sftp_readdir(LIBSSH2_SFTP_HANDLE * handle,char * buffer,size_t buffer_maxlen,char * longentry,size_t longentry_maxlen,LIBSSH2_SFTP_ATTRIBUTES * attrs)1641 static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
1642                             size_t buffer_maxlen, char *longentry,
1643                             size_t longentry_maxlen,
1644                             LIBSSH2_SFTP_ATTRIBUTES *attrs)
1645 {
1646     LIBSSH2_SFTP *sftp = handle->sftp;
1647     LIBSSH2_CHANNEL *channel = sftp->channel;
1648     LIBSSH2_SESSION *session = channel->session;
1649     size_t data_len;
1650     uint32_t num_names;
1651     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
1652     uint32_t packet_len = handle->handle_len + 13;
1653     unsigned char *s, *data;
1654     static const unsigned char read_responses[2] = {
1655         SSH_FXP_NAME, SSH_FXP_STATUS };
1656     ssize_t retcode;
1657 
1658     if (sftp->readdir_state == libssh2_NB_state_idle) {
1659         if (handle->u.dir.names_left) {
1660             /*
1661              * A prior request returned more than one directory entry,
1662              * feed it back from the buffer
1663              */
1664             LIBSSH2_SFTP_ATTRIBUTES attrs_dummy;
1665             size_t real_longentry_len;
1666             size_t real_filename_len;
1667             size_t filename_len;
1668             size_t longentry_len;
1669 
1670             s = (unsigned char *) handle->u.dir.next_name;
1671             real_filename_len = _libssh2_ntohu32(s);
1672 
1673             s += 4;
1674 
1675             filename_len = real_filename_len;
1676             if (filename_len >= buffer_maxlen) {
1677                 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1678                 goto end;
1679             }
1680 
1681             memcpy(buffer, s, filename_len);
1682             buffer[filename_len] = '\0';           /* zero terminate */
1683             s += real_filename_len;
1684 
1685             real_longentry_len = _libssh2_ntohu32(s);
1686             s += 4;
1687 
1688             if (longentry && (longentry_maxlen>1)) {
1689                 longentry_len = real_longentry_len;
1690 
1691                 if (longentry_len >= longentry_maxlen) {
1692                     filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1693                     goto end;
1694                 }
1695 
1696                 memcpy(longentry, s, longentry_len);
1697                 longentry[longentry_len] = '\0'; /* zero terminate */
1698             }
1699             s += real_longentry_len;
1700 
1701             if (attrs)
1702                 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1703 
1704             s += sftp_bin2attr(attrs ? attrs : &attrs_dummy, s);
1705 
1706             handle->u.dir.next_name = (char *) s;
1707           end:
1708 
1709             if ((--handle->u.dir.names_left) == 0)
1710                 LIBSSH2_FREE(session, handle->u.dir.names_packet);
1711 
1712             _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1713                            "libssh2_sftp_readdir_ex() return %d",
1714                            filename_len);
1715             return (ssize_t)filename_len;
1716         }
1717 
1718         /* Request another entry(entries?) */
1719 
1720         s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len);
1721         if (!sftp->readdir_packet)
1722             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1723                                   "Unable to allocate memory for "
1724                                   "FXP_READDIR packet");
1725 
1726         _libssh2_store_u32(&s, packet_len - 4);
1727         *(s++) = SSH_FXP_READDIR;
1728         sftp->readdir_request_id = sftp->request_id++;
1729         _libssh2_store_u32(&s, sftp->readdir_request_id);
1730         _libssh2_store_str(&s, handle->handle, handle->handle_len);
1731 
1732         sftp->readdir_state = libssh2_NB_state_created;
1733     }
1734 
1735     if (sftp->readdir_state == libssh2_NB_state_created) {
1736         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1737                        "Reading entries from directory handle");
1738         retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet,
1739                                          packet_len);
1740         if (retcode == LIBSSH2_ERROR_EAGAIN) {
1741             return retcode;
1742         }
1743         else if ((ssize_t)packet_len != retcode) {
1744             LIBSSH2_FREE(session, sftp->readdir_packet);
1745             sftp->readdir_packet = NULL;
1746             sftp->readdir_state = libssh2_NB_state_idle;
1747             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1748                                   "_libssh2_channel_write() failed");
1749         }
1750 
1751         LIBSSH2_FREE(session, sftp->readdir_packet);
1752         sftp->readdir_packet = NULL;
1753 
1754         sftp->readdir_state = libssh2_NB_state_sent;
1755     }
1756 
1757     retcode = sftp_packet_requirev(sftp, 2, read_responses,
1758                                    sftp->readdir_request_id, &data,
1759                                    &data_len);
1760     if (retcode == LIBSSH2_ERROR_EAGAIN)
1761         return retcode;
1762     else if (retcode) {
1763         sftp->readdir_state = libssh2_NB_state_idle;
1764         return _libssh2_error(session, retcode,
1765                               "Timeout waiting for status message");
1766     }
1767 
1768     if (data[0] == SSH_FXP_STATUS) {
1769         retcode = _libssh2_ntohu32(data + 5);
1770         LIBSSH2_FREE(session, data);
1771         if (retcode == LIBSSH2_FX_EOF) {
1772             sftp->readdir_state = libssh2_NB_state_idle;
1773             return 0;
1774         }
1775         else {
1776             sftp->last_errno = retcode;
1777             sftp->readdir_state = libssh2_NB_state_idle;
1778             return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1779                                   "SFTP Protocol Error");
1780         }
1781     }
1782 
1783     sftp->readdir_state = libssh2_NB_state_idle;
1784 
1785     num_names = _libssh2_ntohu32(data + 5);
1786     _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned",
1787                    num_names);
1788     if (!num_names) {
1789         LIBSSH2_FREE(session, data);
1790         return 0;
1791     }
1792 
1793     handle->u.dir.names_left = num_names;
1794     handle->u.dir.names_packet = data;
1795     handle->u.dir.next_name = (char *) data + 9;
1796 
1797     /* use the name popping mechanism from the start of the function */
1798     return sftp_readdir(handle, buffer, buffer_maxlen, longentry,
1799                         longentry_maxlen, attrs);
1800 }
1801 
1802 /* libssh2_sftp_readdir_ex
1803  * Read from an SFTP directory handle
1804  */
1805 LIBSSH2_API int
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * hnd,char * buffer,size_t buffer_maxlen,char * longentry,size_t longentry_maxlen,LIBSSH2_SFTP_ATTRIBUTES * attrs)1806 libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
1807                         size_t buffer_maxlen, char *longentry,
1808                         size_t longentry_maxlen,
1809                         LIBSSH2_SFTP_ATTRIBUTES *attrs)
1810 {
1811     int rc;
1812     if(!hnd)
1813         return LIBSSH2_ERROR_BAD_USE;
1814     BLOCK_ADJUST(rc, hnd->sftp->channel->session,
1815                  sftp_readdir(hnd, buffer, buffer_maxlen, longentry,
1816                               longentry_maxlen, attrs));
1817     return rc;
1818 }
1819 
1820 /*
1821  * sftp_write
1822  *
1823  * Write data to an SFTP handle. Returns the number of bytes written, or
1824  * a negative error code.
1825  *
1826  * We recommend sending very large data buffers to this function!
1827  *
1828  * Concept:
1829  *
1830  * - Detect how much of the given buffer that was already sent in a previous
1831  *   call by inspecting the linked list of outgoing chunks. Make sure to skip
1832  *   passed the data that has already been taken care of.
1833  *
1834  * - Split all (new) outgoing data in chunks no larger than N.
1835  *
1836  * - Each N bytes chunk gets created as a separate SFTP packet.
1837  *
1838  * - Add all created outgoing packets to the linked list.
1839  *
1840  * - Walk through the list and send the chunks that haven't been sent,
1841  *   as many as possible until EAGAIN. Some of the chunks may have been put
1842  *   in the list in a previous invoke.
1843  *
1844  * - For all the chunks in the list that have been completely sent off, check
1845  *   for ACKs. If a chunk has been ACKed, it is removed from the linked
1846  *   list and the "acked" counter gets increased with that data amount.
1847  *
1848  * - Return TOTAL bytes acked so far.
1849  *
1850  * Caveats:
1851  * -  be careful: we must not return a higher number than what was given!
1852  *
1853  * TODO:
1854  *   Introduce an option that disables this sort of "speculative" ahead writing
1855  *   as there's a risk that it will do harm to some app.
1856  */
1857 
sftp_write(LIBSSH2_SFTP_HANDLE * handle,const char * buffer,size_t count)1858 static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
1859                           size_t count)
1860 {
1861     LIBSSH2_SFTP *sftp = handle->sftp;
1862     LIBSSH2_CHANNEL *channel = sftp->channel;
1863     LIBSSH2_SESSION *session = channel->session;
1864     size_t data_len;
1865     uint32_t retcode;
1866     uint32_t packet_len;
1867     unsigned char *s, *data;
1868     ssize_t rc;
1869     struct sftp_pipeline_chunk *chunk;
1870     struct sftp_pipeline_chunk *next;
1871     size_t acked = 0;
1872     size_t org_count = count;
1873     size_t already;
1874 
1875     switch(sftp->write_state) {
1876     default:
1877     case libssh2_NB_state_idle:
1878 
1879         /* Number of bytes sent off that haven't been acked and therefor we
1880            will get passed in here again.
1881 
1882            Also, add up the number of bytes that actually already have been
1883            acked but we haven't been able to return as such yet, so we will
1884            get that data as well passed in here again.
1885         */
1886         already = (size_t) (handle->u.file.offset_sent - handle->u.file.offset)+
1887             handle->u.file.acked;
1888 
1889         if(count >= already) {
1890             /* skip the part already made into packets */
1891             buffer += already;
1892             count -= already;
1893         }
1894         else
1895             /* there is more data already fine than what we got in this call */
1896             count = 0;
1897 
1898         sftp->write_state = libssh2_NB_state_idle;
1899         while(count) {
1900             /* TODO: Possibly this should have some logic to prevent a very
1901                very small fraction to be left but lets ignore that for now */
1902             uint32_t size = MIN(MAX_SFTP_OUTGOING_SIZE, count);
1903             uint32_t request_id;
1904 
1905             /* 25 = packet_len(4) + packet_type(1) + request_id(4) +
1906                handle_len(4) + offset(8) + count(4) */
1907             packet_len = handle->handle_len + size + 25;
1908 
1909             chunk = LIBSSH2_ALLOC(session, packet_len +
1910                                   sizeof(struct sftp_pipeline_chunk));
1911             if (!chunk)
1912                 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1913                                       "malloc fail for FXP_WRITE");
1914 
1915             chunk->len = size;
1916             chunk->sent = 0;
1917             chunk->lefttosend = packet_len;
1918 
1919             s = chunk->packet;
1920             _libssh2_store_u32(&s, packet_len - 4);
1921 
1922             *(s++) = SSH_FXP_WRITE;
1923             request_id = sftp->request_id++;
1924             chunk->request_id = request_id;
1925             _libssh2_store_u32(&s, request_id);
1926             _libssh2_store_str(&s, handle->handle, handle->handle_len);
1927             _libssh2_store_u64(&s, handle->u.file.offset_sent);
1928             handle->u.file.offset_sent += size; /* advance offset at once */
1929             _libssh2_store_str(&s, buffer, size);
1930 
1931             /* add this new entry LAST in the list */
1932             _libssh2_list_add(&handle->packet_list, &chunk->node);
1933 
1934             buffer += size;
1935             count -= size; /* deduct the size we used, as we might have
1936                               to create more packets */
1937         }
1938 
1939         /* move through the WRITE packets that haven't been sent and send as many
1940            as possible - remember that we don't block */
1941         chunk = _libssh2_list_first(&handle->packet_list);
1942 
1943         while(chunk) {
1944             if(chunk->lefttosend) {
1945                 rc = _libssh2_channel_write(channel, 0,
1946                                             &chunk->packet[chunk->sent],
1947                                             chunk->lefttosend);
1948                 if(rc < 0)
1949                     /* remain in idle state */
1950                     return rc;
1951 
1952                 /* remember where to continue sending the next time */
1953                 chunk->lefttosend -= rc;
1954                 chunk->sent += rc;
1955 
1956                 if(chunk->lefttosend)
1957                     /* data left to send, get out of loop */
1958                     break;
1959             }
1960 
1961             /* move on to the next chunk with data to send */
1962             chunk = _libssh2_list_next(&chunk->node);
1963         }
1964 
1965         /* fall-through */
1966     case libssh2_NB_state_sent:
1967 
1968         sftp->write_state = libssh2_NB_state_idle;
1969         /*
1970          * Count all ACKed packets
1971          */
1972         chunk = _libssh2_list_first(&handle->packet_list);
1973 
1974         while(chunk) {
1975             if(chunk->lefttosend)
1976                 /* if the chunk still has data left to send, we shouldn't wait
1977                    for an ACK for it just yet */
1978                 break;
1979 
1980             else if(acked)
1981                 /* if we have sent data that is acked, we must return that
1982                    info before we call a function that might return EAGAIN */
1983                 break;
1984 
1985             /* we check the packets in order */
1986             rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
1987                                      chunk->request_id, &data, &data_len);
1988             if (rc < 0) {
1989                 if (rc == LIBSSH2_ERROR_EAGAIN)
1990                     sftp->write_state = libssh2_NB_state_sent;
1991                 return rc;
1992             }
1993 
1994             retcode = _libssh2_ntohu32(data + 5);
1995             LIBSSH2_FREE(session, data);
1996 
1997             sftp->last_errno = retcode;
1998             if (retcode == LIBSSH2_FX_OK) {
1999                 acked += chunk->len; /* number of payload data that was acked
2000                                         here */
2001 
2002                 /* we increase the offset value for all acks */
2003                 handle->u.file.offset += chunk->len;
2004 
2005                 next = _libssh2_list_next(&chunk->node);
2006 
2007                 _libssh2_list_remove(&chunk->node); /* remove from list */
2008                 LIBSSH2_FREE(session, chunk); /* free memory */
2009 
2010                 chunk = next;
2011             }
2012             else {
2013                 /* flush all pending packets from the outgoing list */
2014                 sftp_packetlist_flush(handle);
2015 
2016                 /* since we return error now, the application will not get any
2017                    outstanding data acked, so we need to rewind the offset to
2018                    where the application knows it has reached with acked data */
2019                 handle->u.file.offset -= handle->u.file.acked;
2020 
2021                 /* then reset the offset_sent to be the same as the offset */
2022                 handle->u.file.offset_sent = handle->u.file.offset;
2023 
2024                 /* clear the acked counter since we can have no pending data to
2025                    ack after an error */
2026                 handle->u.file.acked = 0;
2027 
2028                 /* the server returned an error for that written chunk, propagate
2029                    this back to our parent function */
2030                 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2031                                       "FXP write failed");
2032             }
2033         }
2034         break;
2035     }
2036 
2037     /* if there were acked data in a previous call that wasn't returned then,
2038        add that up and try to return it all now. This can happen if the app
2039        first sends a huge buffer of data, and then in a second call it sends a
2040        smaller one. */
2041     acked += handle->u.file.acked;
2042 
2043     if(acked) {
2044         ssize_t ret = MIN(acked, org_count);
2045         /* we got data acked so return that amount, but no more than what
2046            was asked to get sent! */
2047 
2048         /* store the remainder. 'ret' is always equal to or less than 'acked'
2049            here */
2050         handle->u.file.acked = acked - ret;
2051 
2052         return ret;
2053     }
2054 
2055     else
2056         return 0; /* nothing was acked, and no EAGAIN was received! */
2057 }
2058 
2059 /* libssh2_sftp_write
2060  * Write data to a file handle
2061  */
2062 LIBSSH2_API ssize_t
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * hnd,const char * buffer,size_t count)2063 libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer,
2064                    size_t count)
2065 {
2066     ssize_t rc;
2067     if(!hnd)
2068         return LIBSSH2_ERROR_BAD_USE;
2069     BLOCK_ADJUST(rc, hnd->sftp->channel->session,
2070                  sftp_write(hnd, buffer, count));
2071     return rc;
2072 
2073 }
2074 
sftp_fsync(LIBSSH2_SFTP_HANDLE * handle)2075 static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
2076 {
2077     LIBSSH2_SFTP *sftp = handle->sftp;
2078     LIBSSH2_CHANNEL *channel = sftp->channel;
2079     LIBSSH2_SESSION *session = channel->session;
2080     /* 34 = packet_len(4) + packet_type(1) + request_id(4) +
2081        string_len(4) + strlen("fsync@openssh.com")(17) + handle_len(4) */
2082     uint32_t packet_len = handle->handle_len + 34;
2083     size_t data_len;
2084     unsigned char *packet, *s, *data;
2085     ssize_t rc;
2086     uint32_t retcode;
2087 
2088     if (sftp->fsync_state == libssh2_NB_state_idle) {
2089         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
2090                        "Issuing fsync command");
2091         s = packet = LIBSSH2_ALLOC(session, packet_len);
2092         if (!packet) {
2093             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2094                                   "Unable to allocate memory for FXP_EXTENDED "
2095                                   "packet");
2096         }
2097 
2098         _libssh2_store_u32(&s, packet_len - 4);
2099         *(s++) = SSH_FXP_EXTENDED;
2100         sftp->fsync_request_id = sftp->request_id++;
2101         _libssh2_store_u32(&s, sftp->fsync_request_id);
2102         _libssh2_store_str(&s, "fsync@openssh.com", 17);
2103         _libssh2_store_str(&s, handle->handle, handle->handle_len);
2104 
2105         sftp->fsync_state = libssh2_NB_state_created;
2106     } else {
2107         packet = sftp->fsync_packet;
2108     }
2109 
2110     if (sftp->fsync_state == libssh2_NB_state_created) {
2111         rc = _libssh2_channel_write(channel, 0, packet, packet_len);
2112         if (rc == LIBSSH2_ERROR_EAGAIN ||
2113             (0 <= rc && rc < (ssize_t)packet_len)) {
2114             sftp->fsync_packet = packet;
2115             return LIBSSH2_ERROR_EAGAIN;
2116         }
2117 
2118         LIBSSH2_FREE(session, packet);
2119         sftp->fsync_packet = NULL;
2120 
2121         if (rc < 0) {
2122             sftp->fsync_state = libssh2_NB_state_idle;
2123             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2124                                   "_libssh2_channel_write() failed");
2125         }
2126         sftp->fsync_state = libssh2_NB_state_sent;
2127     }
2128 
2129     rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2130                              sftp->fsync_request_id, &data, &data_len);
2131     if (rc == LIBSSH2_ERROR_EAGAIN) {
2132         return rc;
2133     } else if (rc) {
2134         sftp->fsync_state = libssh2_NB_state_idle;
2135         return _libssh2_error(session, rc,
2136                               "Error waiting for FXP EXTENDED REPLY");
2137     }
2138 
2139     sftp->fsync_state = libssh2_NB_state_idle;
2140 
2141     retcode = _libssh2_ntohu32(data + 5);
2142     LIBSSH2_FREE(session, data);
2143 
2144     if (retcode != LIBSSH2_FX_OK) {
2145         sftp->last_errno = retcode;
2146         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2147                               "fsync failed");
2148     }
2149 
2150     return 0;
2151 }
2152 
2153 /* libssh2_sftp_fsync
2154  * Commit data on the handle to disk.
2155  */
2156 LIBSSH2_API int
libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE * hnd)2157 libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *hnd)
2158 {
2159     int rc;
2160     if(!hnd)
2161         return LIBSSH2_ERROR_BAD_USE;
2162     BLOCK_ADJUST(rc, hnd->sftp->channel->session,
2163                  sftp_fsync(hnd));
2164     return rc;
2165 }
2166 
2167 
2168 /*
2169  * sftp_fstat
2170  *
2171  * Get or Set stat on a file
2172  */
sftp_fstat(LIBSSH2_SFTP_HANDLE * handle,LIBSSH2_SFTP_ATTRIBUTES * attrs,int setstat)2173 static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
2174                       LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
2175 {
2176     LIBSSH2_SFTP *sftp = handle->sftp;
2177     LIBSSH2_CHANNEL *channel = sftp->channel;
2178     LIBSSH2_SESSION *session = channel->session;
2179     size_t data_len;
2180     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
2181     uint32_t packet_len =
2182         handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0);
2183     unsigned char *s, *data;
2184     static const unsigned char fstat_responses[2] =
2185         { SSH_FXP_ATTRS, SSH_FXP_STATUS };
2186     ssize_t rc;
2187 
2188     if (sftp->fstat_state == libssh2_NB_state_idle) {
2189         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command",
2190                        setstat ? "set-stat" : "stat");
2191         s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
2192         if (!sftp->fstat_packet) {
2193             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2194                                   "Unable to allocate memory for "
2195                                   "FSTAT/FSETSTAT packet");
2196         }
2197 
2198         _libssh2_store_u32(&s, packet_len - 4);
2199         *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT;
2200         sftp->fstat_request_id = sftp->request_id++;
2201         _libssh2_store_u32(&s, sftp->fstat_request_id);
2202         _libssh2_store_str(&s, handle->handle, handle->handle_len);
2203 
2204         if (setstat) {
2205             s += sftp_attr2bin(s, attrs);
2206         }
2207 
2208         sftp->fstat_state = libssh2_NB_state_created;
2209     }
2210 
2211     if (sftp->fstat_state == libssh2_NB_state_created) {
2212         rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet,
2213                                     packet_len);
2214         if (rc == LIBSSH2_ERROR_EAGAIN) {
2215             return rc;
2216         }
2217         else if ((ssize_t)packet_len != rc) {
2218             LIBSSH2_FREE(session, sftp->fstat_packet);
2219             sftp->fstat_packet = NULL;
2220             sftp->fstat_state = libssh2_NB_state_idle;
2221             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2222                                   (setstat ? "Unable to send FXP_FSETSTAT"
2223                                    : "Unable to send FXP_FSTAT command"));
2224         }
2225         LIBSSH2_FREE(session, sftp->fstat_packet);
2226         sftp->fstat_packet = NULL;
2227 
2228         sftp->fstat_state = libssh2_NB_state_sent;
2229     }
2230 
2231     rc = sftp_packet_requirev(sftp, 2, fstat_responses,
2232                               sftp->fstat_request_id, &data,
2233                               &data_len);
2234     if (rc == LIBSSH2_ERROR_EAGAIN)
2235         return rc;
2236     else if (rc) {
2237         sftp->fstat_state = libssh2_NB_state_idle;
2238         return _libssh2_error(session, rc,
2239                               "Timeout waiting for status message");
2240     }
2241 
2242     sftp->fstat_state = libssh2_NB_state_idle;
2243 
2244     if (data[0] == SSH_FXP_STATUS) {
2245         uint32_t retcode;
2246 
2247         retcode = _libssh2_ntohu32(data + 5);
2248         LIBSSH2_FREE(session, data);
2249         if (retcode == LIBSSH2_FX_OK) {
2250             return 0;
2251         } else {
2252             sftp->last_errno = retcode;
2253             return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2254                                   "SFTP Protocol Error");
2255         }
2256     }
2257 
2258     sftp_bin2attr(attrs, data + 5);
2259     LIBSSH2_FREE(session, data);
2260 
2261     return 0;
2262 }
2263 
2264 /* libssh2_sftp_fstat_ex
2265  * Get or Set stat on a file
2266  */
2267 LIBSSH2_API int
libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * hnd,LIBSSH2_SFTP_ATTRIBUTES * attrs,int setstat)2268 libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd,
2269                       LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
2270 {
2271     int rc;
2272     if(!hnd || !attrs)
2273         return LIBSSH2_ERROR_BAD_USE;
2274     BLOCK_ADJUST(rc, hnd->sftp->channel->session,
2275                  sftp_fstat(hnd, attrs, setstat));
2276     return rc;
2277 }
2278 
2279 
2280 /* libssh2_sftp_seek64
2281  * Set the read/write pointer to an arbitrary position within the file
2282  */
2283 LIBSSH2_API void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle,libssh2_uint64_t offset)2284 libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset)
2285 {
2286     if(!handle)
2287         return;
2288     if(handle->u.file.offset == offset && handle->u.file.offset_sent == offset)
2289         return;
2290 
2291     handle->u.file.offset = handle->u.file.offset_sent = offset;
2292     /* discard all pending requests and currently read data */
2293     sftp_packetlist_flush(handle);
2294 
2295     /* free the left received buffered data */
2296     if (handle->u.file.data_left) {
2297         LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data);
2298         handle->u.file.data_left = handle->u.file.data_len = 0;
2299         handle->u.file.data = NULL;
2300     }
2301 
2302     /* reset EOF to False */
2303     handle->u.file.eof = FALSE;
2304 }
2305 
2306 /* libssh2_sftp_seek
2307  * Set the read/write pointer to an arbitrary position within the file
2308  */
2309 LIBSSH2_API void
libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE * handle,size_t offset)2310 libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset)
2311 {
2312     libssh2_sftp_seek64(handle, (libssh2_uint64_t)offset);
2313 }
2314 
2315 /* libssh2_sftp_tell
2316  * Return the current read/write pointer's offset
2317  */
2318 LIBSSH2_API size_t
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)2319 libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle)
2320 {
2321     if(!handle)
2322         return 0; /* no handle, no size */
2323 
2324     /* NOTE: this may very well truncate the size if it is larger than what
2325        size_t can hold, so libssh2_sftp_tell64() is really the function you
2326        should use */
2327     return (size_t)(handle->u.file.offset);
2328 }
2329 
2330 /* libssh2_sftp_tell64
2331  * Return the current read/write pointer's offset
2332  */
2333 LIBSSH2_API libssh2_uint64_t
libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE * handle)2334 libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle)
2335 {
2336     if(!handle)
2337         return 0; /* no handle, no size */
2338 
2339     return handle->u.file.offset;
2340 }
2341 
2342 /*
2343  * Flush all remaining incoming SFTP packets and zombies.
2344  */
sftp_packet_flush(LIBSSH2_SFTP * sftp)2345 static void sftp_packet_flush(LIBSSH2_SFTP *sftp)
2346 {
2347     LIBSSH2_CHANNEL *channel = sftp->channel;
2348     LIBSSH2_SESSION *session = channel->session;
2349     LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets);
2350     struct sftp_zombie_requests *zombie =
2351         _libssh2_list_first(&sftp->zombie_requests);
2352 
2353     while(packet) {
2354         LIBSSH2_SFTP_PACKET *next;
2355 
2356         /* check next struct in the list */
2357         next =  _libssh2_list_next(&packet->node);
2358         _libssh2_list_remove(&packet->node);
2359         LIBSSH2_FREE(session, packet->data);
2360         LIBSSH2_FREE(session, packet);
2361 
2362         packet = next;
2363     }
2364 
2365     while(zombie) {
2366         /* figure out the next node */
2367         struct sftp_zombie_requests *next = _libssh2_list_next(&zombie->node);
2368         /* unlink the current one */
2369         _libssh2_list_remove(&zombie->node);
2370         /* free the memory */
2371         LIBSSH2_FREE(session, zombie);
2372         zombie = next;
2373     }
2374 
2375 }
2376 
2377 /* sftp_close_handle
2378  *
2379  * Close a file or directory handle.
2380  * Also frees handle resource and unlinks it from the SFTP structure.
2381  * The handle is no longer usable after return of this function, unless
2382  * the return value is LIBSSH2_ERROR_EAGAIN in which case this function
2383  * should be called again.
2384  */
2385 static int
sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)2386 sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
2387 {
2388     LIBSSH2_SFTP *sftp = handle->sftp;
2389     LIBSSH2_CHANNEL *channel = sftp->channel;
2390     LIBSSH2_SESSION *session = channel->session;
2391     size_t data_len;
2392     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
2393     uint32_t packet_len = handle->handle_len + 13;
2394     unsigned char *s, *data = NULL;
2395     int rc = 0;
2396 
2397     if (handle->close_state == libssh2_NB_state_idle) {
2398         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle");
2399         s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
2400         if (!handle->close_packet) {
2401             handle->close_state = libssh2_NB_state_idle;
2402             rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2403                                 "Unable to allocate memory for FXP_CLOSE "
2404                                 "packet");
2405         } else {
2406 
2407             _libssh2_store_u32(&s, packet_len - 4);
2408             *(s++) = SSH_FXP_CLOSE;
2409             handle->close_request_id = sftp->request_id++;
2410             _libssh2_store_u32(&s, handle->close_request_id);
2411             _libssh2_store_str(&s, handle->handle, handle->handle_len);
2412             handle->close_state = libssh2_NB_state_created;
2413         }
2414     }
2415 
2416     if (handle->close_state == libssh2_NB_state_created) {
2417         rc = _libssh2_channel_write(channel, 0, handle->close_packet,
2418                                     packet_len);
2419         if (rc == LIBSSH2_ERROR_EAGAIN) {
2420             return rc;
2421         } else if ((ssize_t)packet_len != rc) {
2422             handle->close_state = libssh2_NB_state_idle;
2423             rc = _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2424                                 "Unable to send FXP_CLOSE command");
2425         } else
2426             handle->close_state = libssh2_NB_state_sent;
2427 
2428         LIBSSH2_FREE(session, handle->close_packet);
2429         handle->close_packet = NULL;
2430     }
2431 
2432     if (handle->close_state == libssh2_NB_state_sent) {
2433         rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2434                                  handle->close_request_id, &data,
2435                                  &data_len);
2436         if (rc == LIBSSH2_ERROR_EAGAIN) {
2437             return rc;
2438 
2439         } else if (rc) {
2440             _libssh2_error(session, rc,
2441                            "Error waiting for status message");
2442         }
2443 
2444         handle->close_state = libssh2_NB_state_sent1;
2445     }
2446 
2447     if(!data) {
2448         /* if it reaches this point with data unset, something unwanted
2449            happened for which we should have set an error code */
2450         assert(rc);
2451 
2452     } else {
2453         int retcode = _libssh2_ntohu32(data + 5);
2454         LIBSSH2_FREE(session, data);
2455 
2456         if (retcode != LIBSSH2_FX_OK) {
2457             sftp->last_errno = retcode;
2458             handle->close_state = libssh2_NB_state_idle;
2459             rc = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2460                                 "SFTP Protocol Error");
2461         }
2462     }
2463 
2464     /* remove this handle from the parent's list */
2465     _libssh2_list_remove(&handle->node);
2466 
2467     if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR)
2468         && handle->u.dir.names_left) {
2469         LIBSSH2_FREE(session, handle->u.dir.names_packet);
2470     }
2471     else {
2472         if(handle->u.file.data)
2473             LIBSSH2_FREE(session, handle->u.file.data);
2474     }
2475 
2476     sftp_packetlist_flush(handle);
2477     sftp->read_state = libssh2_NB_state_idle;
2478 
2479     handle->close_state = libssh2_NB_state_idle;
2480 
2481     LIBSSH2_FREE(session, handle);
2482 
2483     return rc;
2484 }
2485 
2486 /* libssh2_sftp_close_handle
2487  *
2488  * Close a file or directory handle
2489  * Also frees handle resource and unlinks it from the SFTP structure
2490  */
2491 LIBSSH2_API int
libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * hnd)2492 libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *hnd)
2493 {
2494     int rc;
2495     if(!hnd)
2496         return LIBSSH2_ERROR_BAD_USE;
2497     BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd));
2498     return rc;
2499 }
2500 
2501 /* sftp_unlink
2502  * Delete a file from the remote server
2503  */
sftp_unlink(LIBSSH2_SFTP * sftp,const char * filename,size_t filename_len)2504 static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
2505                        size_t filename_len)
2506 {
2507     LIBSSH2_CHANNEL *channel = sftp->channel;
2508     LIBSSH2_SESSION *session = channel->session;
2509     size_t data_len;
2510     int retcode;
2511     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
2512     uint32_t packet_len = filename_len + 13;
2513     unsigned char *s, *data;
2514     int rc;
2515 
2516     if (sftp->unlink_state == libssh2_NB_state_idle) {
2517         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename);
2518         s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
2519         if (!sftp->unlink_packet) {
2520             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2521                                   "Unable to allocate memory for FXP_REMOVE "
2522                                   "packet");
2523         }
2524 
2525         _libssh2_store_u32(&s, packet_len - 4);
2526         *(s++) = SSH_FXP_REMOVE;
2527         sftp->unlink_request_id = sftp->request_id++;
2528         _libssh2_store_u32(&s, sftp->unlink_request_id);
2529         _libssh2_store_str(&s, filename, filename_len);
2530         sftp->unlink_state = libssh2_NB_state_created;
2531     }
2532 
2533     if (sftp->unlink_state == libssh2_NB_state_created) {
2534         rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet,
2535                                     packet_len);
2536         if (rc == LIBSSH2_ERROR_EAGAIN) {
2537             return rc;
2538         } else if ((ssize_t)packet_len != rc) {
2539             LIBSSH2_FREE(session, sftp->unlink_packet);
2540             sftp->unlink_packet = NULL;
2541             sftp->unlink_state = libssh2_NB_state_idle;
2542             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2543                                   "Unable to send FXP_REMOVE command");
2544         }
2545         LIBSSH2_FREE(session, sftp->unlink_packet);
2546         sftp->unlink_packet = NULL;
2547 
2548         sftp->unlink_state = libssh2_NB_state_sent;
2549     }
2550 
2551     rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2552                              sftp->unlink_request_id, &data,
2553                              &data_len);
2554     if (rc == LIBSSH2_ERROR_EAGAIN) {
2555         return rc;
2556     }
2557     else if (rc) {
2558         sftp->unlink_state = libssh2_NB_state_idle;
2559         return _libssh2_error(session, rc,
2560                               "Error waiting for FXP STATUS");
2561     }
2562 
2563     sftp->unlink_state = libssh2_NB_state_idle;
2564 
2565     retcode = _libssh2_ntohu32(data + 5);
2566     LIBSSH2_FREE(session, data);
2567 
2568     if (retcode == LIBSSH2_FX_OK) {
2569         return 0;
2570     } else {
2571         sftp->last_errno = retcode;
2572         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2573                               "SFTP Protocol Error");
2574     }
2575 }
2576 
2577 /* libssh2_sftp_unlink_ex
2578  * Delete a file from the remote server
2579  */
2580 LIBSSH2_API int
libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp,const char * filename,unsigned int filename_len)2581 libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename,
2582                        unsigned int filename_len)
2583 {
2584     int rc;
2585     if(!sftp)
2586         return LIBSSH2_ERROR_BAD_USE;
2587     BLOCK_ADJUST(rc, sftp->channel->session,
2588                  sftp_unlink(sftp, filename, filename_len));
2589     return rc;
2590 }
2591 
2592 /*
2593  * sftp_rename
2594  *
2595  * Rename a file on the remote server
2596  */
sftp_rename(LIBSSH2_SFTP * sftp,const char * source_filename,unsigned int source_filename_len,const char * dest_filename,unsigned int dest_filename_len,long flags)2597 static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
2598                        unsigned int source_filename_len,
2599                        const char *dest_filename,
2600                        unsigned int dest_filename_len, long flags)
2601 {
2602     LIBSSH2_CHANNEL *channel = sftp->channel;
2603     LIBSSH2_SESSION *session = channel->session;
2604     size_t data_len;
2605     int retcode;
2606     uint32_t packet_len =
2607         source_filename_len + dest_filename_len + 17 + (sftp->version >=
2608                                                         5 ? 4 : 0);
2609     /* packet_len(4) + packet_type(1) + request_id(4) +
2610        source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
2611     unsigned char *data;
2612     ssize_t rc;
2613 
2614     if (sftp->version < 2) {
2615         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2616                               "Server does not support RENAME");
2617     }
2618 
2619     if (sftp->rename_state == libssh2_NB_state_idle) {
2620         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s",
2621                        source_filename, dest_filename);
2622         sftp->rename_s = sftp->rename_packet =
2623             LIBSSH2_ALLOC(session, packet_len);
2624         if (!sftp->rename_packet) {
2625             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2626                                   "Unable to allocate memory for FXP_RENAME "
2627                                   "packet");
2628         }
2629 
2630         _libssh2_store_u32(&sftp->rename_s, packet_len - 4);
2631         *(sftp->rename_s++) = SSH_FXP_RENAME;
2632         sftp->rename_request_id = sftp->request_id++;
2633         _libssh2_store_u32(&sftp->rename_s, sftp->rename_request_id);
2634         _libssh2_store_str(&sftp->rename_s, source_filename,
2635                            source_filename_len);
2636         _libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len);
2637 
2638         if (sftp->version >= 5)
2639             _libssh2_store_u32(&sftp->rename_s, flags);
2640 
2641         sftp->rename_state = libssh2_NB_state_created;
2642     }
2643 
2644     if (sftp->rename_state == libssh2_NB_state_created) {
2645         rc = _libssh2_channel_write(channel, 0, sftp->rename_packet,
2646                                     sftp->rename_s - sftp->rename_packet);
2647         if (rc == LIBSSH2_ERROR_EAGAIN) {
2648             return rc;
2649         } else if ((ssize_t)packet_len != rc) {
2650             LIBSSH2_FREE(session, sftp->rename_packet);
2651             sftp->rename_packet = NULL;
2652             sftp->rename_state = libssh2_NB_state_idle;
2653             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2654                                   "Unable to send FXP_RENAME command");
2655         }
2656         LIBSSH2_FREE(session, sftp->rename_packet);
2657         sftp->rename_packet = NULL;
2658 
2659         sftp->rename_state = libssh2_NB_state_sent;
2660     }
2661 
2662     rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2663                              sftp->rename_request_id, &data,
2664                              &data_len);
2665     if (rc == LIBSSH2_ERROR_EAGAIN) {
2666         return rc;
2667     } else if (rc) {
2668         sftp->rename_state = libssh2_NB_state_idle;
2669         return _libssh2_error(session, rc,
2670                               "Error waiting for FXP STATUS");
2671     }
2672 
2673     sftp->rename_state = libssh2_NB_state_idle;
2674 
2675     retcode = _libssh2_ntohu32(data + 5);
2676     LIBSSH2_FREE(session, data);
2677 
2678     sftp->last_errno = retcode;
2679 
2680     /* now convert the SFTP error code to libssh2 return code or error
2681        message */
2682     switch (retcode) {
2683     case LIBSSH2_FX_OK:
2684         retcode = LIBSSH2_ERROR_NONE;
2685         break;
2686 
2687     case LIBSSH2_FX_FILE_ALREADY_EXISTS:
2688         retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2689                                  "File already exists and "
2690                                  "SSH_FXP_RENAME_OVERWRITE not specified");
2691         break;
2692 
2693     case LIBSSH2_FX_OP_UNSUPPORTED:
2694         retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2695                                  "Operation Not Supported");
2696         break;
2697 
2698     default:
2699         retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2700                                  "SFTP Protocol Error");
2701         break;
2702     }
2703 
2704     return retcode;
2705 }
2706 
2707 /* libssh2_sftp_rename_ex
2708  * Rename a file on the remote server
2709  */
2710 LIBSSH2_API int
libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp,const char * source_filename,unsigned int source_filename_len,const char * dest_filename,unsigned int dest_filename_len,long flags)2711 libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename,
2712                        unsigned int source_filename_len,
2713                        const char *dest_filename,
2714                        unsigned int dest_filename_len, long flags)
2715 {
2716     int rc;
2717     if(!sftp)
2718         return LIBSSH2_ERROR_BAD_USE;
2719     BLOCK_ADJUST(rc, sftp->channel->session,
2720                  sftp_rename(sftp, source_filename, source_filename_len,
2721                              dest_filename, dest_filename_len, flags));
2722     return rc;
2723 }
2724 
2725 /*
2726  * sftp_fstatvfs
2727  *
2728  * Get file system statistics
2729  */
sftp_fstatvfs(LIBSSH2_SFTP_HANDLE * handle,LIBSSH2_SFTP_STATVFS * st)2730 static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
2731 {
2732     LIBSSH2_SFTP *sftp = handle->sftp;
2733     LIBSSH2_CHANNEL *channel = sftp->channel;
2734     LIBSSH2_SESSION *session = channel->session;
2735     size_t data_len;
2736     /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
2737        + handle_len (4) */
2738     /* 20 = strlen ("fstatvfs@openssh.com") */
2739     uint32_t packet_len = handle->handle_len + 20 + 17;
2740     unsigned char *packet, *s, *data;
2741     ssize_t rc;
2742     unsigned int flag;
2743     static const unsigned char responses[2] =
2744         { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
2745 
2746     if (sftp->fstatvfs_state == libssh2_NB_state_idle) {
2747         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
2748                        "Getting file system statistics");
2749         s = packet = LIBSSH2_ALLOC(session, packet_len);
2750         if (!packet) {
2751             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2752                                   "Unable to allocate memory for FXP_EXTENDED "
2753                                   "packet");
2754         }
2755 
2756         _libssh2_store_u32(&s, packet_len - 4);
2757         *(s++) = SSH_FXP_EXTENDED;
2758         sftp->fstatvfs_request_id = sftp->request_id++;
2759         _libssh2_store_u32(&s, sftp->fstatvfs_request_id);
2760         _libssh2_store_str(&s, "fstatvfs@openssh.com", 20);
2761         _libssh2_store_str(&s, handle->handle, handle->handle_len);
2762 
2763         sftp->fstatvfs_state = libssh2_NB_state_created;
2764     }
2765     else {
2766         packet = sftp->fstatvfs_packet;
2767     }
2768 
2769     if (sftp->fstatvfs_state == libssh2_NB_state_created) {
2770         rc = _libssh2_channel_write(channel, 0, packet, packet_len);
2771         if (rc == LIBSSH2_ERROR_EAGAIN ||
2772             (0 <= rc && rc < (ssize_t)packet_len)) {
2773             sftp->fstatvfs_packet = packet;
2774             return LIBSSH2_ERROR_EAGAIN;
2775         }
2776 
2777         LIBSSH2_FREE(session, packet);
2778         sftp->fstatvfs_packet = NULL;
2779 
2780         if (rc < 0) {
2781             sftp->fstatvfs_state = libssh2_NB_state_idle;
2782             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2783                                   "_libssh2_channel_write() failed");
2784         }
2785         sftp->fstatvfs_state = libssh2_NB_state_sent;
2786     }
2787 
2788     rc = sftp_packet_requirev(sftp, 2, responses, sftp->fstatvfs_request_id,
2789                               &data, &data_len);
2790 
2791     if (rc == LIBSSH2_ERROR_EAGAIN) {
2792         return rc;
2793     } else if (rc) {
2794         sftp->fstatvfs_state = libssh2_NB_state_idle;
2795         return _libssh2_error(session, rc,
2796                               "Error waiting for FXP EXTENDED REPLY");
2797     }
2798 
2799     if (data[0] == SSH_FXP_STATUS) {
2800         int retcode = _libssh2_ntohu32(data + 5);
2801         sftp->fstatvfs_state = libssh2_NB_state_idle;
2802         LIBSSH2_FREE(session, data);
2803         sftp->last_errno = retcode;
2804         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2805                               "SFTP Protocol Error");
2806     }
2807 
2808     if (data_len < 93) {
2809         LIBSSH2_FREE(session, data);
2810         sftp->fstatvfs_state = libssh2_NB_state_idle;
2811         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2812                               "SFTP Protocol Error: short response");
2813     }
2814 
2815     sftp->fstatvfs_state = libssh2_NB_state_idle;
2816 
2817     st->f_bsize = _libssh2_ntohu64(data + 5);
2818     st->f_frsize = _libssh2_ntohu64(data + 13);
2819     st->f_blocks = _libssh2_ntohu64(data + 21);
2820     st->f_bfree = _libssh2_ntohu64(data + 29);
2821     st->f_bavail = _libssh2_ntohu64(data + 37);
2822     st->f_files = _libssh2_ntohu64(data + 45);
2823     st->f_ffree = _libssh2_ntohu64(data + 53);
2824     st->f_favail = _libssh2_ntohu64(data + 61);
2825     st->f_fsid = _libssh2_ntohu64(data + 69);
2826     flag = (unsigned int)_libssh2_ntohu64(data + 77);
2827     st->f_namemax = _libssh2_ntohu64(data + 85);
2828 
2829     st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
2830         ? LIBSSH2_SFTP_ST_RDONLY : 0;
2831     st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID)
2832         ? LIBSSH2_SFTP_ST_NOSUID : 0;
2833 
2834     LIBSSH2_FREE(session, data);
2835     return 0;
2836 }
2837 
2838 /* libssh2_sftp_fstatvfs
2839  * Get filesystem space and inode utilization (requires fstatvfs@openssh.com
2840  * support on the server)
2841  */
2842 LIBSSH2_API int
libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE * handle,LIBSSH2_SFTP_STATVFS * st)2843 libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
2844 {
2845     int rc;
2846     if(!handle || !st)
2847         return LIBSSH2_ERROR_BAD_USE;
2848     BLOCK_ADJUST(rc, handle->sftp->channel->session, sftp_fstatvfs(handle, st));
2849     return rc;
2850 }
2851 
2852 /*
2853  * sftp_statvfs
2854  *
2855  * Get file system statistics
2856  */
sftp_statvfs(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,LIBSSH2_SFTP_STATVFS * st)2857 static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
2858                         unsigned int path_len, LIBSSH2_SFTP_STATVFS *st)
2859 {
2860     LIBSSH2_CHANNEL *channel = sftp->channel;
2861     LIBSSH2_SESSION *session = channel->session;
2862     size_t data_len;
2863     /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
2864        + path_len (4) */
2865     /* 19 = strlen ("statvfs@openssh.com") */
2866     uint32_t packet_len = path_len + 19 + 17;
2867     unsigned char *packet, *s, *data;
2868     ssize_t rc;
2869     unsigned int flag;
2870     static const unsigned char responses[2] =
2871         { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
2872 
2873     if (sftp->statvfs_state == libssh2_NB_state_idle) {
2874         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
2875                        "Getting file system statistics of %s", path);
2876         s = packet = LIBSSH2_ALLOC(session, packet_len);
2877         if (!packet) {
2878             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2879                                   "Unable to allocate memory for FXP_EXTENDED "
2880                                   "packet");
2881         }
2882 
2883         _libssh2_store_u32(&s, packet_len - 4);
2884         *(s++) = SSH_FXP_EXTENDED;
2885         sftp->statvfs_request_id = sftp->request_id++;
2886         _libssh2_store_u32(&s, sftp->statvfs_request_id);
2887         _libssh2_store_str(&s, "statvfs@openssh.com", 19);
2888         _libssh2_store_str(&s, path, path_len);
2889 
2890         sftp->statvfs_state = libssh2_NB_state_created;
2891     }
2892     else {
2893         packet = sftp->statvfs_packet;
2894     }
2895 
2896     if (sftp->statvfs_state == libssh2_NB_state_created) {
2897         rc = _libssh2_channel_write(channel, 0, packet, packet_len);
2898         if (rc == LIBSSH2_ERROR_EAGAIN ||
2899             (0 <= rc && rc < (ssize_t)packet_len)) {
2900             sftp->statvfs_packet = packet;
2901             return LIBSSH2_ERROR_EAGAIN;
2902         }
2903 
2904         LIBSSH2_FREE(session, packet);
2905         sftp->statvfs_packet = NULL;
2906 
2907         if (rc < 0) {
2908             sftp->statvfs_state = libssh2_NB_state_idle;
2909             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2910                                   "_libssh2_channel_write() failed");
2911         }
2912         sftp->statvfs_state = libssh2_NB_state_sent;
2913     }
2914 
2915     rc = sftp_packet_requirev(sftp, 2, responses, sftp->statvfs_request_id,
2916                               &data, &data_len);
2917     if (rc == LIBSSH2_ERROR_EAGAIN) {
2918         return rc;
2919     } else if (rc) {
2920         sftp->statvfs_state = libssh2_NB_state_idle;
2921         return _libssh2_error(session, rc,
2922                               "Error waiting for FXP EXTENDED REPLY");
2923     }
2924 
2925     if (data[0] == SSH_FXP_STATUS) {
2926         int retcode = _libssh2_ntohu32(data + 5);
2927         sftp->statvfs_state = libssh2_NB_state_idle;
2928         LIBSSH2_FREE(session, data);
2929         sftp->last_errno = retcode;
2930         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2931                               "SFTP Protocol Error");
2932     }
2933 
2934     if (data_len < 93) {
2935         LIBSSH2_FREE(session, data);
2936         sftp->statvfs_state = libssh2_NB_state_idle;
2937         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2938                               "SFTP Protocol Error: short response");
2939     }
2940 
2941     sftp->statvfs_state = libssh2_NB_state_idle;
2942 
2943     st->f_bsize = _libssh2_ntohu64(data + 5);
2944     st->f_frsize = _libssh2_ntohu64(data + 13);
2945     st->f_blocks = _libssh2_ntohu64(data + 21);
2946     st->f_bfree = _libssh2_ntohu64(data + 29);
2947     st->f_bavail = _libssh2_ntohu64(data + 37);
2948     st->f_files = _libssh2_ntohu64(data + 45);
2949     st->f_ffree = _libssh2_ntohu64(data + 53);
2950     st->f_favail = _libssh2_ntohu64(data + 61);
2951     st->f_fsid = _libssh2_ntohu64(data + 69);
2952     flag = (unsigned int)_libssh2_ntohu64(data + 77);
2953     st->f_namemax = _libssh2_ntohu64(data + 85);
2954 
2955     st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
2956         ? LIBSSH2_SFTP_ST_RDONLY : 0;
2957     st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID)
2958         ? LIBSSH2_SFTP_ST_NOSUID : 0;
2959 
2960     LIBSSH2_FREE(session, data);
2961     return 0;
2962 }
2963 
2964 /* libssh2_sftp_statvfs_ex
2965  * Get filesystem space and inode utilization (requires statvfs@openssh.com
2966  * support on the server)
2967  */
2968 LIBSSH2_API int
libssh2_sftp_statvfs(LIBSSH2_SFTP * sftp,const char * path,size_t path_len,LIBSSH2_SFTP_STATVFS * st)2969 libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
2970                      size_t path_len, LIBSSH2_SFTP_STATVFS *st)
2971 {
2972     int rc;
2973     if(!sftp || !st)
2974         return LIBSSH2_ERROR_BAD_USE;
2975     BLOCK_ADJUST(rc, sftp->channel->session, sftp_statvfs(sftp, path, path_len,
2976                                                           st));
2977     return rc;
2978 }
2979 
2980 
2981 /*
2982  * sftp_mkdir
2983  *
2984  * Create an SFTP directory
2985  */
sftp_mkdir(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,long mode)2986 static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
2987                       unsigned int path_len, long mode)
2988 {
2989     LIBSSH2_CHANNEL *channel = sftp->channel;
2990     LIBSSH2_SESSION *session = channel->session;
2991     LIBSSH2_SFTP_ATTRIBUTES attrs = {
2992         LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
2993     };
2994     size_t data_len;
2995     int retcode;
2996     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
2997     ssize_t packet_len = path_len + 13 +
2998         sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS);
2999     unsigned char *packet, *s, *data;
3000     int rc;
3001 
3002     if (sftp->mkdir_state == libssh2_NB_state_idle) {
3003         _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
3004                        "Creating directory %s with mode 0%lo", path, mode);
3005         s = packet = LIBSSH2_ALLOC(session, packet_len);
3006         if (!packet) {
3007             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3008                                   "Unable to allocate memory for FXP_MKDIR "
3009                                   "packet");
3010         }
3011         /* Filetype in SFTP 3 and earlier */
3012         attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
3013 
3014         _libssh2_store_u32(&s, packet_len - 4);
3015         *(s++) = SSH_FXP_MKDIR;
3016         sftp->mkdir_request_id = sftp->request_id++;
3017         _libssh2_store_u32(&s, sftp->mkdir_request_id);
3018         _libssh2_store_str(&s, path, path_len);
3019 
3020         s += sftp_attr2bin(s, &attrs);
3021 
3022         sftp->mkdir_state = libssh2_NB_state_created;
3023     }
3024     else {
3025         packet = sftp->mkdir_packet;
3026     }
3027 
3028     if (sftp->mkdir_state == libssh2_NB_state_created) {
3029         rc = _libssh2_channel_write(channel, 0, packet, packet_len);
3030         if (rc == LIBSSH2_ERROR_EAGAIN) {
3031             sftp->mkdir_packet = packet;
3032             return rc;
3033         }
3034         if (packet_len != rc) {
3035             LIBSSH2_FREE(session, packet);
3036             sftp->mkdir_state = libssh2_NB_state_idle;
3037             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3038                                   "_libssh2_channel_write() failed");
3039         }
3040         LIBSSH2_FREE(session, packet);
3041         sftp->mkdir_state = libssh2_NB_state_sent;
3042         sftp->mkdir_packet = NULL;
3043     }
3044 
3045     rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id,
3046                              &data, &data_len);
3047     if (rc == LIBSSH2_ERROR_EAGAIN) {
3048         return rc;
3049     } else if (rc) {
3050         sftp->mkdir_state = libssh2_NB_state_idle;
3051         return _libssh2_error(session, rc,
3052                               "Error waiting for FXP STATUS");
3053     }
3054 
3055     sftp->mkdir_state = libssh2_NB_state_idle;
3056 
3057     retcode = _libssh2_ntohu32(data + 5);
3058     LIBSSH2_FREE(session, data);
3059 
3060     if (retcode == LIBSSH2_FX_OK) {
3061         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!");
3062         return 0;
3063     } else {
3064         sftp->last_errno = retcode;
3065         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3066                               "SFTP Protocol Error");
3067     }
3068 }
3069 
3070 /*
3071  * libssh2_sftp_mkdir_ex
3072  *
3073  * Create an SFTP directory
3074  */
3075 LIBSSH2_API int
libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,long mode)3076 libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path,
3077                       unsigned int path_len, long mode)
3078 {
3079     int rc;
3080     if(!sftp)
3081         return LIBSSH2_ERROR_BAD_USE;
3082     BLOCK_ADJUST(rc, sftp->channel->session,
3083                  sftp_mkdir(sftp, path, path_len, mode));
3084     return rc;
3085 }
3086 
3087 /* sftp_rmdir
3088  * Remove a directory
3089  */
sftp_rmdir(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len)3090 static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
3091                       unsigned int path_len)
3092 {
3093     LIBSSH2_CHANNEL *channel = sftp->channel;
3094     LIBSSH2_SESSION *session = channel->session;
3095     size_t data_len;
3096     int retcode;
3097     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3098     ssize_t packet_len = path_len + 13;
3099     unsigned char *s, *data;
3100     int rc;
3101 
3102     if (sftp->rmdir_state == libssh2_NB_state_idle) {
3103         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s",
3104                        path);
3105         s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
3106         if (!sftp->rmdir_packet) {
3107             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3108                                   "Unable to allocate memory for FXP_RMDIR "
3109                                   "packet");
3110         }
3111 
3112         _libssh2_store_u32(&s, packet_len - 4);
3113         *(s++) = SSH_FXP_RMDIR;
3114         sftp->rmdir_request_id = sftp->request_id++;
3115         _libssh2_store_u32(&s, sftp->rmdir_request_id);
3116         _libssh2_store_str(&s, path, path_len);
3117 
3118         sftp->rmdir_state = libssh2_NB_state_created;
3119     }
3120 
3121     if (sftp->rmdir_state == libssh2_NB_state_created) {
3122         rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet,
3123                                     packet_len);
3124         if (rc == LIBSSH2_ERROR_EAGAIN) {
3125             return rc;
3126         } else if (packet_len != rc) {
3127             LIBSSH2_FREE(session, sftp->rmdir_packet);
3128             sftp->rmdir_packet = NULL;
3129             sftp->rmdir_state = libssh2_NB_state_idle;
3130             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3131                                   "Unable to send FXP_RMDIR command");
3132         }
3133         LIBSSH2_FREE(session, sftp->rmdir_packet);
3134         sftp->rmdir_packet = NULL;
3135 
3136         sftp->rmdir_state = libssh2_NB_state_sent;
3137     }
3138 
3139     rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
3140                              sftp->rmdir_request_id, &data, &data_len);
3141     if (rc == LIBSSH2_ERROR_EAGAIN) {
3142         return rc;
3143     } else if (rc) {
3144         sftp->rmdir_state = libssh2_NB_state_idle;
3145         return _libssh2_error(session, rc,
3146                               "Error waiting for FXP STATUS");
3147     }
3148 
3149     sftp->rmdir_state = libssh2_NB_state_idle;
3150 
3151     retcode = _libssh2_ntohu32(data + 5);
3152     LIBSSH2_FREE(session, data);
3153 
3154     if (retcode == LIBSSH2_FX_OK) {
3155         return 0;
3156     } else {
3157         sftp->last_errno = retcode;
3158         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3159                               "SFTP Protocol Error");
3160     }
3161 }
3162 
3163 /* libssh2_sftp_rmdir_ex
3164  * Remove a directory
3165  */
3166 LIBSSH2_API int
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len)3167 libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path,
3168                       unsigned int path_len)
3169 {
3170     int rc;
3171     if(!sftp)
3172         return LIBSSH2_ERROR_BAD_USE;
3173     BLOCK_ADJUST(rc, sftp->channel->session,
3174                  sftp_rmdir(sftp, path, path_len));
3175     return rc;
3176 }
3177 
3178 /* sftp_stat
3179  * Stat a file or symbolic link
3180  */
sftp_stat(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,int stat_type,LIBSSH2_SFTP_ATTRIBUTES * attrs)3181 static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
3182                      unsigned int path_len, int stat_type,
3183                      LIBSSH2_SFTP_ATTRIBUTES * attrs)
3184 {
3185     LIBSSH2_CHANNEL *channel = sftp->channel;
3186     LIBSSH2_SESSION *session = channel->session;
3187     size_t data_len;
3188     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3189     ssize_t packet_len =
3190         path_len + 13 +
3191         ((stat_type ==
3192           LIBSSH2_SFTP_SETSTAT) ? sftp_attrsize(attrs->flags) : 0);
3193     unsigned char *s, *data;
3194     static const unsigned char stat_responses[2] =
3195         { SSH_FXP_ATTRS, SSH_FXP_STATUS };
3196     int rc;
3197 
3198     if (sftp->stat_state == libssh2_NB_state_idle) {
3199         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s",
3200                        (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
3201                        (stat_type ==
3202                         LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
3203         s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len);
3204         if (!sftp->stat_packet) {
3205             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3206                                   "Unable to allocate memory for FXP_*STAT "
3207                                   "packet");
3208         }
3209 
3210         _libssh2_store_u32(&s, packet_len - 4);
3211 
3212         switch (stat_type) {
3213         case LIBSSH2_SFTP_SETSTAT:
3214             *(s++) = SSH_FXP_SETSTAT;
3215             break;
3216 
3217         case LIBSSH2_SFTP_LSTAT:
3218             *(s++) = SSH_FXP_LSTAT;
3219             break;
3220 
3221         case LIBSSH2_SFTP_STAT:
3222         default:
3223             *(s++) = SSH_FXP_STAT;
3224         }
3225         sftp->stat_request_id = sftp->request_id++;
3226         _libssh2_store_u32(&s, sftp->stat_request_id);
3227         _libssh2_store_str(&s, path, path_len);
3228 
3229         if (stat_type == LIBSSH2_SFTP_SETSTAT)
3230             s += sftp_attr2bin(s, attrs);
3231 
3232         sftp->stat_state = libssh2_NB_state_created;
3233     }
3234 
3235     if (sftp->stat_state == libssh2_NB_state_created) {
3236         rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len);
3237         if (rc == LIBSSH2_ERROR_EAGAIN) {
3238             return rc;
3239         } else if (packet_len != rc) {
3240             LIBSSH2_FREE(session, sftp->stat_packet);
3241             sftp->stat_packet = NULL;
3242             sftp->stat_state = libssh2_NB_state_idle;
3243             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3244                                   "Unable to send STAT/LSTAT/SETSTAT command");
3245         }
3246         LIBSSH2_FREE(session, sftp->stat_packet);
3247         sftp->stat_packet = NULL;
3248 
3249         sftp->stat_state = libssh2_NB_state_sent;
3250     }
3251 
3252     rc = sftp_packet_requirev(sftp, 2, stat_responses,
3253                               sftp->stat_request_id, &data, &data_len);
3254     if (rc == LIBSSH2_ERROR_EAGAIN)
3255         return rc;
3256     else if (rc) {
3257         sftp->stat_state = libssh2_NB_state_idle;
3258         return _libssh2_error(session, rc,
3259                               "Timeout waiting for status message");
3260     }
3261 
3262     sftp->stat_state = libssh2_NB_state_idle;
3263 
3264     if (data[0] == SSH_FXP_STATUS) {
3265         int retcode;
3266 
3267         retcode = _libssh2_ntohu32(data + 5);
3268         LIBSSH2_FREE(session, data);
3269         if (retcode == LIBSSH2_FX_OK) {
3270             return 0;
3271         } else {
3272             sftp->last_errno = retcode;
3273             return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3274                                   "SFTP Protocol Error");
3275         }
3276     }
3277 
3278     memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
3279     sftp_bin2attr(attrs, data + 5);
3280     LIBSSH2_FREE(session, data);
3281 
3282     return 0;
3283 }
3284 
3285 /* libssh2_sftp_stat_ex
3286  * Stat a file or symbolic link
3287  */
3288 LIBSSH2_API int
libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,int stat_type,LIBSSH2_SFTP_ATTRIBUTES * attrs)3289 libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path,
3290                      unsigned int path_len, int stat_type,
3291                      LIBSSH2_SFTP_ATTRIBUTES *attrs)
3292 {
3293     int rc;
3294     if(!sftp)
3295         return LIBSSH2_ERROR_BAD_USE;
3296     BLOCK_ADJUST(rc, sftp->channel->session,
3297                  sftp_stat(sftp, path, path_len, stat_type, attrs));
3298     return rc;
3299 }
3300 
3301 /* sftp_symlink
3302  * Read or set a symlink
3303  */
sftp_symlink(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,char * target,unsigned int target_len,int link_type)3304 static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
3305                         unsigned int path_len, char *target,
3306                         unsigned int target_len, int link_type)
3307 {
3308     LIBSSH2_CHANNEL *channel = sftp->channel;
3309     LIBSSH2_SESSION *session = channel->session;
3310     size_t data_len, link_len;
3311     /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3312     ssize_t packet_len =
3313         path_len + 13 +
3314         ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
3315     unsigned char *s, *data;
3316     static const unsigned char link_responses[2] =
3317         { SSH_FXP_NAME, SSH_FXP_STATUS };
3318     int retcode;
3319 
3320     if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
3321         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3322                               "Server does not support SYMLINK or READLINK");
3323     }
3324 
3325     if (sftp->symlink_state == libssh2_NB_state_idle) {
3326         s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
3327         if (!sftp->symlink_packet) {
3328             return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3329                                   "Unable to allocate memory for "
3330                                   "SYMLINK/READLINK/REALPATH packet");
3331         }
3332 
3333         _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s",
3334                        (link_type ==
3335                         LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
3336                        (link_type ==
3337                         LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path);
3338 
3339         _libssh2_store_u32(&s, packet_len - 4);
3340 
3341         switch (link_type) {
3342         case LIBSSH2_SFTP_REALPATH:
3343             *(s++) = SSH_FXP_REALPATH;
3344             break;
3345 
3346         case LIBSSH2_SFTP_SYMLINK:
3347             *(s++) = SSH_FXP_SYMLINK;
3348             break;
3349 
3350         case LIBSSH2_SFTP_READLINK:
3351         default:
3352             *(s++) = SSH_FXP_READLINK;
3353         }
3354         sftp->symlink_request_id = sftp->request_id++;
3355         _libssh2_store_u32(&s, sftp->symlink_request_id);
3356         _libssh2_store_str(&s, path, path_len);
3357 
3358         if (link_type == LIBSSH2_SFTP_SYMLINK)
3359             _libssh2_store_str(&s, target, target_len);
3360 
3361         sftp->symlink_state = libssh2_NB_state_created;
3362     }
3363 
3364     if (sftp->symlink_state == libssh2_NB_state_created) {
3365         ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet,
3366                                             packet_len);
3367         if (rc == LIBSSH2_ERROR_EAGAIN)
3368             return rc;
3369         else if (packet_len != rc) {
3370             LIBSSH2_FREE(session, sftp->symlink_packet);
3371             sftp->symlink_packet = NULL;
3372             sftp->symlink_state = libssh2_NB_state_idle;
3373             return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3374                                   "Unable to send SYMLINK/READLINK command");
3375         }
3376         LIBSSH2_FREE(session, sftp->symlink_packet);
3377         sftp->symlink_packet = NULL;
3378 
3379         sftp->symlink_state = libssh2_NB_state_sent;
3380     }
3381 
3382     retcode = sftp_packet_requirev(sftp, 2, link_responses,
3383                                    sftp->symlink_request_id, &data,
3384                                    &data_len);
3385     if (retcode == LIBSSH2_ERROR_EAGAIN)
3386         return retcode;
3387     else if (retcode) {
3388         sftp->symlink_state = libssh2_NB_state_idle;
3389         return _libssh2_error(session, retcode,
3390                               "Error waiting for status message");
3391     }
3392 
3393     sftp->symlink_state = libssh2_NB_state_idle;
3394 
3395     if (data[0] == SSH_FXP_STATUS) {
3396         retcode = _libssh2_ntohu32(data + 5);
3397         LIBSSH2_FREE(session, data);
3398         if (retcode == LIBSSH2_FX_OK)
3399             return LIBSSH2_ERROR_NONE;
3400         else {
3401             sftp->last_errno = retcode;
3402             return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3403                                   "SFTP Protocol Error");
3404         }
3405     }
3406 
3407     if (_libssh2_ntohu32(data + 5) < 1) {
3408         LIBSSH2_FREE(session, data);
3409         return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3410                               "Invalid READLINK/REALPATH response, "
3411                               "no name entries");
3412     }
3413 
3414     /* this reads a u32 and stores it into a signed 32bit value */
3415     link_len = _libssh2_ntohu32(data + 9);
3416     if (link_len < target_len) {
3417         memcpy(target, data + 13, link_len);
3418         target[link_len] = 0;
3419         retcode = (int)link_len;
3420     }
3421     else
3422         retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
3423     LIBSSH2_FREE(session, data);
3424 
3425     return retcode;
3426 }
3427 
3428 /* libssh2_sftp_symlink_ex
3429  * Read or set a symlink
3430  */
3431 LIBSSH2_API int
libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,char * target,unsigned int target_len,int link_type)3432 libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
3433                         unsigned int path_len, char *target,
3434                         unsigned int target_len, int link_type)
3435 {
3436     int rc;
3437     if(!sftp)
3438         return LIBSSH2_ERROR_BAD_USE;
3439     BLOCK_ADJUST(rc, sftp->channel->session,
3440                  sftp_symlink(sftp, path, path_len, target, target_len,
3441                               link_type));
3442     return rc;
3443 }
3444 
3445 /* libssh2_sftp_last_error
3446  * Returns the last error code reported by SFTP
3447  */
3448 LIBSSH2_API unsigned long
libssh2_sftp_last_error(LIBSSH2_SFTP * sftp)3449 libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
3450 {
3451     if(!sftp)
3452         return 0;
3453 
3454     return sftp->last_errno;
3455 }
3456 
3457 /* libssh2_sftp_get_channel
3458  * Return the channel of sftp, then caller can control the channel's behavior.
3459  */
3460 LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_sftp_get_channel(LIBSSH2_SFTP * sftp)3461 libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp)
3462 {
3463     if (!sftp)
3464         return NULL;
3465 
3466     return sftp->channel;
3467 }
3468