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