]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/sftp-client.c
libevent: Import libevent 2.1.12
[FreeBSD/FreeBSD.git] / crypto / openssh / sftp-client.c
1 /* $OpenBSD: sftp-client.c,v 1.174 2023/09/08 06:10:02 djm Exp $ */
2 /*
3  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* XXX: memleaks */
19 /* XXX: signed vs unsigned */
20 /* XXX: remove all logging, only return status codes */
21 /* XXX: copy between two remote sites */
22
23 #include "includes.h"
24
25 #include <sys/types.h>
26 #ifdef HAVE_SYS_STATVFS_H
27 #include <sys/statvfs.h>
28 #endif
29 #include "openbsd-compat/sys-queue.h"
30 #ifdef HAVE_SYS_STAT_H
31 # include <sys/stat.h>
32 #endif
33 #ifdef HAVE_SYS_TIME_H
34 # include <sys/time.h>
35 #endif
36 #include <sys/uio.h>
37
38 #include <dirent.h>
39 #include <errno.h>
40 #ifdef HAVE_POLL_H
41 #include <poll.h>
42 #else
43 # ifdef HAVE_SYS_POLL_H
44 #  include <sys/poll.h>
45 # endif
46 #endif
47 #include <fcntl.h>
48 #include <signal.h>
49 #include <stdarg.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54
55 #include "xmalloc.h"
56 #include "ssherr.h"
57 #include "sshbuf.h"
58 #include "log.h"
59 #include "atomicio.h"
60 #include "progressmeter.h"
61 #include "misc.h"
62 #include "utf8.h"
63
64 #include "sftp.h"
65 #include "sftp-common.h"
66 #include "sftp-client.h"
67
68 extern volatile sig_atomic_t interrupted;
69 extern int showprogress;
70
71 /* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */
72 #define DEFAULT_COPY_BUFLEN     32768
73
74 /* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */
75 #define DEFAULT_NUM_REQUESTS    64
76
77 /* Minimum amount of data to read at a time */
78 #define MIN_READ_SIZE   512
79
80 /* Maximum depth to descend in directory trees */
81 #define MAX_DIR_DEPTH 64
82
83 /* Directory separator characters */
84 #ifdef HAVE_CYGWIN
85 # define SFTP_DIRECTORY_CHARS      "/\\"
86 #else /* HAVE_CYGWIN */
87 # define SFTP_DIRECTORY_CHARS      "/"
88 #endif /* HAVE_CYGWIN */
89
90 struct sftp_conn {
91         int fd_in;
92         int fd_out;
93         u_int download_buflen;
94         u_int upload_buflen;
95         u_int num_requests;
96         u_int version;
97         u_int msg_id;
98 #define SFTP_EXT_POSIX_RENAME           0x00000001
99 #define SFTP_EXT_STATVFS                0x00000002
100 #define SFTP_EXT_FSTATVFS               0x00000004
101 #define SFTP_EXT_HARDLINK               0x00000008
102 #define SFTP_EXT_FSYNC                  0x00000010
103 #define SFTP_EXT_LSETSTAT               0x00000020
104 #define SFTP_EXT_LIMITS                 0x00000040
105 #define SFTP_EXT_PATH_EXPAND            0x00000080
106 #define SFTP_EXT_COPY_DATA              0x00000100
107 #define SFTP_EXT_GETUSERSGROUPS_BY_ID   0x00000200
108         u_int exts;
109         u_int64_t limit_kbps;
110         struct bwlimit bwlimit_in, bwlimit_out;
111 };
112
113 /* Tracks in-progress requests during file transfers */
114 struct request {
115         u_int id;
116         size_t len;
117         u_int64_t offset;
118         TAILQ_ENTRY(request) tq;
119 };
120 TAILQ_HEAD(requests, request);
121
122 static u_char *
123 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
124     const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
125
126 static struct request *
127 request_enqueue(struct requests *requests, u_int id, size_t len,
128     uint64_t offset)
129 {
130         struct request *req;
131
132         req = xcalloc(1, sizeof(*req));
133         req->id = id;
134         req->len = len;
135         req->offset = offset;
136         TAILQ_INSERT_TAIL(requests, req, tq);
137         return req;
138 }
139
140 static struct request *
141 request_find(struct requests *requests, u_int id)
142 {
143         struct request *req;
144
145         for (req = TAILQ_FIRST(requests);
146             req != NULL && req->id != id;
147             req = TAILQ_NEXT(req, tq))
148                 ;
149         return req;
150 }
151
152 static int
153 sftpio(void *_bwlimit, size_t amount)
154 {
155         struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
156
157         refresh_progress_meter(0);
158         if (bwlimit != NULL)
159                 bandwidth_limit(bwlimit, amount);
160         return 0;
161 }
162
163 static void
164 send_msg(struct sftp_conn *conn, struct sshbuf *m)
165 {
166         u_char mlen[4];
167         struct iovec iov[2];
168
169         if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
170                 fatal("Outbound message too long %zu", sshbuf_len(m));
171
172         /* Send length first */
173         put_u32(mlen, sshbuf_len(m));
174         iov[0].iov_base = mlen;
175         iov[0].iov_len = sizeof(mlen);
176         iov[1].iov_base = (u_char *)sshbuf_ptr(m);
177         iov[1].iov_len = sshbuf_len(m);
178
179         if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
180             conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
181             sshbuf_len(m) + sizeof(mlen))
182                 fatal("Couldn't send packet: %s", strerror(errno));
183
184         sshbuf_reset(m);
185 }
186
187 static void
188 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
189 {
190         u_int msg_len;
191         u_char *p;
192         int r;
193
194         sshbuf_reset(m);
195         if ((r = sshbuf_reserve(m, 4, &p)) != 0)
196                 fatal_fr(r, "reserve");
197         if (atomicio6(read, conn->fd_in, p, 4, sftpio,
198             conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
199                 if (errno == EPIPE || errno == ECONNRESET)
200                         fatal("Connection closed");
201                 else
202                         fatal("Couldn't read packet: %s", strerror(errno));
203         }
204
205         if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
206                 fatal_fr(r, "sshbuf_get_u32");
207         if (msg_len > SFTP_MAX_MSG_LENGTH) {
208                 do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
209                     "Received message too long %u", msg_len);
210                 fatal("Ensure the remote shell produces no output "
211                     "for non-interactive sessions.");
212         }
213
214         if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
215                 fatal_fr(r, "reserve");
216         if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
217             conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
218             != msg_len) {
219                 if (errno == EPIPE)
220                         fatal("Connection closed");
221                 else
222                         fatal("Read packet: %s", strerror(errno));
223         }
224 }
225
226 static void
227 get_msg(struct sftp_conn *conn, struct sshbuf *m)
228 {
229         get_msg_extended(conn, m, 0);
230 }
231
232 static void
233 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
234     u_int len)
235 {
236         struct sshbuf *msg;
237         int r;
238
239         if ((msg = sshbuf_new()) == NULL)
240                 fatal_f("sshbuf_new failed");
241         if ((r = sshbuf_put_u8(msg, code)) != 0 ||
242             (r = sshbuf_put_u32(msg, id)) != 0 ||
243             (r = sshbuf_put_string(msg, s, len)) != 0)
244                 fatal_fr(r, "compose");
245         send_msg(conn, msg);
246         debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
247         sshbuf_free(msg);
248 }
249
250 static void
251 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
252     const void *s, u_int len, Attrib *a)
253 {
254         struct sshbuf *msg;
255         int r;
256
257         if ((msg = sshbuf_new()) == NULL)
258                 fatal_f("sshbuf_new failed");
259         if ((r = sshbuf_put_u8(msg, code)) != 0 ||
260             (r = sshbuf_put_u32(msg, id)) != 0 ||
261             (r = sshbuf_put_string(msg, s, len)) != 0 ||
262             (r = encode_attrib(msg, a)) != 0)
263                 fatal_fr(r, "compose");
264         send_msg(conn, msg);
265         debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o",
266             conn->fd_out, code, id, a->flags, a->perm);
267         sshbuf_free(msg);
268 }
269
270 static u_int
271 get_status(struct sftp_conn *conn, u_int expected_id)
272 {
273         struct sshbuf *msg;
274         u_char type;
275         u_int id, status;
276         int r;
277
278         if ((msg = sshbuf_new()) == NULL)
279                 fatal_f("sshbuf_new failed");
280         get_msg(conn, msg);
281         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
282             (r = sshbuf_get_u32(msg, &id)) != 0)
283                 fatal_fr(r, "compose");
284
285         if (id != expected_id)
286                 fatal("ID mismatch (%u != %u)", id, expected_id);
287         if (type != SSH2_FXP_STATUS)
288                 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
289                     SSH2_FXP_STATUS, type);
290
291         if ((r = sshbuf_get_u32(msg, &status)) != 0)
292                 fatal_fr(r, "parse");
293         sshbuf_free(msg);
294
295         debug3("SSH2_FXP_STATUS %u", status);
296
297         return status;
298 }
299
300 static u_char *
301 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
302     const char *errfmt, ...)
303 {
304         struct sshbuf *msg;
305         u_int id, status;
306         u_char type;
307         u_char *handle;
308         char errmsg[256];
309         va_list args;
310         int r;
311
312         va_start(args, errfmt);
313         if (errfmt != NULL)
314                 vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
315         va_end(args);
316
317         if ((msg = sshbuf_new()) == NULL)
318                 fatal_f("sshbuf_new failed");
319         get_msg(conn, msg);
320         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
321             (r = sshbuf_get_u32(msg, &id)) != 0)
322                 fatal_fr(r, "parse");
323
324         if (id != expected_id)
325                 fatal("%s: ID mismatch (%u != %u)",
326                     errfmt == NULL ? __func__ : errmsg, id, expected_id);
327         if (type == SSH2_FXP_STATUS) {
328                 if ((r = sshbuf_get_u32(msg, &status)) != 0)
329                         fatal_fr(r, "parse status");
330                 if (errfmt != NULL)
331                         error("%s: %s", errmsg, fx2txt(status));
332                 sshbuf_free(msg);
333                 return(NULL);
334         } else if (type != SSH2_FXP_HANDLE)
335                 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
336                     errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
337
338         if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
339                 fatal_fr(r, "parse handle");
340         sshbuf_free(msg);
341
342         return handle;
343 }
344
345 static int
346 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a)
347 {
348         struct sshbuf *msg;
349         u_int id;
350         u_char type;
351         int r;
352         Attrib attr;
353
354         if (a != NULL)
355                 memset(a, '\0', sizeof(*a));
356         if ((msg = sshbuf_new()) == NULL)
357                 fatal_f("sshbuf_new failed");
358         get_msg(conn, msg);
359
360         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
361             (r = sshbuf_get_u32(msg, &id)) != 0)
362                 fatal_fr(r, "parse");
363
364         if (id != expected_id)
365                 fatal("ID mismatch (%u != %u)", id, expected_id);
366         if (type == SSH2_FXP_STATUS) {
367                 u_int status;
368
369                 if ((r = sshbuf_get_u32(msg, &status)) != 0)
370                         fatal_fr(r, "parse status");
371                 if (quiet)
372                         debug("stat remote: %s", fx2txt(status));
373                 else
374                         error("stat remote: %s", fx2txt(status));
375                 sshbuf_free(msg);
376                 return -1;
377         } else if (type != SSH2_FXP_ATTRS) {
378                 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
379                     SSH2_FXP_ATTRS, type);
380         }
381         if ((r = decode_attrib(msg, &attr)) != 0) {
382                 error_fr(r, "decode_attrib");
383                 sshbuf_free(msg);
384                 return -1;
385         }
386         /* success */
387         if (a != NULL)
388                 *a = attr;
389         debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o",
390             type, id, attr.flags, attr.perm);
391         sshbuf_free(msg);
392
393         return 0;
394 }
395
396 static int
397 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
398     u_int expected_id, int quiet)
399 {
400         struct sshbuf *msg;
401         u_char type;
402         u_int id;
403         u_int64_t flag;
404         int r;
405
406         if ((msg = sshbuf_new()) == NULL)
407                 fatal_f("sshbuf_new failed");
408         get_msg(conn, msg);
409
410         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
411             (r = sshbuf_get_u32(msg, &id)) != 0)
412                 fatal_fr(r, "parse");
413
414         debug3("Received statvfs reply T:%u I:%u", type, id);
415         if (id != expected_id)
416                 fatal("ID mismatch (%u != %u)", id, expected_id);
417         if (type == SSH2_FXP_STATUS) {
418                 u_int status;
419
420                 if ((r = sshbuf_get_u32(msg, &status)) != 0)
421                         fatal_fr(r, "parse status");
422                 if (quiet)
423                         debug("remote statvfs: %s", fx2txt(status));
424                 else
425                         error("remote statvfs: %s", fx2txt(status));
426                 sshbuf_free(msg);
427                 return -1;
428         } else if (type != SSH2_FXP_EXTENDED_REPLY) {
429                 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
430                     SSH2_FXP_EXTENDED_REPLY, type);
431         }
432
433         memset(st, 0, sizeof(*st));
434         if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
435             (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
436             (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
437             (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
438             (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
439             (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
440             (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
441             (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
442             (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
443             (r = sshbuf_get_u64(msg, &flag)) != 0 ||
444             (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
445                 fatal_fr(r, "parse statvfs");
446
447         st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
448         st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
449
450         sshbuf_free(msg);
451
452         return 0;
453 }
454
455 struct sftp_conn *
456 sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
457     u_int64_t limit_kbps)
458 {
459         u_char type;
460         struct sshbuf *msg;
461         struct sftp_conn *ret;
462         int r;
463
464         ret = xcalloc(1, sizeof(*ret));
465         ret->msg_id = 1;
466         ret->fd_in = fd_in;
467         ret->fd_out = fd_out;
468         ret->download_buflen = ret->upload_buflen =
469             transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN;
470         ret->num_requests =
471             num_requests ? num_requests : DEFAULT_NUM_REQUESTS;
472         ret->exts = 0;
473         ret->limit_kbps = 0;
474
475         if ((msg = sshbuf_new()) == NULL)
476                 fatal_f("sshbuf_new failed");
477         if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
478             (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
479                 fatal_fr(r, "parse");
480
481         send_msg(ret, msg);
482
483         get_msg_extended(ret, msg, 1);
484
485         /* Expecting a VERSION reply */
486         if ((r = sshbuf_get_u8(msg, &type)) != 0)
487                 fatal_fr(r, "parse type");
488         if (type != SSH2_FXP_VERSION) {
489                 error("Invalid packet back from SSH2_FXP_INIT (type %u)",
490                     type);
491                 sshbuf_free(msg);
492                 free(ret);
493                 return(NULL);
494         }
495         if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
496                 fatal_fr(r, "parse version");
497
498         debug2("Remote version: %u", ret->version);
499
500         /* Check for extensions */
501         while (sshbuf_len(msg) > 0) {
502                 char *name;
503                 u_char *value;
504                 size_t vlen;
505                 int known = 0;
506
507                 if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
508                     (r = sshbuf_get_string(msg, &value, &vlen)) != 0)
509                         fatal_fr(r, "parse extension");
510                 if (strcmp(name, "posix-rename@openssh.com") == 0 &&
511                     strcmp((char *)value, "1") == 0) {
512                         ret->exts |= SFTP_EXT_POSIX_RENAME;
513                         known = 1;
514                 } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
515                     strcmp((char *)value, "2") == 0) {
516                         ret->exts |= SFTP_EXT_STATVFS;
517                         known = 1;
518                 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
519                     strcmp((char *)value, "2") == 0) {
520                         ret->exts |= SFTP_EXT_FSTATVFS;
521                         known = 1;
522                 } else if (strcmp(name, "hardlink@openssh.com") == 0 &&
523                     strcmp((char *)value, "1") == 0) {
524                         ret->exts |= SFTP_EXT_HARDLINK;
525                         known = 1;
526                 } else if (strcmp(name, "fsync@openssh.com") == 0 &&
527                     strcmp((char *)value, "1") == 0) {
528                         ret->exts |= SFTP_EXT_FSYNC;
529                         known = 1;
530                 } else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
531                     strcmp((char *)value, "1") == 0) {
532                         ret->exts |= SFTP_EXT_LSETSTAT;
533                         known = 1;
534                 } else if (strcmp(name, "limits@openssh.com") == 0 &&
535                     strcmp((char *)value, "1") == 0) {
536                         ret->exts |= SFTP_EXT_LIMITS;
537                         known = 1;
538                 } else if (strcmp(name, "expand-path@openssh.com") == 0 &&
539                     strcmp((char *)value, "1") == 0) {
540                         ret->exts |= SFTP_EXT_PATH_EXPAND;
541                         known = 1;
542                 } else if (strcmp(name, "copy-data") == 0 &&
543                     strcmp((char *)value, "1") == 0) {
544                         ret->exts |= SFTP_EXT_COPY_DATA;
545                         known = 1;
546                 } else if (strcmp(name,
547                     "users-groups-by-id@openssh.com") == 0 &&
548                     strcmp((char *)value, "1") == 0) {
549                         ret->exts |= SFTP_EXT_GETUSERSGROUPS_BY_ID;
550                         known = 1;
551                 }
552                 if (known) {
553                         debug2("Server supports extension \"%s\" revision %s",
554                             name, value);
555                 } else {
556                         debug2("Unrecognised server extension \"%s\"", name);
557                 }
558                 free(name);
559                 free(value);
560         }
561
562         sshbuf_free(msg);
563
564         /* Query the server for its limits */
565         if (ret->exts & SFTP_EXT_LIMITS) {
566                 struct sftp_limits limits;
567                 if (sftp_get_limits(ret, &limits) != 0)
568                         fatal_f("limits failed");
569
570                 /* If the caller did not specify, find a good value */
571                 if (transfer_buflen == 0) {
572                         ret->download_buflen = MINIMUM(limits.read_length,
573                             SFTP_MAX_MSG_LENGTH - 1024);
574                         ret->upload_buflen = MINIMUM(limits.write_length,
575                             SFTP_MAX_MSG_LENGTH - 1024);
576                         ret->download_buflen = MAXIMUM(ret->download_buflen, 64);
577                         ret->upload_buflen = MAXIMUM(ret->upload_buflen, 64);
578                         debug3("server upload/download buffer sizes "
579                             "%llu / %llu; using %u / %u",
580                             (unsigned long long)limits.write_length,
581                             (unsigned long long)limits.read_length,
582                             ret->upload_buflen, ret->download_buflen);
583                 }
584
585                 /* Use the server limit to scale down our value only */
586                 if (num_requests == 0 && limits.open_handles) {
587                         ret->num_requests =
588                             MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles);
589                         if (ret->num_requests == 0)
590                                 ret->num_requests = 1;
591                         debug3("server handle limit %llu; using %u",
592                             (unsigned long long)limits.open_handles,
593                             ret->num_requests);
594                 }
595         }
596
597         /* Some filexfer v.0 servers don't support large packets */
598         if (ret->version == 0) {
599                 ret->download_buflen = MINIMUM(ret->download_buflen, 20480);
600                 ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480);
601         }
602
603         ret->limit_kbps = limit_kbps;
604         if (ret->limit_kbps > 0) {
605                 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
606                     ret->download_buflen);
607                 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
608                     ret->upload_buflen);
609         }
610
611         return ret;
612 }
613
614 u_int
615 sftp_proto_version(struct sftp_conn *conn)
616 {
617         return conn->version;
618 }
619
620 int
621 sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits)
622 {
623         u_int id, msg_id;
624         u_char type;
625         struct sshbuf *msg;
626         int r;
627
628         if ((conn->exts & SFTP_EXT_LIMITS) == 0) {
629                 error("Server does not support limits@openssh.com extension");
630                 return -1;
631         }
632
633         if ((msg = sshbuf_new()) == NULL)
634                 fatal_f("sshbuf_new failed");
635
636         id = conn->msg_id++;
637         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
638             (r = sshbuf_put_u32(msg, id)) != 0 ||
639             (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0)
640                 fatal_fr(r, "compose");
641         send_msg(conn, msg);
642         debug3("Sent message limits@openssh.com I:%u", id);
643
644         get_msg(conn, msg);
645
646         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
647             (r = sshbuf_get_u32(msg, &msg_id)) != 0)
648                 fatal_fr(r, "parse");
649
650         debug3("Received limits reply T:%u I:%u", type, msg_id);
651         if (id != msg_id)
652                 fatal("ID mismatch (%u != %u)", msg_id, id);
653         if (type != SSH2_FXP_EXTENDED_REPLY) {
654                 debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
655                     SSH2_FXP_EXTENDED_REPLY, type);
656                 /* Disable the limits extension */
657                 conn->exts &= ~SFTP_EXT_LIMITS;
658                 sshbuf_free(msg);
659                 return 0;
660         }
661
662         memset(limits, 0, sizeof(*limits));
663         if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 ||
664             (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 ||
665             (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 ||
666             (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0)
667                 fatal_fr(r, "parse limits");
668
669         sshbuf_free(msg);
670
671         return 0;
672 }
673
674 int
675 sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
676 {
677         u_int id, status;
678         struct sshbuf *msg;
679         int r;
680
681         if ((msg = sshbuf_new()) == NULL)
682                 fatal_f("sshbuf_new failed");
683
684         id = conn->msg_id++;
685         if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
686             (r = sshbuf_put_u32(msg, id)) != 0 ||
687             (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
688                 fatal_fr(r, "parse");
689         send_msg(conn, msg);
690         debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
691
692         status = get_status(conn, id);
693         if (status != SSH2_FX_OK)
694                 error("close remote: %s", fx2txt(status));
695
696         sshbuf_free(msg);
697
698         return status == SSH2_FX_OK ? 0 : -1;
699 }
700
701
702 static int
703 sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
704     SFTP_DIRENT ***dir)
705 {
706         struct sshbuf *msg;
707         u_int count, id, i, expected_id, ents = 0;
708         size_t handle_len;
709         u_char type, *handle;
710         int status = SSH2_FX_FAILURE;
711         int r;
712
713         if (dir)
714                 *dir = NULL;
715
716         id = conn->msg_id++;
717
718         if ((msg = sshbuf_new()) == NULL)
719                 fatal_f("sshbuf_new failed");
720         if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
721             (r = sshbuf_put_u32(msg, id)) != 0 ||
722             (r = sshbuf_put_cstring(msg, path)) != 0)
723                 fatal_fr(r, "compose OPENDIR");
724         send_msg(conn, msg);
725
726         handle = get_handle(conn, id, &handle_len,
727             "remote readdir(\"%s\")", path);
728         if (handle == NULL) {
729                 sshbuf_free(msg);
730                 return -1;
731         }
732
733         if (dir) {
734                 ents = 0;
735                 *dir = xcalloc(1, sizeof(**dir));
736                 (*dir)[0] = NULL;
737         }
738
739         for (; !interrupted;) {
740                 id = expected_id = conn->msg_id++;
741
742                 debug3("Sending SSH2_FXP_READDIR I:%u", id);
743
744                 sshbuf_reset(msg);
745                 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
746                     (r = sshbuf_put_u32(msg, id)) != 0 ||
747                     (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
748                         fatal_fr(r, "compose READDIR");
749                 send_msg(conn, msg);
750
751                 sshbuf_reset(msg);
752
753                 get_msg(conn, msg);
754
755                 if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
756                     (r = sshbuf_get_u32(msg, &id)) != 0)
757                         fatal_fr(r, "parse");
758
759                 debug3("Received reply T:%u I:%u", type, id);
760
761                 if (id != expected_id)
762                         fatal("ID mismatch (%u != %u)", id, expected_id);
763
764                 if (type == SSH2_FXP_STATUS) {
765                         u_int rstatus;
766
767                         if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
768                                 fatal_fr(r, "parse status");
769                         debug3("Received SSH2_FXP_STATUS %d", rstatus);
770                         if (rstatus == SSH2_FX_EOF)
771                                 break;
772                         error("Couldn't read directory: %s", fx2txt(rstatus));
773                         goto out;
774                 } else if (type != SSH2_FXP_NAME)
775                         fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
776                             SSH2_FXP_NAME, type);
777
778                 if ((r = sshbuf_get_u32(msg, &count)) != 0)
779                         fatal_fr(r, "parse count");
780                 if (count > SSHBUF_SIZE_MAX)
781                         fatal_f("nonsensical number of entries");
782                 if (count == 0)
783                         break;
784                 debug3("Received %d SSH2_FXP_NAME responses", count);
785                 for (i = 0; i < count; i++) {
786                         char *filename, *longname;
787                         Attrib a;
788
789                         if ((r = sshbuf_get_cstring(msg, &filename,
790                             NULL)) != 0 ||
791                             (r = sshbuf_get_cstring(msg, &longname,
792                             NULL)) != 0)
793                                 fatal_fr(r, "parse filenames");
794                         if ((r = decode_attrib(msg, &a)) != 0) {
795                                 error_fr(r, "couldn't decode attrib");
796                                 free(filename);
797                                 free(longname);
798                                 goto out;
799                         }
800
801                         if (print_flag)
802                                 mprintf("%s\n", longname);
803
804                         /*
805                          * Directory entries should never contain '/'
806                          * These can be used to attack recursive ops
807                          * (e.g. send '../../../../etc/passwd')
808                          */
809                         if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) {
810                                 error("Server sent suspect path \"%s\" "
811                                     "during readdir of \"%s\"", filename, path);
812                         } else if (dir) {
813                                 *dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
814                                 (*dir)[ents] = xcalloc(1, sizeof(***dir));
815                                 (*dir)[ents]->filename = xstrdup(filename);
816                                 (*dir)[ents]->longname = xstrdup(longname);
817                                 memcpy(&(*dir)[ents]->a, &a, sizeof(a));
818                                 (*dir)[++ents] = NULL;
819                         }
820                         free(filename);
821                         free(longname);
822                 }
823         }
824         status = 0;
825
826  out:
827         sshbuf_free(msg);
828         sftp_close(conn, handle, handle_len);
829         free(handle);
830
831         if (status != 0 && dir != NULL) {
832                 /* Don't return results on error */
833                 sftp_free_dirents(*dir);
834                 *dir = NULL;
835         } else if (interrupted && dir != NULL && *dir != NULL) {
836                 /* Don't return partial matches on interrupt */
837                 sftp_free_dirents(*dir);
838                 *dir = xcalloc(1, sizeof(**dir));
839                 **dir = NULL;
840         }
841
842         return status == SSH2_FX_OK ? 0 : -1;
843 }
844
845 int
846 sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
847 {
848         return sftp_lsreaddir(conn, path, 0, dir);
849 }
850
851 void sftp_free_dirents(SFTP_DIRENT **s)
852 {
853         int i;
854
855         if (s == NULL)
856                 return;
857         for (i = 0; s[i]; i++) {
858                 free(s[i]->filename);
859                 free(s[i]->longname);
860                 free(s[i]);
861         }
862         free(s);
863 }
864
865 int
866 sftp_rm(struct sftp_conn *conn, const char *path)
867 {
868         u_int status, id;
869
870         debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
871
872         id = conn->msg_id++;
873         send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
874         status = get_status(conn, id);
875         if (status != SSH2_FX_OK)
876                 error("remote delete %s: %s", path, fx2txt(status));
877         return status == SSH2_FX_OK ? 0 : -1;
878 }
879
880 int
881 sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
882 {
883         u_int status, id;
884
885         debug2("Sending SSH2_FXP_MKDIR \"%s\"", path);
886
887         id = conn->msg_id++;
888         send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
889             strlen(path), a);
890
891         status = get_status(conn, id);
892         if (status != SSH2_FX_OK && print_flag)
893                 error("remote mkdir \"%s\": %s", path, fx2txt(status));
894
895         return status == SSH2_FX_OK ? 0 : -1;
896 }
897
898 int
899 sftp_rmdir(struct sftp_conn *conn, const char *path)
900 {
901         u_int status, id;
902
903         debug2("Sending SSH2_FXP_RMDIR \"%s\"", path);
904
905         id = conn->msg_id++;
906         send_string_request(conn, id, SSH2_FXP_RMDIR, path,
907             strlen(path));
908
909         status = get_status(conn, id);
910         if (status != SSH2_FX_OK)
911                 error("remote rmdir \"%s\": %s", path, fx2txt(status));
912
913         return status == SSH2_FX_OK ? 0 : -1;
914 }
915
916 int
917 sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
918 {
919         u_int id;
920
921         debug2("Sending SSH2_FXP_STAT \"%s\"", path);
922
923         id = conn->msg_id++;
924
925         send_string_request(conn, id,
926             conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
927             path, strlen(path));
928
929         return get_decode_stat(conn, id, quiet, a);
930 }
931
932 int
933 sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
934 {
935         u_int id;
936
937         if (conn->version == 0) {
938                 do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
939                     "Server version does not support lstat operation");
940                 return sftp_stat(conn, path, quiet, a);
941         }
942
943         id = conn->msg_id++;
944         send_string_request(conn, id, SSH2_FXP_LSTAT, path,
945             strlen(path));
946
947         return get_decode_stat(conn, id, quiet, a);
948 }
949
950 #ifdef notyet
951 int
952 sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
953     int quiet, Attrib *a)
954 {
955         u_int id;
956
957         debug2("Sending SSH2_FXP_FSTAT \"%s\"");
958
959         id = conn->msg_id++;
960         send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
961             handle_len);
962
963         return get_decode_stat(conn, id, quiet, a);
964 }
965 #endif
966
967 int
968 sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
969 {
970         u_int status, id;
971
972         debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path);
973
974         id = conn->msg_id++;
975         send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
976             strlen(path), a);
977
978         status = get_status(conn, id);
979         if (status != SSH2_FX_OK)
980                 error("remote setstat \"%s\": %s", path, fx2txt(status));
981
982         return status == SSH2_FX_OK ? 0 : -1;
983 }
984
985 int
986 sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
987     Attrib *a)
988 {
989         u_int status, id;
990
991         debug2("Sending SSH2_FXP_FSETSTAT");
992
993         id = conn->msg_id++;
994         send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
995             handle_len, a);
996
997         status = get_status(conn, id);
998         if (status != SSH2_FX_OK)
999                 error("remote fsetstat: %s", fx2txt(status));
1000
1001         return status == SSH2_FX_OK ? 0 : -1;
1002 }
1003
1004 /* Implements both the realpath and expand-path operations */
1005 static char *
1006 sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
1007 {
1008         struct sshbuf *msg;
1009         u_int expected_id, count, id;
1010         char *filename, *longname;
1011         Attrib a;
1012         u_char type;
1013         int r;
1014         const char *what = "SSH2_FXP_REALPATH";
1015
1016         if (expand)
1017                 what = "expand-path@openssh.com";
1018         if ((msg = sshbuf_new()) == NULL)
1019                 fatal_f("sshbuf_new failed");
1020
1021         expected_id = id = conn->msg_id++;
1022         if (expand) {
1023                 debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) "
1024                     "\"%s\"", path);
1025                 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1026                     (r = sshbuf_put_u32(msg, id)) != 0 ||
1027                     (r = sshbuf_put_cstring(msg,
1028                     "expand-path@openssh.com")) != 0 ||
1029                     (r = sshbuf_put_cstring(msg, path)) != 0)
1030                         fatal_fr(r, "compose %s", what);
1031                 send_msg(conn, msg);
1032         } else {
1033                 debug2("Sending SSH2_FXP_REALPATH \"%s\"", path);
1034                 send_string_request(conn, id, SSH2_FXP_REALPATH,
1035                     path, strlen(path));
1036         }
1037         get_msg(conn, msg);
1038         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1039             (r = sshbuf_get_u32(msg, &id)) != 0)
1040                 fatal_fr(r, "parse");
1041
1042         if (id != expected_id)
1043                 fatal("ID mismatch (%u != %u)", id, expected_id);
1044
1045         if (type == SSH2_FXP_STATUS) {
1046                 u_int status;
1047                 char *errmsg;
1048
1049                 if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
1050                     (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
1051                         fatal_fr(r, "parse status");
1052                 error("%s %s: %s", expand ? "expand" : "realpath",
1053                     path, *errmsg == '\0' ? fx2txt(status) : errmsg);
1054                 free(errmsg);
1055                 sshbuf_free(msg);
1056                 return NULL;
1057         } else if (type != SSH2_FXP_NAME)
1058                 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1059                     SSH2_FXP_NAME, type);
1060
1061         if ((r = sshbuf_get_u32(msg, &count)) != 0)
1062                 fatal_fr(r, "parse count");
1063         if (count != 1)
1064                 fatal("Got multiple names (%d) from %s", count, what);
1065
1066         if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1067             (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1068             (r = decode_attrib(msg, &a)) != 0)
1069                 fatal_fr(r, "parse filename/attrib");
1070
1071         debug3("%s %s -> %s", what, path, filename);
1072
1073         free(longname);
1074
1075         sshbuf_free(msg);
1076
1077         return(filename);
1078 }
1079
1080 char *
1081 sftp_realpath(struct sftp_conn *conn, const char *path)
1082 {
1083         return sftp_realpath_expand(conn, path, 0);
1084 }
1085
1086 int
1087 sftp_can_expand_path(struct sftp_conn *conn)
1088 {
1089         return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0;
1090 }
1091
1092 char *
1093 sftp_expand_path(struct sftp_conn *conn, const char *path)
1094 {
1095         if (!sftp_can_expand_path(conn)) {
1096                 debug3_f("no server support, fallback to realpath");
1097                 return sftp_realpath_expand(conn, path, 0);
1098         }
1099         return sftp_realpath_expand(conn, path, 1);
1100 }
1101
1102 int
1103 sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1104 {
1105         Attrib junk, attr;
1106         struct sshbuf *msg;
1107         u_char *old_handle, *new_handle;
1108         u_int mode, status, id;
1109         size_t old_handle_len, new_handle_len;
1110         int r;
1111
1112         /* Return if the extension is not supported */
1113         if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) {
1114                 error("Server does not support copy-data extension");
1115                 return -1;
1116         }
1117
1118         /* Make sure the file exists, and we can copy its perms */
1119         if (sftp_stat(conn, oldpath, 0, &attr) != 0)
1120                 return -1;
1121
1122         /* Do not preserve set[ug]id here, as we do not preserve ownership */
1123         if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1124                 mode = attr.perm & 0777;
1125
1126                 if (!S_ISREG(attr.perm)) {
1127                         error("Cannot copy non-regular file: %s", oldpath);
1128                         return -1;
1129                 }
1130         } else {
1131                 /* NB: The user's umask will apply to this */
1132                 mode = 0666;
1133         }
1134
1135         /* Set up the new perms for the new file */
1136         attrib_clear(&attr);
1137         attr.perm = mode;
1138         attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1139
1140         if ((msg = sshbuf_new()) == NULL)
1141                 fatal("%s: sshbuf_new failed", __func__);
1142
1143         attrib_clear(&junk); /* Send empty attributes */
1144
1145         /* Open the old file for reading */
1146         id = conn->msg_id++;
1147         if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1148             (r = sshbuf_put_u32(msg, id)) != 0 ||
1149             (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1150             (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
1151             (r = encode_attrib(msg, &junk)) != 0)
1152                 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1153         send_msg(conn, msg);
1154         debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath);
1155
1156         sshbuf_reset(msg);
1157
1158         old_handle = get_handle(conn, id, &old_handle_len,
1159             "remote open(\"%s\")", oldpath);
1160         if (old_handle == NULL) {
1161                 sshbuf_free(msg);
1162                 return -1;
1163         }
1164
1165         /* Open the new file for writing */
1166         id = conn->msg_id++;
1167         if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1168             (r = sshbuf_put_u32(msg, id)) != 0 ||
1169             (r = sshbuf_put_cstring(msg, newpath)) != 0 ||
1170             (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1171             SSH2_FXF_TRUNC)) != 0 ||
1172             (r = encode_attrib(msg, &attr)) != 0)
1173                 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1174         send_msg(conn, msg);
1175         debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath);
1176
1177         sshbuf_reset(msg);
1178
1179         new_handle = get_handle(conn, id, &new_handle_len,
1180             "remote open(\"%s\")", newpath);
1181         if (new_handle == NULL) {
1182                 sshbuf_free(msg);
1183                 free(old_handle);
1184                 return -1;
1185         }
1186
1187         /* Copy the file data */
1188         id = conn->msg_id++;
1189         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1190             (r = sshbuf_put_u32(msg, id)) != 0 ||
1191             (r = sshbuf_put_cstring(msg, "copy-data")) != 0 ||
1192             (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 ||
1193             (r = sshbuf_put_u64(msg, 0)) != 0 ||
1194             (r = sshbuf_put_u64(msg, 0)) != 0 ||
1195             (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 ||
1196             (r = sshbuf_put_u64(msg, 0)) != 0)
1197                 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1198         send_msg(conn, msg);
1199         debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0",
1200                oldpath, newpath);
1201
1202         status = get_status(conn, id);
1203         if (status != SSH2_FX_OK)
1204                 error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath,
1205                     newpath, fx2txt(status));
1206
1207         /* Clean up everything */
1208         sshbuf_free(msg);
1209         sftp_close(conn, old_handle, old_handle_len);
1210         sftp_close(conn, new_handle, new_handle_len);
1211         free(old_handle);
1212         free(new_handle);
1213
1214         return status == SSH2_FX_OK ? 0 : -1;
1215 }
1216
1217 int
1218 sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
1219     int force_legacy)
1220 {
1221         struct sshbuf *msg;
1222         u_int status, id;
1223         int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
1224
1225         if ((msg = sshbuf_new()) == NULL)
1226                 fatal_f("sshbuf_new failed");
1227
1228         /* Send rename request */
1229         id = conn->msg_id++;
1230         if (use_ext) {
1231                 debug2("Sending SSH2_FXP_EXTENDED(posix-rename@openssh.com) "
1232                     "\"%s\" to \"%s\"", oldpath, newpath);
1233                 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1234                     (r = sshbuf_put_u32(msg, id)) != 0 ||
1235                     (r = sshbuf_put_cstring(msg,
1236                     "posix-rename@openssh.com")) != 0)
1237                         fatal_fr(r, "compose posix-rename");
1238         } else {
1239                 debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"",
1240                     oldpath, newpath);
1241                 if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
1242                     (r = sshbuf_put_u32(msg, id)) != 0)
1243                         fatal_fr(r, "compose rename");
1244         }
1245         if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1246             (r = sshbuf_put_cstring(msg, newpath)) != 0)
1247                 fatal_fr(r, "compose paths");
1248         send_msg(conn, msg);
1249         debug3("Sent message %s \"%s\" -> \"%s\"",
1250             use_ext ? "posix-rename@openssh.com" :
1251             "SSH2_FXP_RENAME", oldpath, newpath);
1252         sshbuf_free(msg);
1253
1254         status = get_status(conn, id);
1255         if (status != SSH2_FX_OK)
1256                 error("remote rename \"%s\" to \"%s\": %s", oldpath,
1257                     newpath, fx2txt(status));
1258
1259         return status == SSH2_FX_OK ? 0 : -1;
1260 }
1261
1262 int
1263 sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1264 {
1265         struct sshbuf *msg;
1266         u_int status, id;
1267         int r;
1268
1269         if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
1270                 error("Server does not support hardlink@openssh.com extension");
1271                 return -1;
1272         }
1273         debug2("Sending SSH2_FXP_EXTENDED(hardlink@openssh.com) "
1274             "\"%s\" to \"%s\"", oldpath, newpath);
1275
1276         if ((msg = sshbuf_new()) == NULL)
1277                 fatal_f("sshbuf_new failed");
1278
1279         /* Send link request */
1280         id = conn->msg_id++;
1281         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1282             (r = sshbuf_put_u32(msg, id)) != 0 ||
1283             (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
1284             (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1285             (r = sshbuf_put_cstring(msg, newpath)) != 0)
1286                 fatal_fr(r, "compose");
1287         send_msg(conn, msg);
1288         debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
1289             oldpath, newpath);
1290         sshbuf_free(msg);
1291
1292         status = get_status(conn, id);
1293         if (status != SSH2_FX_OK)
1294                 error("remote link \"%s\" to \"%s\": %s", oldpath,
1295                     newpath, fx2txt(status));
1296
1297         return status == SSH2_FX_OK ? 0 : -1;
1298 }
1299
1300 int
1301 sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1302 {
1303         struct sshbuf *msg;
1304         u_int status, id;
1305         int r;
1306
1307         if (conn->version < 3) {
1308                 error("This server does not support the symlink operation");
1309                 return(SSH2_FX_OP_UNSUPPORTED);
1310         }
1311         debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath);
1312
1313         if ((msg = sshbuf_new()) == NULL)
1314                 fatal_f("sshbuf_new failed");
1315
1316         /* Send symlink request */
1317         id = conn->msg_id++;
1318         if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
1319             (r = sshbuf_put_u32(msg, id)) != 0 ||
1320             (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1321             (r = sshbuf_put_cstring(msg, newpath)) != 0)
1322                 fatal_fr(r, "compose");
1323         send_msg(conn, msg);
1324         debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
1325             newpath);
1326         sshbuf_free(msg);
1327
1328         status = get_status(conn, id);
1329         if (status != SSH2_FX_OK)
1330                 error("remote symlink file \"%s\" to \"%s\": %s", oldpath,
1331                     newpath, fx2txt(status));
1332
1333         return status == SSH2_FX_OK ? 0 : -1;
1334 }
1335
1336 int
1337 sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
1338 {
1339         struct sshbuf *msg;
1340         u_int status, id;
1341         int r;
1342
1343         /* Silently return if the extension is not supported */
1344         if ((conn->exts & SFTP_EXT_FSYNC) == 0)
1345                 return -1;
1346         debug2("Sending SSH2_FXP_EXTENDED(fsync@openssh.com)");
1347
1348         /* Send fsync request */
1349         if ((msg = sshbuf_new()) == NULL)
1350                 fatal_f("sshbuf_new failed");
1351         id = conn->msg_id++;
1352         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1353             (r = sshbuf_put_u32(msg, id)) != 0 ||
1354             (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
1355             (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1356                 fatal_fr(r, "compose");
1357         send_msg(conn, msg);
1358         debug3("Sent message fsync@openssh.com I:%u", id);
1359         sshbuf_free(msg);
1360
1361         status = get_status(conn, id);
1362         if (status != SSH2_FX_OK)
1363                 error("remote fsync: %s", fx2txt(status));
1364
1365         return status == SSH2_FX_OK ? 0 : -1;
1366 }
1367
1368 #ifdef notyet
1369 char *
1370 sftp_readlink(struct sftp_conn *conn, const char *path)
1371 {
1372         struct sshbuf *msg;
1373         u_int expected_id, count, id;
1374         char *filename, *longname;
1375         Attrib a;
1376         u_char type;
1377         int r;
1378
1379         debug2("Sending SSH2_FXP_READLINK \"%s\"", path);
1380
1381         expected_id = id = conn->msg_id++;
1382         send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
1383
1384         if ((msg = sshbuf_new()) == NULL)
1385                 fatal_f("sshbuf_new failed");
1386
1387         get_msg(conn, msg);
1388         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1389             (r = sshbuf_get_u32(msg, &id)) != 0)
1390                 fatal_fr(r, "parse");
1391
1392         if (id != expected_id)
1393                 fatal("ID mismatch (%u != %u)", id, expected_id);
1394
1395         if (type == SSH2_FXP_STATUS) {
1396                 u_int status;
1397
1398                 if ((r = sshbuf_get_u32(msg, &status)) != 0)
1399                         fatal_fr(r, "parse status");
1400                 error("Couldn't readlink: %s", fx2txt(status));
1401                 sshbuf_free(msg);
1402                 return(NULL);
1403         } else if (type != SSH2_FXP_NAME)
1404                 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1405                     SSH2_FXP_NAME, type);
1406
1407         if ((r = sshbuf_get_u32(msg, &count)) != 0)
1408                 fatal_fr(r, "parse count");
1409         if (count != 1)
1410                 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
1411
1412         if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1413             (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1414             (r = decode_attrib(msg, &a)) != 0)
1415                 fatal_fr(r, "parse filenames/attrib");
1416
1417         debug3("SSH_FXP_READLINK %s -> %s", path, filename);
1418
1419         free(longname);
1420
1421         sshbuf_free(msg);
1422
1423         return filename;
1424 }
1425 #endif
1426
1427 int
1428 sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
1429     int quiet)
1430 {
1431         struct sshbuf *msg;
1432         u_int id;
1433         int r;
1434
1435         if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
1436                 error("Server does not support statvfs@openssh.com extension");
1437                 return -1;
1438         }
1439
1440         debug2("Sending SSH2_FXP_EXTENDED(statvfs@openssh.com) \"%s\"", path);
1441
1442         id = conn->msg_id++;
1443
1444         if ((msg = sshbuf_new()) == NULL)
1445                 fatal_f("sshbuf_new failed");
1446         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1447             (r = sshbuf_put_u32(msg, id)) != 0 ||
1448             (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
1449             (r = sshbuf_put_cstring(msg, path)) != 0)
1450                 fatal_fr(r, "compose");
1451         send_msg(conn, msg);
1452         sshbuf_free(msg);
1453
1454         return get_decode_statvfs(conn, st, id, quiet);
1455 }
1456
1457 #ifdef notyet
1458 int
1459 sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1460     struct sftp_statvfs *st, int quiet)
1461 {
1462         struct sshbuf *msg;
1463         u_int id;
1464
1465         if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
1466                 error("Server does not support fstatvfs@openssh.com extension");
1467                 return -1;
1468         }
1469
1470         debug2("Sending SSH2_FXP_EXTENDED(fstatvfs@openssh.com)");
1471
1472         id = conn->msg_id++;
1473
1474         if ((msg = sshbuf_new()) == NULL)
1475                 fatal_f("sshbuf_new failed");
1476         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1477             (r = sshbuf_put_u32(msg, id)) != 0 ||
1478             (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
1479             (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1480                 fatal_fr(r, "compose");
1481         send_msg(conn, msg);
1482         sshbuf_free(msg);
1483
1484         return get_decode_statvfs(conn, st, id, quiet);
1485 }
1486 #endif
1487
1488 int
1489 sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
1490 {
1491         struct sshbuf *msg;
1492         u_int status, id;
1493         int r;
1494
1495         if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
1496                 error("Server does not support lsetstat@openssh.com extension");
1497                 return -1;
1498         }
1499
1500         debug2("Sending SSH2_FXP_EXTENDED(lsetstat@openssh.com) \"%s\"", path);
1501
1502         id = conn->msg_id++;
1503         if ((msg = sshbuf_new()) == NULL)
1504                 fatal_f("sshbuf_new failed");
1505         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1506             (r = sshbuf_put_u32(msg, id)) != 0 ||
1507             (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
1508             (r = sshbuf_put_cstring(msg, path)) != 0 ||
1509             (r = encode_attrib(msg, a)) != 0)
1510                 fatal_fr(r, "compose");
1511         send_msg(conn, msg);
1512         sshbuf_free(msg);
1513
1514         status = get_status(conn, id);
1515         if (status != SSH2_FX_OK)
1516                 error("remote lsetstat \"%s\": %s", path, fx2txt(status));
1517
1518         return status == SSH2_FX_OK ? 0 : -1;
1519 }
1520
1521 static void
1522 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1523     u_int len, const u_char *handle, u_int handle_len)
1524 {
1525         struct sshbuf *msg;
1526         int r;
1527
1528         if ((msg = sshbuf_new()) == NULL)
1529                 fatal_f("sshbuf_new failed");
1530         if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
1531             (r = sshbuf_put_u32(msg, id)) != 0 ||
1532             (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
1533             (r = sshbuf_put_u64(msg, offset)) != 0 ||
1534             (r = sshbuf_put_u32(msg, len)) != 0)
1535                 fatal_fr(r, "compose");
1536         send_msg(conn, msg);
1537         sshbuf_free(msg);
1538 }
1539
1540 static int
1541 send_open(struct sftp_conn *conn, const char *path, const char *tag,
1542     u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp)
1543 {
1544         Attrib junk;
1545         u_char *handle;
1546         size_t handle_len;
1547         struct sshbuf *msg;
1548         int r;
1549         u_int id;
1550
1551         debug2("Sending SSH2_FXP_OPEN \"%s\"", path);
1552
1553         *handlep = NULL;
1554         *handle_lenp = 0;
1555
1556         if (a == NULL) {
1557                 attrib_clear(&junk); /* Send empty attributes */
1558                 a = &junk;
1559         }
1560         /* Send open request */
1561         if ((msg = sshbuf_new()) == NULL)
1562                 fatal_f("sshbuf_new failed");
1563         id = conn->msg_id++;
1564         if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1565             (r = sshbuf_put_u32(msg, id)) != 0 ||
1566             (r = sshbuf_put_cstring(msg, path)) != 0 ||
1567             (r = sshbuf_put_u32(msg, openmode)) != 0 ||
1568             (r = encode_attrib(msg, a)) != 0)
1569                 fatal_fr(r, "compose %s open", tag);
1570         send_msg(conn, msg);
1571         sshbuf_free(msg);
1572         debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x",
1573             tag, id, path, openmode);
1574         if ((handle = get_handle(conn, id, &handle_len,
1575             "%s open \"%s\"", tag, path)) == NULL)
1576                 return -1;
1577         /* success */
1578         *handlep = handle;
1579         *handle_lenp = handle_len;
1580         return 0;
1581 }
1582
1583 static const char *
1584 progress_meter_path(const char *path)
1585 {
1586         const char *progresspath;
1587
1588         if ((progresspath = strrchr(path, '/')) == NULL)
1589                 return path;
1590         progresspath++;
1591         if (*progresspath == '\0')
1592                 return path;
1593         return progresspath;
1594 }
1595
1596 int
1597 sftp_download(struct sftp_conn *conn, const char *remote_path,
1598     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
1599     int fsync_flag, int inplace_flag)
1600 {
1601         struct sshbuf *msg;
1602         u_char *handle;
1603         int local_fd = -1, write_error;
1604         int read_error, write_errno, lmodified = 0, reordered = 0, r;
1605         u_int64_t offset = 0, size, highwater = 0, maxack = 0;
1606         u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
1607         off_t progress_counter;
1608         size_t handle_len;
1609         struct stat st;
1610         struct requests requests;
1611         struct request *req;
1612         u_char type;
1613         Attrib attr;
1614
1615         debug2_f("download remote \"%s\" to local \"%s\"",
1616             remote_path, local_path);
1617
1618         TAILQ_INIT(&requests);
1619
1620         if (a == NULL) {
1621                 if (sftp_stat(conn, remote_path, 0, &attr) != 0)
1622                         return -1;
1623                 a = &attr;
1624         }
1625
1626         /* Do not preserve set[ug]id here, as we do not preserve ownership */
1627         if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
1628                 mode = a->perm & 0777;
1629         else
1630                 mode = 0666;
1631
1632         if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
1633             (!S_ISREG(a->perm))) {
1634                 error("download %s: not a regular file", remote_path);
1635                 return(-1);
1636         }
1637
1638         if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
1639                 size = a->size;
1640         else
1641                 size = 0;
1642
1643         buflen = conn->download_buflen;
1644
1645         /* Send open request */
1646         if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL,
1647             &handle, &handle_len) != 0)
1648                 return -1;
1649
1650         local_fd = open(local_path, O_WRONLY | O_CREAT |
1651         ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR);
1652         if (local_fd == -1) {
1653                 error("open local \"%s\": %s", local_path, strerror(errno));
1654                 goto fail;
1655         }
1656         if (resume_flag) {
1657                 if (fstat(local_fd, &st) == -1) {
1658                         error("stat local \"%s\": %s",
1659                             local_path, strerror(errno));
1660                         goto fail;
1661                 }
1662                 if (st.st_size < 0) {
1663                         error("\"%s\" has negative size", local_path);
1664                         goto fail;
1665                 }
1666                 if ((u_int64_t)st.st_size > size) {
1667                         error("Unable to resume download of \"%s\": "
1668                             "local file is larger than remote", local_path);
1669  fail:
1670                         sftp_close(conn, handle, handle_len);
1671                         free(handle);
1672                         if (local_fd != -1)
1673                                 close(local_fd);
1674                         return -1;
1675                 }
1676                 offset = highwater = maxack = st.st_size;
1677         }
1678
1679         /* Read from remote and write to local */
1680         write_error = read_error = write_errno = num_req = 0;
1681         max_req = 1;
1682         progress_counter = offset;
1683
1684         if (showprogress && size != 0) {
1685                 start_progress_meter(progress_meter_path(remote_path),
1686                     size, &progress_counter);
1687         }
1688
1689         if ((msg = sshbuf_new()) == NULL)
1690                 fatal_f("sshbuf_new failed");
1691
1692         while (num_req > 0 || max_req > 0) {
1693                 u_char *data;
1694                 size_t len;
1695
1696                 /*
1697                  * Simulate EOF on interrupt: stop sending new requests and
1698                  * allow outstanding requests to drain gracefully
1699                  */
1700                 if (interrupted) {
1701                         if (num_req == 0) /* If we haven't started yet... */
1702                                 break;
1703                         max_req = 0;
1704                 }
1705
1706                 /* Send some more requests */
1707                 while (num_req < max_req) {
1708                         debug3("Request range %llu -> %llu (%d/%d)",
1709                             (unsigned long long)offset,
1710                             (unsigned long long)offset + buflen - 1,
1711                             num_req, max_req);
1712                         req = request_enqueue(&requests, conn->msg_id++,
1713                             buflen, offset);
1714                         offset += buflen;
1715                         num_req++;
1716                         send_read_request(conn, req->id, req->offset,
1717                             req->len, handle, handle_len);
1718                 }
1719
1720                 sshbuf_reset(msg);
1721                 get_msg(conn, msg);
1722                 if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1723                     (r = sshbuf_get_u32(msg, &id)) != 0)
1724                         fatal_fr(r, "parse");
1725                 debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
1726
1727                 /* Find the request in our queue */
1728                 if ((req = request_find(&requests, id)) == NULL)
1729                         fatal("Unexpected reply %u", id);
1730
1731                 switch (type) {
1732                 case SSH2_FXP_STATUS:
1733                         if ((r = sshbuf_get_u32(msg, &status)) != 0)
1734                                 fatal_fr(r, "parse status");
1735                         if (status != SSH2_FX_EOF)
1736                                 read_error = 1;
1737                         max_req = 0;
1738                         TAILQ_REMOVE(&requests, req, tq);
1739                         free(req);
1740                         num_req--;
1741                         break;
1742                 case SSH2_FXP_DATA:
1743                         if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
1744                                 fatal_fr(r, "parse data");
1745                         debug3("Received data %llu -> %llu",
1746                             (unsigned long long)req->offset,
1747                             (unsigned long long)req->offset + len - 1);
1748                         if (len > req->len)
1749                                 fatal("Received more data than asked for "
1750                                     "%zu > %zu", len, req->len);
1751                         lmodified = 1;
1752                         if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
1753                             atomicio(vwrite, local_fd, data, len) != len) &&
1754                             !write_error) {
1755                                 write_errno = errno;
1756                                 write_error = 1;
1757                                 max_req = 0;
1758                         } else {
1759                                 /*
1760                                  * Track both the highest offset acknowledged
1761                                  * and the highest *contiguous* offset
1762                                  * acknowledged.
1763                                  * We'll need the latter for ftruncate()ing
1764                                  * interrupted transfers.
1765                                  */
1766                                 if (maxack < req->offset + len)
1767                                         maxack = req->offset + len;
1768                                 if (!reordered && req->offset <= highwater)
1769                                         highwater = maxack;
1770                                 else if (!reordered && req->offset > highwater)
1771                                         reordered = 1;
1772                         }
1773                         progress_counter += len;
1774                         free(data);
1775
1776                         if (len == req->len) {
1777                                 TAILQ_REMOVE(&requests, req, tq);
1778                                 free(req);
1779                                 num_req--;
1780                         } else {
1781                                 /* Resend the request for the missing data */
1782                                 debug3("Short data block, re-requesting "
1783                                     "%llu -> %llu (%2d)",
1784                                     (unsigned long long)req->offset + len,
1785                                     (unsigned long long)req->offset +
1786                                     req->len - 1, num_req);
1787                                 req->id = conn->msg_id++;
1788                                 req->len -= len;
1789                                 req->offset += len;
1790                                 send_read_request(conn, req->id,
1791                                     req->offset, req->len, handle, handle_len);
1792                                 /* Reduce the request size */
1793                                 if (len < buflen)
1794                                         buflen = MAXIMUM(MIN_READ_SIZE, len);
1795                         }
1796                         if (max_req > 0) { /* max_req = 0 iff EOF received */
1797                                 if (size > 0 && offset > size) {
1798                                         /* Only one request at a time
1799                                          * after the expected EOF */
1800                                         debug3("Finish at %llu (%2d)",
1801                                             (unsigned long long)offset,
1802                                             num_req);
1803                                         max_req = 1;
1804                                 } else if (max_req < conn->num_requests) {
1805                                         ++max_req;
1806                                 }
1807                         }
1808                         break;
1809                 default:
1810                         fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
1811                             SSH2_FXP_DATA, type);
1812                 }
1813         }
1814
1815         if (showprogress && size)
1816                 stop_progress_meter();
1817
1818         /* Sanity check */
1819         if (TAILQ_FIRST(&requests) != NULL)
1820                 fatal("Transfer complete, but requests still in queue");
1821
1822         if (!read_error && !write_error && !interrupted) {
1823                 /* we got everything */
1824                 highwater = maxack;
1825         }
1826
1827         /*
1828          * Truncate at highest contiguous point to avoid holes on interrupt,
1829          * or unconditionally if writing in place.
1830          */
1831         if (inplace_flag || read_error || write_error || interrupted) {
1832                 if (reordered && resume_flag &&
1833                     (read_error || write_error || interrupted)) {
1834                         error("Unable to resume download of \"%s\": "
1835                             "server reordered requests", local_path);
1836                 }
1837                 debug("truncating at %llu", (unsigned long long)highwater);
1838                 if (ftruncate(local_fd, highwater) == -1)
1839                         error("local ftruncate \"%s\": %s", local_path,
1840                             strerror(errno));
1841         }
1842         if (read_error) {
1843                 error("read remote \"%s\" : %s", remote_path, fx2txt(status));
1844                 status = -1;
1845                 sftp_close(conn, handle, handle_len);
1846         } else if (write_error) {
1847                 error("write local \"%s\": %s", local_path,
1848                     strerror(write_errno));
1849                 status = SSH2_FX_FAILURE;
1850                 sftp_close(conn, handle, handle_len);
1851         } else {
1852                 if (sftp_close(conn, handle, handle_len) != 0 || interrupted)
1853                         status = SSH2_FX_FAILURE;
1854                 else
1855                         status = SSH2_FX_OK;
1856                 /* Override umask and utimes if asked */
1857 #ifdef HAVE_FCHMOD
1858                 if (preserve_flag && fchmod(local_fd, mode) == -1)
1859 #else
1860                 if (preserve_flag && chmod(local_path, mode) == -1)
1861 #endif /* HAVE_FCHMOD */
1862                         error("local chmod \"%s\": %s", local_path,
1863                             strerror(errno));
1864                 if (preserve_flag &&
1865                     (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1866                         struct timeval tv[2];
1867                         tv[0].tv_sec = a->atime;
1868                         tv[1].tv_sec = a->mtime;
1869                         tv[0].tv_usec = tv[1].tv_usec = 0;
1870                         if (utimes(local_path, tv) == -1)
1871                                 error("local set times \"%s\": %s",
1872                                     local_path, strerror(errno));
1873                 }
1874                 if (resume_flag && !lmodified)
1875                         logit("File \"%s\" was not modified", local_path);
1876                 else if (fsync_flag) {
1877                         debug("syncing \"%s\"", local_path);
1878                         if (fsync(local_fd) == -1)
1879                                 error("local sync \"%s\": %s",
1880                                     local_path, strerror(errno));
1881                 }
1882         }
1883         close(local_fd);
1884         sshbuf_free(msg);
1885         free(handle);
1886
1887         return status == SSH2_FX_OK ? 0 : -1;
1888 }
1889
1890 static int
1891 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1892     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
1893     int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag)
1894 {
1895         int i, ret = 0;
1896         SFTP_DIRENT **dir_entries;
1897         char *filename, *new_src = NULL, *new_dst = NULL;
1898         mode_t mode = 0777, tmpmode = mode;
1899         Attrib *a, ldirattrib, lsym;
1900
1901         if (depth >= MAX_DIR_DEPTH) {
1902                 error("Maximum directory depth exceeded: %d levels", depth);
1903                 return -1;
1904         }
1905
1906         debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst);
1907
1908         if (dirattrib == NULL) {
1909                 if (sftp_stat(conn, src, 1, &ldirattrib) != 0) {
1910                         error("stat remote \"%s\" directory failed", src);
1911                         return -1;
1912                 }
1913                 dirattrib = &ldirattrib;
1914         }
1915         if (!S_ISDIR(dirattrib->perm)) {
1916                 error("\"%s\" is not a directory", src);
1917                 return -1;
1918         }
1919         if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
1920                 mprintf("Retrieving %s\n", src);
1921
1922         if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1923                 mode = dirattrib->perm & 01777;
1924                 tmpmode = mode | (S_IWUSR|S_IXUSR);
1925         } else {
1926                 debug("download remote \"%s\": server "
1927                     "did not send permissions", dst);
1928         }
1929
1930         if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) {
1931                 error("mkdir %s: %s", dst, strerror(errno));
1932                 return -1;
1933         }
1934
1935         if (sftp_readdir(conn, src, &dir_entries) == -1) {
1936                 error("remote readdir \"%s\" failed", src);
1937                 return -1;
1938         }
1939
1940         for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
1941                 free(new_dst);
1942                 free(new_src);
1943
1944                 filename = dir_entries[i]->filename;
1945                 new_dst = sftp_path_append(dst, filename);
1946                 new_src = sftp_path_append(src, filename);
1947
1948                 a = &dir_entries[i]->a;
1949                 if (S_ISLNK(a->perm)) {
1950                         if (!follow_link_flag) {
1951                                 logit("download \"%s\": not a regular file",
1952                                     new_src);
1953                                 continue;
1954                         }
1955                         /* Replace the stat contents with the symlink target */
1956                         if (sftp_stat(conn, new_src, 1, &lsym) != 0) {
1957                                 logit("remote stat \"%s\" failed", new_src);
1958                                 ret = -1;
1959                                 continue;
1960                         }
1961                         a = &lsym;
1962                 }
1963
1964                 if (S_ISDIR(a->perm)) {
1965                         if (strcmp(filename, ".") == 0 ||
1966                             strcmp(filename, "..") == 0)
1967                                 continue;
1968                         if (download_dir_internal(conn, new_src, new_dst,
1969                             depth + 1, a, preserve_flag,
1970                             print_flag, resume_flag,
1971                             fsync_flag, follow_link_flag, inplace_flag) == -1)
1972                                 ret = -1;
1973                 } else if (S_ISREG(a->perm)) {
1974                         if (sftp_download(conn, new_src, new_dst, a,
1975                             preserve_flag, resume_flag, fsync_flag,
1976                             inplace_flag) == -1) {
1977                                 error("Download of file %s to %s failed",
1978                                     new_src, new_dst);
1979                                 ret = -1;
1980                         }
1981                 } else
1982                         logit("download \"%s\": not a regular file", new_src);
1983
1984         }
1985         free(new_dst);
1986         free(new_src);
1987
1988         if (preserve_flag) {
1989                 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1990                         struct timeval tv[2];
1991                         tv[0].tv_sec = dirattrib->atime;
1992                         tv[1].tv_sec = dirattrib->mtime;
1993                         tv[0].tv_usec = tv[1].tv_usec = 0;
1994                         if (utimes(dst, tv) == -1)
1995                                 error("local set times on \"%s\": %s",
1996                                     dst, strerror(errno));
1997                 } else
1998                         debug("Server did not send times for directory "
1999                             "\"%s\"", dst);
2000         }
2001
2002         if (mode != tmpmode && chmod(dst, mode) == -1)
2003                 error("local chmod directory \"%s\": %s", dst,
2004                     strerror(errno));
2005
2006         sftp_free_dirents(dir_entries);
2007
2008         return ret;
2009 }
2010
2011 int
2012 sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst,
2013     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
2014     int fsync_flag, int follow_link_flag, int inplace_flag)
2015 {
2016         char *src_canon;
2017         int ret;
2018
2019         if ((src_canon = sftp_realpath(conn, src)) == NULL) {
2020                 error("download \"%s\": path canonicalization failed", src);
2021                 return -1;
2022         }
2023
2024         ret = download_dir_internal(conn, src_canon, dst, 0,
2025             dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag,
2026             follow_link_flag, inplace_flag);
2027         free(src_canon);
2028         return ret;
2029 }
2030
2031 int
2032 sftp_upload(struct sftp_conn *conn, const char *local_path,
2033     const char *remote_path, int preserve_flag, int resume,
2034     int fsync_flag, int inplace_flag)
2035 {
2036         int r, local_fd;
2037         u_int openmode, id, status = SSH2_FX_OK, reordered = 0;
2038         off_t offset, progress_counter;
2039         u_char type, *handle, *data;
2040         struct sshbuf *msg;
2041         struct stat sb;
2042         Attrib a, t, c;
2043         u_int32_t startid, ackid;
2044         u_int64_t highwater = 0, maxack = 0;
2045         struct request *ack = NULL;
2046         struct requests acks;
2047         size_t handle_len;
2048
2049         debug2_f("upload local \"%s\" to remote \"%s\"",
2050             local_path, remote_path);
2051
2052         TAILQ_INIT(&acks);
2053
2054         if ((local_fd = open(local_path, O_RDONLY)) == -1) {
2055                 error("open local \"%s\": %s", local_path, strerror(errno));
2056                 return(-1);
2057         }
2058         if (fstat(local_fd, &sb) == -1) {
2059                 error("fstat local \"%s\": %s", local_path, strerror(errno));
2060                 close(local_fd);
2061                 return(-1);
2062         }
2063         if (!S_ISREG(sb.st_mode)) {
2064                 error("local \"%s\" is not a regular file", local_path);
2065                 close(local_fd);
2066                 return(-1);
2067         }
2068         stat_to_attrib(&sb, &a);
2069
2070         a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2071         a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2072         a.perm &= 0777;
2073         if (!preserve_flag)
2074                 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
2075
2076         if (resume) {
2077                 /* Get remote file size if it exists */
2078                 if (sftp_stat(conn, remote_path, 0, &c) != 0) {
2079                         close(local_fd);
2080                         return -1;
2081                 }
2082
2083                 if ((off_t)c.size >= sb.st_size) {
2084                         error("resume \"%s\": destination file "
2085                             "same size or larger", local_path);
2086                         close(local_fd);
2087                         return -1;
2088                 }
2089
2090                 if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) {
2091                         close(local_fd);
2092                         return -1;
2093                 }
2094         }
2095
2096         openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT;
2097         if (resume)
2098                 openmode |= SSH2_FXF_APPEND;
2099         else if (!inplace_flag)
2100                 openmode |= SSH2_FXF_TRUNC;
2101
2102         /* Send open request */
2103         if (send_open(conn, remote_path, "dest", openmode, &a,
2104             &handle, &handle_len) != 0) {
2105                 close(local_fd);
2106                 return -1;
2107         }
2108
2109         id = conn->msg_id;
2110         startid = ackid = id + 1;
2111         data = xmalloc(conn->upload_buflen);
2112
2113         /* Read from local and write to remote */
2114         offset = progress_counter = (resume ? c.size : 0);
2115         if (showprogress) {
2116                 start_progress_meter(progress_meter_path(local_path),
2117                     sb.st_size, &progress_counter);
2118         }
2119
2120         if ((msg = sshbuf_new()) == NULL)
2121                 fatal_f("sshbuf_new failed");
2122         for (;;) {
2123                 int len;
2124
2125                 /*
2126                  * Can't use atomicio here because it returns 0 on EOF,
2127                  * thus losing the last block of the file.
2128                  * Simulate an EOF on interrupt, allowing ACKs from the
2129                  * server to drain.
2130                  */
2131                 if (interrupted || status != SSH2_FX_OK)
2132                         len = 0;
2133                 else do
2134                         len = read(local_fd, data, conn->upload_buflen);
2135                 while ((len == -1) &&
2136                     (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
2137
2138                 if (len == -1) {
2139                         fatal("read local \"%s\": %s",
2140                             local_path, strerror(errno));
2141                 } else if (len != 0) {
2142                         ack = request_enqueue(&acks, ++id, len, offset);
2143                         sshbuf_reset(msg);
2144                         if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
2145                             (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
2146                             (r = sshbuf_put_string(msg, handle,
2147                             handle_len)) != 0 ||
2148                             (r = sshbuf_put_u64(msg, offset)) != 0 ||
2149                             (r = sshbuf_put_string(msg, data, len)) != 0)
2150                                 fatal_fr(r, "compose");
2151                         send_msg(conn, msg);
2152                         debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
2153                             id, (unsigned long long)offset, len);
2154                 } else if (TAILQ_FIRST(&acks) == NULL)
2155                         break;
2156
2157                 if (ack == NULL)
2158                         fatal("Unexpected ACK %u", id);
2159
2160                 if (id == startid || len == 0 ||
2161                     id - ackid >= conn->num_requests) {
2162                         u_int rid;
2163
2164                         sshbuf_reset(msg);
2165                         get_msg(conn, msg);
2166                         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2167                             (r = sshbuf_get_u32(msg, &rid)) != 0)
2168                                 fatal_fr(r, "parse");
2169
2170                         if (type != SSH2_FXP_STATUS)
2171                                 fatal("Expected SSH2_FXP_STATUS(%d) packet, "
2172                                     "got %d", SSH2_FXP_STATUS, type);
2173
2174                         if ((r = sshbuf_get_u32(msg, &status)) != 0)
2175                                 fatal_fr(r, "parse status");
2176                         debug3("SSH2_FXP_STATUS %u", status);
2177
2178                         /* Find the request in our queue */
2179                         if ((ack = request_find(&acks, rid)) == NULL)
2180                                 fatal("Can't find request for ID %u", rid);
2181                         TAILQ_REMOVE(&acks, ack, tq);
2182                         debug3("In write loop, ack for %u %zu bytes at %lld",
2183                             ack->id, ack->len, (unsigned long long)ack->offset);
2184                         ++ackid;
2185                         progress_counter += ack->len;
2186                         /*
2187                          * Track both the highest offset acknowledged and the
2188                          * highest *contiguous* offset acknowledged.
2189                          * We'll need the latter for ftruncate()ing
2190                          * interrupted transfers.
2191                          */
2192                         if (maxack < ack->offset + ack->len)
2193                                 maxack = ack->offset + ack->len;
2194                         if (!reordered && ack->offset <= highwater)
2195                                 highwater = maxack;
2196                         else if (!reordered && ack->offset > highwater) {
2197                                 debug3_f("server reordered ACKs");
2198                                 reordered = 1;
2199                         }
2200                         free(ack);
2201                 }
2202                 offset += len;
2203                 if (offset < 0)
2204                         fatal_f("offset < 0");
2205         }
2206         sshbuf_free(msg);
2207
2208         if (showprogress)
2209                 stop_progress_meter();
2210         free(data);
2211
2212         if (status == SSH2_FX_OK && !interrupted) {
2213                 /* we got everything */
2214                 highwater = maxack;
2215         }
2216         if (status != SSH2_FX_OK) {
2217                 error("write remote \"%s\": %s", remote_path, fx2txt(status));
2218                 status = SSH2_FX_FAILURE;
2219         }
2220
2221         if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) {
2222                 debug("truncating at %llu", (unsigned long long)highwater);
2223                 attrib_clear(&t);
2224                 t.flags = SSH2_FILEXFER_ATTR_SIZE;
2225                 t.size = highwater;
2226                 sftp_fsetstat(conn, handle, handle_len, &t);
2227         }
2228
2229         if (close(local_fd) == -1) {
2230                 error("close local \"%s\": %s", local_path, strerror(errno));
2231                 status = SSH2_FX_FAILURE;
2232         }
2233
2234         /* Override umask and utimes if asked */
2235         if (preserve_flag)
2236                 sftp_fsetstat(conn, handle, handle_len, &a);
2237
2238         if (fsync_flag)
2239                 (void)sftp_fsync(conn, handle, handle_len);
2240
2241         if (sftp_close(conn, handle, handle_len) != 0)
2242                 status = SSH2_FX_FAILURE;
2243
2244         free(handle);
2245
2246         return status == SSH2_FX_OK ? 0 : -1;
2247 }
2248
2249 static int
2250 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
2251     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag,
2252     int follow_link_flag, int inplace_flag)
2253 {
2254         int ret = 0;
2255         DIR *dirp;
2256         struct dirent *dp;
2257         char *filename, *new_src = NULL, *new_dst = NULL;
2258         struct stat sb;
2259         Attrib a, dirattrib;
2260         u_int32_t saved_perm;
2261
2262         debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst);
2263
2264         if (depth >= MAX_DIR_DEPTH) {
2265                 error("Maximum directory depth exceeded: %d levels", depth);
2266                 return -1;
2267         }
2268
2269         if (stat(src, &sb) == -1) {
2270                 error("stat local \"%s\": %s", src, strerror(errno));
2271                 return -1;
2272         }
2273         if (!S_ISDIR(sb.st_mode)) {
2274                 error("\"%s\" is not a directory", src);
2275                 return -1;
2276         }
2277         if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
2278                 mprintf("Entering %s\n", src);
2279
2280         stat_to_attrib(&sb, &a);
2281         a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2282         a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2283         a.perm &= 01777;
2284         if (!preserve_flag)
2285                 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
2286
2287         /*
2288          * sftp lacks a portable status value to match errno EEXIST,
2289          * so if we get a failure back then we must check whether
2290          * the path already existed and is a directory.  Ensure we can
2291          * write to the directory we create for the duration of the transfer.
2292          */
2293         saved_perm = a.perm;
2294         a.perm |= (S_IWUSR|S_IXUSR);
2295         if (sftp_mkdir(conn, dst, &a, 0) != 0) {
2296                 if (sftp_stat(conn, dst, 0, &dirattrib) != 0)
2297                         return -1;
2298                 if (!S_ISDIR(dirattrib.perm)) {
2299                         error("\"%s\" exists but is not a directory", dst);
2300                         return -1;
2301                 }
2302         }
2303         a.perm = saved_perm;
2304
2305         if ((dirp = opendir(src)) == NULL) {
2306                 error("local opendir \"%s\": %s", src, strerror(errno));
2307                 return -1;
2308         }
2309
2310         while (((dp = readdir(dirp)) != NULL) && !interrupted) {
2311                 if (dp->d_ino == 0)
2312                         continue;
2313                 free(new_dst);
2314                 free(new_src);
2315                 filename = dp->d_name;
2316                 new_dst = sftp_path_append(dst, filename);
2317                 new_src = sftp_path_append(src, filename);
2318
2319                 if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
2320                         continue;
2321                 if (lstat(new_src, &sb) == -1) {
2322                         logit("local lstat \"%s\": %s", filename,
2323                             strerror(errno));
2324                         ret = -1;
2325                         continue;
2326                 }
2327                 if (S_ISLNK(sb.st_mode)) {
2328                         if (!follow_link_flag) {
2329                                 logit("%s: not a regular file", filename);
2330                                 continue;
2331                         }
2332                         /* Replace the stat contents with the symlink target */
2333                         if (stat(new_src, &sb) == -1) {
2334                                 logit("local stat \"%s\": %s", filename,
2335                                     strerror(errno));
2336                                 ret = -1;
2337                                 continue;
2338                         }
2339                 }
2340                 if (S_ISDIR(sb.st_mode)) {
2341                         if (upload_dir_internal(conn, new_src, new_dst,
2342                             depth + 1, preserve_flag, print_flag, resume,
2343                             fsync_flag, follow_link_flag, inplace_flag) == -1)
2344                                 ret = -1;
2345                 } else if (S_ISREG(sb.st_mode)) {
2346                         if (sftp_upload(conn, new_src, new_dst,
2347                             preserve_flag, resume, fsync_flag,
2348                             inplace_flag) == -1) {
2349                                 error("upload \"%s\" to \"%s\" failed",
2350                                     new_src, new_dst);
2351                                 ret = -1;
2352                         }
2353                 } else
2354                         logit("%s: not a regular file", filename);
2355         }
2356         free(new_dst);
2357         free(new_src);
2358
2359         sftp_setstat(conn, dst, &a);
2360
2361         (void) closedir(dirp);
2362         return ret;
2363 }
2364
2365 int
2366 sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
2367     int preserve_flag, int print_flag, int resume, int fsync_flag,
2368     int follow_link_flag, int inplace_flag)
2369 {
2370         char *dst_canon;
2371         int ret;
2372
2373         if ((dst_canon = sftp_realpath(conn, dst)) == NULL) {
2374                 error("upload \"%s\": path canonicalization failed", dst);
2375                 return -1;
2376         }
2377
2378         ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
2379             print_flag, resume, fsync_flag, follow_link_flag, inplace_flag);
2380
2381         free(dst_canon);
2382         return ret;
2383 }
2384
2385 static void
2386 handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
2387     u_int *nreqsp, u_int *write_errorp)
2388 {
2389         struct sshbuf *msg;
2390         u_char type;
2391         u_int id, status;
2392         int r;
2393         struct pollfd pfd;
2394
2395         if ((msg = sshbuf_new()) == NULL)
2396                 fatal_f("sshbuf_new failed");
2397
2398         /* Try to eat replies from the upload side */
2399         while (*nreqsp > 0) {
2400                 debug3_f("%u outstanding replies", *nreqsp);
2401                 if (!synchronous) {
2402                         /* Bail out if no data is ready to be read */
2403                         pfd.fd = to->fd_in;
2404                         pfd.events = POLLIN;
2405                         if ((r = poll(&pfd, 1, 0)) == -1) {
2406                                 if (errno == EINTR)
2407                                         break;
2408                                 fatal_f("poll: %s", strerror(errno));
2409                         } else if (r == 0)
2410                                 break; /* fd not ready */
2411                 }
2412                 sshbuf_reset(msg);
2413                 get_msg(to, msg);
2414
2415                 if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2416                     (r = sshbuf_get_u32(msg, &id)) != 0)
2417                         fatal_fr(r, "dest parse");
2418                 debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp);
2419                 if (type != SSH2_FXP_STATUS) {
2420                         fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d",
2421                             SSH2_FXP_STATUS, type);
2422                 }
2423                 if ((r = sshbuf_get_u32(msg, &status)) != 0)
2424                         fatal_fr(r, "parse dest status");
2425                 debug3("dest SSH2_FXP_STATUS %u", status);
2426                 if (status != SSH2_FX_OK) {
2427                         /* record first error */
2428                         if (*write_errorp == 0)
2429                                 *write_errorp = status;
2430                 }
2431                 /*
2432                  * XXX this doesn't do full reply matching like sftp_upload and
2433                  * so cannot gracefully truncate terminated uploads at a
2434                  * high-water mark. ATM the only caller of this function (scp)
2435                  * doesn't support transfer resumption, so this doesn't matter
2436                  * a whole lot.
2437                  *
2438                  * To be safe, sftp_crossload truncates the destination file to
2439                  * zero length on upload failure, since we can't trust the
2440                  * server not to have reordered replies that could have
2441                  * inserted holes where none existed in the source file.
2442                  *
2443                  * XXX we could get a more accutate progress bar if we updated
2444                  * the counter based on the reply from the destination...
2445                  */
2446                 (*nreqsp)--;
2447         }
2448         debug3_f("done: %u outstanding replies", *nreqsp);
2449         sshbuf_free(msg);
2450 }
2451
2452 int
2453 sftp_crossload(struct sftp_conn *from, struct sftp_conn *to,
2454     const char *from_path, const char *to_path,
2455     Attrib *a, int preserve_flag)
2456 {
2457         struct sshbuf *msg;
2458         int write_error, read_error, r;
2459         u_int64_t offset = 0, size;
2460         u_int id, buflen, num_req, max_req, status = SSH2_FX_OK;
2461         u_int num_upload_req;
2462         off_t progress_counter;
2463         u_char *from_handle, *to_handle;
2464         size_t from_handle_len, to_handle_len;
2465         struct requests requests;
2466         struct request *req;
2467         u_char type;
2468         Attrib attr;
2469
2470         debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path);
2471
2472         TAILQ_INIT(&requests);
2473
2474         if (a == NULL) {
2475                 if (sftp_stat(from, from_path, 0, &attr) != 0)
2476                         return -1;
2477                 a = &attr;
2478         }
2479
2480         if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
2481             (!S_ISREG(a->perm))) {
2482                 error("download \"%s\": not a regular file", from_path);
2483                 return(-1);
2484         }
2485         if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
2486                 size = a->size;
2487         else
2488                 size = 0;
2489
2490         buflen = from->download_buflen;
2491         if (buflen > to->upload_buflen)
2492                 buflen = to->upload_buflen;
2493
2494         /* Send open request to read side */
2495         if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL,
2496             &from_handle, &from_handle_len) != 0)
2497                 return -1;
2498
2499         /* Send open request to write side */
2500         a->flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2501         a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2502         a->perm &= 0777;
2503         if (!preserve_flag)
2504                 a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
2505         if (send_open(to, to_path, "dest",
2506             SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
2507             &to_handle, &to_handle_len) != 0) {
2508                 sftp_close(from, from_handle, from_handle_len);
2509                 return -1;
2510         }
2511
2512         /* Read from remote "from" and write to remote "to" */
2513         offset = 0;
2514         write_error = read_error = num_req = num_upload_req = 0;
2515         max_req = 1;
2516         progress_counter = 0;
2517
2518         if (showprogress && size != 0) {
2519                 start_progress_meter(progress_meter_path(from_path),
2520                     size, &progress_counter);
2521         }
2522         if ((msg = sshbuf_new()) == NULL)
2523                 fatal_f("sshbuf_new failed");
2524         while (num_req > 0 || max_req > 0) {
2525                 u_char *data;
2526                 size_t len;
2527
2528                 /*
2529                  * Simulate EOF on interrupt: stop sending new requests and
2530                  * allow outstanding requests to drain gracefully
2531                  */
2532                 if (interrupted) {
2533                         if (num_req == 0) /* If we haven't started yet... */
2534                                 break;
2535                         max_req = 0;
2536                 }
2537
2538                 /* Send some more requests */
2539                 while (num_req < max_req) {
2540                         debug3("Request range %llu -> %llu (%d/%d)",
2541                             (unsigned long long)offset,
2542                             (unsigned long long)offset + buflen - 1,
2543                             num_req, max_req);
2544                         req = request_enqueue(&requests, from->msg_id++,
2545                             buflen, offset);
2546                         offset += buflen;
2547                         num_req++;
2548                         send_read_request(from, req->id, req->offset,
2549                             req->len, from_handle, from_handle_len);
2550                 }
2551
2552                 /* Try to eat replies from the upload side (nonblocking) */
2553                 handle_dest_replies(to, to_path, 0,
2554                     &num_upload_req, &write_error);
2555
2556                 sshbuf_reset(msg);
2557                 get_msg(from, msg);
2558                 if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2559                     (r = sshbuf_get_u32(msg, &id)) != 0)
2560                         fatal_fr(r, "parse");
2561                 debug3("Received origin reply T:%u I:%u R:%d",
2562                     type, id, max_req);
2563
2564                 /* Find the request in our queue */
2565                 if ((req = request_find(&requests, id)) == NULL)
2566                         fatal("Unexpected reply %u", id);
2567
2568                 switch (type) {
2569                 case SSH2_FXP_STATUS:
2570                         if ((r = sshbuf_get_u32(msg, &status)) != 0)
2571                                 fatal_fr(r, "parse status");
2572                         if (status != SSH2_FX_EOF)
2573                                 read_error = 1;
2574                         max_req = 0;
2575                         TAILQ_REMOVE(&requests, req, tq);
2576                         free(req);
2577                         num_req--;
2578                         break;
2579                 case SSH2_FXP_DATA:
2580                         if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
2581                                 fatal_fr(r, "parse data");
2582                         debug3("Received data %llu -> %llu",
2583                             (unsigned long long)req->offset,
2584                             (unsigned long long)req->offset + len - 1);
2585                         if (len > req->len)
2586                                 fatal("Received more data than asked for "
2587                                     "%zu > %zu", len, req->len);
2588
2589                         /* Write this chunk out to the destination */
2590                         sshbuf_reset(msg);
2591                         if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
2592                             (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 ||
2593                             (r = sshbuf_put_string(msg, to_handle,
2594                             to_handle_len)) != 0 ||
2595                             (r = sshbuf_put_u64(msg, req->offset)) != 0 ||
2596                             (r = sshbuf_put_string(msg, data, len)) != 0)
2597                                 fatal_fr(r, "compose write");
2598                         send_msg(to, msg);
2599                         debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu",
2600                             id, (unsigned long long)offset, len);
2601                         num_upload_req++;
2602                         progress_counter += len;
2603                         free(data);
2604
2605                         if (len == req->len) {
2606                                 TAILQ_REMOVE(&requests, req, tq);
2607                                 free(req);
2608                                 num_req--;
2609                         } else {
2610                                 /* Resend the request for the missing data */
2611                                 debug3("Short data block, re-requesting "
2612                                     "%llu -> %llu (%2d)",
2613                                     (unsigned long long)req->offset + len,
2614                                     (unsigned long long)req->offset +
2615                                     req->len - 1, num_req);
2616                                 req->id = from->msg_id++;
2617                                 req->len -= len;
2618                                 req->offset += len;
2619                                 send_read_request(from, req->id,
2620                                     req->offset, req->len,
2621                                     from_handle, from_handle_len);
2622                                 /* Reduce the request size */
2623                                 if (len < buflen)
2624                                         buflen = MAXIMUM(MIN_READ_SIZE, len);
2625                         }
2626                         if (max_req > 0) { /* max_req = 0 iff EOF received */
2627                                 if (size > 0 && offset > size) {
2628                                         /* Only one request at a time
2629                                          * after the expected EOF */
2630                                         debug3("Finish at %llu (%2d)",
2631                                             (unsigned long long)offset,
2632                                             num_req);
2633                                         max_req = 1;
2634                                 } else if (max_req < from->num_requests) {
2635                                         ++max_req;
2636                                 }
2637                         }
2638                         break;
2639                 default:
2640                         fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
2641                             SSH2_FXP_DATA, type);
2642                 }
2643         }
2644
2645         if (showprogress && size)
2646                 stop_progress_meter();
2647
2648         /* Drain replies from the server (blocking) */
2649         debug3_f("waiting for %u replies from destination", num_upload_req);
2650         handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error);
2651
2652         /* Sanity check */
2653         if (TAILQ_FIRST(&requests) != NULL)
2654                 fatal("Transfer complete, but requests still in queue");
2655         /* Truncate at 0 length on interrupt or error to avoid holes at dest */
2656         if (read_error || write_error || interrupted) {
2657                 debug("truncating \"%s\" at 0", to_path);
2658                 sftp_close(to, to_handle, to_handle_len);
2659                 free(to_handle);
2660                 if (send_open(to, to_path, "dest",
2661                     SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
2662                     &to_handle, &to_handle_len) != 0) {
2663                         error("dest truncate \"%s\" failed", to_path);
2664                         to_handle = NULL;
2665                 }
2666         }
2667         if (read_error) {
2668                 error("read origin \"%s\": %s", from_path, fx2txt(status));
2669                 status = -1;
2670                 sftp_close(from, from_handle, from_handle_len);
2671                 if (to_handle != NULL)
2672                         sftp_close(to, to_handle, to_handle_len);
2673         } else if (write_error) {
2674                 error("write dest \"%s\": %s", to_path, fx2txt(write_error));
2675                 status = SSH2_FX_FAILURE;
2676                 sftp_close(from, from_handle, from_handle_len);
2677                 if (to_handle != NULL)
2678                         sftp_close(to, to_handle, to_handle_len);
2679         } else {
2680                 if (sftp_close(from, from_handle, from_handle_len) != 0 ||
2681                     interrupted)
2682                         status = -1;
2683                 else
2684                         status = SSH2_FX_OK;
2685                 if (to_handle != NULL) {
2686                         /* Need to resend utimes after write */
2687                         if (preserve_flag)
2688                                 sftp_fsetstat(to, to_handle, to_handle_len, a);
2689                         sftp_close(to, to_handle, to_handle_len);
2690                 }
2691         }
2692         sshbuf_free(msg);
2693         free(from_handle);
2694         free(to_handle);
2695
2696         return status == SSH2_FX_OK ? 0 : -1;
2697 }
2698
2699 static int
2700 crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
2701     const char *from_path, const char *to_path,
2702     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
2703     int follow_link_flag)
2704 {
2705         int i, ret = 0;
2706         SFTP_DIRENT **dir_entries;
2707         char *filename, *new_from_path = NULL, *new_to_path = NULL;
2708         mode_t mode = 0777;
2709         Attrib *a, curdir, ldirattrib, newdir, lsym;
2710
2711         debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path);
2712
2713         if (depth >= MAX_DIR_DEPTH) {
2714                 error("Maximum directory depth exceeded: %d levels", depth);
2715                 return -1;
2716         }
2717
2718         if (dirattrib == NULL) {
2719                 if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) {
2720                         error("stat remote \"%s\" failed", from_path);
2721                         return -1;
2722                 }
2723                 dirattrib = &ldirattrib;
2724         }
2725         if (!S_ISDIR(dirattrib->perm)) {
2726                 error("\"%s\" is not a directory", from_path);
2727                 return -1;
2728         }
2729         if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
2730                 mprintf("Retrieving %s\n", from_path);
2731
2732         curdir = *dirattrib; /* dirattrib will be clobbered */
2733         curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2734         curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2735         if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) {
2736                 debug("Origin did not send permissions for "
2737                     "directory \"%s\"", to_path);
2738                 curdir.perm = S_IWUSR|S_IXUSR;
2739                 curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
2740         }
2741         /* We need to be able to write to the directory while we transfer it */
2742         mode = curdir.perm & 01777;
2743         curdir.perm = mode | (S_IWUSR|S_IXUSR);
2744
2745         /*
2746          * sftp lacks a portable status value to match errno EEXIST,
2747          * so if we get a failure back then we must check whether
2748          * the path already existed and is a directory.  Ensure we can
2749          * write to the directory we create for the duration of the transfer.
2750          */
2751         if (sftp_mkdir(to, to_path, &curdir, 0) != 0) {
2752                 if (sftp_stat(to, to_path, 0, &newdir) != 0)
2753                         return -1;
2754                 if (!S_ISDIR(newdir.perm)) {
2755                         error("\"%s\" exists but is not a directory", to_path);
2756                         return -1;
2757                 }
2758         }
2759         curdir.perm = mode;
2760
2761         if (sftp_readdir(from, from_path, &dir_entries) == -1) {
2762                 error("origin readdir \"%s\" failed", from_path);
2763                 return -1;
2764         }
2765
2766         for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
2767                 free(new_from_path);
2768                 free(new_to_path);
2769
2770                 filename = dir_entries[i]->filename;
2771                 new_from_path = sftp_path_append(from_path, filename);
2772                 new_to_path = sftp_path_append(to_path, filename);
2773
2774                 a = &dir_entries[i]->a;
2775                 if (S_ISLNK(a->perm)) {
2776                         if (!follow_link_flag) {
2777                                 logit("%s: not a regular file", filename);
2778                                 continue;
2779                         }
2780                         /* Replace the stat contents with the symlink target */
2781                         if (sftp_stat(from, new_from_path, 1, &lsym) != 0) {
2782                                 logit("remote stat \"%s\" failed",
2783                                     new_from_path);
2784                                 ret = -1;
2785                                 continue;
2786                         }
2787                         a = &lsym;
2788                 }
2789                 if (S_ISDIR(a->perm)) {
2790                         if (strcmp(filename, ".") == 0 ||
2791                             strcmp(filename, "..") == 0)
2792                                 continue;
2793                         if (crossload_dir_internal(from, to,
2794                             new_from_path, new_to_path,
2795                             depth + 1, a, preserve_flag,
2796                             print_flag, follow_link_flag) == -1)
2797                                 ret = -1;
2798                 } else if (S_ISREG(a->perm)) {
2799                         if (sftp_crossload(from, to, new_from_path,
2800                             new_to_path, a, preserve_flag) == -1) {
2801                                 error("crossload \"%s\" to \"%s\" failed",
2802                                     new_from_path, new_to_path);
2803                                 ret = -1;
2804                         }
2805                 } else {
2806                         logit("origin \"%s\": not a regular file",
2807                             new_from_path);
2808                 }
2809         }
2810         free(new_to_path);
2811         free(new_from_path);
2812
2813         sftp_setstat(to, to_path, &curdir);
2814
2815         sftp_free_dirents(dir_entries);
2816
2817         return ret;
2818 }
2819
2820 int
2821 sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
2822     const char *from_path, const char *to_path,
2823     Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag)
2824 {
2825         char *from_path_canon;
2826         int ret;
2827
2828         if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) {
2829                 error("crossload \"%s\": path canonicalization failed",
2830                     from_path);
2831                 return -1;
2832         }
2833
2834         ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0,
2835             dirattrib, preserve_flag, print_flag, follow_link_flag);
2836         free(from_path_canon);
2837         return ret;
2838 }
2839
2840 int
2841 sftp_can_get_users_groups_by_id(struct sftp_conn *conn)
2842 {
2843         return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0;
2844 }
2845
2846 int
2847 sftp_get_users_groups_by_id(struct sftp_conn *conn,
2848     const u_int *uids, u_int nuids,
2849     const u_int *gids, u_int ngids,
2850     char ***usernamesp, char ***groupnamesp)
2851 {
2852         struct sshbuf *msg, *uidbuf, *gidbuf;
2853         u_int i, expected_id, id;
2854         char *name, **usernames = NULL, **groupnames = NULL;
2855         u_char type;
2856         int r;
2857
2858         *usernamesp = *groupnamesp = NULL;
2859         if (!sftp_can_get_users_groups_by_id(conn))
2860                 return SSH_ERR_FEATURE_UNSUPPORTED;
2861
2862         if ((msg = sshbuf_new()) == NULL ||
2863             (uidbuf = sshbuf_new()) == NULL ||
2864             (gidbuf = sshbuf_new()) == NULL)
2865                 fatal_f("sshbuf_new failed");
2866         expected_id = id = conn->msg_id++;
2867         debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id@openssh.com)");
2868         for (i = 0; i < nuids; i++) {
2869                 if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0)
2870                         fatal_fr(r, "compose uids");
2871         }
2872         for (i = 0; i < ngids; i++) {
2873                 if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0)
2874                         fatal_fr(r, "compose gids");
2875         }
2876         if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
2877             (r = sshbuf_put_u32(msg, id)) != 0 ||
2878             (r = sshbuf_put_cstring(msg,
2879             "users-groups-by-id@openssh.com")) != 0 ||
2880             (r = sshbuf_put_stringb(msg, uidbuf)) != 0 ||
2881             (r = sshbuf_put_stringb(msg, gidbuf)) != 0)
2882                 fatal_fr(r, "compose");
2883         send_msg(conn, msg);
2884         get_msg(conn, msg);
2885         if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2886             (r = sshbuf_get_u32(msg, &id)) != 0)
2887                 fatal_fr(r, "parse");
2888         if (id != expected_id)
2889                 fatal("ID mismatch (%u != %u)", id, expected_id);
2890         if (type == SSH2_FXP_STATUS) {
2891                 u_int status;
2892                 char *errmsg;
2893
2894                 if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
2895                     (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
2896                         fatal_fr(r, "parse status");
2897                 error("users-groups-by-id %s",
2898                     *errmsg == '\0' ? fx2txt(status) : errmsg);
2899                 free(errmsg);
2900                 sshbuf_free(msg);
2901                 sshbuf_free(uidbuf);
2902                 sshbuf_free(gidbuf);
2903                 return -1;
2904         } else if (type != SSH2_FXP_EXTENDED_REPLY)
2905                 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
2906                     SSH2_FXP_EXTENDED_REPLY, type);
2907
2908         /* reuse */
2909         sshbuf_free(uidbuf);
2910         sshbuf_free(gidbuf);
2911         uidbuf = gidbuf = NULL;
2912         if ((r = sshbuf_froms(msg, &uidbuf)) != 0 ||
2913             (r = sshbuf_froms(msg, &gidbuf)) != 0)
2914                 fatal_fr(r, "parse response");
2915         if (nuids > 0) {
2916                 usernames = xcalloc(nuids, sizeof(*usernames));
2917                 for (i = 0; i < nuids; i++) {
2918                         if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0)
2919                                 fatal_fr(r, "parse user name");
2920                         /* Handle unresolved names */
2921                         if (*name == '\0') {
2922                                 free(name);
2923                                 name = NULL;
2924                         }
2925                         usernames[i] = name;
2926                 }
2927         }
2928         if (ngids > 0) {
2929                 groupnames = xcalloc(ngids, sizeof(*groupnames));
2930                 for (i = 0; i < ngids; i++) {
2931                         if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0)
2932                                 fatal_fr(r, "parse user name");
2933                         /* Handle unresolved names */
2934                         if (*name == '\0') {
2935                                 free(name);
2936                                 name = NULL;
2937                         }
2938                         groupnames[i] = name;
2939                 }
2940         }
2941         if (sshbuf_len(uidbuf) != 0)
2942                 fatal_f("unexpected extra username data");
2943         if (sshbuf_len(gidbuf) != 0)
2944                 fatal_f("unexpected extra groupname data");
2945         sshbuf_free(uidbuf);
2946         sshbuf_free(gidbuf);
2947         sshbuf_free(msg);
2948         /* success */
2949         *usernamesp = usernames;
2950         *groupnamesp = groupnames;
2951         return 0;
2952 }
2953
2954 char *
2955 sftp_path_append(const char *p1, const char *p2)
2956 {
2957         char *ret;
2958         size_t len = strlen(p1) + strlen(p2) + 2;
2959
2960         ret = xmalloc(len);
2961         strlcpy(ret, p1, len);
2962         if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
2963                 strlcat(ret, "/", len);
2964         strlcat(ret, p2, len);
2965
2966         return(ret);
2967 }
2968
2969 /*
2970  * Arg p must be dynamically allocated.  It will either be returned or
2971  * freed and a replacement allocated.  Caller must free returned string.
2972  */
2973 char *
2974 sftp_make_absolute(char *p, const char *pwd)
2975 {
2976         char *abs_str;
2977
2978         /* Derelativise */
2979         if (p && !path_absolute(p)) {
2980                 abs_str = sftp_path_append(pwd, p);
2981                 free(p);
2982                 return(abs_str);
2983         } else
2984                 return(p);
2985 }
2986
2987 int
2988 sftp_remote_is_dir(struct sftp_conn *conn, const char *path)
2989 {
2990         Attrib a;
2991
2992         /* XXX: report errors? */
2993         if (sftp_stat(conn, path, 1, &a) != 0)
2994                 return(0);
2995         if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
2996                 return(0);
2997         return S_ISDIR(a.perm);
2998 }
2999
3000
3001 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
3002 int
3003 sftp_globpath_is_dir(const char *pathname)
3004 {
3005         size_t l = strlen(pathname);
3006
3007         return l > 0 && pathname[l - 1] == '/';
3008 }
3009