• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $OpenBSD: sftp-client.c,v 1.135 2019/10/04 04:31:59 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 				goto out;
635 			}
636 
637 			if (print_flag)
638 				mprintf("%s\n", longname);
639 
640 			/*
641 			 * Directory entries should never contain '/'
642 			 * These can be used to attack recursive ops
643 			 * (e.g. send '../../../../etc/passwd')
644 			 */
645 			if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) {
646 				error("Server sent suspect path \"%s\" "
647 				    "during readdir of \"%s\"", filename, path);
648 			} else if (dir) {
649 				*dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
650 				(*dir)[ents] = xcalloc(1, sizeof(***dir));
651 				(*dir)[ents]->filename = xstrdup(filename);
652 				(*dir)[ents]->longname = xstrdup(longname);
653 				memcpy(&(*dir)[ents]->a, &a, sizeof(a));
654 				(*dir)[++ents] = NULL;
655 			}
656 			free(filename);
657 			free(longname);
658 		}
659 	}
660 	status = 0;
661 
662  out:
663 	sshbuf_free(msg);
664 	do_close(conn, handle, handle_len);
665 	free(handle);
666 
667 	if (status != 0 && dir != NULL) {
668 		/* Don't return results on error */
669 		free_sftp_dirents(*dir);
670 		*dir = NULL;
671 	} else if (interrupted && dir != NULL && *dir != NULL) {
672 		/* Don't return partial matches on interrupt */
673 		free_sftp_dirents(*dir);
674 		*dir = xcalloc(1, sizeof(**dir));
675 		**dir = NULL;
676 	}
677 
678 	return status == SSH2_FX_OK ? 0 : -1;
679 }
680 
681 int
do_readdir(struct sftp_conn * conn,const char * path,SFTP_DIRENT *** dir)682 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
683 {
684 	return(do_lsreaddir(conn, path, 0, dir));
685 }
686 
free_sftp_dirents(SFTP_DIRENT ** s)687 void free_sftp_dirents(SFTP_DIRENT **s)
688 {
689 	int i;
690 
691 	if (s == NULL)
692 		return;
693 	for (i = 0; s[i]; i++) {
694 		free(s[i]->filename);
695 		free(s[i]->longname);
696 		free(s[i]);
697 	}
698 	free(s);
699 }
700 
701 int
do_rm(struct sftp_conn * conn,const char * path)702 do_rm(struct sftp_conn *conn, const char *path)
703 {
704 	u_int status, id;
705 
706 	debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
707 
708 	id = conn->msg_id++;
709 	send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
710 	status = get_status(conn, id);
711 	if (status != SSH2_FX_OK)
712 		error("Couldn't delete file: %s", fx2txt(status));
713 	return status == SSH2_FX_OK ? 0 : -1;
714 }
715 
716 int
do_mkdir(struct sftp_conn * conn,const char * path,Attrib * a,int print_flag)717 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
718 {
719 	u_int status, id;
720 
721 	id = conn->msg_id++;
722 	send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
723 	    strlen(path), a);
724 
725 	status = get_status(conn, id);
726 	if (status != SSH2_FX_OK && print_flag)
727 		error("Couldn't create directory: %s", fx2txt(status));
728 
729 	return status == SSH2_FX_OK ? 0 : -1;
730 }
731 
732 int
do_rmdir(struct sftp_conn * conn,const char * path)733 do_rmdir(struct sftp_conn *conn, const char *path)
734 {
735 	u_int status, id;
736 
737 	id = conn->msg_id++;
738 	send_string_request(conn, id, SSH2_FXP_RMDIR, path,
739 	    strlen(path));
740 
741 	status = get_status(conn, id);
742 	if (status != SSH2_FX_OK)
743 		error("Couldn't remove directory: %s", fx2txt(status));
744 
745 	return status == SSH2_FX_OK ? 0 : -1;
746 }
747 
748 Attrib *
do_stat(struct sftp_conn * conn,const char * path,int quiet)749 do_stat(struct sftp_conn *conn, const char *path, int quiet)
750 {
751 	u_int id;
752 
753 	id = conn->msg_id++;
754 
755 	send_string_request(conn, id,
756 	    conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
757 	    path, strlen(path));
758 
759 	return(get_decode_stat(conn, id, quiet));
760 }
761 
762 Attrib *
do_lstat(struct sftp_conn * conn,const char * path,int quiet)763 do_lstat(struct sftp_conn *conn, const char *path, int quiet)
764 {
765 	u_int id;
766 
767 	if (conn->version == 0) {
768 		if (quiet)
769 			debug("Server version does not support lstat operation");
770 		else
771 			logit("Server version does not support lstat operation");
772 		return(do_stat(conn, path, quiet));
773 	}
774 
775 	id = conn->msg_id++;
776 	send_string_request(conn, id, SSH2_FXP_LSTAT, path,
777 	    strlen(path));
778 
779 	return(get_decode_stat(conn, id, quiet));
780 }
781 
782 #ifdef notyet
783 Attrib *
do_fstat(struct sftp_conn * conn,const u_char * handle,u_int handle_len,int quiet)784 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
785     int quiet)
786 {
787 	u_int id;
788 
789 	id = conn->msg_id++;
790 	send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
791 	    handle_len);
792 
793 	return(get_decode_stat(conn, id, quiet));
794 }
795 #endif
796 
797 int
do_setstat(struct sftp_conn * conn,const char * path,Attrib * a)798 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
799 {
800 	u_int status, id;
801 
802 	id = conn->msg_id++;
803 	send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
804 	    strlen(path), a);
805 
806 	status = get_status(conn, id);
807 	if (status != SSH2_FX_OK)
808 		error("Couldn't setstat on \"%s\": %s", path,
809 		    fx2txt(status));
810 
811 	return status == SSH2_FX_OK ? 0 : -1;
812 }
813 
814 int
do_fsetstat(struct sftp_conn * conn,const u_char * handle,u_int handle_len,Attrib * a)815 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
816     Attrib *a)
817 {
818 	u_int status, id;
819 
820 	id = conn->msg_id++;
821 	send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
822 	    handle_len, a);
823 
824 	status = get_status(conn, id);
825 	if (status != SSH2_FX_OK)
826 		error("Couldn't fsetstat: %s", fx2txt(status));
827 
828 	return status == SSH2_FX_OK ? 0 : -1;
829 }
830 
831 char *
do_realpath(struct sftp_conn * conn,const char * path)832 do_realpath(struct sftp_conn *conn, const char *path)
833 {
834 	struct sshbuf *msg;
835 	u_int expected_id, count, id;
836 	char *filename, *longname;
837 	Attrib a;
838 	u_char type;
839 	int r;
840 
841 	expected_id = id = conn->msg_id++;
842 	send_string_request(conn, id, SSH2_FXP_REALPATH, path,
843 	    strlen(path));
844 
845 	if ((msg = sshbuf_new()) == NULL)
846 		fatal("%s: sshbuf_new failed", __func__);
847 
848 	get_msg(conn, msg);
849 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
850 	    (r = sshbuf_get_u32(msg, &id)) != 0)
851 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
852 
853 	if (id != expected_id)
854 		fatal("ID mismatch (%u != %u)", id, expected_id);
855 
856 	if (type == SSH2_FXP_STATUS) {
857 		u_int status;
858 
859 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
860 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
861 		error("Couldn't canonicalize: %s", fx2txt(status));
862 		sshbuf_free(msg);
863 		return NULL;
864 	} else if (type != SSH2_FXP_NAME)
865 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
866 		    SSH2_FXP_NAME, type);
867 
868 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
869 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
870 	if (count != 1)
871 		fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
872 
873 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
874 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
875 	    (r = decode_attrib(msg, &a)) != 0)
876 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
877 
878 	debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename,
879 	    (unsigned long)a.size);
880 
881 	free(longname);
882 
883 	sshbuf_free(msg);
884 
885 	return(filename);
886 }
887 
888 int
do_rename(struct sftp_conn * conn,const char * oldpath,const char * newpath,int force_legacy)889 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
890     int force_legacy)
891 {
892 	struct sshbuf *msg;
893 	u_int status, id;
894 	int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
895 
896 	if ((msg = sshbuf_new()) == NULL)
897 		fatal("%s: sshbuf_new failed", __func__);
898 
899 	/* Send rename request */
900 	id = conn->msg_id++;
901 	if (use_ext) {
902 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
903 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
904 		    (r = sshbuf_put_cstring(msg,
905 		    "posix-rename@openssh.com")) != 0)
906 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
907 	} else {
908 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
909 		    (r = sshbuf_put_u32(msg, id)) != 0)
910 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
911 	}
912 	if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
913 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
914 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
915 	send_msg(conn, msg);
916 	debug3("Sent message %s \"%s\" -> \"%s\"",
917 	    use_ext ? "posix-rename@openssh.com" :
918 	    "SSH2_FXP_RENAME", oldpath, newpath);
919 	sshbuf_free(msg);
920 
921 	status = get_status(conn, id);
922 	if (status != SSH2_FX_OK)
923 		error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
924 		    newpath, fx2txt(status));
925 
926 	return status == SSH2_FX_OK ? 0 : -1;
927 }
928 
929 int
do_hardlink(struct sftp_conn * conn,const char * oldpath,const char * newpath)930 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
931 {
932 	struct sshbuf *msg;
933 	u_int status, id;
934 	int r;
935 
936 	if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
937 		error("Server does not support hardlink@openssh.com extension");
938 		return -1;
939 	}
940 
941 	if ((msg = sshbuf_new()) == NULL)
942 		fatal("%s: sshbuf_new failed", __func__);
943 
944 	/* Send link request */
945 	id = conn->msg_id++;
946 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
947 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
948 	    (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
949 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
950 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
951 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
952 	send_msg(conn, msg);
953 	debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
954 	       oldpath, newpath);
955 	sshbuf_free(msg);
956 
957 	status = get_status(conn, id);
958 	if (status != SSH2_FX_OK)
959 		error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
960 		    newpath, fx2txt(status));
961 
962 	return status == SSH2_FX_OK ? 0 : -1;
963 }
964 
965 int
do_symlink(struct sftp_conn * conn,const char * oldpath,const char * newpath)966 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
967 {
968 	struct sshbuf *msg;
969 	u_int status, id;
970 	int r;
971 
972 	if (conn->version < 3) {
973 		error("This server does not support the symlink operation");
974 		return(SSH2_FX_OP_UNSUPPORTED);
975 	}
976 
977 	if ((msg = sshbuf_new()) == NULL)
978 		fatal("%s: sshbuf_new failed", __func__);
979 
980 	/* Send symlink request */
981 	id = conn->msg_id++;
982 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
983 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
984 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
985 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
986 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
987 	send_msg(conn, msg);
988 	debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
989 	    newpath);
990 	sshbuf_free(msg);
991 
992 	status = get_status(conn, id);
993 	if (status != SSH2_FX_OK)
994 		error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
995 		    newpath, fx2txt(status));
996 
997 	return status == SSH2_FX_OK ? 0 : -1;
998 }
999 
1000 int
do_fsync(struct sftp_conn * conn,u_char * handle,u_int handle_len)1001 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
1002 {
1003 	struct sshbuf *msg;
1004 	u_int status, id;
1005 	int r;
1006 
1007 	/* Silently return if the extension is not supported */
1008 	if ((conn->exts & SFTP_EXT_FSYNC) == 0)
1009 		return -1;
1010 
1011 	/* Send fsync request */
1012 	if ((msg = sshbuf_new()) == NULL)
1013 		fatal("%s: sshbuf_new failed", __func__);
1014 	id = conn->msg_id++;
1015 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1016 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1017 	    (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
1018 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1019 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1020 	send_msg(conn, msg);
1021 	debug3("Sent message fsync@openssh.com I:%u", id);
1022 	sshbuf_free(msg);
1023 
1024 	status = get_status(conn, id);
1025 	if (status != SSH2_FX_OK)
1026 		error("Couldn't sync file: %s", fx2txt(status));
1027 
1028 	return status == SSH2_FX_OK ? 0 : -1;
1029 }
1030 
1031 #ifdef notyet
1032 char *
do_readlink(struct sftp_conn * conn,const char * path)1033 do_readlink(struct sftp_conn *conn, const char *path)
1034 {
1035 	struct sshbuf *msg;
1036 	u_int expected_id, count, id;
1037 	char *filename, *longname;
1038 	Attrib a;
1039 	u_char type;
1040 	int r;
1041 
1042 	expected_id = id = conn->msg_id++;
1043 	send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
1044 
1045 	if ((msg = sshbuf_new()) == NULL)
1046 		fatal("%s: sshbuf_new failed", __func__);
1047 
1048 	get_msg(conn, msg);
1049 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1050 	    (r = sshbuf_get_u32(msg, &id)) != 0)
1051 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1052 
1053 	if (id != expected_id)
1054 		fatal("ID mismatch (%u != %u)", id, expected_id);
1055 
1056 	if (type == SSH2_FXP_STATUS) {
1057 		u_int status;
1058 
1059 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
1060 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
1061 		error("Couldn't readlink: %s", fx2txt(status));
1062 		sshbuf_free(msg);
1063 		return(NULL);
1064 	} else if (type != SSH2_FXP_NAME)
1065 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1066 		    SSH2_FXP_NAME, type);
1067 
1068 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
1069 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1070 	if (count != 1)
1071 		fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
1072 
1073 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1074 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1075 	    (r = decode_attrib(msg, &a)) != 0)
1076 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1077 
1078 	debug3("SSH_FXP_READLINK %s -> %s", path, filename);
1079 
1080 	free(longname);
1081 
1082 	sshbuf_free(msg);
1083 
1084 	return filename;
1085 }
1086 #endif
1087 
1088 int
do_statvfs(struct sftp_conn * conn,const char * path,struct sftp_statvfs * st,int quiet)1089 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
1090     int quiet)
1091 {
1092 	struct sshbuf *msg;
1093 	u_int id;
1094 	int r;
1095 
1096 	if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
1097 		error("Server does not support statvfs@openssh.com extension");
1098 		return -1;
1099 	}
1100 
1101 	id = conn->msg_id++;
1102 
1103 	if ((msg = sshbuf_new()) == NULL)
1104 		fatal("%s: sshbuf_new failed", __func__);
1105 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1106 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1107 	    (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
1108 	    (r = sshbuf_put_cstring(msg, path)) != 0)
1109 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1110 	send_msg(conn, msg);
1111 	sshbuf_free(msg);
1112 
1113 	return get_decode_statvfs(conn, st, id, quiet);
1114 }
1115 
1116 #ifdef notyet
1117 int
do_fstatvfs(struct sftp_conn * conn,const u_char * handle,u_int handle_len,struct sftp_statvfs * st,int quiet)1118 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1119     struct sftp_statvfs *st, int quiet)
1120 {
1121 	struct sshbuf *msg;
1122 	u_int id;
1123 
1124 	if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
1125 		error("Server does not support fstatvfs@openssh.com extension");
1126 		return -1;
1127 	}
1128 
1129 	id = conn->msg_id++;
1130 
1131 	if ((msg = sshbuf_new()) == NULL)
1132 		fatal("%s: sshbuf_new failed", __func__);
1133 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1134 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1135 	    (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
1136 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1137 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1138 	send_msg(conn, msg);
1139 	sshbuf_free(msg);
1140 
1141 	return get_decode_statvfs(conn, st, id, quiet);
1142 }
1143 #endif
1144 
1145 int
do_lsetstat(struct sftp_conn * conn,const char * path,Attrib * a)1146 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
1147 {
1148 	struct sshbuf *msg;
1149 	u_int status, id;
1150 	int r;
1151 
1152 	if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
1153 		error("Server does not support lsetstat@openssh.com extension");
1154 		return -1;
1155 	}
1156 
1157 	id = conn->msg_id++;
1158 	if ((msg = sshbuf_new()) == NULL)
1159 		fatal("%s: sshbuf_new failed", __func__);
1160 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1161 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1162 	    (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
1163 	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
1164 	    (r = encode_attrib(msg, a)) != 0)
1165 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1166 	send_msg(conn, msg);
1167 	sshbuf_free(msg);
1168 
1169 	status = get_status(conn, id);
1170 	if (status != SSH2_FX_OK)
1171 		error("Couldn't setstat on \"%s\": %s", path,
1172 		    fx2txt(status));
1173 
1174 	return status == SSH2_FX_OK ? 0 : -1;
1175 }
1176 
1177 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)1178 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1179     u_int len, const u_char *handle, u_int handle_len)
1180 {
1181 	struct sshbuf *msg;
1182 	int r;
1183 
1184 	if ((msg = sshbuf_new()) == NULL)
1185 		fatal("%s: sshbuf_new failed", __func__);
1186 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
1187 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1188 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
1189 	    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1190 	    (r = sshbuf_put_u32(msg, len)) != 0)
1191 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1192 	send_msg(conn, msg);
1193 	sshbuf_free(msg);
1194 }
1195 
1196 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)1197 do_download(struct sftp_conn *conn, const char *remote_path,
1198     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
1199     int fsync_flag)
1200 {
1201 	Attrib junk;
1202 	struct sshbuf *msg;
1203 	u_char *handle;
1204 	int local_fd = -1, write_error;
1205 	int read_error, write_errno, lmodified = 0, reordered = 0, r;
1206 	u_int64_t offset = 0, size, highwater;
1207 	u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
1208 	off_t progress_counter;
1209 	size_t handle_len;
1210 	struct stat st;
1211 	struct request {
1212 		u_int id;
1213 		size_t len;
1214 		u_int64_t offset;
1215 		TAILQ_ENTRY(request) tq;
1216 	};
1217 	TAILQ_HEAD(reqhead, request) requests;
1218 	struct request *req;
1219 	u_char type;
1220 
1221 	TAILQ_INIT(&requests);
1222 
1223 	if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
1224 		return -1;
1225 
1226 	/* Do not preserve set[ug]id here, as we do not preserve ownership */
1227 	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
1228 		mode = a->perm & 0777;
1229 	else
1230 		mode = 0666;
1231 
1232 	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
1233 	    (!S_ISREG(a->perm))) {
1234 		error("Cannot download non-regular file: %s", remote_path);
1235 		return(-1);
1236 	}
1237 
1238 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
1239 		size = a->size;
1240 	else
1241 		size = 0;
1242 
1243 	buflen = conn->transfer_buflen;
1244 	if ((msg = sshbuf_new()) == NULL)
1245 		fatal("%s: sshbuf_new failed", __func__);
1246 
1247 	attrib_clear(&junk); /* Send empty attributes */
1248 
1249 	/* Send open request */
1250 	id = conn->msg_id++;
1251 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1252 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1253 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
1254 	    (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
1255 	    (r = encode_attrib(msg, &junk)) != 0)
1256 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1257 	send_msg(conn, msg);
1258 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1259 
1260 	handle = get_handle(conn, id, &handle_len,
1261 	    "remote open(\"%s\")", remote_path);
1262 	if (handle == NULL) {
1263 		sshbuf_free(msg);
1264 		return(-1);
1265 	}
1266 
1267 	local_fd = open(local_path,
1268 	    O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
1269 	if (local_fd == -1) {
1270 		error("Couldn't open local file \"%s\" for writing: %s",
1271 		    local_path, strerror(errno));
1272 		goto fail;
1273 	}
1274 	offset = highwater = 0;
1275 	if (resume_flag) {
1276 		if (fstat(local_fd, &st) == -1) {
1277 			error("Unable to stat local file \"%s\": %s",
1278 			    local_path, strerror(errno));
1279 			goto fail;
1280 		}
1281 		if (st.st_size < 0) {
1282 			error("\"%s\" has negative size", local_path);
1283 			goto fail;
1284 		}
1285 		if ((u_int64_t)st.st_size > size) {
1286 			error("Unable to resume download of \"%s\": "
1287 			    "local file is larger than remote", local_path);
1288  fail:
1289 			do_close(conn, handle, handle_len);
1290 			sshbuf_free(msg);
1291 			free(handle);
1292 			if (local_fd != -1)
1293 				close(local_fd);
1294 			return -1;
1295 		}
1296 		offset = highwater = st.st_size;
1297 	}
1298 
1299 	/* Read from remote and write to local */
1300 	write_error = read_error = write_errno = num_req = 0;
1301 	max_req = 1;
1302 	progress_counter = offset;
1303 
1304 	if (showprogress && size != 0)
1305 		start_progress_meter(remote_path, size, &progress_counter);
1306 
1307 	while (num_req > 0 || max_req > 0) {
1308 		u_char *data;
1309 		size_t len;
1310 
1311 		/*
1312 		 * Simulate EOF on interrupt: stop sending new requests and
1313 		 * allow outstanding requests to drain gracefully
1314 		 */
1315 		if (interrupted) {
1316 			if (num_req == 0) /* If we haven't started yet... */
1317 				break;
1318 			max_req = 0;
1319 		}
1320 
1321 		/* Send some more requests */
1322 		while (num_req < max_req) {
1323 			debug3("Request range %llu -> %llu (%d/%d)",
1324 			    (unsigned long long)offset,
1325 			    (unsigned long long)offset + buflen - 1,
1326 			    num_req, max_req);
1327 			req = xcalloc(1, sizeof(*req));
1328 			req->id = conn->msg_id++;
1329 			req->len = buflen;
1330 			req->offset = offset;
1331 			offset += buflen;
1332 			num_req++;
1333 			TAILQ_INSERT_TAIL(&requests, req, tq);
1334 			send_read_request(conn, req->id, req->offset,
1335 			    req->len, handle, handle_len);
1336 		}
1337 
1338 		sshbuf_reset(msg);
1339 		get_msg(conn, msg);
1340 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1341 		    (r = sshbuf_get_u32(msg, &id)) != 0)
1342 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
1343 		debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
1344 
1345 		/* Find the request in our queue */
1346 		for (req = TAILQ_FIRST(&requests);
1347 		    req != NULL && req->id != id;
1348 		    req = TAILQ_NEXT(req, tq))
1349 			;
1350 		if (req == NULL)
1351 			fatal("Unexpected reply %u", id);
1352 
1353 		switch (type) {
1354 		case SSH2_FXP_STATUS:
1355 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1356 				fatal("%s: buffer error: %s",
1357 				    __func__, ssh_err(r));
1358 			if (status != SSH2_FX_EOF)
1359 				read_error = 1;
1360 			max_req = 0;
1361 			TAILQ_REMOVE(&requests, req, tq);
1362 			free(req);
1363 			num_req--;
1364 			break;
1365 		case SSH2_FXP_DATA:
1366 			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
1367 				fatal("%s: buffer error: %s",
1368 				    __func__, ssh_err(r));
1369 			debug3("Received data %llu -> %llu",
1370 			    (unsigned long long)req->offset,
1371 			    (unsigned long long)req->offset + len - 1);
1372 			if (len > req->len)
1373 				fatal("Received more data than asked for "
1374 				    "%zu > %zu", len, req->len);
1375 			lmodified = 1;
1376 			if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
1377 			    atomicio(vwrite, local_fd, data, len) != len) &&
1378 			    !write_error) {
1379 				write_errno = errno;
1380 				write_error = 1;
1381 				max_req = 0;
1382 			}
1383 			else if (!reordered && req->offset <= highwater)
1384 				highwater = req->offset + len;
1385 			else if (!reordered && req->offset > highwater)
1386 				reordered = 1;
1387 			progress_counter += len;
1388 			free(data);
1389 
1390 			if (len == req->len) {
1391 				TAILQ_REMOVE(&requests, req, tq);
1392 				free(req);
1393 				num_req--;
1394 			} else {
1395 				/* Resend the request for the missing data */
1396 				debug3("Short data block, re-requesting "
1397 				    "%llu -> %llu (%2d)",
1398 				    (unsigned long long)req->offset + len,
1399 				    (unsigned long long)req->offset +
1400 				    req->len - 1, num_req);
1401 				req->id = conn->msg_id++;
1402 				req->len -= len;
1403 				req->offset += len;
1404 				send_read_request(conn, req->id,
1405 				    req->offset, req->len, handle, handle_len);
1406 				/* Reduce the request size */
1407 				if (len < buflen)
1408 					buflen = MAXIMUM(MIN_READ_SIZE, len);
1409 			}
1410 			if (max_req > 0) { /* max_req = 0 iff EOF received */
1411 				if (size > 0 && offset > size) {
1412 					/* Only one request at a time
1413 					 * after the expected EOF */
1414 					debug3("Finish at %llu (%2d)",
1415 					    (unsigned long long)offset,
1416 					    num_req);
1417 					max_req = 1;
1418 				} else if (max_req <= conn->num_requests) {
1419 					++max_req;
1420 				}
1421 			}
1422 			break;
1423 		default:
1424 			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
1425 			    SSH2_FXP_DATA, type);
1426 		}
1427 	}
1428 
1429 	if (showprogress && size)
1430 		stop_progress_meter();
1431 
1432 	/* Sanity check */
1433 	if (TAILQ_FIRST(&requests) != NULL)
1434 		fatal("Transfer complete, but requests still in queue");
1435 	/* Truncate at highest contiguous point to avoid holes on interrupt */
1436 	if (read_error || write_error || interrupted) {
1437 		if (reordered && resume_flag) {
1438 			error("Unable to resume download of \"%s\": "
1439 			    "server reordered requests", local_path);
1440 		}
1441 		debug("truncating at %llu", (unsigned long long)highwater);
1442 		if (ftruncate(local_fd, highwater) == -1)
1443 			error("ftruncate \"%s\": %s", local_path,
1444 			    strerror(errno));
1445 	}
1446 	if (read_error) {
1447 		error("Couldn't read from remote file \"%s\" : %s",
1448 		    remote_path, fx2txt(status));
1449 		status = -1;
1450 		do_close(conn, handle, handle_len);
1451 	} else if (write_error) {
1452 		error("Couldn't write to \"%s\": %s", local_path,
1453 		    strerror(write_errno));
1454 		status = SSH2_FX_FAILURE;
1455 		do_close(conn, handle, handle_len);
1456 	} else {
1457 		if (do_close(conn, handle, handle_len) != 0 || interrupted)
1458 			status = SSH2_FX_FAILURE;
1459 		else
1460 			status = SSH2_FX_OK;
1461 		/* Override umask and utimes if asked */
1462 #ifdef HAVE_FCHMOD
1463 		if (preserve_flag && fchmod(local_fd, mode) == -1)
1464 #else
1465 		if (preserve_flag && chmod(local_path, mode) == -1)
1466 #endif /* HAVE_FCHMOD */
1467 			error("Couldn't set mode on \"%s\": %s", local_path,
1468 			    strerror(errno));
1469 		if (preserve_flag &&
1470 		    (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1471 			struct timeval tv[2];
1472 			tv[0].tv_sec = a->atime;
1473 			tv[1].tv_sec = a->mtime;
1474 			tv[0].tv_usec = tv[1].tv_usec = 0;
1475 			if (utimes(local_path, tv) == -1)
1476 				error("Can't set times on \"%s\": %s",
1477 				    local_path, strerror(errno));
1478 		}
1479 		if (resume_flag && !lmodified)
1480 			logit("File \"%s\" was not modified", local_path);
1481 		else if (fsync_flag) {
1482 			debug("syncing \"%s\"", local_path);
1483 			if (fsync(local_fd) == -1)
1484 				error("Couldn't sync file \"%s\": %s",
1485 				    local_path, strerror(errno));
1486 		}
1487 	}
1488 	close(local_fd);
1489 	sshbuf_free(msg);
1490 	free(handle);
1491 
1492 	return status == SSH2_FX_OK ? 0 : -1;
1493 }
1494 
1495 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)1496 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1497     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
1498     int resume_flag, int fsync_flag)
1499 {
1500 	int i, ret = 0;
1501 	SFTP_DIRENT **dir_entries;
1502 	char *filename, *new_src = NULL, *new_dst = NULL;
1503 	mode_t mode = 0777;
1504 
1505 	if (depth >= MAX_DIR_DEPTH) {
1506 		error("Maximum directory depth exceeded: %d levels", depth);
1507 		return -1;
1508 	}
1509 
1510 	if (dirattrib == NULL &&
1511 	    (dirattrib = do_stat(conn, src, 1)) == NULL) {
1512 		error("Unable to stat remote directory \"%s\"", src);
1513 		return -1;
1514 	}
1515 	if (!S_ISDIR(dirattrib->perm)) {
1516 		error("\"%s\" is not a directory", src);
1517 		return -1;
1518 	}
1519 	if (print_flag)
1520 		mprintf("Retrieving %s\n", src);
1521 
1522 	if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
1523 		mode = dirattrib->perm & 01777;
1524 	else {
1525 		debug("Server did not send permissions for "
1526 		    "directory \"%s\"", dst);
1527 	}
1528 
1529 	if (mkdir(dst, mode) == -1 && errno != EEXIST) {
1530 		error("mkdir %s: %s", dst, strerror(errno));
1531 		return -1;
1532 	}
1533 
1534 	if (do_readdir(conn, src, &dir_entries) == -1) {
1535 		error("%s: Failed to get directory contents", src);
1536 		return -1;
1537 	}
1538 
1539 	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
1540 		free(new_dst);
1541 		free(new_src);
1542 
1543 		filename = dir_entries[i]->filename;
1544 		new_dst = path_append(dst, filename);
1545 		new_src = path_append(src, filename);
1546 
1547 		if (S_ISDIR(dir_entries[i]->a.perm)) {
1548 			if (strcmp(filename, ".") == 0 ||
1549 			    strcmp(filename, "..") == 0)
1550 				continue;
1551 			if (download_dir_internal(conn, new_src, new_dst,
1552 			    depth + 1, &(dir_entries[i]->a), preserve_flag,
1553 			    print_flag, resume_flag, fsync_flag) == -1)
1554 				ret = -1;
1555 		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1556 			if (do_download(conn, new_src, new_dst,
1557 			    &(dir_entries[i]->a), preserve_flag,
1558 			    resume_flag, fsync_flag) == -1) {
1559 				error("Download of file %s to %s failed",
1560 				    new_src, new_dst);
1561 				ret = -1;
1562 			}
1563 		} else
1564 			logit("%s: not a regular file\n", new_src);
1565 
1566 	}
1567 	free(new_dst);
1568 	free(new_src);
1569 
1570 	if (preserve_flag) {
1571 		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1572 			struct timeval tv[2];
1573 			tv[0].tv_sec = dirattrib->atime;
1574 			tv[1].tv_sec = dirattrib->mtime;
1575 			tv[0].tv_usec = tv[1].tv_usec = 0;
1576 			if (utimes(dst, tv) == -1)
1577 				error("Can't set times on \"%s\": %s",
1578 				    dst, strerror(errno));
1579 		} else
1580 			debug("Server did not send times for directory "
1581 			    "\"%s\"", dst);
1582 	}
1583 
1584 	free_sftp_dirents(dir_entries);
1585 
1586 	return ret;
1587 }
1588 
1589 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)1590 download_dir(struct sftp_conn *conn, const char *src, const char *dst,
1591     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
1592     int fsync_flag)
1593 {
1594 	char *src_canon;
1595 	int ret;
1596 
1597 	if ((src_canon = do_realpath(conn, src)) == NULL) {
1598 		error("Unable to canonicalize path \"%s\"", src);
1599 		return -1;
1600 	}
1601 
1602 	ret = download_dir_internal(conn, src_canon, dst, 0,
1603 	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
1604 	free(src_canon);
1605 	return ret;
1606 }
1607 
1608 int
do_upload(struct sftp_conn * conn,const char * local_path,const char * remote_path,int preserve_flag,int resume,int fsync_flag)1609 do_upload(struct sftp_conn *conn, const char *local_path,
1610     const char *remote_path, int preserve_flag, int resume, int fsync_flag)
1611 {
1612 	int r, local_fd;
1613 	u_int status = SSH2_FX_OK;
1614 	u_int id;
1615 	u_char type;
1616 	off_t offset, progress_counter;
1617 	u_char *handle, *data;
1618 	struct sshbuf *msg;
1619 	struct stat sb;
1620 	Attrib a, *c = NULL;
1621 	u_int32_t startid;
1622 	u_int32_t ackid;
1623 	struct outstanding_ack {
1624 		u_int id;
1625 		u_int len;
1626 		off_t offset;
1627 		TAILQ_ENTRY(outstanding_ack) tq;
1628 	};
1629 	TAILQ_HEAD(ackhead, outstanding_ack) acks;
1630 	struct outstanding_ack *ack = NULL;
1631 	size_t handle_len;
1632 
1633 	TAILQ_INIT(&acks);
1634 
1635 	if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
1636 		error("Couldn't open local file \"%s\" for reading: %s",
1637 		    local_path, strerror(errno));
1638 		return(-1);
1639 	}
1640 	if (fstat(local_fd, &sb) == -1) {
1641 		error("Couldn't fstat local file \"%s\": %s",
1642 		    local_path, strerror(errno));
1643 		close(local_fd);
1644 		return(-1);
1645 	}
1646 	if (!S_ISREG(sb.st_mode)) {
1647 		error("%s is not a regular file", local_path);
1648 		close(local_fd);
1649 		return(-1);
1650 	}
1651 	stat_to_attrib(&sb, &a);
1652 
1653 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1654 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1655 	a.perm &= 0777;
1656 	if (!preserve_flag)
1657 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1658 
1659 	if (resume) {
1660 		/* Get remote file size if it exists */
1661 		if ((c = do_stat(conn, remote_path, 0)) == NULL) {
1662 			close(local_fd);
1663 			return -1;
1664 		}
1665 
1666 		if ((off_t)c->size >= sb.st_size) {
1667 			error("destination file bigger or same size as "
1668 			      "source file");
1669 			close(local_fd);
1670 			return -1;
1671 		}
1672 
1673 		if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
1674 			close(local_fd);
1675 			return -1;
1676 		}
1677 	}
1678 
1679 	if ((msg = sshbuf_new()) == NULL)
1680 		fatal("%s: sshbuf_new failed", __func__);
1681 
1682 	/* Send open request */
1683 	id = conn->msg_id++;
1684 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1685 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1686 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
1687 	    (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1688 	    (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
1689 	    (r = encode_attrib(msg, &a)) != 0)
1690 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1691 	send_msg(conn, msg);
1692 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1693 
1694 	sshbuf_reset(msg);
1695 
1696 	handle = get_handle(conn, id, &handle_len,
1697 	    "remote open(\"%s\")", remote_path);
1698 	if (handle == NULL) {
1699 		close(local_fd);
1700 		sshbuf_free(msg);
1701 		return -1;
1702 	}
1703 
1704 	startid = ackid = id + 1;
1705 	data = xmalloc(conn->transfer_buflen);
1706 
1707 	/* Read from local and write to remote */
1708 	offset = progress_counter = (resume ? c->size : 0);
1709 	if (showprogress)
1710 		start_progress_meter(local_path, sb.st_size,
1711 		    &progress_counter);
1712 
1713 	for (;;) {
1714 		int len;
1715 
1716 		/*
1717 		 * Can't use atomicio here because it returns 0 on EOF,
1718 		 * thus losing the last block of the file.
1719 		 * Simulate an EOF on interrupt, allowing ACKs from the
1720 		 * server to drain.
1721 		 */
1722 		if (interrupted || status != SSH2_FX_OK)
1723 			len = 0;
1724 		else do
1725 			len = read(local_fd, data, conn->transfer_buflen);
1726 		while ((len == -1) &&
1727 		    (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
1728 
1729 		if (len == -1)
1730 			fatal("Couldn't read from \"%s\": %s", local_path,
1731 			    strerror(errno));
1732 
1733 		if (len != 0) {
1734 			ack = xcalloc(1, sizeof(*ack));
1735 			ack->id = ++id;
1736 			ack->offset = offset;
1737 			ack->len = len;
1738 			TAILQ_INSERT_TAIL(&acks, ack, tq);
1739 
1740 			sshbuf_reset(msg);
1741 			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
1742 			    (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
1743 			    (r = sshbuf_put_string(msg, handle,
1744 			    handle_len)) != 0 ||
1745 			    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1746 			    (r = sshbuf_put_string(msg, data, len)) != 0)
1747 				fatal("%s: buffer error: %s",
1748 				    __func__, ssh_err(r));
1749 			send_msg(conn, msg);
1750 			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
1751 			    id, (unsigned long long)offset, len);
1752 		} else if (TAILQ_FIRST(&acks) == NULL)
1753 			break;
1754 
1755 		if (ack == NULL)
1756 			fatal("Unexpected ACK %u", id);
1757 
1758 		if (id == startid || len == 0 ||
1759 		    id - ackid >= conn->num_requests) {
1760 			u_int rid;
1761 
1762 			sshbuf_reset(msg);
1763 			get_msg(conn, msg);
1764 			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1765 			    (r = sshbuf_get_u32(msg, &rid)) != 0)
1766 				fatal("%s: buffer error: %s",
1767 				    __func__, ssh_err(r));
1768 
1769 			if (type != SSH2_FXP_STATUS)
1770 				fatal("Expected SSH2_FXP_STATUS(%d) packet, "
1771 				    "got %d", SSH2_FXP_STATUS, type);
1772 
1773 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1774 				fatal("%s: buffer error: %s",
1775 				    __func__, ssh_err(r));
1776 			debug3("SSH2_FXP_STATUS %u", status);
1777 
1778 			/* Find the request in our queue */
1779 			for (ack = TAILQ_FIRST(&acks);
1780 			    ack != NULL && ack->id != rid;
1781 			    ack = TAILQ_NEXT(ack, tq))
1782 				;
1783 			if (ack == NULL)
1784 				fatal("Can't find request for ID %u", rid);
1785 			TAILQ_REMOVE(&acks, ack, tq);
1786 			debug3("In write loop, ack for %u %u bytes at %lld",
1787 			    ack->id, ack->len, (long long)ack->offset);
1788 			++ackid;
1789 			progress_counter += ack->len;
1790 			free(ack);
1791 		}
1792 		offset += len;
1793 		if (offset < 0)
1794 			fatal("%s: offset < 0", __func__);
1795 	}
1796 	sshbuf_free(msg);
1797 
1798 	if (showprogress)
1799 		stop_progress_meter();
1800 	free(data);
1801 
1802 	if (status != SSH2_FX_OK) {
1803 		error("Couldn't write to remote file \"%s\": %s",
1804 		    remote_path, fx2txt(status));
1805 		status = SSH2_FX_FAILURE;
1806 	}
1807 
1808 	if (close(local_fd) == -1) {
1809 		error("Couldn't close local file \"%s\": %s", local_path,
1810 		    strerror(errno));
1811 		status = SSH2_FX_FAILURE;
1812 	}
1813 
1814 	/* Override umask and utimes if asked */
1815 	if (preserve_flag)
1816 		do_fsetstat(conn, handle, handle_len, &a);
1817 
1818 	if (fsync_flag)
1819 		(void)do_fsync(conn, handle, handle_len);
1820 
1821 	if (do_close(conn, handle, handle_len) != 0)
1822 		status = SSH2_FX_FAILURE;
1823 
1824 	free(handle);
1825 
1826 	return status == SSH2_FX_OK ? 0 : -1;
1827 }
1828 
1829 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)1830 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1831     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
1832 {
1833 	int ret = 0;
1834 	DIR *dirp;
1835 	struct dirent *dp;
1836 	char *filename, *new_src = NULL, *new_dst = NULL;
1837 	struct stat sb;
1838 	Attrib a, *dirattrib;
1839 
1840 	if (depth >= MAX_DIR_DEPTH) {
1841 		error("Maximum directory depth exceeded: %d levels", depth);
1842 		return -1;
1843 	}
1844 
1845 	if (stat(src, &sb) == -1) {
1846 		error("Couldn't stat directory \"%s\": %s",
1847 		    src, strerror(errno));
1848 		return -1;
1849 	}
1850 	if (!S_ISDIR(sb.st_mode)) {
1851 		error("\"%s\" is not a directory", src);
1852 		return -1;
1853 	}
1854 	if (print_flag)
1855 		mprintf("Entering %s\n", src);
1856 
1857 	attrib_clear(&a);
1858 	stat_to_attrib(&sb, &a);
1859 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1860 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1861 	a.perm &= 01777;
1862 	if (!preserve_flag)
1863 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1864 
1865 	/*
1866 	 * sftp lacks a portable status value to match errno EEXIST,
1867 	 * so if we get a failure back then we must check whether
1868 	 * the path already existed and is a directory.
1869 	 */
1870 	if (do_mkdir(conn, dst, &a, 0) != 0) {
1871 		if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
1872 			return -1;
1873 		if (!S_ISDIR(dirattrib->perm)) {
1874 			error("\"%s\" exists but is not a directory", dst);
1875 			return -1;
1876 		}
1877 	}
1878 
1879 	if ((dirp = opendir(src)) == NULL) {
1880 		error("Failed to open dir \"%s\": %s", src, strerror(errno));
1881 		return -1;
1882 	}
1883 
1884 	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
1885 		if (dp->d_ino == 0)
1886 			continue;
1887 		free(new_dst);
1888 		free(new_src);
1889 		filename = dp->d_name;
1890 		new_dst = path_append(dst, filename);
1891 		new_src = path_append(src, filename);
1892 
1893 		if (lstat(new_src, &sb) == -1) {
1894 			logit("%s: lstat failed: %s", filename,
1895 			    strerror(errno));
1896 			ret = -1;
1897 		} else if (S_ISDIR(sb.st_mode)) {
1898 			if (strcmp(filename, ".") == 0 ||
1899 			    strcmp(filename, "..") == 0)
1900 				continue;
1901 
1902 			if (upload_dir_internal(conn, new_src, new_dst,
1903 			    depth + 1, preserve_flag, print_flag, resume,
1904 			    fsync_flag) == -1)
1905 				ret = -1;
1906 		} else if (S_ISREG(sb.st_mode)) {
1907 			if (do_upload(conn, new_src, new_dst,
1908 			    preserve_flag, resume, fsync_flag) == -1) {
1909 				error("Uploading of file %s to %s failed!",
1910 				    new_src, new_dst);
1911 				ret = -1;
1912 			}
1913 		} else
1914 			logit("%s: not a regular file\n", filename);
1915 	}
1916 	free(new_dst);
1917 	free(new_src);
1918 
1919 	do_setstat(conn, dst, &a);
1920 
1921 	(void) closedir(dirp);
1922 	return ret;
1923 }
1924 
1925 int
upload_dir(struct sftp_conn * conn,const char * src,const char * dst,int preserve_flag,int print_flag,int resume,int fsync_flag)1926 upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
1927     int preserve_flag, int print_flag, int resume, int fsync_flag)
1928 {
1929 	char *dst_canon;
1930 	int ret;
1931 
1932 	if ((dst_canon = do_realpath(conn, dst)) == NULL) {
1933 		error("Unable to canonicalize path \"%s\"", dst);
1934 		return -1;
1935 	}
1936 
1937 	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
1938 	    print_flag, resume, fsync_flag);
1939 
1940 	free(dst_canon);
1941 	return ret;
1942 }
1943 
1944 char *
path_append(const char * p1,const char * p2)1945 path_append(const char *p1, const char *p2)
1946 {
1947 	char *ret;
1948 	size_t len = strlen(p1) + strlen(p2) + 2;
1949 
1950 	ret = xmalloc(len);
1951 	strlcpy(ret, p1, len);
1952 	if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
1953 		strlcat(ret, "/", len);
1954 	strlcat(ret, p2, len);
1955 
1956 	return(ret);
1957 }
1958 
1959