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