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