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