1/* $OpenBSD: sftp-client.c,v 1.175 2023/11/13 09:18:19 tobhe 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#ifdef HAVE_POLL_H
41#include <poll.h>
42#else
43# ifdef HAVE_SYS_POLL_H
44#  include <sys/poll.h>
45# endif
46#endif
47#include <fcntl.h>
48#include <signal.h>
49#include <stdarg.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54
55#include "xmalloc.h"
56#include "ssherr.h"
57#include "sshbuf.h"
58#include "log.h"
59#include "atomicio.h"
60#include "progressmeter.h"
61#include "misc.h"
62#include "utf8.h"
63
64#include "sftp.h"
65#include "sftp-common.h"
66#include "sftp-client.h"
67
68extern volatile sig_atomic_t interrupted;
69extern int showprogress;
70
71/* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */
72#define DEFAULT_COPY_BUFLEN	32768
73
74/* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */
75#define DEFAULT_NUM_REQUESTS	64
76
77/* Minimum amount of data to read at a time */
78#define MIN_READ_SIZE	512
79
80/* Maximum depth to descend in directory trees */
81#define MAX_DIR_DEPTH 64
82
83/* Directory separator characters */
84#ifdef HAVE_CYGWIN
85# define SFTP_DIRECTORY_CHARS      "/\\"
86#else /* HAVE_CYGWIN */
87# define SFTP_DIRECTORY_CHARS      "/"
88#endif /* HAVE_CYGWIN */
89
90struct sftp_conn {
91	int fd_in;
92	int fd_out;
93	u_int download_buflen;
94	u_int upload_buflen;
95	u_int num_requests;
96	u_int version;
97	u_int msg_id;
98#define SFTP_EXT_POSIX_RENAME		0x00000001
99#define SFTP_EXT_STATVFS		0x00000002
100#define SFTP_EXT_FSTATVFS		0x00000004
101#define SFTP_EXT_HARDLINK		0x00000008
102#define SFTP_EXT_FSYNC			0x00000010
103#define SFTP_EXT_LSETSTAT		0x00000020
104#define SFTP_EXT_LIMITS			0x00000040
105#define SFTP_EXT_PATH_EXPAND		0x00000080
106#define SFTP_EXT_COPY_DATA		0x00000100
107#define SFTP_EXT_GETUSERSGROUPS_BY_ID	0x00000200
108	u_int exts;
109	u_int64_t limit_kbps;
110	struct bwlimit bwlimit_in, bwlimit_out;
111};
112
113/* Tracks in-progress requests during file transfers */
114struct request {
115	u_int id;
116	size_t len;
117	u_int64_t offset;
118	TAILQ_ENTRY(request) tq;
119};
120TAILQ_HEAD(requests, request);
121
122static u_char *
123get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
124    const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
125
126static struct request *
127request_enqueue(struct requests *requests, u_int id, size_t len,
128    uint64_t offset)
129{
130	struct request *req;
131
132	req = xcalloc(1, sizeof(*req));
133	req->id = id;
134	req->len = len;
135	req->offset = offset;
136	TAILQ_INSERT_TAIL(requests, req, tq);
137	return req;
138}
139
140static struct request *
141request_find(struct requests *requests, u_int id)
142{
143	struct request *req;
144
145	for (req = TAILQ_FIRST(requests);
146	    req != NULL && req->id != id;
147	    req = TAILQ_NEXT(req, tq))
148		;
149	return req;
150}
151
152static int
153sftpio(void *_bwlimit, size_t amount)
154{
155	struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
156
157	refresh_progress_meter(0);
158	if (bwlimit != NULL)
159		bandwidth_limit(bwlimit, amount);
160	return 0;
161}
162
163static void
164send_msg(struct sftp_conn *conn, struct sshbuf *m)
165{
166	u_char mlen[4];
167	struct iovec iov[2];
168
169	if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
170		fatal("Outbound message too long %zu", sshbuf_len(m));
171
172	/* Send length first */
173	put_u32(mlen, sshbuf_len(m));
174	iov[0].iov_base = mlen;
175	iov[0].iov_len = sizeof(mlen);
176	iov[1].iov_base = (u_char *)sshbuf_ptr(m);
177	iov[1].iov_len = sshbuf_len(m);
178
179	if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
180	    conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
181	    sshbuf_len(m) + sizeof(mlen))
182		fatal("Couldn't send packet: %s", strerror(errno));
183
184	sshbuf_reset(m);
185}
186
187static void
188get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
189{
190	u_int msg_len;
191	u_char *p;
192	int r;
193
194	sshbuf_reset(m);
195	if ((r = sshbuf_reserve(m, 4, &p)) != 0)
196		fatal_fr(r, "reserve");
197	if (atomicio6(read, conn->fd_in, p, 4, sftpio,
198	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
199		if (errno == EPIPE || errno == ECONNRESET)
200			fatal("Connection closed");
201		else
202			fatal("Couldn't read packet: %s", strerror(errno));
203	}
204
205	if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
206		fatal_fr(r, "sshbuf_get_u32");
207	if (msg_len > SFTP_MAX_MSG_LENGTH) {
208		do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
209		    "Received message too long %u", msg_len);
210		fatal("Ensure the remote shell produces no output "
211		    "for non-interactive sessions.");
212	}
213
214	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
215		fatal_fr(r, "reserve");
216	if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
217	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
218	    != msg_len) {
219		if (errno == EPIPE)
220			fatal("Connection closed");
221		else
222			fatal("Read packet: %s", strerror(errno));
223	}
224}
225
226static void
227get_msg(struct sftp_conn *conn, struct sshbuf *m)
228{
229	get_msg_extended(conn, m, 0);
230}
231
232static void
233send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
234    u_int len)
235{
236	struct sshbuf *msg;
237	int r;
238
239	if ((msg = sshbuf_new()) == NULL)
240		fatal_f("sshbuf_new failed");
241	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
242	    (r = sshbuf_put_u32(msg, id)) != 0 ||
243	    (r = sshbuf_put_string(msg, s, len)) != 0)
244		fatal_fr(r, "compose");
245	send_msg(conn, msg);
246	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
247	sshbuf_free(msg);
248}
249
250static void
251send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
252    const void *s, u_int len, Attrib *a)
253{
254	struct sshbuf *msg;
255	int r;
256
257	if ((msg = sshbuf_new()) == NULL)
258		fatal_f("sshbuf_new failed");
259	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
260	    (r = sshbuf_put_u32(msg, id)) != 0 ||
261	    (r = sshbuf_put_string(msg, s, len)) != 0 ||
262	    (r = encode_attrib(msg, a)) != 0)
263		fatal_fr(r, "compose");
264	send_msg(conn, msg);
265	debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o",
266	    conn->fd_out, code, id, a->flags, a->perm);
267	sshbuf_free(msg);
268}
269
270static u_int
271get_status(struct sftp_conn *conn, u_int expected_id)
272{
273	struct sshbuf *msg;
274	u_char type;
275	u_int id, status;
276	int r;
277
278	if ((msg = sshbuf_new()) == NULL)
279		fatal_f("sshbuf_new failed");
280	get_msg(conn, msg);
281	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
282	    (r = sshbuf_get_u32(msg, &id)) != 0)
283		fatal_fr(r, "compose");
284
285	if (id != expected_id)
286		fatal("ID mismatch (%u != %u)", id, expected_id);
287	if (type != SSH2_FXP_STATUS)
288		fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
289		    SSH2_FXP_STATUS, type);
290
291	if ((r = sshbuf_get_u32(msg, &status)) != 0)
292		fatal_fr(r, "parse");
293	sshbuf_free(msg);
294
295	debug3("SSH2_FXP_STATUS %u", status);
296
297	return status;
298}
299
300static u_char *
301get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
302    const char *errfmt, ...)
303{
304	struct sshbuf *msg;
305	u_int id, status;
306	u_char type;
307	u_char *handle;
308	char errmsg[256];
309	va_list args;
310	int r;
311
312	va_start(args, errfmt);
313	if (errfmt != NULL)
314		vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
315	va_end(args);
316
317	if ((msg = sshbuf_new()) == NULL)
318		fatal_f("sshbuf_new failed");
319	get_msg(conn, msg);
320	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
321	    (r = sshbuf_get_u32(msg, &id)) != 0)
322		fatal_fr(r, "parse");
323
324	if (id != expected_id)
325		fatal("%s: ID mismatch (%u != %u)",
326		    errfmt == NULL ? __func__ : errmsg, id, expected_id);
327	if (type == SSH2_FXP_STATUS) {
328		if ((r = sshbuf_get_u32(msg, &status)) != 0)
329			fatal_fr(r, "parse status");
330		if (errfmt != NULL)
331			error("%s: %s", errmsg, fx2txt(status));
332		sshbuf_free(msg);
333		return(NULL);
334	} else if (type != SSH2_FXP_HANDLE)
335		fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
336		    errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
337
338	if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
339		fatal_fr(r, "parse handle");
340	sshbuf_free(msg);
341
342	return handle;
343}
344
345static int
346get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a)
347{
348	struct sshbuf *msg;
349	u_int id;
350	u_char type;
351	int r;
352	Attrib attr;
353
354	if (a != NULL)
355		memset(a, '\0', sizeof(*a));
356	if ((msg = sshbuf_new()) == NULL)
357		fatal_f("sshbuf_new failed");
358	get_msg(conn, msg);
359
360	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
361	    (r = sshbuf_get_u32(msg, &id)) != 0)
362		fatal_fr(r, "parse");
363
364	if (id != expected_id)
365		fatal("ID mismatch (%u != %u)", id, expected_id);
366	if (type == SSH2_FXP_STATUS) {
367		u_int status;
368
369		if ((r = sshbuf_get_u32(msg, &status)) != 0)
370			fatal_fr(r, "parse status");
371		if (quiet)
372			debug("stat remote: %s", fx2txt(status));
373		else
374			error("stat remote: %s", fx2txt(status));
375		sshbuf_free(msg);
376		return -1;
377	} else if (type != SSH2_FXP_ATTRS) {
378		fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
379		    SSH2_FXP_ATTRS, type);
380	}
381	if ((r = decode_attrib(msg, &attr)) != 0) {
382		error_fr(r, "decode_attrib");
383		sshbuf_free(msg);
384		return -1;
385	}
386	/* success */
387	if (a != NULL)
388		*a = attr;
389	debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o",
390	    type, id, attr.flags, attr.perm);
391	sshbuf_free(msg);
392
393	return 0;
394}
395
396static int
397get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
398    u_int expected_id, int quiet)
399{
400	struct sshbuf *msg;
401	u_char type;
402	u_int id;
403	u_int64_t flag;
404	int r;
405
406	if ((msg = sshbuf_new()) == NULL)
407		fatal_f("sshbuf_new failed");
408	get_msg(conn, msg);
409
410	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
411	    (r = sshbuf_get_u32(msg, &id)) != 0)
412		fatal_fr(r, "parse");
413
414	debug3("Received statvfs reply T:%u I:%u", type, id);
415	if (id != expected_id)
416		fatal("ID mismatch (%u != %u)", id, expected_id);
417	if (type == SSH2_FXP_STATUS) {
418		u_int status;
419
420		if ((r = sshbuf_get_u32(msg, &status)) != 0)
421			fatal_fr(r, "parse status");
422		if (quiet)
423			debug("remote statvfs: %s", fx2txt(status));
424		else
425			error("remote statvfs: %s", fx2txt(status));
426		sshbuf_free(msg);
427		return -1;
428	} else if (type != SSH2_FXP_EXTENDED_REPLY) {
429		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
430		    SSH2_FXP_EXTENDED_REPLY, type);
431	}
432
433	memset(st, 0, sizeof(*st));
434	if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
435	    (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
436	    (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
437	    (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
438	    (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
439	    (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
440	    (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
441	    (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
442	    (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
443	    (r = sshbuf_get_u64(msg, &flag)) != 0 ||
444	    (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
445		fatal_fr(r, "parse statvfs");
446
447	st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
448	st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
449
450	sshbuf_free(msg);
451
452	return 0;
453}
454
455struct sftp_conn *
456sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
457    u_int64_t limit_kbps)
458{
459	u_char type;
460	struct sshbuf *msg;
461	struct sftp_conn *ret;
462	int r;
463
464	ret = xcalloc(1, sizeof(*ret));
465	ret->msg_id = 1;
466	ret->fd_in = fd_in;
467	ret->fd_out = fd_out;
468	ret->download_buflen = ret->upload_buflen =
469	    transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN;
470	ret->num_requests =
471	    num_requests ? num_requests : DEFAULT_NUM_REQUESTS;
472	ret->exts = 0;
473	ret->limit_kbps = 0;
474
475	if ((msg = sshbuf_new()) == NULL)
476		fatal_f("sshbuf_new failed");
477	if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
478	    (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
479		fatal_fr(r, "parse");
480
481	send_msg(ret, msg);
482
483	get_msg_extended(ret, msg, 1);
484
485	/* Expecting a VERSION reply */
486	if ((r = sshbuf_get_u8(msg, &type)) != 0)
487		fatal_fr(r, "parse type");
488	if (type != SSH2_FXP_VERSION) {
489		error("Invalid packet back from SSH2_FXP_INIT (type %u)",
490		    type);
491		sshbuf_free(msg);
492		free(ret);
493		return(NULL);
494	}
495	if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
496		fatal_fr(r, "parse version");
497
498	debug2("Remote version: %u", ret->version);
499
500	/* Check for extensions */
501	while (sshbuf_len(msg) > 0) {
502		char *name;
503		u_char *value;
504		size_t vlen;
505		int known = 0;
506
507		if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
508		    (r = sshbuf_get_string(msg, &value, &vlen)) != 0)
509			fatal_fr(r, "parse extension");
510		if (strcmp(name, "posix-rename@openssh.com") == 0 &&
511		    strcmp((char *)value, "1") == 0) {
512			ret->exts |= SFTP_EXT_POSIX_RENAME;
513			known = 1;
514		} else if (strcmp(name, "statvfs@openssh.com") == 0 &&
515		    strcmp((char *)value, "2") == 0) {
516			ret->exts |= SFTP_EXT_STATVFS;
517			known = 1;
518		} else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
519		    strcmp((char *)value, "2") == 0) {
520			ret->exts |= SFTP_EXT_FSTATVFS;
521			known = 1;
522		} else if (strcmp(name, "hardlink@openssh.com") == 0 &&
523		    strcmp((char *)value, "1") == 0) {
524			ret->exts |= SFTP_EXT_HARDLINK;
525			known = 1;
526		} else if (strcmp(name, "fsync@openssh.com") == 0 &&
527		    strcmp((char *)value, "1") == 0) {
528			ret->exts |= SFTP_EXT_FSYNC;
529			known = 1;
530		} else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
531		    strcmp((char *)value, "1") == 0) {
532			ret->exts |= SFTP_EXT_LSETSTAT;
533			known = 1;
534		} else if (strcmp(name, "limits@openssh.com") == 0 &&
535		    strcmp((char *)value, "1") == 0) {
536			ret->exts |= SFTP_EXT_LIMITS;
537			known = 1;
538		} else if (strcmp(name, "expand-path@openssh.com") == 0 &&
539		    strcmp((char *)value, "1") == 0) {
540			ret->exts |= SFTP_EXT_PATH_EXPAND;
541			known = 1;
542		} else if (strcmp(name, "copy-data") == 0 &&
543		    strcmp((char *)value, "1") == 0) {
544			ret->exts |= SFTP_EXT_COPY_DATA;
545			known = 1;
546		} else if (strcmp(name,
547		    "users-groups-by-id@openssh.com") == 0 &&
548		    strcmp((char *)value, "1") == 0) {
549			ret->exts |= SFTP_EXT_GETUSERSGROUPS_BY_ID;
550			known = 1;
551		}
552		if (known) {
553			debug2("Server supports extension \"%s\" revision %s",
554			    name, value);
555		} else {
556			debug2("Unrecognised server extension \"%s\"", name);
557		}
558		free(name);
559		free(value);
560	}
561
562	sshbuf_free(msg);
563
564	/* Query the server for its limits */
565	if (ret->exts & SFTP_EXT_LIMITS) {
566		struct sftp_limits limits;
567		if (sftp_get_limits(ret, &limits) != 0)
568			fatal_f("limits failed");
569
570		/* If the caller did not specify, find a good value */
571		if (transfer_buflen == 0) {
572			ret->download_buflen = MINIMUM(limits.read_length,
573			    SFTP_MAX_MSG_LENGTH - 1024);
574			ret->upload_buflen = MINIMUM(limits.write_length,
575			    SFTP_MAX_MSG_LENGTH - 1024);
576			ret->download_buflen = MAXIMUM(ret->download_buflen, 64);
577			ret->upload_buflen = MAXIMUM(ret->upload_buflen, 64);
578			debug3("server upload/download buffer sizes "
579			    "%llu / %llu; using %u / %u",
580			    (unsigned long long)limits.write_length,
581			    (unsigned long long)limits.read_length,
582			    ret->upload_buflen, ret->download_buflen);
583		}
584
585		/* Use the server limit to scale down our value only */
586		if (num_requests == 0 && limits.open_handles) {
587			ret->num_requests =
588			    MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles);
589			if (ret->num_requests == 0)
590				ret->num_requests = 1;
591			debug3("server handle limit %llu; using %u",
592			    (unsigned long long)limits.open_handles,
593			    ret->num_requests);
594		}
595	}
596
597	/* Some filexfer v.0 servers don't support large packets */
598	if (ret->version == 0) {
599		ret->download_buflen = MINIMUM(ret->download_buflen, 20480);
600		ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480);
601	}
602
603	ret->limit_kbps = limit_kbps;
604	if (ret->limit_kbps > 0) {
605		bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
606		    ret->download_buflen);
607		bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
608		    ret->upload_buflen);
609	}
610
611	return ret;
612}
613
614u_int
615sftp_proto_version(struct sftp_conn *conn)
616{
617	return conn->version;
618}
619
620int
621sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits)
622{
623	u_int id, msg_id;
624	u_char type;
625	struct sshbuf *msg;
626	int r;
627
628	if ((conn->exts & SFTP_EXT_LIMITS) == 0) {
629		error("Server does not support limits@openssh.com extension");
630		return -1;
631	}
632
633	if ((msg = sshbuf_new()) == NULL)
634		fatal_f("sshbuf_new failed");
635
636	id = conn->msg_id++;
637	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
638	    (r = sshbuf_put_u32(msg, id)) != 0 ||
639	    (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0)
640		fatal_fr(r, "compose");
641	send_msg(conn, msg);
642	debug3("Sent message limits@openssh.com I:%u", id);
643
644	get_msg(conn, msg);
645
646	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
647	    (r = sshbuf_get_u32(msg, &msg_id)) != 0)
648		fatal_fr(r, "parse");
649
650	debug3("Received limits reply T:%u I:%u", type, msg_id);
651	if (id != msg_id)
652		fatal("ID mismatch (%u != %u)", msg_id, id);
653	if (type != SSH2_FXP_EXTENDED_REPLY) {
654		debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
655		    SSH2_FXP_EXTENDED_REPLY, type);
656		/* Disable the limits extension */
657		conn->exts &= ~SFTP_EXT_LIMITS;
658		sshbuf_free(msg);
659		return -1;
660	}
661
662	memset(limits, 0, sizeof(*limits));
663	if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 ||
664	    (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 ||
665	    (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 ||
666	    (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0)
667		fatal_fr(r, "parse limits");
668
669	sshbuf_free(msg);
670
671	return 0;
672}
673
674int
675sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
676{
677	u_int id, status;
678	struct sshbuf *msg;
679	int r;
680
681	if ((msg = sshbuf_new()) == NULL)
682		fatal_f("sshbuf_new failed");
683
684	id = conn->msg_id++;
685	if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
686	    (r = sshbuf_put_u32(msg, id)) != 0 ||
687	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
688		fatal_fr(r, "parse");
689	send_msg(conn, msg);
690	debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
691
692	status = get_status(conn, id);
693	if (status != SSH2_FX_OK)
694		error("close remote: %s", fx2txt(status));
695
696	sshbuf_free(msg);
697
698	return status == SSH2_FX_OK ? 0 : -1;
699}
700
701
702static int
703sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
704    SFTP_DIRENT ***dir)
705{
706	struct sshbuf *msg;
707	u_int count, id, i, expected_id, ents = 0;
708	size_t handle_len;
709	u_char type, *handle;
710	int status = SSH2_FX_FAILURE;
711	int r;
712
713	if (dir)
714		*dir = NULL;
715
716	id = conn->msg_id++;
717
718	if ((msg = sshbuf_new()) == NULL)
719		fatal_f("sshbuf_new failed");
720	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
721	    (r = sshbuf_put_u32(msg, id)) != 0 ||
722	    (r = sshbuf_put_cstring(msg, path)) != 0)
723		fatal_fr(r, "compose OPENDIR");
724	send_msg(conn, msg);
725
726	handle = get_handle(conn, id, &handle_len,
727	    "remote readdir(\"%s\")", path);
728	if (handle == NULL) {
729		sshbuf_free(msg);
730		return -1;
731	}
732
733	if (dir) {
734		ents = 0;
735		*dir = xcalloc(1, sizeof(**dir));
736		(*dir)[0] = NULL;
737	}
738
739	for (; !interrupted;) {
740		id = expected_id = conn->msg_id++;
741
742		debug3("Sending SSH2_FXP_READDIR I:%u", id);
743
744		sshbuf_reset(msg);
745		if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
746		    (r = sshbuf_put_u32(msg, id)) != 0 ||
747		    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
748			fatal_fr(r, "compose READDIR");
749		send_msg(conn, msg);
750
751		sshbuf_reset(msg);
752
753		get_msg(conn, msg);
754
755		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
756		    (r = sshbuf_get_u32(msg, &id)) != 0)
757			fatal_fr(r, "parse");
758
759		debug3("Received reply T:%u I:%u", type, id);
760
761		if (id != expected_id)
762			fatal("ID mismatch (%u != %u)", id, expected_id);
763
764		if (type == SSH2_FXP_STATUS) {
765			u_int rstatus;
766
767			if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
768				fatal_fr(r, "parse status");
769			debug3("Received SSH2_FXP_STATUS %d", rstatus);
770			if (rstatus == SSH2_FX_EOF)
771				break;
772			error("Couldn't read directory: %s", fx2txt(rstatus));
773			goto out;
774		} else if (type != SSH2_FXP_NAME)
775			fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
776			    SSH2_FXP_NAME, type);
777
778		if ((r = sshbuf_get_u32(msg, &count)) != 0)
779			fatal_fr(r, "parse count");
780		if (count > SSHBUF_SIZE_MAX)
781			fatal_f("nonsensical number of entries");
782		if (count == 0)
783			break;
784		debug3("Received %d SSH2_FXP_NAME responses", count);
785		for (i = 0; i < count; i++) {
786			char *filename, *longname;
787			Attrib a;
788
789			if ((r = sshbuf_get_cstring(msg, &filename,
790			    NULL)) != 0 ||
791			    (r = sshbuf_get_cstring(msg, &longname,
792			    NULL)) != 0)
793				fatal_fr(r, "parse filenames");
794			if ((r = decode_attrib(msg, &a)) != 0) {
795				error_fr(r, "couldn't decode attrib");
796				free(filename);
797				free(longname);
798				goto out;
799			}
800
801			if (print_flag)
802				mprintf("%s\n", longname);
803
804			/*
805			 * Directory entries should never contain '/'
806			 * These can be used to attack recursive ops
807			 * (e.g. send '../../../../etc/passwd')
808			 */
809			if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) {
810				error("Server sent suspect path \"%s\" "
811				    "during readdir of \"%s\"", filename, path);
812			} else if (dir) {
813				*dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
814				(*dir)[ents] = xcalloc(1, sizeof(***dir));
815				(*dir)[ents]->filename = xstrdup(filename);
816				(*dir)[ents]->longname = xstrdup(longname);
817				memcpy(&(*dir)[ents]->a, &a, sizeof(a));
818				(*dir)[++ents] = NULL;
819			}
820			free(filename);
821			free(longname);
822		}
823	}
824	status = 0;
825
826 out:
827	sshbuf_free(msg);
828	sftp_close(conn, handle, handle_len);
829	free(handle);
830
831	if (status != 0 && dir != NULL) {
832		/* Don't return results on error */
833		sftp_free_dirents(*dir);
834		*dir = NULL;
835	} else if (interrupted && dir != NULL && *dir != NULL) {
836		/* Don't return partial matches on interrupt */
837		sftp_free_dirents(*dir);
838		*dir = xcalloc(1, sizeof(**dir));
839		**dir = NULL;
840	}
841
842	return status == SSH2_FX_OK ? 0 : -1;
843}
844
845int
846sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
847{
848	return sftp_lsreaddir(conn, path, 0, dir);
849}
850
851void sftp_free_dirents(SFTP_DIRENT **s)
852{
853	int i;
854
855	if (s == NULL)
856		return;
857	for (i = 0; s[i]; i++) {
858		free(s[i]->filename);
859		free(s[i]->longname);
860		free(s[i]);
861	}
862	free(s);
863}
864
865int
866sftp_rm(struct sftp_conn *conn, const char *path)
867{
868	u_int status, id;
869
870	debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
871
872	id = conn->msg_id++;
873	send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
874	status = get_status(conn, id);
875	if (status != SSH2_FX_OK)
876		error("remote delete %s: %s", path, fx2txt(status));
877	return status == SSH2_FX_OK ? 0 : -1;
878}
879
880int
881sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
882{
883	u_int status, id;
884
885	debug2("Sending SSH2_FXP_MKDIR \"%s\"", path);
886
887	id = conn->msg_id++;
888	send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
889	    strlen(path), a);
890
891	status = get_status(conn, id);
892	if (status != SSH2_FX_OK && print_flag)
893		error("remote mkdir \"%s\": %s", path, fx2txt(status));
894
895	return status == SSH2_FX_OK ? 0 : -1;
896}
897
898int
899sftp_rmdir(struct sftp_conn *conn, const char *path)
900{
901	u_int status, id;
902
903	debug2("Sending SSH2_FXP_RMDIR \"%s\"", path);
904
905	id = conn->msg_id++;
906	send_string_request(conn, id, SSH2_FXP_RMDIR, path,
907	    strlen(path));
908
909	status = get_status(conn, id);
910	if (status != SSH2_FX_OK)
911		error("remote rmdir \"%s\": %s", path, fx2txt(status));
912
913	return status == SSH2_FX_OK ? 0 : -1;
914}
915
916int
917sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
918{
919	u_int id;
920
921	debug2("Sending SSH2_FXP_STAT \"%s\"", path);
922
923	id = conn->msg_id++;
924
925	send_string_request(conn, id,
926	    conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
927	    path, strlen(path));
928
929	return get_decode_stat(conn, id, quiet, a);
930}
931
932int
933sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
934{
935	u_int id;
936
937	if (conn->version == 0) {
938		do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
939		    "Server version does not support lstat operation");
940		return sftp_stat(conn, path, quiet, a);
941	}
942
943	id = conn->msg_id++;
944	send_string_request(conn, id, SSH2_FXP_LSTAT, path,
945	    strlen(path));
946
947	return get_decode_stat(conn, id, quiet, a);
948}
949
950#ifdef notyet
951int
952sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
953    int quiet, Attrib *a)
954{
955	u_int id;
956
957	debug2("Sending SSH2_FXP_FSTAT \"%s\"");
958
959	id = conn->msg_id++;
960	send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
961	    handle_len);
962
963	return get_decode_stat(conn, id, quiet, a);
964}
965#endif
966
967int
968sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
969{
970	u_int status, id;
971
972	debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path);
973
974	id = conn->msg_id++;
975	send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
976	    strlen(path), a);
977
978	status = get_status(conn, id);
979	if (status != SSH2_FX_OK)
980		error("remote setstat \"%s\": %s", path, fx2txt(status));
981
982	return status == SSH2_FX_OK ? 0 : -1;
983}
984
985int
986sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
987    Attrib *a)
988{
989	u_int status, id;
990
991	debug2("Sending SSH2_FXP_FSETSTAT");
992
993	id = conn->msg_id++;
994	send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
995	    handle_len, a);
996
997	status = get_status(conn, id);
998	if (status != SSH2_FX_OK)
999		error("remote fsetstat: %s", fx2txt(status));
1000
1001	return status == SSH2_FX_OK ? 0 : -1;
1002}
1003
1004/* Implements both the realpath and expand-path operations */
1005static char *
1006sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
1007{
1008	struct sshbuf *msg;
1009	u_int expected_id, count, id;
1010	char *filename, *longname;
1011	Attrib a;
1012	u_char type;
1013	int r;
1014	const char *what = "SSH2_FXP_REALPATH";
1015
1016	if (expand)
1017		what = "expand-path@openssh.com";
1018	if ((msg = sshbuf_new()) == NULL)
1019		fatal_f("sshbuf_new failed");
1020
1021	expected_id = id = conn->msg_id++;
1022	if (expand) {
1023		debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) "
1024		    "\"%s\"", path);
1025		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1026		    (r = sshbuf_put_u32(msg, id)) != 0 ||
1027		    (r = sshbuf_put_cstring(msg,
1028		    "expand-path@openssh.com")) != 0 ||
1029		    (r = sshbuf_put_cstring(msg, path)) != 0)
1030			fatal_fr(r, "compose %s", what);
1031		send_msg(conn, msg);
1032	} else {
1033		debug2("Sending SSH2_FXP_REALPATH \"%s\"", path);
1034		send_string_request(conn, id, SSH2_FXP_REALPATH,
1035		    path, strlen(path));
1036	}
1037	get_msg(conn, msg);
1038	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1039	    (r = sshbuf_get_u32(msg, &id)) != 0)
1040		fatal_fr(r, "parse");
1041
1042	if (id != expected_id)
1043		fatal("ID mismatch (%u != %u)", id, expected_id);
1044
1045	if (type == SSH2_FXP_STATUS) {
1046		u_int status;
1047		char *errmsg;
1048
1049		if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
1050		    (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
1051			fatal_fr(r, "parse status");
1052		error("%s %s: %s", expand ? "expand" : "realpath",
1053		    path, *errmsg == '\0' ? fx2txt(status) : errmsg);
1054		free(errmsg);
1055		sshbuf_free(msg);
1056		return NULL;
1057	} else if (type != SSH2_FXP_NAME)
1058		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1059		    SSH2_FXP_NAME, type);
1060
1061	if ((r = sshbuf_get_u32(msg, &count)) != 0)
1062		fatal_fr(r, "parse count");
1063	if (count != 1)
1064		fatal("Got multiple names (%d) from %s", count, what);
1065
1066	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1067	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1068	    (r = decode_attrib(msg, &a)) != 0)
1069		fatal_fr(r, "parse filename/attrib");
1070
1071	debug3("%s %s -> %s", what, path, filename);
1072
1073	free(longname);
1074
1075	sshbuf_free(msg);
1076
1077	return(filename);
1078}
1079
1080char *
1081sftp_realpath(struct sftp_conn *conn, const char *path)
1082{
1083	return sftp_realpath_expand(conn, path, 0);
1084}
1085
1086int
1087sftp_can_expand_path(struct sftp_conn *conn)
1088{
1089	return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0;
1090}
1091
1092char *
1093sftp_expand_path(struct sftp_conn *conn, const char *path)
1094{
1095	if (!sftp_can_expand_path(conn)) {
1096		debug3_f("no server support, fallback to realpath");
1097		return sftp_realpath_expand(conn, path, 0);
1098	}
1099	return sftp_realpath_expand(conn, path, 1);
1100}
1101
1102int
1103sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1104{
1105	Attrib junk, attr;
1106	struct sshbuf *msg;
1107	u_char *old_handle, *new_handle;
1108	u_int mode, status, id;
1109	size_t old_handle_len, new_handle_len;
1110	int r;
1111
1112	/* Return if the extension is not supported */
1113	if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) {
1114		error("Server does not support copy-data extension");
1115		return -1;
1116	}
1117
1118	/* Make sure the file exists, and we can copy its perms */
1119	if (sftp_stat(conn, oldpath, 0, &attr) != 0)
1120		return -1;
1121
1122	/* Do not preserve set[ug]id here, as we do not preserve ownership */
1123	if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1124		mode = attr.perm & 0777;
1125
1126		if (!S_ISREG(attr.perm)) {
1127			error("Cannot copy non-regular file: %s", oldpath);
1128			return -1;
1129		}
1130	} else {
1131		/* NB: The user's umask will apply to this */
1132		mode = 0666;
1133	}
1134
1135	/* Set up the new perms for the new file */
1136	attrib_clear(&attr);
1137	attr.perm = mode;
1138	attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1139
1140	if ((msg = sshbuf_new()) == NULL)
1141		fatal("%s: sshbuf_new failed", __func__);
1142
1143	attrib_clear(&junk); /* Send empty attributes */
1144
1145	/* Open the old file for reading */
1146	id = conn->msg_id++;
1147	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1148	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1149	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1150	    (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
1151	    (r = encode_attrib(msg, &junk)) != 0)
1152		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1153	send_msg(conn, msg);
1154	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath);
1155
1156	sshbuf_reset(msg);
1157
1158	old_handle = get_handle(conn, id, &old_handle_len,
1159	    "remote open(\"%s\")", oldpath);
1160	if (old_handle == NULL) {
1161		sshbuf_free(msg);
1162		return -1;
1163	}
1164
1165	/* Open the new file for writing */
1166	id = conn->msg_id++;
1167	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1168	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1169	    (r = sshbuf_put_cstring(msg, newpath)) != 0 ||
1170	    (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1171	    SSH2_FXF_TRUNC)) != 0 ||
1172	    (r = encode_attrib(msg, &attr)) != 0)
1173		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1174	send_msg(conn, msg);
1175	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath);
1176
1177	sshbuf_reset(msg);
1178
1179	new_handle = get_handle(conn, id, &new_handle_len,
1180	    "remote open(\"%s\")", newpath);
1181	if (new_handle == NULL) {
1182		sshbuf_free(msg);
1183		free(old_handle);
1184		return -1;
1185	}
1186
1187	/* Copy the file data */
1188	id = conn->msg_id++;
1189	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1190	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1191	    (r = sshbuf_put_cstring(msg, "copy-data")) != 0 ||
1192	    (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 ||
1193	    (r = sshbuf_put_u64(msg, 0)) != 0 ||
1194	    (r = sshbuf_put_u64(msg, 0)) != 0 ||
1195	    (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 ||
1196	    (r = sshbuf_put_u64(msg, 0)) != 0)
1197		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1198	send_msg(conn, msg);
1199	debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0",
1200	       oldpath, newpath);
1201
1202	status = get_status(conn, id);
1203	if (status != SSH2_FX_OK)
1204		error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath,
1205		    newpath, fx2txt(status));
1206
1207	/* Clean up everything */
1208	sshbuf_free(msg);
1209	sftp_close(conn, old_handle, old_handle_len);
1210	sftp_close(conn, new_handle, new_handle_len);
1211	free(old_handle);
1212	free(new_handle);
1213
1214	return status == SSH2_FX_OK ? 0 : -1;
1215}
1216
1217int
1218sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
1219    int force_legacy)
1220{
1221	struct sshbuf *msg;
1222	u_int status, id;
1223	int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
1224
1225	if ((msg = sshbuf_new()) == NULL)
1226		fatal_f("sshbuf_new failed");
1227
1228	/* Send rename request */
1229	id = conn->msg_id++;
1230	if (use_ext) {
1231		debug2("Sending SSH2_FXP_EXTENDED(posix-rename@openssh.com) "
1232		    "\"%s\" to \"%s\"", oldpath, newpath);
1233		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1234		    (r = sshbuf_put_u32(msg, id)) != 0 ||
1235		    (r = sshbuf_put_cstring(msg,
1236		    "posix-rename@openssh.com")) != 0)
1237			fatal_fr(r, "compose posix-rename");
1238	} else {
1239		debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"",
1240		    oldpath, newpath);
1241		if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
1242		    (r = sshbuf_put_u32(msg, id)) != 0)
1243			fatal_fr(r, "compose rename");
1244	}
1245	if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1246	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1247		fatal_fr(r, "compose paths");
1248	send_msg(conn, msg);
1249	debug3("Sent message %s \"%s\" -> \"%s\"",
1250	    use_ext ? "posix-rename@openssh.com" :
1251	    "SSH2_FXP_RENAME", oldpath, newpath);
1252	sshbuf_free(msg);
1253
1254	status = get_status(conn, id);
1255	if (status != SSH2_FX_OK)
1256		error("remote rename \"%s\" to \"%s\": %s", oldpath,
1257		    newpath, fx2txt(status));
1258
1259	return status == SSH2_FX_OK ? 0 : -1;
1260}
1261
1262int
1263sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1264{
1265	struct sshbuf *msg;
1266	u_int status, id;
1267	int r;
1268
1269	if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
1270		error("Server does not support hardlink@openssh.com extension");
1271		return -1;
1272	}
1273	debug2("Sending SSH2_FXP_EXTENDED(hardlink@openssh.com) "
1274	    "\"%s\" to \"%s\"", oldpath, newpath);
1275
1276	if ((msg = sshbuf_new()) == NULL)
1277		fatal_f("sshbuf_new failed");
1278
1279	/* Send link request */
1280	id = conn->msg_id++;
1281	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1282	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1283	    (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
1284	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1285	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1286		fatal_fr(r, "compose");
1287	send_msg(conn, msg);
1288	debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
1289	    oldpath, newpath);
1290	sshbuf_free(msg);
1291
1292	status = get_status(conn, id);
1293	if (status != SSH2_FX_OK)
1294		error("remote link \"%s\" to \"%s\": %s", oldpath,
1295		    newpath, fx2txt(status));
1296
1297	return status == SSH2_FX_OK ? 0 : -1;
1298}
1299
1300int
1301sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1302{
1303	struct sshbuf *msg;
1304	u_int status, id;
1305	int r;
1306
1307	if (conn->version < 3) {
1308		error("This server does not support the symlink operation");
1309		return(SSH2_FX_OP_UNSUPPORTED);
1310	}
1311	debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath);
1312
1313	if ((msg = sshbuf_new()) == NULL)
1314		fatal_f("sshbuf_new failed");
1315
1316	/* Send symlink request */
1317	id = conn->msg_id++;
1318	if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
1319	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1320	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1321	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1322		fatal_fr(r, "compose");
1323	send_msg(conn, msg);
1324	debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
1325	    newpath);
1326	sshbuf_free(msg);
1327
1328	status = get_status(conn, id);
1329	if (status != SSH2_FX_OK)
1330		error("remote symlink file \"%s\" to \"%s\": %s", oldpath,
1331		    newpath, fx2txt(status));
1332
1333	return status == SSH2_FX_OK ? 0 : -1;
1334}
1335
1336int
1337sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
1338{
1339	struct sshbuf *msg;
1340	u_int status, id;
1341	int r;
1342
1343	/* Silently return if the extension is not supported */
1344	if ((conn->exts & SFTP_EXT_FSYNC) == 0)
1345		return -1;
1346	debug2("Sending SSH2_FXP_EXTENDED(fsync@openssh.com)");
1347
1348	/* Send fsync request */
1349	if ((msg = sshbuf_new()) == NULL)
1350		fatal_f("sshbuf_new failed");
1351	id = conn->msg_id++;
1352	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1353	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1354	    (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
1355	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1356		fatal_fr(r, "compose");
1357	send_msg(conn, msg);
1358	debug3("Sent message fsync@openssh.com I:%u", id);
1359	sshbuf_free(msg);
1360
1361	status = get_status(conn, id);
1362	if (status != SSH2_FX_OK)
1363		error("remote fsync: %s", fx2txt(status));
1364
1365	return status == SSH2_FX_OK ? 0 : -1;
1366}
1367
1368#ifdef notyet
1369char *
1370sftp_readlink(struct sftp_conn *conn, const char *path)
1371{
1372	struct sshbuf *msg;
1373	u_int expected_id, count, id;
1374	char *filename, *longname;
1375	Attrib a;
1376	u_char type;
1377	int r;
1378
1379	debug2("Sending SSH2_FXP_READLINK \"%s\"", path);
1380
1381	expected_id = id = conn->msg_id++;
1382	send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
1383
1384	if ((msg = sshbuf_new()) == NULL)
1385		fatal_f("sshbuf_new failed");
1386
1387	get_msg(conn, msg);
1388	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1389	    (r = sshbuf_get_u32(msg, &id)) != 0)
1390		fatal_fr(r, "parse");
1391
1392	if (id != expected_id)
1393		fatal("ID mismatch (%u != %u)", id, expected_id);
1394
1395	if (type == SSH2_FXP_STATUS) {
1396		u_int status;
1397
1398		if ((r = sshbuf_get_u32(msg, &status)) != 0)
1399			fatal_fr(r, "parse status");
1400		error("Couldn't readlink: %s", fx2txt(status));
1401		sshbuf_free(msg);
1402		return(NULL);
1403	} else if (type != SSH2_FXP_NAME)
1404		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1405		    SSH2_FXP_NAME, type);
1406
1407	if ((r = sshbuf_get_u32(msg, &count)) != 0)
1408		fatal_fr(r, "parse count");
1409	if (count != 1)
1410		fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
1411
1412	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1413	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1414	    (r = decode_attrib(msg, &a)) != 0)
1415		fatal_fr(r, "parse filenames/attrib");
1416
1417	debug3("SSH_FXP_READLINK %s -> %s", path, filename);
1418
1419	free(longname);
1420
1421	sshbuf_free(msg);
1422
1423	return filename;
1424}
1425#endif
1426
1427int
1428sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
1429    int quiet)
1430{
1431	struct sshbuf *msg;
1432	u_int id;
1433	int r;
1434
1435	if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
1436		error("Server does not support statvfs@openssh.com extension");
1437		return -1;
1438	}
1439
1440	debug2("Sending SSH2_FXP_EXTENDED(statvfs@openssh.com) \"%s\"", path);
1441
1442	id = conn->msg_id++;
1443
1444	if ((msg = sshbuf_new()) == NULL)
1445		fatal_f("sshbuf_new failed");
1446	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1447	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1448	    (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
1449	    (r = sshbuf_put_cstring(msg, path)) != 0)
1450		fatal_fr(r, "compose");
1451	send_msg(conn, msg);
1452	sshbuf_free(msg);
1453
1454	return get_decode_statvfs(conn, st, id, quiet);
1455}
1456
1457#ifdef notyet
1458int
1459sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1460    struct sftp_statvfs *st, int quiet)
1461{
1462	struct sshbuf *msg;
1463	u_int id;
1464
1465	if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
1466		error("Server does not support fstatvfs@openssh.com extension");
1467		return -1;
1468	}
1469
1470	debug2("Sending SSH2_FXP_EXTENDED(fstatvfs@openssh.com)");
1471
1472	id = conn->msg_id++;
1473
1474	if ((msg = sshbuf_new()) == NULL)
1475		fatal_f("sshbuf_new failed");
1476	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1477	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1478	    (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
1479	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1480		fatal_fr(r, "compose");
1481	send_msg(conn, msg);
1482	sshbuf_free(msg);
1483
1484	return get_decode_statvfs(conn, st, id, quiet);
1485}
1486#endif
1487
1488int
1489sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
1490{
1491	struct sshbuf *msg;
1492	u_int status, id;
1493	int r;
1494
1495	if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
1496		error("Server does not support lsetstat@openssh.com extension");
1497		return -1;
1498	}
1499
1500	debug2("Sending SSH2_FXP_EXTENDED(lsetstat@openssh.com) \"%s\"", path);
1501
1502	id = conn->msg_id++;
1503	if ((msg = sshbuf_new()) == NULL)
1504		fatal_f("sshbuf_new failed");
1505	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1506	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1507	    (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
1508	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
1509	    (r = encode_attrib(msg, a)) != 0)
1510		fatal_fr(r, "compose");
1511	send_msg(conn, msg);
1512	sshbuf_free(msg);
1513
1514	status = get_status(conn, id);
1515	if (status != SSH2_FX_OK)
1516		error("remote lsetstat \"%s\": %s", path, fx2txt(status));
1517
1518	return status == SSH2_FX_OK ? 0 : -1;
1519}
1520
1521static void
1522send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1523    u_int len, const u_char *handle, u_int handle_len)
1524{
1525	struct sshbuf *msg;
1526	int r;
1527
1528	if ((msg = sshbuf_new()) == NULL)
1529		fatal_f("sshbuf_new failed");
1530	if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
1531	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1532	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
1533	    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1534	    (r = sshbuf_put_u32(msg, len)) != 0)
1535		fatal_fr(r, "compose");
1536	send_msg(conn, msg);
1537	sshbuf_free(msg);
1538}
1539
1540static int
1541send_open(struct sftp_conn *conn, const char *path, const char *tag,
1542    u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp)
1543{
1544	Attrib junk;
1545	u_char *handle;
1546	size_t handle_len;
1547	struct sshbuf *msg;
1548	int r;
1549	u_int id;
1550
1551	debug2("Sending SSH2_FXP_OPEN \"%s\"", path);
1552
1553	*handlep = NULL;
1554	*handle_lenp = 0;
1555
1556	if (a == NULL) {
1557		attrib_clear(&junk); /* Send empty attributes */
1558		a = &junk;
1559	}
1560	/* Send open request */
1561	if ((msg = sshbuf_new()) == NULL)
1562		fatal_f("sshbuf_new failed");
1563	id = conn->msg_id++;
1564	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1565	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1566	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
1567	    (r = sshbuf_put_u32(msg, openmode)) != 0 ||
1568	    (r = encode_attrib(msg, a)) != 0)
1569		fatal_fr(r, "compose %s open", tag);
1570	send_msg(conn, msg);
1571	sshbuf_free(msg);
1572	debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x",
1573	    tag, id, path, openmode);
1574	if ((handle = get_handle(conn, id, &handle_len,
1575	    "%s open \"%s\"", tag, path)) == NULL)
1576		return -1;
1577	/* success */
1578	*handlep = handle;
1579	*handle_lenp = handle_len;
1580	return 0;
1581}
1582
1583static const char *
1584progress_meter_path(const char *path)
1585{
1586	const char *progresspath;
1587
1588	if ((progresspath = strrchr(path, '/')) == NULL)
1589		return path;
1590	progresspath++;
1591	if (*progresspath == '\0')
1592		return path;
1593	return progresspath;
1594}
1595
1596int
1597sftp_download(struct sftp_conn *conn, const char *remote_path,
1598    const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
1599    int fsync_flag, int inplace_flag)
1600{
1601	struct sshbuf *msg;
1602	u_char *handle;
1603	int local_fd = -1, write_error;
1604	int read_error, write_errno, lmodified = 0, reordered = 0, r;
1605	u_int64_t offset = 0, size, highwater = 0, maxack = 0;
1606	u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
1607	off_t progress_counter;
1608	size_t handle_len;
1609	struct stat st;
1610	struct requests requests;
1611	struct request *req;
1612	u_char type;
1613	Attrib attr;
1614
1615	debug2_f("download remote \"%s\" to local \"%s\"",
1616	    remote_path, local_path);
1617
1618	TAILQ_INIT(&requests);
1619
1620	if (a == NULL) {
1621		if (sftp_stat(conn, remote_path, 0, &attr) != 0)
1622			return -1;
1623		a = &attr;
1624	}
1625
1626	/* Do not preserve set[ug]id here, as we do not preserve ownership */
1627	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
1628		mode = a->perm & 0777;
1629	else
1630		mode = 0666;
1631
1632	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
1633	    (!S_ISREG(a->perm))) {
1634		error("download %s: not a regular file", remote_path);
1635		return(-1);
1636	}
1637
1638	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
1639		size = a->size;
1640	else
1641		size = 0;
1642
1643	buflen = conn->download_buflen;
1644
1645	/* Send open request */
1646	if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL,
1647	    &handle, &handle_len) != 0)
1648		return -1;
1649
1650	local_fd = open(local_path, O_WRONLY | O_CREAT |
1651	((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR);
1652	if (local_fd == -1) {
1653		error("open local \"%s\": %s", local_path, strerror(errno));
1654		goto fail;
1655	}
1656	if (resume_flag) {
1657		if (fstat(local_fd, &st) == -1) {
1658			error("stat local \"%s\": %s",
1659			    local_path, strerror(errno));
1660			goto fail;
1661		}
1662		if (st.st_size < 0) {
1663			error("\"%s\" has negative size", local_path);
1664			goto fail;
1665		}
1666		if ((u_int64_t)st.st_size > size) {
1667			error("Unable to resume download of \"%s\": "
1668			    "local file is larger than remote", local_path);
1669 fail:
1670			sftp_close(conn, handle, handle_len);
1671			free(handle);
1672			if (local_fd != -1)
1673				close(local_fd);
1674			return -1;
1675		}
1676		offset = highwater = maxack = st.st_size;
1677	}
1678
1679	/* Read from remote and write to local */
1680	write_error = read_error = write_errno = num_req = 0;
1681	max_req = 1;
1682	progress_counter = offset;
1683
1684	if (showprogress && size != 0) {
1685		start_progress_meter(progress_meter_path(remote_path),
1686		    size, &progress_counter);
1687	}
1688
1689	if ((msg = sshbuf_new()) == NULL)
1690		fatal_f("sshbuf_new failed");
1691
1692	while (num_req > 0 || max_req > 0) {
1693		u_char *data;
1694		size_t len;
1695
1696		/*
1697		 * Simulate EOF on interrupt: stop sending new requests and
1698		 * allow outstanding requests to drain gracefully
1699		 */
1700		if (interrupted) {
1701			if (num_req == 0) /* If we haven't started yet... */
1702				break;
1703			max_req = 0;
1704		}
1705
1706		/* Send some more requests */
1707		while (num_req < max_req) {
1708			debug3("Request range %llu -> %llu (%d/%d)",
1709			    (unsigned long long)offset,
1710			    (unsigned long long)offset + buflen - 1,
1711			    num_req, max_req);
1712			req = request_enqueue(&requests, conn->msg_id++,
1713			    buflen, offset);
1714			offset += buflen;
1715			num_req++;
1716			send_read_request(conn, req->id, req->offset,
1717			    req->len, handle, handle_len);
1718		}
1719
1720		sshbuf_reset(msg);
1721		get_msg(conn, msg);
1722		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1723		    (r = sshbuf_get_u32(msg, &id)) != 0)
1724			fatal_fr(r, "parse");
1725		debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
1726
1727		/* Find the request in our queue */
1728		if ((req = request_find(&requests, id)) == NULL)
1729			fatal("Unexpected reply %u", id);
1730
1731		switch (type) {
1732		case SSH2_FXP_STATUS:
1733			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1734				fatal_fr(r, "parse status");
1735			if (status != SSH2_FX_EOF)
1736				read_error = 1;
1737			max_req = 0;
1738			TAILQ_REMOVE(&requests, req, tq);
1739			free(req);
1740			num_req--;
1741			break;
1742		case SSH2_FXP_DATA:
1743			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
1744				fatal_fr(r, "parse data");
1745			debug3("Received data %llu -> %llu",
1746			    (unsigned long long)req->offset,
1747			    (unsigned long long)req->offset + len - 1);
1748			if (len > req->len)
1749				fatal("Received more data than asked for "
1750				    "%zu > %zu", len, req->len);
1751			lmodified = 1;
1752			if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
1753			    atomicio(vwrite, local_fd, data, len) != len) &&
1754			    !write_error) {
1755				write_errno = errno;
1756				write_error = 1;
1757				max_req = 0;
1758			} else {
1759				/*
1760				 * Track both the highest offset acknowledged
1761				 * and the highest *contiguous* offset
1762				 * acknowledged.
1763				 * We'll need the latter for ftruncate()ing
1764				 * interrupted transfers.
1765				 */
1766				if (maxack < req->offset + len)
1767					maxack = req->offset + len;
1768				if (!reordered && req->offset <= highwater)
1769					highwater = maxack;
1770				else if (!reordered && req->offset > highwater)
1771					reordered = 1;
1772			}
1773			progress_counter += len;
1774			free(data);
1775
1776			if (len == req->len) {
1777				TAILQ_REMOVE(&requests, req, tq);
1778				free(req);
1779				num_req--;
1780			} else {
1781				/* Resend the request for the missing data */
1782				debug3("Short data block, re-requesting "
1783				    "%llu -> %llu (%2d)",
1784				    (unsigned long long)req->offset + len,
1785				    (unsigned long long)req->offset +
1786				    req->len - 1, num_req);
1787				req->id = conn->msg_id++;
1788				req->len -= len;
1789				req->offset += len;
1790				send_read_request(conn, req->id,
1791				    req->offset, req->len, handle, handle_len);
1792				/* Reduce the request size */
1793				if (len < buflen)
1794					buflen = MAXIMUM(MIN_READ_SIZE, len);
1795			}
1796			if (max_req > 0) { /* max_req = 0 iff EOF received */
1797				if (size > 0 && offset > size) {
1798					/* Only one request at a time
1799					 * after the expected EOF */
1800					debug3("Finish at %llu (%2d)",
1801					    (unsigned long long)offset,
1802					    num_req);
1803					max_req = 1;
1804				} else if (max_req < conn->num_requests) {
1805					++max_req;
1806				}
1807			}
1808			break;
1809		default:
1810			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
1811			    SSH2_FXP_DATA, type);
1812		}
1813	}
1814
1815	if (showprogress && size)
1816		stop_progress_meter();
1817
1818	/* Sanity check */
1819	if (TAILQ_FIRST(&requests) != NULL)
1820		fatal("Transfer complete, but requests still in queue");
1821
1822	if (!read_error && !write_error && !interrupted) {
1823		/* we got everything */
1824		highwater = maxack;
1825	}
1826
1827	/*
1828	 * Truncate at highest contiguous point to avoid holes on interrupt,
1829	 * or unconditionally if writing in place.
1830	 */
1831	if (inplace_flag || read_error || write_error || interrupted) {
1832		if (reordered && resume_flag &&
1833		    (read_error || write_error || interrupted)) {
1834			error("Unable to resume download of \"%s\": "
1835			    "server reordered requests", local_path);
1836		}
1837		debug("truncating at %llu", (unsigned long long)highwater);
1838		if (ftruncate(local_fd, highwater) == -1)
1839			error("local ftruncate \"%s\": %s", local_path,
1840			    strerror(errno));
1841	}
1842	if (read_error) {
1843		error("read remote \"%s\" : %s", remote_path, fx2txt(status));
1844		status = -1;
1845		sftp_close(conn, handle, handle_len);
1846	} else if (write_error) {
1847		error("write local \"%s\": %s", local_path,
1848		    strerror(write_errno));
1849		status = SSH2_FX_FAILURE;
1850		sftp_close(conn, handle, handle_len);
1851	} else {
1852		if (sftp_close(conn, handle, handle_len) != 0 || interrupted)
1853			status = SSH2_FX_FAILURE;
1854		else
1855			status = SSH2_FX_OK;
1856		/* Override umask and utimes if asked */
1857#ifdef HAVE_FCHMOD
1858		if (preserve_flag && fchmod(local_fd, mode) == -1)
1859#else
1860		if (preserve_flag && chmod(local_path, mode) == -1)
1861#endif /* HAVE_FCHMOD */
1862			error("local chmod \"%s\": %s", local_path,
1863			    strerror(errno));
1864		if (preserve_flag &&
1865		    (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1866			struct timeval tv[2];
1867			tv[0].tv_sec = a->atime;
1868			tv[1].tv_sec = a->mtime;
1869			tv[0].tv_usec = tv[1].tv_usec = 0;
1870			if (utimes(local_path, tv) == -1)
1871				error("local set times \"%s\": %s",
1872				    local_path, strerror(errno));
1873		}
1874		if (resume_flag && !lmodified)
1875			logit("File \"%s\" was not modified", local_path);
1876		else if (fsync_flag) {
1877			debug("syncing \"%s\"", local_path);
1878			if (fsync(local_fd) == -1)
1879				error("local sync \"%s\": %s",
1880				    local_path, strerror(errno));
1881		}
1882	}
1883	close(local_fd);
1884	sshbuf_free(msg);
1885	free(handle);
1886
1887	return status == SSH2_FX_OK ? 0 : -1;
1888}
1889
1890static int
1891download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1892    int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
1893    int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag)
1894{
1895	int i, ret = 0;
1896	SFTP_DIRENT **dir_entries;
1897	char *filename, *new_src = NULL, *new_dst = NULL;
1898	mode_t mode = 0777, tmpmode = mode;
1899	Attrib *a, ldirattrib, lsym;
1900
1901	if (depth >= MAX_DIR_DEPTH) {
1902		error("Maximum directory depth exceeded: %d levels", depth);
1903		return -1;
1904	}
1905
1906	debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst);
1907
1908	if (dirattrib == NULL) {
1909		if (sftp_stat(conn, src, 1, &ldirattrib) != 0) {
1910			error("stat remote \"%s\" directory failed", src);
1911			return -1;
1912		}
1913		dirattrib = &ldirattrib;
1914	}
1915	if (!S_ISDIR(dirattrib->perm)) {
1916		error("\"%s\" is not a directory", src);
1917		return -1;
1918	}
1919	if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
1920		mprintf("Retrieving %s\n", src);
1921
1922	if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1923		mode = dirattrib->perm & 01777;
1924		tmpmode = mode | (S_IWUSR|S_IXUSR);
1925	} else {
1926		debug("download remote \"%s\": server "
1927		    "did not send permissions", dst);
1928	}
1929
1930	if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) {
1931		error("mkdir %s: %s", dst, strerror(errno));
1932		return -1;
1933	}
1934
1935	if (sftp_readdir(conn, src, &dir_entries) == -1) {
1936		error("remote readdir \"%s\" failed", src);
1937		return -1;
1938	}
1939
1940	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
1941		free(new_dst);
1942		free(new_src);
1943
1944		filename = dir_entries[i]->filename;
1945		new_dst = sftp_path_append(dst, filename);
1946		new_src = sftp_path_append(src, filename);
1947
1948		a = &dir_entries[i]->a;
1949		if (S_ISLNK(a->perm)) {
1950			if (!follow_link_flag) {
1951				logit("download \"%s\": not a regular file",
1952				    new_src);
1953				continue;
1954			}
1955			/* Replace the stat contents with the symlink target */
1956			if (sftp_stat(conn, new_src, 1, &lsym) != 0) {
1957				logit("remote stat \"%s\" failed", new_src);
1958				ret = -1;
1959				continue;
1960			}
1961			a = &lsym;
1962		}
1963
1964		if (S_ISDIR(a->perm)) {
1965			if (strcmp(filename, ".") == 0 ||
1966			    strcmp(filename, "..") == 0)
1967				continue;
1968			if (download_dir_internal(conn, new_src, new_dst,
1969			    depth + 1, a, preserve_flag,
1970			    print_flag, resume_flag,
1971			    fsync_flag, follow_link_flag, inplace_flag) == -1)
1972				ret = -1;
1973		} else if (S_ISREG(a->perm)) {
1974			if (sftp_download(conn, new_src, new_dst, a,
1975			    preserve_flag, resume_flag, fsync_flag,
1976			    inplace_flag) == -1) {
1977				error("Download of file %s to %s failed",
1978				    new_src, new_dst);
1979				ret = -1;
1980			}
1981		} else
1982			logit("download \"%s\": not a regular file", new_src);
1983
1984	}
1985	free(new_dst);
1986	free(new_src);
1987
1988	if (preserve_flag) {
1989		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1990			struct timeval tv[2];
1991			tv[0].tv_sec = dirattrib->atime;
1992			tv[1].tv_sec = dirattrib->mtime;
1993			tv[0].tv_usec = tv[1].tv_usec = 0;
1994			if (utimes(dst, tv) == -1)
1995				error("local set times on \"%s\": %s",
1996				    dst, strerror(errno));
1997		} else
1998			debug("Server did not send times for directory "
1999			    "\"%s\"", dst);
2000	}
2001
2002	if (mode != tmpmode && chmod(dst, mode) == -1)
2003		error("local chmod directory \"%s\": %s", dst,
2004		    strerror(errno));
2005
2006	sftp_free_dirents(dir_entries);
2007
2008	return ret;
2009}
2010
2011int
2012sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst,
2013    Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
2014    int fsync_flag, int follow_link_flag, int inplace_flag)
2015{
2016	char *src_canon;
2017	int ret;
2018
2019	if ((src_canon = sftp_realpath(conn, src)) == NULL) {
2020		error("download \"%s\": path canonicalization failed", src);
2021		return -1;
2022	}
2023
2024	ret = download_dir_internal(conn, src_canon, dst, 0,
2025	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag,
2026	    follow_link_flag, inplace_flag);
2027	free(src_canon);
2028	return ret;
2029}
2030
2031int
2032sftp_upload(struct sftp_conn *conn, const char *local_path,
2033    const char *remote_path, int preserve_flag, int resume,
2034    int fsync_flag, int inplace_flag)
2035{
2036	int r, local_fd;
2037	u_int openmode, id, status = SSH2_FX_OK, reordered = 0;
2038	off_t offset, progress_counter;
2039	u_char type, *handle, *data;
2040	struct sshbuf *msg;
2041	struct stat sb;
2042	Attrib a, t, c;
2043	u_int32_t startid, ackid;
2044	u_int64_t highwater = 0, maxack = 0;
2045	struct request *ack = NULL;
2046	struct requests acks;
2047	size_t handle_len;
2048
2049	debug2_f("upload local \"%s\" to remote \"%s\"",
2050	    local_path, remote_path);
2051
2052	TAILQ_INIT(&acks);
2053
2054	if ((local_fd = open(local_path, O_RDONLY)) == -1) {
2055		error("open local \"%s\": %s", local_path, strerror(errno));
2056		return(-1);
2057	}
2058	if (fstat(local_fd, &sb) == -1) {
2059		error("fstat local \"%s\": %s", local_path, strerror(errno));
2060		close(local_fd);
2061		return(-1);
2062	}
2063	if (!S_ISREG(sb.st_mode)) {
2064		error("local \"%s\" is not a regular file", local_path);
2065		close(local_fd);
2066		return(-1);
2067	}
2068	stat_to_attrib(&sb, &a);
2069
2070	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2071	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2072	a.perm &= 0777;
2073	if (!preserve_flag)
2074		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
2075
2076	if (resume) {
2077		/* Get remote file size if it exists */
2078		if (sftp_stat(conn, remote_path, 0, &c) != 0) {
2079			close(local_fd);
2080			return -1;
2081		}
2082
2083		if ((off_t)c.size >= sb.st_size) {
2084			error("resume \"%s\": destination file "
2085			    "same size or larger", local_path);
2086			close(local_fd);
2087			return -1;
2088		}
2089
2090		if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) {
2091			close(local_fd);
2092			return -1;
2093		}
2094	}
2095
2096	openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT;
2097	if (resume)
2098		openmode |= SSH2_FXF_APPEND;
2099	else if (!inplace_flag)
2100		openmode |= SSH2_FXF_TRUNC;
2101
2102	/* Send open request */
2103	if (send_open(conn, remote_path, "dest", openmode, &a,
2104	    &handle, &handle_len) != 0) {
2105		close(local_fd);
2106		return -1;
2107	}
2108
2109	id = conn->msg_id;
2110	startid = ackid = id + 1;
2111	data = xmalloc(conn->upload_buflen);
2112
2113	/* Read from local and write to remote */
2114	offset = progress_counter = (resume ? c.size : 0);
2115	if (showprogress) {
2116		start_progress_meter(progress_meter_path(local_path),
2117		    sb.st_size, &progress_counter);
2118	}
2119
2120	if ((msg = sshbuf_new()) == NULL)
2121		fatal_f("sshbuf_new failed");
2122	for (;;) {
2123		int len;
2124
2125		/*
2126		 * Can't use atomicio here because it returns 0 on EOF,
2127		 * thus losing the last block of the file.
2128		 * Simulate an EOF on interrupt, allowing ACKs from the
2129		 * server to drain.
2130		 */
2131		if (interrupted || status != SSH2_FX_OK)
2132			len = 0;
2133		else do
2134			len = read(local_fd, data, conn->upload_buflen);
2135		while ((len == -1) &&
2136		    (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
2137
2138		if (len == -1) {
2139			fatal("read local \"%s\": %s",
2140			    local_path, strerror(errno));
2141		} else if (len != 0) {
2142			ack = request_enqueue(&acks, ++id, len, offset);
2143			sshbuf_reset(msg);
2144			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
2145			    (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
2146			    (r = sshbuf_put_string(msg, handle,
2147			    handle_len)) != 0 ||
2148			    (r = sshbuf_put_u64(msg, offset)) != 0 ||
2149			    (r = sshbuf_put_string(msg, data, len)) != 0)
2150				fatal_fr(r, "compose");
2151			send_msg(conn, msg);
2152			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
2153			    id, (unsigned long long)offset, len);
2154		} else if (TAILQ_FIRST(&acks) == NULL)
2155			break;
2156
2157		if (ack == NULL)
2158			fatal("Unexpected ACK %u", id);
2159
2160		if (id == startid || len == 0 ||
2161		    id - ackid >= conn->num_requests) {
2162			u_int rid;
2163
2164			sshbuf_reset(msg);
2165			get_msg(conn, msg);
2166			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2167			    (r = sshbuf_get_u32(msg, &rid)) != 0)
2168				fatal_fr(r, "parse");
2169
2170			if (type != SSH2_FXP_STATUS)
2171				fatal("Expected SSH2_FXP_STATUS(%d) packet, "
2172				    "got %d", SSH2_FXP_STATUS, type);
2173
2174			if ((r = sshbuf_get_u32(msg, &status)) != 0)
2175				fatal_fr(r, "parse status");
2176			debug3("SSH2_FXP_STATUS %u", status);
2177
2178			/* Find the request in our queue */
2179			if ((ack = request_find(&acks, rid)) == NULL)
2180				fatal("Can't find request for ID %u", rid);
2181			TAILQ_REMOVE(&acks, ack, tq);
2182			debug3("In write loop, ack for %u %zu bytes at %lld",
2183			    ack->id, ack->len, (unsigned long long)ack->offset);
2184			++ackid;
2185			progress_counter += ack->len;
2186			/*
2187			 * Track both the highest offset acknowledged and the
2188			 * highest *contiguous* offset acknowledged.
2189			 * We'll need the latter for ftruncate()ing
2190			 * interrupted transfers.
2191			 */
2192			if (maxack < ack->offset + ack->len)
2193				maxack = ack->offset + ack->len;
2194			if (!reordered && ack->offset <= highwater)
2195				highwater = maxack;
2196			else if (!reordered && ack->offset > highwater) {
2197				debug3_f("server reordered ACKs");
2198				reordered = 1;
2199			}
2200			free(ack);
2201		}
2202		offset += len;
2203		if (offset < 0)
2204			fatal_f("offset < 0");
2205	}
2206	sshbuf_free(msg);
2207
2208	if (showprogress)
2209		stop_progress_meter();
2210	free(data);
2211
2212	if (status == SSH2_FX_OK && !interrupted) {
2213		/* we got everything */
2214		highwater = maxack;
2215	}
2216	if (status != SSH2_FX_OK) {
2217		error("write remote \"%s\": %s", remote_path, fx2txt(status));
2218		status = SSH2_FX_FAILURE;
2219	}
2220
2221	if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) {
2222		debug("truncating at %llu", (unsigned long long)highwater);
2223		attrib_clear(&t);
2224		t.flags = SSH2_FILEXFER_ATTR_SIZE;
2225		t.size = highwater;
2226		sftp_fsetstat(conn, handle, handle_len, &t);
2227	}
2228
2229	if (close(local_fd) == -1) {
2230		error("close local \"%s\": %s", local_path, strerror(errno));
2231		status = SSH2_FX_FAILURE;
2232	}
2233
2234	/* Override umask and utimes if asked */
2235	if (preserve_flag)
2236		sftp_fsetstat(conn, handle, handle_len, &a);
2237
2238	if (fsync_flag)
2239		(void)sftp_fsync(conn, handle, handle_len);
2240
2241	if (sftp_close(conn, handle, handle_len) != 0)
2242		status = SSH2_FX_FAILURE;
2243
2244	free(handle);
2245
2246	return status == SSH2_FX_OK ? 0 : -1;
2247}
2248
2249static int
2250upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
2251    int depth, int preserve_flag, int print_flag, int resume, int fsync_flag,
2252    int follow_link_flag, int inplace_flag)
2253{
2254	int ret = 0;
2255	DIR *dirp;
2256	struct dirent *dp;
2257	char *filename, *new_src = NULL, *new_dst = NULL;
2258	struct stat sb;
2259	Attrib a, dirattrib;
2260	u_int32_t saved_perm;
2261
2262	debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst);
2263
2264	if (depth >= MAX_DIR_DEPTH) {
2265		error("Maximum directory depth exceeded: %d levels", depth);
2266		return -1;
2267	}
2268
2269	if (stat(src, &sb) == -1) {
2270		error("stat local \"%s\": %s", src, strerror(errno));
2271		return -1;
2272	}
2273	if (!S_ISDIR(sb.st_mode)) {
2274		error("\"%s\" is not a directory", src);
2275		return -1;
2276	}
2277	if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
2278		mprintf("Entering %s\n", src);
2279
2280	stat_to_attrib(&sb, &a);
2281	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2282	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2283	a.perm &= 01777;
2284	if (!preserve_flag)
2285		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
2286
2287	/*
2288	 * sftp lacks a portable status value to match errno EEXIST,
2289	 * so if we get a failure back then we must check whether
2290	 * the path already existed and is a directory.  Ensure we can
2291	 * write to the directory we create for the duration of the transfer.
2292	 */
2293	saved_perm = a.perm;
2294	a.perm |= (S_IWUSR|S_IXUSR);
2295	if (sftp_mkdir(conn, dst, &a, 0) != 0) {
2296		if (sftp_stat(conn, dst, 0, &dirattrib) != 0)
2297			return -1;
2298		if (!S_ISDIR(dirattrib.perm)) {
2299			error("\"%s\" exists but is not a directory", dst);
2300			return -1;
2301		}
2302	}
2303	a.perm = saved_perm;
2304
2305	if ((dirp = opendir(src)) == NULL) {
2306		error("local opendir \"%s\": %s", src, strerror(errno));
2307		return -1;
2308	}
2309
2310	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
2311		if (dp->d_ino == 0)
2312			continue;
2313		free(new_dst);
2314		free(new_src);
2315		filename = dp->d_name;
2316		new_dst = sftp_path_append(dst, filename);
2317		new_src = sftp_path_append(src, filename);
2318
2319		if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
2320			continue;
2321		if (lstat(new_src, &sb) == -1) {
2322			logit("local lstat \"%s\": %s", filename,
2323			    strerror(errno));
2324			ret = -1;
2325			continue;
2326		}
2327		if (S_ISLNK(sb.st_mode)) {
2328			if (!follow_link_flag) {
2329				logit("%s: not a regular file", filename);
2330				continue;
2331			}
2332			/* Replace the stat contents with the symlink target */
2333			if (stat(new_src, &sb) == -1) {
2334				logit("local stat \"%s\": %s", filename,
2335				    strerror(errno));
2336				ret = -1;
2337				continue;
2338			}
2339		}
2340		if (S_ISDIR(sb.st_mode)) {
2341			if (upload_dir_internal(conn, new_src, new_dst,
2342			    depth + 1, preserve_flag, print_flag, resume,
2343			    fsync_flag, follow_link_flag, inplace_flag) == -1)
2344				ret = -1;
2345		} else if (S_ISREG(sb.st_mode)) {
2346			if (sftp_upload(conn, new_src, new_dst,
2347			    preserve_flag, resume, fsync_flag,
2348			    inplace_flag) == -1) {
2349				error("upload \"%s\" to \"%s\" failed",
2350				    new_src, new_dst);
2351				ret = -1;
2352			}
2353		} else
2354			logit("%s: not a regular file", filename);
2355	}
2356	free(new_dst);
2357	free(new_src);
2358
2359	sftp_setstat(conn, dst, &a);
2360
2361	(void) closedir(dirp);
2362	return ret;
2363}
2364
2365int
2366sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
2367    int preserve_flag, int print_flag, int resume, int fsync_flag,
2368    int follow_link_flag, int inplace_flag)
2369{
2370	char *dst_canon;
2371	int ret;
2372
2373	if ((dst_canon = sftp_realpath(conn, dst)) == NULL) {
2374		error("upload \"%s\": path canonicalization failed", dst);
2375		return -1;
2376	}
2377
2378	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
2379	    print_flag, resume, fsync_flag, follow_link_flag, inplace_flag);
2380
2381	free(dst_canon);
2382	return ret;
2383}
2384
2385static void
2386handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
2387    u_int *nreqsp, u_int *write_errorp)
2388{
2389	struct sshbuf *msg;
2390	u_char type;
2391	u_int id, status;
2392	int r;
2393	struct pollfd pfd;
2394
2395	if ((msg = sshbuf_new()) == NULL)
2396		fatal_f("sshbuf_new failed");
2397
2398	/* Try to eat replies from the upload side */
2399	while (*nreqsp > 0) {
2400		debug3_f("%u outstanding replies", *nreqsp);
2401		if (!synchronous) {
2402			/* Bail out if no data is ready to be read */
2403			pfd.fd = to->fd_in;
2404			pfd.events = POLLIN;
2405			if ((r = poll(&pfd, 1, 0)) == -1) {
2406				if (errno == EINTR)
2407					break;
2408				fatal_f("poll: %s", strerror(errno));
2409			} else if (r == 0)
2410				break; /* fd not ready */
2411		}
2412		sshbuf_reset(msg);
2413		get_msg(to, msg);
2414
2415		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2416		    (r = sshbuf_get_u32(msg, &id)) != 0)
2417			fatal_fr(r, "dest parse");
2418		debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp);
2419		if (type != SSH2_FXP_STATUS) {
2420			fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d",
2421			    SSH2_FXP_STATUS, type);
2422		}
2423		if ((r = sshbuf_get_u32(msg, &status)) != 0)
2424			fatal_fr(r, "parse dest status");
2425		debug3("dest SSH2_FXP_STATUS %u", status);
2426		if (status != SSH2_FX_OK) {
2427			/* record first error */
2428			if (*write_errorp == 0)
2429				*write_errorp = status;
2430		}
2431		/*
2432		 * XXX this doesn't do full reply matching like sftp_upload and
2433		 * so cannot gracefully truncate terminated uploads at a
2434		 * high-water mark. ATM the only caller of this function (scp)
2435		 * doesn't support transfer resumption, so this doesn't matter
2436		 * a whole lot.
2437		 *
2438		 * To be safe, sftp_crossload truncates the destination file to
2439		 * zero length on upload failure, since we can't trust the
2440		 * server not to have reordered replies that could have
2441		 * inserted holes where none existed in the source file.
2442		 *
2443		 * XXX we could get a more accutate progress bar if we updated
2444		 * the counter based on the reply from the destination...
2445		 */
2446		(*nreqsp)--;
2447	}
2448	debug3_f("done: %u outstanding replies", *nreqsp);
2449	sshbuf_free(msg);
2450}
2451
2452int
2453sftp_crossload(struct sftp_conn *from, struct sftp_conn *to,
2454    const char *from_path, const char *to_path,
2455    Attrib *a, int preserve_flag)
2456{
2457	struct sshbuf *msg;
2458	int write_error, read_error, r;
2459	u_int64_t offset = 0, size;
2460	u_int id, buflen, num_req, max_req, status = SSH2_FX_OK;
2461	u_int num_upload_req;
2462	off_t progress_counter;
2463	u_char *from_handle, *to_handle;
2464	size_t from_handle_len, to_handle_len;
2465	struct requests requests;
2466	struct request *req;
2467	u_char type;
2468	Attrib attr;
2469
2470	debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path);
2471
2472	TAILQ_INIT(&requests);
2473
2474	if (a == NULL) {
2475		if (sftp_stat(from, from_path, 0, &attr) != 0)
2476			return -1;
2477		a = &attr;
2478	}
2479
2480	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
2481	    (!S_ISREG(a->perm))) {
2482		error("download \"%s\": not a regular file", from_path);
2483		return(-1);
2484	}
2485	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
2486		size = a->size;
2487	else
2488		size = 0;
2489
2490	buflen = from->download_buflen;
2491	if (buflen > to->upload_buflen)
2492		buflen = to->upload_buflen;
2493
2494	/* Send open request to read side */
2495	if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL,
2496	    &from_handle, &from_handle_len) != 0)
2497		return -1;
2498
2499	/* Send open request to write side */
2500	a->flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2501	a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2502	a->perm &= 0777;
2503	if (!preserve_flag)
2504		a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
2505	if (send_open(to, to_path, "dest",
2506	    SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
2507	    &to_handle, &to_handle_len) != 0) {
2508		sftp_close(from, from_handle, from_handle_len);
2509		return -1;
2510	}
2511
2512	/* Read from remote "from" and write to remote "to" */
2513	offset = 0;
2514	write_error = read_error = num_req = num_upload_req = 0;
2515	max_req = 1;
2516	progress_counter = 0;
2517
2518	if (showprogress && size != 0) {
2519		start_progress_meter(progress_meter_path(from_path),
2520		    size, &progress_counter);
2521	}
2522	if ((msg = sshbuf_new()) == NULL)
2523		fatal_f("sshbuf_new failed");
2524	while (num_req > 0 || max_req > 0) {
2525		u_char *data;
2526		size_t len;
2527
2528		/*
2529		 * Simulate EOF on interrupt: stop sending new requests and
2530		 * allow outstanding requests to drain gracefully
2531		 */
2532		if (interrupted) {
2533			if (num_req == 0) /* If we haven't started yet... */
2534				break;
2535			max_req = 0;
2536		}
2537
2538		/* Send some more requests */
2539		while (num_req < max_req) {
2540			debug3("Request range %llu -> %llu (%d/%d)",
2541			    (unsigned long long)offset,
2542			    (unsigned long long)offset + buflen - 1,
2543			    num_req, max_req);
2544			req = request_enqueue(&requests, from->msg_id++,
2545			    buflen, offset);
2546			offset += buflen;
2547			num_req++;
2548			send_read_request(from, req->id, req->offset,
2549			    req->len, from_handle, from_handle_len);
2550		}
2551
2552		/* Try to eat replies from the upload side (nonblocking) */
2553		handle_dest_replies(to, to_path, 0,
2554		    &num_upload_req, &write_error);
2555
2556		sshbuf_reset(msg);
2557		get_msg(from, msg);
2558		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2559		    (r = sshbuf_get_u32(msg, &id)) != 0)
2560			fatal_fr(r, "parse");
2561		debug3("Received origin reply T:%u I:%u R:%d",
2562		    type, id, max_req);
2563
2564		/* Find the request in our queue */
2565		if ((req = request_find(&requests, id)) == NULL)
2566			fatal("Unexpected reply %u", id);
2567
2568		switch (type) {
2569		case SSH2_FXP_STATUS:
2570			if ((r = sshbuf_get_u32(msg, &status)) != 0)
2571				fatal_fr(r, "parse status");
2572			if (status != SSH2_FX_EOF)
2573				read_error = 1;
2574			max_req = 0;
2575			TAILQ_REMOVE(&requests, req, tq);
2576			free(req);
2577			num_req--;
2578			break;
2579		case SSH2_FXP_DATA:
2580			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
2581				fatal_fr(r, "parse data");
2582			debug3("Received data %llu -> %llu",
2583			    (unsigned long long)req->offset,
2584			    (unsigned long long)req->offset + len - 1);
2585			if (len > req->len)
2586				fatal("Received more data than asked for "
2587				    "%zu > %zu", len, req->len);
2588
2589			/* Write this chunk out to the destination */
2590			sshbuf_reset(msg);
2591			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
2592			    (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 ||
2593			    (r = sshbuf_put_string(msg, to_handle,
2594			    to_handle_len)) != 0 ||
2595			    (r = sshbuf_put_u64(msg, req->offset)) != 0 ||
2596			    (r = sshbuf_put_string(msg, data, len)) != 0)
2597				fatal_fr(r, "compose write");
2598			send_msg(to, msg);
2599			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu",
2600			    id, (unsigned long long)offset, len);
2601			num_upload_req++;
2602			progress_counter += len;
2603			free(data);
2604
2605			if (len == req->len) {
2606				TAILQ_REMOVE(&requests, req, tq);
2607				free(req);
2608				num_req--;
2609			} else {
2610				/* Resend the request for the missing data */
2611				debug3("Short data block, re-requesting "
2612				    "%llu -> %llu (%2d)",
2613				    (unsigned long long)req->offset + len,
2614				    (unsigned long long)req->offset +
2615				    req->len - 1, num_req);
2616				req->id = from->msg_id++;
2617				req->len -= len;
2618				req->offset += len;
2619				send_read_request(from, req->id,
2620				    req->offset, req->len,
2621				    from_handle, from_handle_len);
2622				/* Reduce the request size */
2623				if (len < buflen)
2624					buflen = MAXIMUM(MIN_READ_SIZE, len);
2625			}
2626			if (max_req > 0) { /* max_req = 0 iff EOF received */
2627				if (size > 0 && offset > size) {
2628					/* Only one request at a time
2629					 * after the expected EOF */
2630					debug3("Finish at %llu (%2d)",
2631					    (unsigned long long)offset,
2632					    num_req);
2633					max_req = 1;
2634				} else if (max_req < from->num_requests) {
2635					++max_req;
2636				}
2637			}
2638			break;
2639		default:
2640			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
2641			    SSH2_FXP_DATA, type);
2642		}
2643	}
2644
2645	if (showprogress && size)
2646		stop_progress_meter();
2647
2648	/* Drain replies from the server (blocking) */
2649	debug3_f("waiting for %u replies from destination", num_upload_req);
2650	handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error);
2651
2652	/* Sanity check */
2653	if (TAILQ_FIRST(&requests) != NULL)
2654		fatal("Transfer complete, but requests still in queue");
2655	/* Truncate at 0 length on interrupt or error to avoid holes at dest */
2656	if (read_error || write_error || interrupted) {
2657		debug("truncating \"%s\" at 0", to_path);
2658		sftp_close(to, to_handle, to_handle_len);
2659		free(to_handle);
2660		if (send_open(to, to_path, "dest",
2661		    SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
2662		    &to_handle, &to_handle_len) != 0) {
2663			error("dest truncate \"%s\" failed", to_path);
2664			to_handle = NULL;
2665		}
2666	}
2667	if (read_error) {
2668		error("read origin \"%s\": %s", from_path, fx2txt(status));
2669		status = -1;
2670		sftp_close(from, from_handle, from_handle_len);
2671		if (to_handle != NULL)
2672			sftp_close(to, to_handle, to_handle_len);
2673	} else if (write_error) {
2674		error("write dest \"%s\": %s", to_path, fx2txt(write_error));
2675		status = SSH2_FX_FAILURE;
2676		sftp_close(from, from_handle, from_handle_len);
2677		if (to_handle != NULL)
2678			sftp_close(to, to_handle, to_handle_len);
2679	} else {
2680		if (sftp_close(from, from_handle, from_handle_len) != 0 ||
2681		    interrupted)
2682			status = -1;
2683		else
2684			status = SSH2_FX_OK;
2685		if (to_handle != NULL) {
2686			/* Need to resend utimes after write */
2687			if (preserve_flag)
2688				sftp_fsetstat(to, to_handle, to_handle_len, a);
2689			sftp_close(to, to_handle, to_handle_len);
2690		}
2691	}
2692	sshbuf_free(msg);
2693	free(from_handle);
2694	free(to_handle);
2695
2696	return status == SSH2_FX_OK ? 0 : -1;
2697}
2698
2699static int
2700crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
2701    const char *from_path, const char *to_path,
2702    int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
2703    int follow_link_flag)
2704{
2705	int i, ret = 0;
2706	SFTP_DIRENT **dir_entries;
2707	char *filename, *new_from_path = NULL, *new_to_path = NULL;
2708	mode_t mode = 0777;
2709	Attrib *a, curdir, ldirattrib, newdir, lsym;
2710
2711	debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path);
2712
2713	if (depth >= MAX_DIR_DEPTH) {
2714		error("Maximum directory depth exceeded: %d levels", depth);
2715		return -1;
2716	}
2717
2718	if (dirattrib == NULL) {
2719		if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) {
2720			error("stat remote \"%s\" failed", from_path);
2721			return -1;
2722		}
2723		dirattrib = &ldirattrib;
2724	}
2725	if (!S_ISDIR(dirattrib->perm)) {
2726		error("\"%s\" is not a directory", from_path);
2727		return -1;
2728	}
2729	if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
2730		mprintf("Retrieving %s\n", from_path);
2731
2732	curdir = *dirattrib; /* dirattrib will be clobbered */
2733	curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
2734	curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
2735	if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) {
2736		debug("Origin did not send permissions for "
2737		    "directory \"%s\"", to_path);
2738		curdir.perm = S_IWUSR|S_IXUSR;
2739		curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
2740	}
2741	/* We need to be able to write to the directory while we transfer it */
2742	mode = curdir.perm & 01777;
2743	curdir.perm = mode | (S_IWUSR|S_IXUSR);
2744
2745	/*
2746	 * sftp lacks a portable status value to match errno EEXIST,
2747	 * so if we get a failure back then we must check whether
2748	 * the path already existed and is a directory.  Ensure we can
2749	 * write to the directory we create for the duration of the transfer.
2750	 */
2751	if (sftp_mkdir(to, to_path, &curdir, 0) != 0) {
2752		if (sftp_stat(to, to_path, 0, &newdir) != 0)
2753			return -1;
2754		if (!S_ISDIR(newdir.perm)) {
2755			error("\"%s\" exists but is not a directory", to_path);
2756			return -1;
2757		}
2758	}
2759	curdir.perm = mode;
2760
2761	if (sftp_readdir(from, from_path, &dir_entries) == -1) {
2762		error("origin readdir \"%s\" failed", from_path);
2763		return -1;
2764	}
2765
2766	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
2767		free(new_from_path);
2768		free(new_to_path);
2769
2770		filename = dir_entries[i]->filename;
2771		new_from_path = sftp_path_append(from_path, filename);
2772		new_to_path = sftp_path_append(to_path, filename);
2773
2774		a = &dir_entries[i]->a;
2775		if (S_ISLNK(a->perm)) {
2776			if (!follow_link_flag) {
2777				logit("%s: not a regular file", filename);
2778				continue;
2779			}
2780			/* Replace the stat contents with the symlink target */
2781			if (sftp_stat(from, new_from_path, 1, &lsym) != 0) {
2782				logit("remote stat \"%s\" failed",
2783				    new_from_path);
2784				ret = -1;
2785				continue;
2786			}
2787			a = &lsym;
2788		}
2789		if (S_ISDIR(a->perm)) {
2790			if (strcmp(filename, ".") == 0 ||
2791			    strcmp(filename, "..") == 0)
2792				continue;
2793			if (crossload_dir_internal(from, to,
2794			    new_from_path, new_to_path,
2795			    depth + 1, a, preserve_flag,
2796			    print_flag, follow_link_flag) == -1)
2797				ret = -1;
2798		} else if (S_ISREG(a->perm)) {
2799			if (sftp_crossload(from, to, new_from_path,
2800			    new_to_path, a, preserve_flag) == -1) {
2801				error("crossload \"%s\" to \"%s\" failed",
2802				    new_from_path, new_to_path);
2803				ret = -1;
2804			}
2805		} else {
2806			logit("origin \"%s\": not a regular file",
2807			    new_from_path);
2808		}
2809	}
2810	free(new_to_path);
2811	free(new_from_path);
2812
2813	sftp_setstat(to, to_path, &curdir);
2814
2815	sftp_free_dirents(dir_entries);
2816
2817	return ret;
2818}
2819
2820int
2821sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
2822    const char *from_path, const char *to_path,
2823    Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag)
2824{
2825	char *from_path_canon;
2826	int ret;
2827
2828	if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) {
2829		error("crossload \"%s\": path canonicalization failed",
2830		    from_path);
2831		return -1;
2832	}
2833
2834	ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0,
2835	    dirattrib, preserve_flag, print_flag, follow_link_flag);
2836	free(from_path_canon);
2837	return ret;
2838}
2839
2840int
2841sftp_can_get_users_groups_by_id(struct sftp_conn *conn)
2842{
2843	return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0;
2844}
2845
2846int
2847sftp_get_users_groups_by_id(struct sftp_conn *conn,
2848    const u_int *uids, u_int nuids,
2849    const u_int *gids, u_int ngids,
2850    char ***usernamesp, char ***groupnamesp)
2851{
2852	struct sshbuf *msg, *uidbuf, *gidbuf;
2853	u_int i, expected_id, id;
2854	char *name, **usernames = NULL, **groupnames = NULL;
2855	u_char type;
2856	int r;
2857
2858	*usernamesp = *groupnamesp = NULL;
2859	if (!sftp_can_get_users_groups_by_id(conn))
2860		return SSH_ERR_FEATURE_UNSUPPORTED;
2861
2862	if ((msg = sshbuf_new()) == NULL ||
2863	    (uidbuf = sshbuf_new()) == NULL ||
2864	    (gidbuf = sshbuf_new()) == NULL)
2865		fatal_f("sshbuf_new failed");
2866	expected_id = id = conn->msg_id++;
2867	debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id@openssh.com)");
2868	for (i = 0; i < nuids; i++) {
2869		if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0)
2870			fatal_fr(r, "compose uids");
2871	}
2872	for (i = 0; i < ngids; i++) {
2873		if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0)
2874			fatal_fr(r, "compose gids");
2875	}
2876	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
2877	    (r = sshbuf_put_u32(msg, id)) != 0 ||
2878	    (r = sshbuf_put_cstring(msg,
2879	    "users-groups-by-id@openssh.com")) != 0 ||
2880	    (r = sshbuf_put_stringb(msg, uidbuf)) != 0 ||
2881	    (r = sshbuf_put_stringb(msg, gidbuf)) != 0)
2882		fatal_fr(r, "compose");
2883	send_msg(conn, msg);
2884	get_msg(conn, msg);
2885	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
2886	    (r = sshbuf_get_u32(msg, &id)) != 0)
2887		fatal_fr(r, "parse");
2888	if (id != expected_id)
2889		fatal("ID mismatch (%u != %u)", id, expected_id);
2890	if (type == SSH2_FXP_STATUS) {
2891		u_int status;
2892		char *errmsg;
2893
2894		if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
2895		    (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
2896			fatal_fr(r, "parse status");
2897		error("users-groups-by-id %s",
2898		    *errmsg == '\0' ? fx2txt(status) : errmsg);
2899		free(errmsg);
2900		sshbuf_free(msg);
2901		sshbuf_free(uidbuf);
2902		sshbuf_free(gidbuf);
2903		return -1;
2904	} else if (type != SSH2_FXP_EXTENDED_REPLY)
2905		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
2906		    SSH2_FXP_EXTENDED_REPLY, type);
2907
2908	/* reuse */
2909	sshbuf_free(uidbuf);
2910	sshbuf_free(gidbuf);
2911	uidbuf = gidbuf = NULL;
2912	if ((r = sshbuf_froms(msg, &uidbuf)) != 0 ||
2913	    (r = sshbuf_froms(msg, &gidbuf)) != 0)
2914		fatal_fr(r, "parse response");
2915	if (nuids > 0) {
2916		usernames = xcalloc(nuids, sizeof(*usernames));
2917		for (i = 0; i < nuids; i++) {
2918			if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0)
2919				fatal_fr(r, "parse user name");
2920			/* Handle unresolved names */
2921			if (*name == '\0') {
2922				free(name);
2923				name = NULL;
2924			}
2925			usernames[i] = name;
2926		}
2927	}
2928	if (ngids > 0) {
2929		groupnames = xcalloc(ngids, sizeof(*groupnames));
2930		for (i = 0; i < ngids; i++) {
2931			if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0)
2932				fatal_fr(r, "parse user name");
2933			/* Handle unresolved names */
2934			if (*name == '\0') {
2935				free(name);
2936				name = NULL;
2937			}
2938			groupnames[i] = name;
2939		}
2940	}
2941	if (sshbuf_len(uidbuf) != 0)
2942		fatal_f("unexpected extra username data");
2943	if (sshbuf_len(gidbuf) != 0)
2944		fatal_f("unexpected extra groupname data");
2945	sshbuf_free(uidbuf);
2946	sshbuf_free(gidbuf);
2947	sshbuf_free(msg);
2948	/* success */
2949	*usernamesp = usernames;
2950	*groupnamesp = groupnames;
2951	return 0;
2952}
2953
2954char *
2955sftp_path_append(const char *p1, const char *p2)
2956{
2957	char *ret;
2958	size_t len = strlen(p1) + strlen(p2) + 2;
2959
2960	ret = xmalloc(len);
2961	strlcpy(ret, p1, len);
2962	if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
2963		strlcat(ret, "/", len);
2964	strlcat(ret, p2, len);
2965
2966	return(ret);
2967}
2968
2969/*
2970 * Arg p must be dynamically allocated.  It will either be returned or
2971 * freed and a replacement allocated.  Caller must free returned string.
2972 */
2973char *
2974sftp_make_absolute(char *p, const char *pwd)
2975{
2976	char *abs_str;
2977
2978	/* Derelativise */
2979	if (p && !path_absolute(p)) {
2980		abs_str = sftp_path_append(pwd, p);
2981		free(p);
2982		return(abs_str);
2983	} else
2984		return(p);
2985}
2986
2987int
2988sftp_remote_is_dir(struct sftp_conn *conn, const char *path)
2989{
2990	Attrib a;
2991
2992	/* XXX: report errors? */
2993	if (sftp_stat(conn, path, 1, &a) != 0)
2994		return(0);
2995	if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
2996		return(0);
2997	return S_ISDIR(a.perm);
2998}
2999
3000
3001/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
3002int
3003sftp_globpath_is_dir(const char *pathname)
3004{
3005	size_t l = strlen(pathname);
3006
3007	return l > 0 && pathname[l - 1] == '/';
3008}
3009
3010