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