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