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