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