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