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