xref: /openbsd-src/usr.bin/ssh/sftp-client.c (revision 24bb5fcea3ed904bc467217bdaadb5dfc618d5bf)
1 /* $OpenBSD: sftp-client.c,v 1.143 2021/06/06 03:17:02 djm Exp $ */
2 /*
3  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* XXX: memleaks */
19 /* XXX: signed vs unsigned */
20 /* XXX: remove all logging, only return status codes */
21 /* XXX: copy between two remote sites */
22 
23 #include <sys/types.h>
24 #include <sys/poll.h>
25 #include <sys/queue.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <sys/statvfs.h>
29 #include <sys/uio.h>
30 
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 #include "xmalloc.h"
42 #include "ssherr.h"
43 #include "sshbuf.h"
44 #include "log.h"
45 #include "atomicio.h"
46 #include "progressmeter.h"
47 #include "misc.h"
48 #include "utf8.h"
49 
50 #include "sftp.h"
51 #include "sftp-common.h"
52 #include "sftp-client.h"
53 
54 extern volatile sig_atomic_t interrupted;
55 extern int showprogress;
56 
57 /* Default size of buffer for up/download */
58 #define DEFAULT_COPY_BUFLEN	32768
59 
60 /* Default number of concurrent outstanding requests */
61 #define DEFAULT_NUM_REQUESTS	64
62 
63 /* Minimum amount of data to read at a time */
64 #define MIN_READ_SIZE	512
65 
66 /* Maximum depth to descend in directory trees */
67 #define MAX_DIR_DEPTH 64
68 
69 struct sftp_conn {
70 	int fd_in;
71 	int fd_out;
72 	u_int download_buflen;
73 	u_int upload_buflen;
74 	u_int num_requests;
75 	u_int version;
76 	u_int msg_id;
77 #define SFTP_EXT_POSIX_RENAME	0x00000001
78 #define SFTP_EXT_STATVFS	0x00000002
79 #define SFTP_EXT_FSTATVFS	0x00000004
80 #define SFTP_EXT_HARDLINK	0x00000008
81 #define SFTP_EXT_FSYNC		0x00000010
82 #define SFTP_EXT_LSETSTAT	0x00000020
83 #define SFTP_EXT_LIMITS		0x00000040
84 	u_int exts;
85 	u_int64_t limit_kbps;
86 	struct bwlimit bwlimit_in, bwlimit_out;
87 };
88 
89 static u_char *
90 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
91     const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
92 
93 /* ARGSUSED */
94 static int
95 sftpio(void *_bwlimit, size_t amount)
96 {
97 	struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
98 
99 	refresh_progress_meter(0);
100 	if (bwlimit != NULL)
101 		bandwidth_limit(bwlimit, amount);
102 	return 0;
103 }
104 
105 static void
106 send_msg(struct sftp_conn *conn, struct sshbuf *m)
107 {
108 	u_char mlen[4];
109 	struct iovec iov[2];
110 
111 	if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
112 		fatal("Outbound message too long %zu", sshbuf_len(m));
113 
114 	/* Send length first */
115 	put_u32(mlen, sshbuf_len(m));
116 	iov[0].iov_base = mlen;
117 	iov[0].iov_len = sizeof(mlen);
118 	iov[1].iov_base = (u_char *)sshbuf_ptr(m);
119 	iov[1].iov_len = sshbuf_len(m);
120 
121 	if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
122 	    conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
123 	    sshbuf_len(m) + sizeof(mlen))
124 		fatal("Couldn't send packet: %s", strerror(errno));
125 
126 	sshbuf_reset(m);
127 }
128 
129 static void
130 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
131 {
132 	u_int msg_len;
133 	u_char *p;
134 	int r;
135 
136 	if ((r = sshbuf_reserve(m, 4, &p)) != 0)
137 		fatal_fr(r, "reserve");
138 	if (atomicio6(read, conn->fd_in, p, 4, sftpio,
139 	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
140 		if (errno == EPIPE || errno == ECONNRESET)
141 			fatal("Connection closed");
142 		else
143 			fatal("Couldn't read packet: %s", strerror(errno));
144 	}
145 
146 	if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
147 		fatal_fr(r, "sshbuf_get_u32");
148 	if (msg_len > SFTP_MAX_MSG_LENGTH) {
149 		do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
150 		    "Received message too long %u", msg_len);
151 		fatal("Ensure the remote shell produces no output "
152 		    "for non-interactive sessions.");
153 	}
154 
155 	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
156 		fatal_fr(r, "reserve");
157 	if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
158 	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
159 	    != msg_len) {
160 		if (errno == EPIPE)
161 			fatal("Connection closed");
162 		else
163 			fatal("Read packet: %s", strerror(errno));
164 	}
165 }
166 
167 static void
168 get_msg(struct sftp_conn *conn, struct sshbuf *m)
169 {
170 	get_msg_extended(conn, m, 0);
171 }
172 
173 static void
174 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
175     u_int len)
176 {
177 	struct sshbuf *msg;
178 	int r;
179 
180 	if ((msg = sshbuf_new()) == NULL)
181 		fatal_f("sshbuf_new failed");
182 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
183 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
184 	    (r = sshbuf_put_string(msg, s, len)) != 0)
185 		fatal_fr(r, "compose");
186 	send_msg(conn, msg);
187 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
188 	sshbuf_free(msg);
189 }
190 
191 static void
192 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
193     const void *s, u_int len, Attrib *a)
194 {
195 	struct sshbuf *msg;
196 	int r;
197 
198 	if ((msg = sshbuf_new()) == NULL)
199 		fatal_f("sshbuf_new failed");
200 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
201 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
202 	    (r = sshbuf_put_string(msg, s, len)) != 0 ||
203 	    (r = encode_attrib(msg, a)) != 0)
204 		fatal_fr(r, "compose");
205 	send_msg(conn, msg);
206 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
207 	sshbuf_free(msg);
208 }
209 
210 static u_int
211 get_status(struct sftp_conn *conn, u_int expected_id)
212 {
213 	struct sshbuf *msg;
214 	u_char type;
215 	u_int id, status;
216 	int r;
217 
218 	if ((msg = sshbuf_new()) == NULL)
219 		fatal_f("sshbuf_new failed");
220 	get_msg(conn, msg);
221 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
222 	    (r = sshbuf_get_u32(msg, &id)) != 0)
223 		fatal_fr(r, "compose");
224 
225 	if (id != expected_id)
226 		fatal("ID mismatch (%u != %u)", id, expected_id);
227 	if (type != SSH2_FXP_STATUS)
228 		fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
229 		    SSH2_FXP_STATUS, type);
230 
231 	if ((r = sshbuf_get_u32(msg, &status)) != 0)
232 		fatal_fr(r, "parse");
233 	sshbuf_free(msg);
234 
235 	debug3("SSH2_FXP_STATUS %u", status);
236 
237 	return status;
238 }
239 
240 static u_char *
241 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
242     const char *errfmt, ...)
243 {
244 	struct sshbuf *msg;
245 	u_int id, status;
246 	u_char type;
247 	u_char *handle;
248 	char errmsg[256];
249 	va_list args;
250 	int r;
251 
252 	va_start(args, errfmt);
253 	if (errfmt != NULL)
254 		vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
255 	va_end(args);
256 
257 	if ((msg = sshbuf_new()) == NULL)
258 		fatal_f("sshbuf_new failed");
259 	get_msg(conn, msg);
260 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
261 	    (r = sshbuf_get_u32(msg, &id)) != 0)
262 		fatal_fr(r, "parse");
263 
264 	if (id != expected_id)
265 		fatal("%s: ID mismatch (%u != %u)",
266 		    errfmt == NULL ? __func__ : errmsg, id, expected_id);
267 	if (type == SSH2_FXP_STATUS) {
268 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
269 			fatal_fr(r, "parse status");
270 		if (errfmt != NULL)
271 			error("%s: %s", errmsg, fx2txt(status));
272 		sshbuf_free(msg);
273 		return(NULL);
274 	} else if (type != SSH2_FXP_HANDLE)
275 		fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
276 		    errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
277 
278 	if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
279 		fatal_fr(r, "parse handle");
280 	sshbuf_free(msg);
281 
282 	return handle;
283 }
284 
285 static Attrib *
286 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
287 {
288 	struct sshbuf *msg;
289 	u_int id;
290 	u_char type;
291 	int r;
292 	static Attrib a;
293 
294 	if ((msg = sshbuf_new()) == NULL)
295 		fatal_f("sshbuf_new failed");
296 	get_msg(conn, msg);
297 
298 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
299 	    (r = sshbuf_get_u32(msg, &id)) != 0)
300 		fatal_fr(r, "parse");
301 
302 	debug3("Received stat reply T:%u I:%u", type, id);
303 	if (id != expected_id)
304 		fatal("ID mismatch (%u != %u)", id, expected_id);
305 	if (type == SSH2_FXP_STATUS) {
306 		u_int status;
307 
308 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
309 			fatal_fr(r, "parse status");
310 		if (quiet)
311 			debug("Couldn't stat remote file: %s", fx2txt(status));
312 		else
313 			error("Couldn't stat remote file: %s", fx2txt(status));
314 		sshbuf_free(msg);
315 		return(NULL);
316 	} else if (type != SSH2_FXP_ATTRS) {
317 		fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
318 		    SSH2_FXP_ATTRS, type);
319 	}
320 	if ((r = decode_attrib(msg, &a)) != 0) {
321 		error_fr(r, "decode_attrib");
322 		sshbuf_free(msg);
323 		return NULL;
324 	}
325 	sshbuf_free(msg);
326 
327 	return &a;
328 }
329 
330 static int
331 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
332     u_int expected_id, int quiet)
333 {
334 	struct sshbuf *msg;
335 	u_char type;
336 	u_int id;
337 	u_int64_t flag;
338 	int r;
339 
340 	if ((msg = sshbuf_new()) == NULL)
341 		fatal_f("sshbuf_new failed");
342 	get_msg(conn, msg);
343 
344 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
345 	    (r = sshbuf_get_u32(msg, &id)) != 0)
346 		fatal_fr(r, "parse");
347 
348 	debug3("Received statvfs reply T:%u I:%u", type, id);
349 	if (id != expected_id)
350 		fatal("ID mismatch (%u != %u)", id, expected_id);
351 	if (type == SSH2_FXP_STATUS) {
352 		u_int status;
353 
354 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
355 			fatal_fr(r, "parse status");
356 		if (quiet)
357 			debug("Couldn't statvfs: %s", fx2txt(status));
358 		else
359 			error("Couldn't statvfs: %s", fx2txt(status));
360 		sshbuf_free(msg);
361 		return -1;
362 	} else if (type != SSH2_FXP_EXTENDED_REPLY) {
363 		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
364 		    SSH2_FXP_EXTENDED_REPLY, type);
365 	}
366 
367 	memset(st, 0, sizeof(*st));
368 	if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
369 	    (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
370 	    (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
371 	    (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
372 	    (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
373 	    (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
374 	    (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
375 	    (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
376 	    (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
377 	    (r = sshbuf_get_u64(msg, &flag)) != 0 ||
378 	    (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
379 		fatal_fr(r, "parse statvfs");
380 
381 	st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
382 	st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
383 
384 	sshbuf_free(msg);
385 
386 	return 0;
387 }
388 
389 struct sftp_conn *
390 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
391     u_int64_t limit_kbps)
392 {
393 	u_char type;
394 	struct sshbuf *msg;
395 	struct sftp_conn *ret;
396 	int r;
397 
398 	ret = xcalloc(1, sizeof(*ret));
399 	ret->msg_id = 1;
400 	ret->fd_in = fd_in;
401 	ret->fd_out = fd_out;
402 	ret->download_buflen = ret->upload_buflen =
403 	    transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN;
404 	ret->num_requests =
405 	    num_requests ? num_requests : DEFAULT_NUM_REQUESTS;
406 	ret->exts = 0;
407 	ret->limit_kbps = 0;
408 
409 	if ((msg = sshbuf_new()) == NULL)
410 		fatal_f("sshbuf_new failed");
411 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
412 	    (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
413 		fatal_fr(r, "parse");
414 
415 	send_msg(ret, msg);
416 
417 	get_msg_extended(ret, msg, 1);
418 
419 	/* Expecting a VERSION reply */
420 	if ((r = sshbuf_get_u8(msg, &type)) != 0)
421 		fatal_fr(r, "parse type");
422 	if (type != SSH2_FXP_VERSION) {
423 		error("Invalid packet back from SSH2_FXP_INIT (type %u)",
424 		    type);
425 		sshbuf_free(msg);
426 		free(ret);
427 		return(NULL);
428 	}
429 	if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
430 		fatal_fr(r, "parse version");
431 
432 	debug2("Remote version: %u", ret->version);
433 
434 	/* Check for extensions */
435 	while (sshbuf_len(msg) > 0) {
436 		char *name;
437 		u_char *value;
438 		size_t vlen;
439 		int known = 0;
440 
441 		if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
442 		    (r = sshbuf_get_string(msg, &value, &vlen)) != 0)
443 			fatal_fr(r, "parse extension");
444 		if (strcmp(name, "posix-rename@openssh.com") == 0 &&
445 		    strcmp((char *)value, "1") == 0) {
446 			ret->exts |= SFTP_EXT_POSIX_RENAME;
447 			known = 1;
448 		} else if (strcmp(name, "statvfs@openssh.com") == 0 &&
449 		    strcmp((char *)value, "2") == 0) {
450 			ret->exts |= SFTP_EXT_STATVFS;
451 			known = 1;
452 		} else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
453 		    strcmp((char *)value, "2") == 0) {
454 			ret->exts |= SFTP_EXT_FSTATVFS;
455 			known = 1;
456 		} else if (strcmp(name, "hardlink@openssh.com") == 0 &&
457 		    strcmp((char *)value, "1") == 0) {
458 			ret->exts |= SFTP_EXT_HARDLINK;
459 			known = 1;
460 		} else if (strcmp(name, "fsync@openssh.com") == 0 &&
461 		    strcmp((char *)value, "1") == 0) {
462 			ret->exts |= SFTP_EXT_FSYNC;
463 			known = 1;
464 		} else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
465 		    strcmp((char *)value, "1") == 0) {
466 			ret->exts |= SFTP_EXT_LSETSTAT;
467 			known = 1;
468 		} else if (strcmp(name, "limits@openssh.com") == 0 &&
469 		    strcmp((char *)value, "1") == 0) {
470 			ret->exts |= SFTP_EXT_LIMITS;
471 			known = 1;
472 		}
473 		if (known) {
474 			debug2("Server supports extension \"%s\" revision %s",
475 			    name, value);
476 		} else {
477 			debug2("Unrecognised server extension \"%s\"", name);
478 		}
479 		free(name);
480 		free(value);
481 	}
482 
483 	sshbuf_free(msg);
484 
485 	/* Query the server for its limits */
486 	if (ret->exts & SFTP_EXT_LIMITS) {
487 		struct sftp_limits limits;
488 		if (do_limits(ret, &limits) != 0)
489 			fatal_f("limits failed");
490 
491 		/* If the caller did not specify, find a good value */
492 		if (transfer_buflen == 0) {
493 			ret->download_buflen = limits.read_length;
494 			ret->upload_buflen = limits.write_length;
495 			debug("Using server download size %u", ret->download_buflen);
496 			debug("Using server upload size %u", ret->upload_buflen);
497 		}
498 
499 		/* Use the server limit to scale down our value only */
500 		if (num_requests == 0 && limits.open_handles) {
501 			ret->num_requests =
502 			    MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles);
503 			debug("Server handle limit %llu; using %u",
504 			    (unsigned long long)limits.open_handles,
505 			    ret->num_requests);
506 		}
507 	}
508 
509 	/* Some filexfer v.0 servers don't support large packets */
510 	if (ret->version == 0) {
511 		ret->download_buflen = MINIMUM(ret->download_buflen, 20480);
512 		ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480);
513 	}
514 
515 	ret->limit_kbps = limit_kbps;
516 	if (ret->limit_kbps > 0) {
517 		bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
518 		    ret->download_buflen);
519 		bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
520 		    ret->upload_buflen);
521 	}
522 
523 	return ret;
524 }
525 
526 u_int
527 sftp_proto_version(struct sftp_conn *conn)
528 {
529 	return conn->version;
530 }
531 
532 int
533 do_limits(struct sftp_conn *conn, struct sftp_limits *limits)
534 {
535 	u_int id, msg_id;
536 	u_char type;
537 	struct sshbuf *msg;
538 	int r;
539 
540 	if ((conn->exts & SFTP_EXT_LIMITS) == 0) {
541 		error("Server does not support limits@openssh.com extension");
542 		return -1;
543 	}
544 
545 	if ((msg = sshbuf_new()) == NULL)
546 		fatal_f("sshbuf_new failed");
547 
548 	id = conn->msg_id++;
549 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
550 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
551 	    (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0)
552 		fatal_fr(r, "compose");
553 	send_msg(conn, msg);
554 	debug3("Sent message limits@openssh.com I:%u", id);
555 
556 	get_msg(conn, msg);
557 
558 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
559 	    (r = sshbuf_get_u32(msg, &msg_id)) != 0)
560 		fatal_fr(r, "parse");
561 
562 	debug3("Received limits reply T:%u I:%u", type, msg_id);
563 	if (id != msg_id)
564 		fatal("ID mismatch (%u != %u)", msg_id, id);
565 	if (type != SSH2_FXP_EXTENDED_REPLY) {
566 		debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
567 		    SSH2_FXP_EXTENDED_REPLY, type);
568 		/* Disable the limits extension */
569 		conn->exts &= ~SFTP_EXT_LIMITS;
570 		sshbuf_free(msg);
571 		return 0;
572 	}
573 
574 	memset(limits, 0, sizeof(*limits));
575 	if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 ||
576 	    (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 ||
577 	    (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 ||
578 	    (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0)
579 		fatal_fr(r, "parse limits");
580 
581 	sshbuf_free(msg);
582 
583 	return 0;
584 }
585 
586 int
587 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
588 {
589 	u_int id, status;
590 	struct sshbuf *msg;
591 	int r;
592 
593 	if ((msg = sshbuf_new()) == NULL)
594 		fatal_f("sshbuf_new failed");
595 
596 	id = conn->msg_id++;
597 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
598 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
599 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
600 		fatal_fr(r, "parse");
601 	send_msg(conn, msg);
602 	debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
603 
604 	status = get_status(conn, id);
605 	if (status != SSH2_FX_OK)
606 		error("Couldn't close file: %s", fx2txt(status));
607 
608 	sshbuf_free(msg);
609 
610 	return status == SSH2_FX_OK ? 0 : -1;
611 }
612 
613 
614 static int
615 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
616     SFTP_DIRENT ***dir)
617 {
618 	struct sshbuf *msg;
619 	u_int count, id, i, expected_id, ents = 0;
620 	size_t handle_len;
621 	u_char type, *handle;
622 	int status = SSH2_FX_FAILURE;
623 	int r;
624 
625 	if (dir)
626 		*dir = NULL;
627 
628 	id = conn->msg_id++;
629 
630 	if ((msg = sshbuf_new()) == NULL)
631 		fatal_f("sshbuf_new failed");
632 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
633 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
634 	    (r = sshbuf_put_cstring(msg, path)) != 0)
635 		fatal_fr(r, "compose OPENDIR");
636 	send_msg(conn, msg);
637 
638 	handle = get_handle(conn, id, &handle_len,
639 	    "remote readdir(\"%s\")", path);
640 	if (handle == NULL) {
641 		sshbuf_free(msg);
642 		return -1;
643 	}
644 
645 	if (dir) {
646 		ents = 0;
647 		*dir = xcalloc(1, sizeof(**dir));
648 		(*dir)[0] = NULL;
649 	}
650 
651 	for (; !interrupted;) {
652 		id = expected_id = conn->msg_id++;
653 
654 		debug3("Sending SSH2_FXP_READDIR I:%u", id);
655 
656 		sshbuf_reset(msg);
657 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
658 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
659 		    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
660 			fatal_fr(r, "compose READDIR");
661 		send_msg(conn, msg);
662 
663 		sshbuf_reset(msg);
664 
665 		get_msg(conn, msg);
666 
667 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
668 		    (r = sshbuf_get_u32(msg, &id)) != 0)
669 			fatal_fr(r, "parse");
670 
671 		debug3("Received reply T:%u I:%u", type, id);
672 
673 		if (id != expected_id)
674 			fatal("ID mismatch (%u != %u)", id, expected_id);
675 
676 		if (type == SSH2_FXP_STATUS) {
677 			u_int rstatus;
678 
679 			if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
680 				fatal_fr(r, "parse status");
681 			debug3("Received SSH2_FXP_STATUS %d", rstatus);
682 			if (rstatus == SSH2_FX_EOF)
683 				break;
684 			error("Couldn't read directory: %s", fx2txt(rstatus));
685 			goto out;
686 		} else if (type != SSH2_FXP_NAME)
687 			fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
688 			    SSH2_FXP_NAME, type);
689 
690 		if ((r = sshbuf_get_u32(msg, &count)) != 0)
691 			fatal_fr(r, "parse count");
692 		if (count > SSHBUF_SIZE_MAX)
693 			fatal_f("nonsensical number of entries");
694 		if (count == 0)
695 			break;
696 		debug3("Received %d SSH2_FXP_NAME responses", count);
697 		for (i = 0; i < count; i++) {
698 			char *filename, *longname;
699 			Attrib a;
700 
701 			if ((r = sshbuf_get_cstring(msg, &filename,
702 			    NULL)) != 0 ||
703 			    (r = sshbuf_get_cstring(msg, &longname,
704 			    NULL)) != 0)
705 				fatal_fr(r, "parse filenames");
706 			if ((r = decode_attrib(msg, &a)) != 0) {
707 				error_fr(r, "couldn't decode attrib");
708 				free(filename);
709 				free(longname);
710 				goto out;
711 			}
712 
713 			if (print_flag)
714 				mprintf("%s\n", longname);
715 
716 			/*
717 			 * Directory entries should never contain '/'
718 			 * These can be used to attack recursive ops
719 			 * (e.g. send '../../../../etc/passwd')
720 			 */
721 			if (strchr(filename, '/') != NULL) {
722 				error("Server sent suspect path \"%s\" "
723 				    "during readdir of \"%s\"", filename, path);
724 			} else if (dir) {
725 				*dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
726 				(*dir)[ents] = xcalloc(1, sizeof(***dir));
727 				(*dir)[ents]->filename = xstrdup(filename);
728 				(*dir)[ents]->longname = xstrdup(longname);
729 				memcpy(&(*dir)[ents]->a, &a, sizeof(a));
730 				(*dir)[++ents] = NULL;
731 			}
732 			free(filename);
733 			free(longname);
734 		}
735 	}
736 	status = 0;
737 
738  out:
739 	sshbuf_free(msg);
740 	do_close(conn, handle, handle_len);
741 	free(handle);
742 
743 	if (status != 0 && dir != NULL) {
744 		/* Don't return results on error */
745 		free_sftp_dirents(*dir);
746 		*dir = NULL;
747 	} else if (interrupted && dir != NULL && *dir != NULL) {
748 		/* Don't return partial matches on interrupt */
749 		free_sftp_dirents(*dir);
750 		*dir = xcalloc(1, sizeof(**dir));
751 		**dir = NULL;
752 	}
753 
754 	return status == SSH2_FX_OK ? 0 : -1;
755 }
756 
757 int
758 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
759 {
760 	return(do_lsreaddir(conn, path, 0, dir));
761 }
762 
763 void free_sftp_dirents(SFTP_DIRENT **s)
764 {
765 	int i;
766 
767 	if (s == NULL)
768 		return;
769 	for (i = 0; s[i]; i++) {
770 		free(s[i]->filename);
771 		free(s[i]->longname);
772 		free(s[i]);
773 	}
774 	free(s);
775 }
776 
777 int
778 do_rm(struct sftp_conn *conn, const char *path)
779 {
780 	u_int status, id;
781 
782 	debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
783 
784 	id = conn->msg_id++;
785 	send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
786 	status = get_status(conn, id);
787 	if (status != SSH2_FX_OK)
788 		error("Couldn't delete file: %s", fx2txt(status));
789 	return status == SSH2_FX_OK ? 0 : -1;
790 }
791 
792 int
793 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
794 {
795 	u_int status, id;
796 
797 	id = conn->msg_id++;
798 	send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
799 	    strlen(path), a);
800 
801 	status = get_status(conn, id);
802 	if (status != SSH2_FX_OK && print_flag)
803 		error("Couldn't create directory: %s", fx2txt(status));
804 
805 	return status == SSH2_FX_OK ? 0 : -1;
806 }
807 
808 int
809 do_rmdir(struct sftp_conn *conn, const char *path)
810 {
811 	u_int status, id;
812 
813 	id = conn->msg_id++;
814 	send_string_request(conn, id, SSH2_FXP_RMDIR, path,
815 	    strlen(path));
816 
817 	status = get_status(conn, id);
818 	if (status != SSH2_FX_OK)
819 		error("Couldn't remove directory: %s", fx2txt(status));
820 
821 	return status == SSH2_FX_OK ? 0 : -1;
822 }
823 
824 Attrib *
825 do_stat(struct sftp_conn *conn, const char *path, int quiet)
826 {
827 	u_int id;
828 
829 	id = conn->msg_id++;
830 
831 	send_string_request(conn, id,
832 	    conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
833 	    path, strlen(path));
834 
835 	return(get_decode_stat(conn, id, quiet));
836 }
837 
838 Attrib *
839 do_lstat(struct sftp_conn *conn, const char *path, int quiet)
840 {
841 	u_int id;
842 
843 	if (conn->version == 0) {
844 		if (quiet)
845 			debug("Server version does not support lstat operation");
846 		else
847 			logit("Server version does not support lstat operation");
848 		return(do_stat(conn, path, quiet));
849 	}
850 
851 	id = conn->msg_id++;
852 	send_string_request(conn, id, SSH2_FXP_LSTAT, path,
853 	    strlen(path));
854 
855 	return(get_decode_stat(conn, id, quiet));
856 }
857 
858 #ifdef notyet
859 Attrib *
860 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
861     int quiet)
862 {
863 	u_int id;
864 
865 	id = conn->msg_id++;
866 	send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
867 	    handle_len);
868 
869 	return(get_decode_stat(conn, id, quiet));
870 }
871 #endif
872 
873 int
874 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
875 {
876 	u_int status, id;
877 
878 	id = conn->msg_id++;
879 	send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
880 	    strlen(path), a);
881 
882 	status = get_status(conn, id);
883 	if (status != SSH2_FX_OK)
884 		error("Couldn't setstat on \"%s\": %s", path,
885 		    fx2txt(status));
886 
887 	return status == SSH2_FX_OK ? 0 : -1;
888 }
889 
890 int
891 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
892     Attrib *a)
893 {
894 	u_int status, id;
895 
896 	id = conn->msg_id++;
897 	send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
898 	    handle_len, a);
899 
900 	status = get_status(conn, id);
901 	if (status != SSH2_FX_OK)
902 		error("Couldn't fsetstat: %s", fx2txt(status));
903 
904 	return status == SSH2_FX_OK ? 0 : -1;
905 }
906 
907 char *
908 do_realpath(struct sftp_conn *conn, const char *path)
909 {
910 	struct sshbuf *msg;
911 	u_int expected_id, count, id;
912 	char *filename, *longname;
913 	Attrib a;
914 	u_char type;
915 	int r;
916 
917 	expected_id = id = conn->msg_id++;
918 	send_string_request(conn, id, SSH2_FXP_REALPATH, path,
919 	    strlen(path));
920 
921 	if ((msg = sshbuf_new()) == NULL)
922 		fatal_f("sshbuf_new failed");
923 
924 	get_msg(conn, msg);
925 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
926 	    (r = sshbuf_get_u32(msg, &id)) != 0)
927 		fatal_fr(r, "parse");
928 
929 	if (id != expected_id)
930 		fatal("ID mismatch (%u != %u)", id, expected_id);
931 
932 	if (type == SSH2_FXP_STATUS) {
933 		u_int status;
934 
935 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
936 			fatal_fr(r, "parse status");
937 		error("Couldn't canonicalize: %s", fx2txt(status));
938 		sshbuf_free(msg);
939 		return NULL;
940 	} else if (type != SSH2_FXP_NAME)
941 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
942 		    SSH2_FXP_NAME, type);
943 
944 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
945 		fatal_fr(r, "parse count");
946 	if (count != 1)
947 		fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
948 
949 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
950 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
951 	    (r = decode_attrib(msg, &a)) != 0)
952 		fatal_fr(r, "parse filename/attrib");
953 
954 	debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename,
955 	    (unsigned long)a.size);
956 
957 	free(longname);
958 
959 	sshbuf_free(msg);
960 
961 	return(filename);
962 }
963 
964 int
965 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
966     int force_legacy)
967 {
968 	struct sshbuf *msg;
969 	u_int status, id;
970 	int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
971 
972 	if ((msg = sshbuf_new()) == NULL)
973 		fatal_f("sshbuf_new failed");
974 
975 	/* Send rename request */
976 	id = conn->msg_id++;
977 	if (use_ext) {
978 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
979 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
980 		    (r = sshbuf_put_cstring(msg,
981 		    "posix-rename@openssh.com")) != 0)
982 			fatal_fr(r, "compose posix-rename");
983 	} else {
984 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
985 		    (r = sshbuf_put_u32(msg, id)) != 0)
986 			fatal_fr(r, "compose rename");
987 	}
988 	if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
989 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
990 		fatal_fr(r, "compose paths");
991 	send_msg(conn, msg);
992 	debug3("Sent message %s \"%s\" -> \"%s\"",
993 	    use_ext ? "posix-rename@openssh.com" :
994 	    "SSH2_FXP_RENAME", oldpath, newpath);
995 	sshbuf_free(msg);
996 
997 	status = get_status(conn, id);
998 	if (status != SSH2_FX_OK)
999 		error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
1000 		    newpath, fx2txt(status));
1001 
1002 	return status == SSH2_FX_OK ? 0 : -1;
1003 }
1004 
1005 int
1006 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1007 {
1008 	struct sshbuf *msg;
1009 	u_int status, id;
1010 	int r;
1011 
1012 	if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
1013 		error("Server does not support hardlink@openssh.com extension");
1014 		return -1;
1015 	}
1016 
1017 	if ((msg = sshbuf_new()) == NULL)
1018 		fatal_f("sshbuf_new failed");
1019 
1020 	/* Send link request */
1021 	id = conn->msg_id++;
1022 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1023 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1024 	    (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
1025 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1026 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1027 		fatal_fr(r, "compose");
1028 	send_msg(conn, msg);
1029 	debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
1030 	    oldpath, newpath);
1031 	sshbuf_free(msg);
1032 
1033 	status = get_status(conn, id);
1034 	if (status != SSH2_FX_OK)
1035 		error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
1036 		    newpath, fx2txt(status));
1037 
1038 	return status == SSH2_FX_OK ? 0 : -1;
1039 }
1040 
1041 int
1042 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1043 {
1044 	struct sshbuf *msg;
1045 	u_int status, id;
1046 	int r;
1047 
1048 	if (conn->version < 3) {
1049 		error("This server does not support the symlink operation");
1050 		return(SSH2_FX_OP_UNSUPPORTED);
1051 	}
1052 
1053 	if ((msg = sshbuf_new()) == NULL)
1054 		fatal_f("sshbuf_new failed");
1055 
1056 	/* Send symlink request */
1057 	id = conn->msg_id++;
1058 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
1059 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1060 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1061 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1062 		fatal_fr(r, "compose");
1063 	send_msg(conn, msg);
1064 	debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
1065 	    newpath);
1066 	sshbuf_free(msg);
1067 
1068 	status = get_status(conn, id);
1069 	if (status != SSH2_FX_OK)
1070 		error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
1071 		    newpath, fx2txt(status));
1072 
1073 	return status == SSH2_FX_OK ? 0 : -1;
1074 }
1075 
1076 int
1077 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
1078 {
1079 	struct sshbuf *msg;
1080 	u_int status, id;
1081 	int r;
1082 
1083 	/* Silently return if the extension is not supported */
1084 	if ((conn->exts & SFTP_EXT_FSYNC) == 0)
1085 		return -1;
1086 
1087 	/* Send fsync request */
1088 	if ((msg = sshbuf_new()) == NULL)
1089 		fatal_f("sshbuf_new failed");
1090 	id = conn->msg_id++;
1091 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1092 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1093 	    (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
1094 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1095 		fatal_fr(r, "compose");
1096 	send_msg(conn, msg);
1097 	debug3("Sent message fsync@openssh.com I:%u", id);
1098 	sshbuf_free(msg);
1099 
1100 	status = get_status(conn, id);
1101 	if (status != SSH2_FX_OK)
1102 		error("Couldn't sync file: %s", fx2txt(status));
1103 
1104 	return status == SSH2_FX_OK ? 0 : -1;
1105 }
1106 
1107 #ifdef notyet
1108 char *
1109 do_readlink(struct sftp_conn *conn, const char *path)
1110 {
1111 	struct sshbuf *msg;
1112 	u_int expected_id, count, id;
1113 	char *filename, *longname;
1114 	Attrib a;
1115 	u_char type;
1116 	int r;
1117 
1118 	expected_id = id = conn->msg_id++;
1119 	send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
1120 
1121 	if ((msg = sshbuf_new()) == NULL)
1122 		fatal_f("sshbuf_new failed");
1123 
1124 	get_msg(conn, msg);
1125 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1126 	    (r = sshbuf_get_u32(msg, &id)) != 0)
1127 		fatal_fr(r, "parse");
1128 
1129 	if (id != expected_id)
1130 		fatal("ID mismatch (%u != %u)", id, expected_id);
1131 
1132 	if (type == SSH2_FXP_STATUS) {
1133 		u_int status;
1134 
1135 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
1136 			fatal_fr(r, "parse status");
1137 		error("Couldn't readlink: %s", fx2txt(status));
1138 		sshbuf_free(msg);
1139 		return(NULL);
1140 	} else if (type != SSH2_FXP_NAME)
1141 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1142 		    SSH2_FXP_NAME, type);
1143 
1144 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
1145 		fatal_fr(r, "parse count");
1146 	if (count != 1)
1147 		fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
1148 
1149 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1150 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1151 	    (r = decode_attrib(msg, &a)) != 0)
1152 		fatal_fr(r, "parse filenames/attrib");
1153 
1154 	debug3("SSH_FXP_READLINK %s -> %s", path, filename);
1155 
1156 	free(longname);
1157 
1158 	sshbuf_free(msg);
1159 
1160 	return filename;
1161 }
1162 #endif
1163 
1164 int
1165 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
1166     int quiet)
1167 {
1168 	struct sshbuf *msg;
1169 	u_int id;
1170 	int r;
1171 
1172 	if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
1173 		error("Server does not support statvfs@openssh.com extension");
1174 		return -1;
1175 	}
1176 
1177 	id = conn->msg_id++;
1178 
1179 	if ((msg = sshbuf_new()) == NULL)
1180 		fatal_f("sshbuf_new failed");
1181 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1182 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1183 	    (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
1184 	    (r = sshbuf_put_cstring(msg, path)) != 0)
1185 		fatal_fr(r, "compose");
1186 	send_msg(conn, msg);
1187 	sshbuf_free(msg);
1188 
1189 	return get_decode_statvfs(conn, st, id, quiet);
1190 }
1191 
1192 #ifdef notyet
1193 int
1194 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1195     struct sftp_statvfs *st, int quiet)
1196 {
1197 	struct sshbuf *msg;
1198 	u_int id;
1199 
1200 	if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
1201 		error("Server does not support fstatvfs@openssh.com extension");
1202 		return -1;
1203 	}
1204 
1205 	id = conn->msg_id++;
1206 
1207 	if ((msg = sshbuf_new()) == NULL)
1208 		fatal_f("sshbuf_new failed");
1209 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1210 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1211 	    (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
1212 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1213 		fatal_fr(r, "compose");
1214 	send_msg(conn, msg);
1215 	sshbuf_free(msg);
1216 
1217 	return get_decode_statvfs(conn, st, id, quiet);
1218 }
1219 #endif
1220 
1221 int
1222 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
1223 {
1224 	struct sshbuf *msg;
1225 	u_int status, id;
1226 	int r;
1227 
1228 	if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
1229 		error("Server does not support lsetstat@openssh.com extension");
1230 		return -1;
1231 	}
1232 
1233 	id = conn->msg_id++;
1234 	if ((msg = sshbuf_new()) == NULL)
1235 		fatal_f("sshbuf_new failed");
1236 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1237 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1238 	    (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
1239 	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
1240 	    (r = encode_attrib(msg, a)) != 0)
1241 		fatal_fr(r, "compose");
1242 	send_msg(conn, msg);
1243 	sshbuf_free(msg);
1244 
1245 	status = get_status(conn, id);
1246 	if (status != SSH2_FX_OK)
1247 		error("Couldn't setstat on \"%s\": %s", path,
1248 		    fx2txt(status));
1249 
1250 	return status == SSH2_FX_OK ? 0 : -1;
1251 }
1252 
1253 static void
1254 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1255     u_int len, const u_char *handle, u_int handle_len)
1256 {
1257 	struct sshbuf *msg;
1258 	int r;
1259 
1260 	if ((msg = sshbuf_new()) == NULL)
1261 		fatal_f("sshbuf_new failed");
1262 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
1263 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1264 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
1265 	    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1266 	    (r = sshbuf_put_u32(msg, len)) != 0)
1267 		fatal_fr(r, "compose");
1268 	send_msg(conn, msg);
1269 	sshbuf_free(msg);
1270 }
1271 
1272 int
1273 do_download(struct sftp_conn *conn, const char *remote_path,
1274     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
1275     int fsync_flag)
1276 {
1277 	Attrib junk;
1278 	struct sshbuf *msg;
1279 	u_char *handle;
1280 	int local_fd = -1, write_error;
1281 	int read_error, write_errno, lmodified = 0, reordered = 0, r;
1282 	u_int64_t offset = 0, size, highwater;
1283 	u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
1284 	off_t progress_counter;
1285 	size_t handle_len;
1286 	struct stat st;
1287 	struct request {
1288 		u_int id;
1289 		size_t len;
1290 		u_int64_t offset;
1291 		TAILQ_ENTRY(request) tq;
1292 	};
1293 	TAILQ_HEAD(reqhead, request) requests;
1294 	struct request *req;
1295 	u_char type;
1296 
1297 	TAILQ_INIT(&requests);
1298 
1299 	if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
1300 		return -1;
1301 
1302 	/* Do not preserve set[ug]id here, as we do not preserve ownership */
1303 	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
1304 		mode = a->perm & 0777;
1305 	else
1306 		mode = 0666;
1307 
1308 	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
1309 	    (!S_ISREG(a->perm))) {
1310 		error("Cannot download non-regular file: %s", remote_path);
1311 		return(-1);
1312 	}
1313 
1314 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
1315 		size = a->size;
1316 	else
1317 		size = 0;
1318 
1319 	buflen = conn->download_buflen;
1320 	if ((msg = sshbuf_new()) == NULL)
1321 		fatal_f("sshbuf_new failed");
1322 
1323 	attrib_clear(&junk); /* Send empty attributes */
1324 
1325 	/* Send open request */
1326 	id = conn->msg_id++;
1327 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1328 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1329 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
1330 	    (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
1331 	    (r = encode_attrib(msg, &junk)) != 0)
1332 		fatal_fr(r, "compose");
1333 	send_msg(conn, msg);
1334 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1335 
1336 	handle = get_handle(conn, id, &handle_len,
1337 	    "remote open(\"%s\")", remote_path);
1338 	if (handle == NULL) {
1339 		sshbuf_free(msg);
1340 		return(-1);
1341 	}
1342 
1343 	local_fd = open(local_path,
1344 	    O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
1345 	if (local_fd == -1) {
1346 		error("Couldn't open local file \"%s\" for writing: %s",
1347 		    local_path, strerror(errno));
1348 		goto fail;
1349 	}
1350 	offset = highwater = 0;
1351 	if (resume_flag) {
1352 		if (fstat(local_fd, &st) == -1) {
1353 			error("Unable to stat local file \"%s\": %s",
1354 			    local_path, strerror(errno));
1355 			goto fail;
1356 		}
1357 		if (st.st_size < 0) {
1358 			error("\"%s\" has negative size", local_path);
1359 			goto fail;
1360 		}
1361 		if ((u_int64_t)st.st_size > size) {
1362 			error("Unable to resume download of \"%s\": "
1363 			    "local file is larger than remote", local_path);
1364  fail:
1365 			do_close(conn, handle, handle_len);
1366 			sshbuf_free(msg);
1367 			free(handle);
1368 			if (local_fd != -1)
1369 				close(local_fd);
1370 			return -1;
1371 		}
1372 		offset = highwater = st.st_size;
1373 	}
1374 
1375 	/* Read from remote and write to local */
1376 	write_error = read_error = write_errno = num_req = 0;
1377 	max_req = 1;
1378 	progress_counter = offset;
1379 
1380 	if (showprogress && size != 0)
1381 		start_progress_meter(remote_path, size, &progress_counter);
1382 
1383 	while (num_req > 0 || max_req > 0) {
1384 		u_char *data;
1385 		size_t len;
1386 
1387 		/*
1388 		 * Simulate EOF on interrupt: stop sending new requests and
1389 		 * allow outstanding requests to drain gracefully
1390 		 */
1391 		if (interrupted) {
1392 			if (num_req == 0) /* If we haven't started yet... */
1393 				break;
1394 			max_req = 0;
1395 		}
1396 
1397 		/* Send some more requests */
1398 		while (num_req < max_req) {
1399 			debug3("Request range %llu -> %llu (%d/%d)",
1400 			    (unsigned long long)offset,
1401 			    (unsigned long long)offset + buflen - 1,
1402 			    num_req, max_req);
1403 			req = xcalloc(1, sizeof(*req));
1404 			req->id = conn->msg_id++;
1405 			req->len = buflen;
1406 			req->offset = offset;
1407 			offset += buflen;
1408 			num_req++;
1409 			TAILQ_INSERT_TAIL(&requests, req, tq);
1410 			send_read_request(conn, req->id, req->offset,
1411 			    req->len, handle, handle_len);
1412 		}
1413 
1414 		sshbuf_reset(msg);
1415 		get_msg(conn, msg);
1416 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1417 		    (r = sshbuf_get_u32(msg, &id)) != 0)
1418 			fatal_fr(r, "parse");
1419 		debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
1420 
1421 		/* Find the request in our queue */
1422 		for (req = TAILQ_FIRST(&requests);
1423 		    req != NULL && req->id != id;
1424 		    req = TAILQ_NEXT(req, tq))
1425 			;
1426 		if (req == NULL)
1427 			fatal("Unexpected reply %u", id);
1428 
1429 		switch (type) {
1430 		case SSH2_FXP_STATUS:
1431 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1432 				fatal_fr(r, "parse status");
1433 			if (status != SSH2_FX_EOF)
1434 				read_error = 1;
1435 			max_req = 0;
1436 			TAILQ_REMOVE(&requests, req, tq);
1437 			free(req);
1438 			num_req--;
1439 			break;
1440 		case SSH2_FXP_DATA:
1441 			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
1442 				fatal_fr(r, "parse data");
1443 			debug3("Received data %llu -> %llu",
1444 			    (unsigned long long)req->offset,
1445 			    (unsigned long long)req->offset + len - 1);
1446 			if (len > req->len)
1447 				fatal("Received more data than asked for "
1448 				    "%zu > %zu", len, req->len);
1449 			lmodified = 1;
1450 			if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
1451 			    atomicio(vwrite, local_fd, data, len) != len) &&
1452 			    !write_error) {
1453 				write_errno = errno;
1454 				write_error = 1;
1455 				max_req = 0;
1456 			}
1457 			else if (!reordered && req->offset <= highwater)
1458 				highwater = req->offset + len;
1459 			else if (!reordered && req->offset > highwater)
1460 				reordered = 1;
1461 			progress_counter += len;
1462 			free(data);
1463 
1464 			if (len == req->len) {
1465 				TAILQ_REMOVE(&requests, req, tq);
1466 				free(req);
1467 				num_req--;
1468 			} else {
1469 				/* Resend the request for the missing data */
1470 				debug3("Short data block, re-requesting "
1471 				    "%llu -> %llu (%2d)",
1472 				    (unsigned long long)req->offset + len,
1473 				    (unsigned long long)req->offset +
1474 				    req->len - 1, num_req);
1475 				req->id = conn->msg_id++;
1476 				req->len -= len;
1477 				req->offset += len;
1478 				send_read_request(conn, req->id,
1479 				    req->offset, req->len, handle, handle_len);
1480 				/* Reduce the request size */
1481 				if (len < buflen)
1482 					buflen = MAXIMUM(MIN_READ_SIZE, len);
1483 			}
1484 			if (max_req > 0) { /* max_req = 0 iff EOF received */
1485 				if (size > 0 && offset > size) {
1486 					/* Only one request at a time
1487 					 * after the expected EOF */
1488 					debug3("Finish at %llu (%2d)",
1489 					    (unsigned long long)offset,
1490 					    num_req);
1491 					max_req = 1;
1492 				} else if (max_req < conn->num_requests) {
1493 					++max_req;
1494 				}
1495 			}
1496 			break;
1497 		default:
1498 			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
1499 			    SSH2_FXP_DATA, type);
1500 		}
1501 	}
1502 
1503 	if (showprogress && size)
1504 		stop_progress_meter();
1505 
1506 	/* Sanity check */
1507 	if (TAILQ_FIRST(&requests) != NULL)
1508 		fatal("Transfer complete, but requests still in queue");
1509 	/* Truncate at highest contiguous point to avoid holes on interrupt */
1510 	if (read_error || write_error || interrupted) {
1511 		if (reordered && resume_flag) {
1512 			error("Unable to resume download of \"%s\": "
1513 			    "server reordered requests", local_path);
1514 		}
1515 		debug("truncating at %llu", (unsigned long long)highwater);
1516 		if (ftruncate(local_fd, highwater) == -1)
1517 			error("ftruncate \"%s\": %s", local_path,
1518 			    strerror(errno));
1519 	}
1520 	if (read_error) {
1521 		error("Couldn't read from remote file \"%s\" : %s",
1522 		    remote_path, fx2txt(status));
1523 		status = -1;
1524 		do_close(conn, handle, handle_len);
1525 	} else if (write_error) {
1526 		error("Couldn't write to \"%s\": %s", local_path,
1527 		    strerror(write_errno));
1528 		status = SSH2_FX_FAILURE;
1529 		do_close(conn, handle, handle_len);
1530 	} else {
1531 		if (do_close(conn, handle, handle_len) != 0 || interrupted)
1532 			status = SSH2_FX_FAILURE;
1533 		else
1534 			status = SSH2_FX_OK;
1535 		/* Override umask and utimes if asked */
1536 		if (preserve_flag && fchmod(local_fd, mode) == -1)
1537 			error("Couldn't set mode on \"%s\": %s", local_path,
1538 			    strerror(errno));
1539 		if (preserve_flag &&
1540 		    (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1541 			struct timeval tv[2];
1542 			tv[0].tv_sec = a->atime;
1543 			tv[1].tv_sec = a->mtime;
1544 			tv[0].tv_usec = tv[1].tv_usec = 0;
1545 			if (utimes(local_path, tv) == -1)
1546 				error("Can't set times on \"%s\": %s",
1547 				    local_path, strerror(errno));
1548 		}
1549 		if (resume_flag && !lmodified)
1550 			logit("File \"%s\" was not modified", local_path);
1551 		else if (fsync_flag) {
1552 			debug("syncing \"%s\"", local_path);
1553 			if (fsync(local_fd) == -1)
1554 				error("Couldn't sync file \"%s\": %s",
1555 				    local_path, strerror(errno));
1556 		}
1557 	}
1558 	close(local_fd);
1559 	sshbuf_free(msg);
1560 	free(handle);
1561 
1562 	return status == SSH2_FX_OK ? 0 : -1;
1563 }
1564 
1565 static int
1566 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1567     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
1568     int resume_flag, int fsync_flag)
1569 {
1570 	int i, ret = 0;
1571 	SFTP_DIRENT **dir_entries;
1572 	char *filename, *new_src = NULL, *new_dst = NULL;
1573 	mode_t mode = 0777, tmpmode = mode;
1574 
1575 	if (depth >= MAX_DIR_DEPTH) {
1576 		error("Maximum directory depth exceeded: %d levels", depth);
1577 		return -1;
1578 	}
1579 
1580 	if (dirattrib == NULL &&
1581 	    (dirattrib = do_stat(conn, src, 1)) == NULL) {
1582 		error("Unable to stat remote directory \"%s\"", src);
1583 		return -1;
1584 	}
1585 	if (!S_ISDIR(dirattrib->perm)) {
1586 		error("\"%s\" is not a directory", src);
1587 		return -1;
1588 	}
1589 	if (print_flag)
1590 		mprintf("Retrieving %s\n", src);
1591 
1592 	if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1593 		mode = dirattrib->perm & 01777;
1594 		tmpmode = mode | (S_IWUSR|S_IXUSR);
1595 	} else {
1596 		debug("Server did not send permissions for "
1597 		    "directory \"%s\"", dst);
1598 	}
1599 
1600 	if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) {
1601 		error("mkdir %s: %s", dst, strerror(errno));
1602 		return -1;
1603 	}
1604 
1605 	if (do_readdir(conn, src, &dir_entries) == -1) {
1606 		error("%s: Failed to get directory contents", src);
1607 		return -1;
1608 	}
1609 
1610 	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
1611 		free(new_dst);
1612 		free(new_src);
1613 
1614 		filename = dir_entries[i]->filename;
1615 		new_dst = path_append(dst, filename);
1616 		new_src = path_append(src, filename);
1617 
1618 		if (S_ISDIR(dir_entries[i]->a.perm)) {
1619 			if (strcmp(filename, ".") == 0 ||
1620 			    strcmp(filename, "..") == 0)
1621 				continue;
1622 			if (download_dir_internal(conn, new_src, new_dst,
1623 			    depth + 1, &(dir_entries[i]->a), preserve_flag,
1624 			    print_flag, resume_flag, fsync_flag) == -1)
1625 				ret = -1;
1626 		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1627 			if (do_download(conn, new_src, new_dst,
1628 			    &(dir_entries[i]->a), preserve_flag,
1629 			    resume_flag, fsync_flag) == -1) {
1630 				error("Download of file %s to %s failed",
1631 				    new_src, new_dst);
1632 				ret = -1;
1633 			}
1634 		} else
1635 			logit("%s: not a regular file\n", new_src);
1636 
1637 	}
1638 	free(new_dst);
1639 	free(new_src);
1640 
1641 	if (preserve_flag) {
1642 		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1643 			struct timeval tv[2];
1644 			tv[0].tv_sec = dirattrib->atime;
1645 			tv[1].tv_sec = dirattrib->mtime;
1646 			tv[0].tv_usec = tv[1].tv_usec = 0;
1647 			if (utimes(dst, tv) == -1)
1648 				error("Can't set times on \"%s\": %s",
1649 				    dst, strerror(errno));
1650 		} else
1651 			debug("Server did not send times for directory "
1652 			    "\"%s\"", dst);
1653 	}
1654 
1655 	if (mode != tmpmode && chmod(dst, mode) == -1)
1656 		error("Can't set final mode on \"%s\": %s", dst,
1657 		    strerror(errno));
1658 
1659 	free_sftp_dirents(dir_entries);
1660 
1661 	return ret;
1662 }
1663 
1664 int
1665 download_dir(struct sftp_conn *conn, const char *src, const char *dst,
1666     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
1667     int fsync_flag)
1668 {
1669 	char *src_canon;
1670 	int ret;
1671 
1672 	if ((src_canon = do_realpath(conn, src)) == NULL) {
1673 		error("Unable to canonicalize path \"%s\"", src);
1674 		return -1;
1675 	}
1676 
1677 	ret = download_dir_internal(conn, src_canon, dst, 0,
1678 	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
1679 	free(src_canon);
1680 	return ret;
1681 }
1682 
1683 int
1684 do_upload(struct sftp_conn *conn, const char *local_path,
1685     const char *remote_path, int preserve_flag, int resume, int fsync_flag)
1686 {
1687 	int r, local_fd;
1688 	u_int status = SSH2_FX_OK;
1689 	u_int id;
1690 	u_char type;
1691 	off_t offset, progress_counter;
1692 	u_char *handle, *data;
1693 	struct sshbuf *msg;
1694 	struct stat sb;
1695 	Attrib a, *c = NULL;
1696 	u_int32_t startid;
1697 	u_int32_t ackid;
1698 	struct outstanding_ack {
1699 		u_int id;
1700 		u_int len;
1701 		off_t offset;
1702 		TAILQ_ENTRY(outstanding_ack) tq;
1703 	};
1704 	TAILQ_HEAD(ackhead, outstanding_ack) acks;
1705 	struct outstanding_ack *ack = NULL;
1706 	size_t handle_len;
1707 
1708 	TAILQ_INIT(&acks);
1709 
1710 	if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
1711 		error("Couldn't open local file \"%s\" for reading: %s",
1712 		    local_path, strerror(errno));
1713 		return(-1);
1714 	}
1715 	if (fstat(local_fd, &sb) == -1) {
1716 		error("Couldn't fstat local file \"%s\": %s",
1717 		    local_path, strerror(errno));
1718 		close(local_fd);
1719 		return(-1);
1720 	}
1721 	if (!S_ISREG(sb.st_mode)) {
1722 		error("%s is not a regular file", local_path);
1723 		close(local_fd);
1724 		return(-1);
1725 	}
1726 	stat_to_attrib(&sb, &a);
1727 
1728 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1729 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1730 	a.perm &= 0777;
1731 	if (!preserve_flag)
1732 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1733 
1734 	if (resume) {
1735 		/* Get remote file size if it exists */
1736 		if ((c = do_stat(conn, remote_path, 0)) == NULL) {
1737 			close(local_fd);
1738 			return -1;
1739 		}
1740 
1741 		if ((off_t)c->size >= sb.st_size) {
1742 			error("destination file bigger or same size as "
1743 			    "source file");
1744 			close(local_fd);
1745 			return -1;
1746 		}
1747 
1748 		if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
1749 			close(local_fd);
1750 			return -1;
1751 		}
1752 	}
1753 
1754 	if ((msg = sshbuf_new()) == NULL)
1755 		fatal_f("sshbuf_new failed");
1756 
1757 	/* Send open request */
1758 	id = conn->msg_id++;
1759 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1760 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1761 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
1762 	    (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1763 	    (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
1764 	    (r = encode_attrib(msg, &a)) != 0)
1765 		fatal_fr(r, "compose");
1766 	send_msg(conn, msg);
1767 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1768 
1769 	sshbuf_reset(msg);
1770 
1771 	handle = get_handle(conn, id, &handle_len,
1772 	    "remote open(\"%s\")", remote_path);
1773 	if (handle == NULL) {
1774 		close(local_fd);
1775 		sshbuf_free(msg);
1776 		return -1;
1777 	}
1778 
1779 	startid = ackid = id + 1;
1780 	data = xmalloc(conn->upload_buflen);
1781 
1782 	/* Read from local and write to remote */
1783 	offset = progress_counter = (resume ? c->size : 0);
1784 	if (showprogress)
1785 		start_progress_meter(local_path, sb.st_size,
1786 		    &progress_counter);
1787 
1788 	for (;;) {
1789 		int len;
1790 
1791 		/*
1792 		 * Can't use atomicio here because it returns 0 on EOF,
1793 		 * thus losing the last block of the file.
1794 		 * Simulate an EOF on interrupt, allowing ACKs from the
1795 		 * server to drain.
1796 		 */
1797 		if (interrupted || status != SSH2_FX_OK)
1798 			len = 0;
1799 		else do
1800 			len = read(local_fd, data, conn->upload_buflen);
1801 		while ((len == -1) && (errno == EINTR || errno == EAGAIN));
1802 
1803 		if (len == -1)
1804 			fatal("Couldn't read from \"%s\": %s", local_path,
1805 			    strerror(errno));
1806 
1807 		if (len != 0) {
1808 			ack = xcalloc(1, sizeof(*ack));
1809 			ack->id = ++id;
1810 			ack->offset = offset;
1811 			ack->len = len;
1812 			TAILQ_INSERT_TAIL(&acks, ack, tq);
1813 
1814 			sshbuf_reset(msg);
1815 			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
1816 			    (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
1817 			    (r = sshbuf_put_string(msg, handle,
1818 			    handle_len)) != 0 ||
1819 			    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1820 			    (r = sshbuf_put_string(msg, data, len)) != 0)
1821 				fatal_fr(r, "compose");
1822 			send_msg(conn, msg);
1823 			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
1824 			    id, (unsigned long long)offset, len);
1825 		} else if (TAILQ_FIRST(&acks) == NULL)
1826 			break;
1827 
1828 		if (ack == NULL)
1829 			fatal("Unexpected ACK %u", id);
1830 
1831 		if (id == startid || len == 0 ||
1832 		    id - ackid >= conn->num_requests) {
1833 			u_int rid;
1834 
1835 			sshbuf_reset(msg);
1836 			get_msg(conn, msg);
1837 			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1838 			    (r = sshbuf_get_u32(msg, &rid)) != 0)
1839 				fatal_fr(r, "parse");
1840 
1841 			if (type != SSH2_FXP_STATUS)
1842 				fatal("Expected SSH2_FXP_STATUS(%d) packet, "
1843 				    "got %d", SSH2_FXP_STATUS, type);
1844 
1845 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1846 				fatal_fr(r, "parse status");
1847 			debug3("SSH2_FXP_STATUS %u", status);
1848 
1849 			/* Find the request in our queue */
1850 			for (ack = TAILQ_FIRST(&acks);
1851 			    ack != NULL && ack->id != rid;
1852 			    ack = TAILQ_NEXT(ack, tq))
1853 				;
1854 			if (ack == NULL)
1855 				fatal("Can't find request for ID %u", rid);
1856 			TAILQ_REMOVE(&acks, ack, tq);
1857 			debug3("In write loop, ack for %u %u bytes at %lld",
1858 			    ack->id, ack->len, (long long)ack->offset);
1859 			++ackid;
1860 			progress_counter += ack->len;
1861 			free(ack);
1862 		}
1863 		offset += len;
1864 		if (offset < 0)
1865 			fatal_f("offset < 0");
1866 	}
1867 	sshbuf_free(msg);
1868 
1869 	if (showprogress)
1870 		stop_progress_meter();
1871 	free(data);
1872 
1873 	if (status != SSH2_FX_OK) {
1874 		error("Couldn't write to remote file \"%s\": %s",
1875 		    remote_path, fx2txt(status));
1876 		status = SSH2_FX_FAILURE;
1877 	}
1878 
1879 	if (close(local_fd) == -1) {
1880 		error("Couldn't close local file \"%s\": %s", local_path,
1881 		    strerror(errno));
1882 		status = SSH2_FX_FAILURE;
1883 	}
1884 
1885 	/* Override umask and utimes if asked */
1886 	if (preserve_flag)
1887 		do_fsetstat(conn, handle, handle_len, &a);
1888 
1889 	if (fsync_flag)
1890 		(void)do_fsync(conn, handle, handle_len);
1891 
1892 	if (do_close(conn, handle, handle_len) != 0)
1893 		status = SSH2_FX_FAILURE;
1894 
1895 	free(handle);
1896 
1897 	return status == SSH2_FX_OK ? 0 : -1;
1898 }
1899 
1900 static int
1901 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1902     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
1903 {
1904 	int ret = 0;
1905 	DIR *dirp;
1906 	struct dirent *dp;
1907 	char *filename, *new_src = NULL, *new_dst = NULL;
1908 	struct stat sb;
1909 	Attrib a, *dirattrib;
1910 	u_int32_t saved_perm;
1911 
1912 	if (depth >= MAX_DIR_DEPTH) {
1913 		error("Maximum directory depth exceeded: %d levels", depth);
1914 		return -1;
1915 	}
1916 
1917 	if (stat(src, &sb) == -1) {
1918 		error("Couldn't stat directory \"%s\": %s",
1919 		    src, strerror(errno));
1920 		return -1;
1921 	}
1922 	if (!S_ISDIR(sb.st_mode)) {
1923 		error("\"%s\" is not a directory", src);
1924 		return -1;
1925 	}
1926 	if (print_flag)
1927 		mprintf("Entering %s\n", src);
1928 
1929 	attrib_clear(&a);
1930 	stat_to_attrib(&sb, &a);
1931 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1932 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1933 	a.perm &= 01777;
1934 	if (!preserve_flag)
1935 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1936 
1937 	/*
1938 	 * sftp lacks a portable status value to match errno EEXIST,
1939 	 * so if we get a failure back then we must check whether
1940 	 * the path already existed and is a directory.  Ensure we can
1941 	 * write to the directory we create for the duration of the transfer.
1942 	 */
1943 	saved_perm = a.perm;
1944 	a.perm |= (S_IWUSR|S_IXUSR);
1945 	if (do_mkdir(conn, dst, &a, 0) != 0) {
1946 		if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
1947 			return -1;
1948 		if (!S_ISDIR(dirattrib->perm)) {
1949 			error("\"%s\" exists but is not a directory", dst);
1950 			return -1;
1951 		}
1952 	}
1953 	a.perm = saved_perm;
1954 
1955 	if ((dirp = opendir(src)) == NULL) {
1956 		error("Failed to open dir \"%s\": %s", src, strerror(errno));
1957 		return -1;
1958 	}
1959 
1960 	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
1961 		if (dp->d_ino == 0)
1962 			continue;
1963 		free(new_dst);
1964 		free(new_src);
1965 		filename = dp->d_name;
1966 		new_dst = path_append(dst, filename);
1967 		new_src = path_append(src, filename);
1968 
1969 		if (lstat(new_src, &sb) == -1) {
1970 			logit("%s: lstat failed: %s", filename,
1971 			    strerror(errno));
1972 			ret = -1;
1973 		} else if (S_ISDIR(sb.st_mode)) {
1974 			if (strcmp(filename, ".") == 0 ||
1975 			    strcmp(filename, "..") == 0)
1976 				continue;
1977 
1978 			if (upload_dir_internal(conn, new_src, new_dst,
1979 			    depth + 1, preserve_flag, print_flag, resume,
1980 			    fsync_flag) == -1)
1981 				ret = -1;
1982 		} else if (S_ISREG(sb.st_mode)) {
1983 			if (do_upload(conn, new_src, new_dst,
1984 			    preserve_flag, resume, fsync_flag) == -1) {
1985 				error("Uploading of file %s to %s failed!",
1986 				    new_src, new_dst);
1987 				ret = -1;
1988 			}
1989 		} else
1990 			logit("%s: not a regular file\n", filename);
1991 	}
1992 	free(new_dst);
1993 	free(new_src);
1994 
1995 	do_setstat(conn, dst, &a);
1996 
1997 	(void) closedir(dirp);
1998 	return ret;
1999 }
2000 
2001 int
2002 upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
2003     int preserve_flag, int print_flag, int resume, int fsync_flag)
2004 {
2005 	char *dst_canon;
2006 	int ret;
2007 
2008 	if ((dst_canon = do_realpath(conn, dst)) == NULL) {
2009 		error("Unable to canonicalize path \"%s\"", dst);
2010 		return -1;
2011 	}
2012 
2013 	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
2014 	    print_flag, resume, fsync_flag);
2015 
2016 	free(dst_canon);
2017 	return ret;
2018 }
2019 
2020 char *
2021 path_append(const char *p1, const char *p2)
2022 {
2023 	char *ret;
2024 	size_t len = strlen(p1) + strlen(p2) + 2;
2025 
2026 	ret = xmalloc(len);
2027 	strlcpy(ret, p1, len);
2028 	if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
2029 		strlcat(ret, "/", len);
2030 	strlcat(ret, p2, len);
2031 
2032 	return(ret);
2033 }
2034 
2035 char *
2036 make_absolute(char *p, const char *pwd)
2037 {
2038 	char *abs_str;
2039 
2040 	/* Derelativise */
2041 	if (p && !path_absolute(p)) {
2042 		abs_str = path_append(pwd, p);
2043 		free(p);
2044 		return(abs_str);
2045 	} else
2046 		return(p);
2047 }
2048 
2049 int
2050 remote_is_dir(struct sftp_conn *conn, const char *path)
2051 {
2052 	Attrib *a;
2053 
2054 	/* XXX: report errors? */
2055 	if ((a = do_stat(conn, path, 1)) == NULL)
2056 		return(0);
2057 	if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
2058 		return(0);
2059 	return(S_ISDIR(a->perm));
2060 }
2061 
2062 
2063 int
2064 local_is_dir(const char *path)
2065 {
2066 	struct stat sb;
2067 
2068 	/* XXX: report errors? */
2069 	if (stat(path, &sb) == -1)
2070 		return(0);
2071 
2072 	return(S_ISDIR(sb.st_mode));
2073 }
2074 
2075 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
2076 int
2077 globpath_is_dir(const char *pathname)
2078 {
2079 	size_t l = strlen(pathname);
2080 
2081 	return l > 0 && pathname[l - 1] == '/';
2082 }
2083 
2084