xref: /openbsd-src/usr.bin/ssh/sftp-server.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /* $OpenBSD: sftp-server.c,v 1.129 2021/08/09 23:47:44 djm Exp $ */
2 /*
3  * Copyright (c) 2000-2004 Markus Friedl.  All rights reserved.
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 #include <sys/types.h>
19 #include <sys/resource.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <sys/mount.h>
23 #include <sys/statvfs.h>
24 
25 #include <dirent.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <pwd.h>
32 #include <time.h>
33 #include <unistd.h>
34 #include <stdarg.h>
35 
36 #include "xmalloc.h"
37 #include "sshbuf.h"
38 #include "ssherr.h"
39 #include "log.h"
40 #include "misc.h"
41 #include "match.h"
42 #include "uidswap.h"
43 
44 #include "sftp.h"
45 #include "sftp-common.h"
46 
47 char *sftp_realpath(const char *, char *); /* sftp-realpath.c */
48 
49 /* Maximum data read that we are willing to accept */
50 #define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024)
51 
52 /* Our verbosity */
53 static LogLevel log_level = SYSLOG_LEVEL_ERROR;
54 
55 /* Our client */
56 static struct passwd *pw = NULL;
57 static char *client_addr = NULL;
58 
59 /* input and output queue */
60 struct sshbuf *iqueue;
61 struct sshbuf *oqueue;
62 
63 /* Version of client */
64 static u_int version;
65 
66 /* SSH2_FXP_INIT received */
67 static int init_done;
68 
69 /* Disable writes */
70 static int readonly;
71 
72 /* Requests that are allowed/denied */
73 static char *request_allowlist, *request_denylist;
74 
75 /* portable attributes, etc. */
76 typedef struct Stat Stat;
77 
78 struct Stat {
79 	char *name;
80 	char *long_name;
81 	Attrib attrib;
82 };
83 
84 /* Packet handlers */
85 static void process_open(u_int32_t id);
86 static void process_close(u_int32_t id);
87 static void process_read(u_int32_t id);
88 static void process_write(u_int32_t id);
89 static void process_stat(u_int32_t id);
90 static void process_lstat(u_int32_t id);
91 static void process_fstat(u_int32_t id);
92 static void process_setstat(u_int32_t id);
93 static void process_fsetstat(u_int32_t id);
94 static void process_opendir(u_int32_t id);
95 static void process_readdir(u_int32_t id);
96 static void process_remove(u_int32_t id);
97 static void process_mkdir(u_int32_t id);
98 static void process_rmdir(u_int32_t id);
99 static void process_realpath(u_int32_t id);
100 static void process_rename(u_int32_t id);
101 static void process_readlink(u_int32_t id);
102 static void process_symlink(u_int32_t id);
103 static void process_extended_posix_rename(u_int32_t id);
104 static void process_extended_statvfs(u_int32_t id);
105 static void process_extended_fstatvfs(u_int32_t id);
106 static void process_extended_hardlink(u_int32_t id);
107 static void process_extended_fsync(u_int32_t id);
108 static void process_extended_lsetstat(u_int32_t id);
109 static void process_extended_limits(u_int32_t id);
110 static void process_extended_expand(u_int32_t id);
111 static void process_extended(u_int32_t id);
112 
113 struct sftp_handler {
114 	const char *name;	/* user-visible name for fine-grained perms */
115 	const char *ext_name;	/* extended request name */
116 	u_int type;		/* packet type, for non extended packets */
117 	void (*handler)(u_int32_t);
118 	int does_write;		/* if nonzero, banned for readonly mode */
119 };
120 
121 static const struct sftp_handler handlers[] = {
122 	/* NB. SSH2_FXP_OPEN does the readonly check in the handler itself */
123 	{ "open", NULL, SSH2_FXP_OPEN, process_open, 0 },
124 	{ "close", NULL, SSH2_FXP_CLOSE, process_close, 0 },
125 	{ "read", NULL, SSH2_FXP_READ, process_read, 0 },
126 	{ "write", NULL, SSH2_FXP_WRITE, process_write, 1 },
127 	{ "lstat", NULL, SSH2_FXP_LSTAT, process_lstat, 0 },
128 	{ "fstat", NULL, SSH2_FXP_FSTAT, process_fstat, 0 },
129 	{ "setstat", NULL, SSH2_FXP_SETSTAT, process_setstat, 1 },
130 	{ "fsetstat", NULL, SSH2_FXP_FSETSTAT, process_fsetstat, 1 },
131 	{ "opendir", NULL, SSH2_FXP_OPENDIR, process_opendir, 0 },
132 	{ "readdir", NULL, SSH2_FXP_READDIR, process_readdir, 0 },
133 	{ "remove", NULL, SSH2_FXP_REMOVE, process_remove, 1 },
134 	{ "mkdir", NULL, SSH2_FXP_MKDIR, process_mkdir, 1 },
135 	{ "rmdir", NULL, SSH2_FXP_RMDIR, process_rmdir, 1 },
136 	{ "realpath", NULL, SSH2_FXP_REALPATH, process_realpath, 0 },
137 	{ "stat", NULL, SSH2_FXP_STAT, process_stat, 0 },
138 	{ "rename", NULL, SSH2_FXP_RENAME, process_rename, 1 },
139 	{ "readlink", NULL, SSH2_FXP_READLINK, process_readlink, 0 },
140 	{ "symlink", NULL, SSH2_FXP_SYMLINK, process_symlink, 1 },
141 	{ NULL, NULL, 0, NULL, 0 }
142 };
143 
144 /* SSH2_FXP_EXTENDED submessages */
145 static const struct sftp_handler extended_handlers[] = {
146 	{ "posix-rename", "posix-rename@openssh.com", 0,
147 	    process_extended_posix_rename, 1 },
148 	{ "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs, 0 },
149 	{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 },
150 	{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 },
151 	{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 },
152 	{ "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 },
153 	{ "limits", "limits@openssh.com", 0, process_extended_limits, 0 },
154 	{ "expand-path", "expand-path@openssh.com", 0,
155 	    process_extended_expand, 0 },
156 	{ NULL, NULL, 0, NULL, 0 }
157 };
158 
159 static const struct sftp_handler *
160 extended_handler_byname(const char *name)
161 {
162 	int i;
163 
164 	for (i = 0; extended_handlers[i].handler != NULL; i++) {
165 		if (strcmp(name, extended_handlers[i].ext_name) == 0)
166 			return &extended_handlers[i];
167 	}
168 	return NULL;
169 }
170 
171 static int
172 request_permitted(const struct sftp_handler *h)
173 {
174 	char *result;
175 
176 	if (readonly && h->does_write) {
177 		verbose("Refusing %s request in read-only mode", h->name);
178 		return 0;
179 	}
180 	if (request_denylist != NULL &&
181 	    ((result = match_list(h->name, request_denylist, NULL))) != NULL) {
182 		free(result);
183 		verbose("Refusing denylisted %s request", h->name);
184 		return 0;
185 	}
186 	if (request_allowlist != NULL &&
187 	    ((result = match_list(h->name, request_allowlist, NULL))) != NULL) {
188 		free(result);
189 		debug2("Permitting allowlisted %s request", h->name);
190 		return 1;
191 	}
192 	if (request_allowlist != NULL) {
193 		verbose("Refusing non-allowlisted %s request", h->name);
194 		return 0;
195 	}
196 	return 1;
197 }
198 
199 static int
200 errno_to_portable(int unixerrno)
201 {
202 	int ret = 0;
203 
204 	switch (unixerrno) {
205 	case 0:
206 		ret = SSH2_FX_OK;
207 		break;
208 	case ENOENT:
209 	case ENOTDIR:
210 	case EBADF:
211 	case ELOOP:
212 		ret = SSH2_FX_NO_SUCH_FILE;
213 		break;
214 	case EPERM:
215 	case EACCES:
216 	case EFAULT:
217 		ret = SSH2_FX_PERMISSION_DENIED;
218 		break;
219 	case ENAMETOOLONG:
220 	case EINVAL:
221 		ret = SSH2_FX_BAD_MESSAGE;
222 		break;
223 	case ENOSYS:
224 		ret = SSH2_FX_OP_UNSUPPORTED;
225 		break;
226 	default:
227 		ret = SSH2_FX_FAILURE;
228 		break;
229 	}
230 	return ret;
231 }
232 
233 static int
234 flags_from_portable(int pflags)
235 {
236 	int flags = 0;
237 
238 	if ((pflags & SSH2_FXF_READ) &&
239 	    (pflags & SSH2_FXF_WRITE)) {
240 		flags = O_RDWR;
241 	} else if (pflags & SSH2_FXF_READ) {
242 		flags = O_RDONLY;
243 	} else if (pflags & SSH2_FXF_WRITE) {
244 		flags = O_WRONLY;
245 	}
246 	if (pflags & SSH2_FXF_APPEND)
247 		flags |= O_APPEND;
248 	if (pflags & SSH2_FXF_CREAT)
249 		flags |= O_CREAT;
250 	if (pflags & SSH2_FXF_TRUNC)
251 		flags |= O_TRUNC;
252 	if (pflags & SSH2_FXF_EXCL)
253 		flags |= O_EXCL;
254 	return flags;
255 }
256 
257 static const char *
258 string_from_portable(int pflags)
259 {
260 	static char ret[128];
261 
262 	*ret = '\0';
263 
264 #define PAPPEND(str)	{				\
265 		if (*ret != '\0')			\
266 			strlcat(ret, ",", sizeof(ret));	\
267 		strlcat(ret, str, sizeof(ret));		\
268 	}
269 
270 	if (pflags & SSH2_FXF_READ)
271 		PAPPEND("READ")
272 	if (pflags & SSH2_FXF_WRITE)
273 		PAPPEND("WRITE")
274 	if (pflags & SSH2_FXF_APPEND)
275 		PAPPEND("APPEND")
276 	if (pflags & SSH2_FXF_CREAT)
277 		PAPPEND("CREATE")
278 	if (pflags & SSH2_FXF_TRUNC)
279 		PAPPEND("TRUNCATE")
280 	if (pflags & SSH2_FXF_EXCL)
281 		PAPPEND("EXCL")
282 
283 	return ret;
284 }
285 
286 /* handle handles */
287 
288 typedef struct Handle Handle;
289 struct Handle {
290 	int use;
291 	DIR *dirp;
292 	int fd;
293 	int flags;
294 	char *name;
295 	u_int64_t bytes_read, bytes_write;
296 	int next_unused;
297 };
298 
299 enum {
300 	HANDLE_UNUSED,
301 	HANDLE_DIR,
302 	HANDLE_FILE
303 };
304 
305 static Handle *handles = NULL;
306 static u_int num_handles = 0;
307 static int first_unused_handle = -1;
308 
309 static void handle_unused(int i)
310 {
311 	handles[i].use = HANDLE_UNUSED;
312 	handles[i].next_unused = first_unused_handle;
313 	first_unused_handle = i;
314 }
315 
316 static int
317 handle_new(int use, const char *name, int fd, int flags, DIR *dirp)
318 {
319 	int i;
320 
321 	if (first_unused_handle == -1) {
322 		if (num_handles + 1 <= num_handles)
323 			return -1;
324 		num_handles++;
325 		handles = xreallocarray(handles, num_handles, sizeof(Handle));
326 		handle_unused(num_handles - 1);
327 	}
328 
329 	i = first_unused_handle;
330 	first_unused_handle = handles[i].next_unused;
331 
332 	handles[i].use = use;
333 	handles[i].dirp = dirp;
334 	handles[i].fd = fd;
335 	handles[i].flags = flags;
336 	handles[i].name = xstrdup(name);
337 	handles[i].bytes_read = handles[i].bytes_write = 0;
338 
339 	return i;
340 }
341 
342 static int
343 handle_is_ok(int i, int type)
344 {
345 	return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
346 }
347 
348 static int
349 handle_to_string(int handle, u_char **stringp, int *hlenp)
350 {
351 	if (stringp == NULL || hlenp == NULL)
352 		return -1;
353 	*stringp = xmalloc(sizeof(int32_t));
354 	put_u32(*stringp, handle);
355 	*hlenp = sizeof(int32_t);
356 	return 0;
357 }
358 
359 static int
360 handle_from_string(const u_char *handle, u_int hlen)
361 {
362 	int val;
363 
364 	if (hlen != sizeof(int32_t))
365 		return -1;
366 	val = get_u32(handle);
367 	if (handle_is_ok(val, HANDLE_FILE) ||
368 	    handle_is_ok(val, HANDLE_DIR))
369 		return val;
370 	return -1;
371 }
372 
373 static char *
374 handle_to_name(int handle)
375 {
376 	if (handle_is_ok(handle, HANDLE_DIR)||
377 	    handle_is_ok(handle, HANDLE_FILE))
378 		return handles[handle].name;
379 	return NULL;
380 }
381 
382 static DIR *
383 handle_to_dir(int handle)
384 {
385 	if (handle_is_ok(handle, HANDLE_DIR))
386 		return handles[handle].dirp;
387 	return NULL;
388 }
389 
390 static int
391 handle_to_fd(int handle)
392 {
393 	if (handle_is_ok(handle, HANDLE_FILE))
394 		return handles[handle].fd;
395 	return -1;
396 }
397 
398 static int
399 handle_to_flags(int handle)
400 {
401 	if (handle_is_ok(handle, HANDLE_FILE))
402 		return handles[handle].flags;
403 	return 0;
404 }
405 
406 static void
407 handle_update_read(int handle, ssize_t bytes)
408 {
409 	if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
410 		handles[handle].bytes_read += bytes;
411 }
412 
413 static void
414 handle_update_write(int handle, ssize_t bytes)
415 {
416 	if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
417 		handles[handle].bytes_write += bytes;
418 }
419 
420 static u_int64_t
421 handle_bytes_read(int handle)
422 {
423 	if (handle_is_ok(handle, HANDLE_FILE))
424 		return (handles[handle].bytes_read);
425 	return 0;
426 }
427 
428 static u_int64_t
429 handle_bytes_write(int handle)
430 {
431 	if (handle_is_ok(handle, HANDLE_FILE))
432 		return (handles[handle].bytes_write);
433 	return 0;
434 }
435 
436 static int
437 handle_close(int handle)
438 {
439 	int ret = -1;
440 
441 	if (handle_is_ok(handle, HANDLE_FILE)) {
442 		ret = close(handles[handle].fd);
443 		free(handles[handle].name);
444 		handle_unused(handle);
445 	} else if (handle_is_ok(handle, HANDLE_DIR)) {
446 		ret = closedir(handles[handle].dirp);
447 		free(handles[handle].name);
448 		handle_unused(handle);
449 	} else {
450 		errno = ENOENT;
451 	}
452 	return ret;
453 }
454 
455 static void
456 handle_log_close(int handle, char *emsg)
457 {
458 	if (handle_is_ok(handle, HANDLE_FILE)) {
459 		logit("%s%sclose \"%s\" bytes read %llu written %llu",
460 		    emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
461 		    handle_to_name(handle),
462 		    (unsigned long long)handle_bytes_read(handle),
463 		    (unsigned long long)handle_bytes_write(handle));
464 	} else {
465 		logit("%s%sclosedir \"%s\"",
466 		    emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
467 		    handle_to_name(handle));
468 	}
469 }
470 
471 static void
472 handle_log_exit(void)
473 {
474 	u_int i;
475 
476 	for (i = 0; i < num_handles; i++)
477 		if (handles[i].use != HANDLE_UNUSED)
478 			handle_log_close(i, "forced");
479 }
480 
481 static int
482 get_handle(struct sshbuf *queue, int *hp)
483 {
484 	u_char *handle;
485 	int r;
486 	size_t hlen;
487 
488 	*hp = -1;
489 	if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0)
490 		return r;
491 	if (hlen < 256)
492 		*hp = handle_from_string(handle, hlen);
493 	free(handle);
494 	return 0;
495 }
496 
497 /* send replies */
498 
499 static void
500 send_msg(struct sshbuf *m)
501 {
502 	int r;
503 
504 	if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
505 		fatal_fr(r, "enqueue");
506 	sshbuf_reset(m);
507 }
508 
509 static const char *
510 status_to_message(u_int32_t status)
511 {
512 	const char *status_messages[] = {
513 		"Success",			/* SSH_FX_OK */
514 		"End of file",			/* SSH_FX_EOF */
515 		"No such file",			/* SSH_FX_NO_SUCH_FILE */
516 		"Permission denied",		/* SSH_FX_PERMISSION_DENIED */
517 		"Failure",			/* SSH_FX_FAILURE */
518 		"Bad message",			/* SSH_FX_BAD_MESSAGE */
519 		"No connection",		/* SSH_FX_NO_CONNECTION */
520 		"Connection lost",		/* SSH_FX_CONNECTION_LOST */
521 		"Operation unsupported",	/* SSH_FX_OP_UNSUPPORTED */
522 		"Unknown error"			/* Others */
523 	};
524 	return (status_messages[MINIMUM(status,SSH2_FX_MAX)]);
525 }
526 
527 static void
528 send_status(u_int32_t id, u_int32_t status)
529 {
530 	struct sshbuf *msg;
531 	int r;
532 
533 	debug3("request %u: sent status %u", id, status);
534 	if (log_level > SYSLOG_LEVEL_VERBOSE ||
535 	    (status != SSH2_FX_OK && status != SSH2_FX_EOF))
536 		logit("sent status %s", status_to_message(status));
537 	if ((msg = sshbuf_new()) == NULL)
538 		fatal_f("sshbuf_new failed");
539 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 ||
540 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
541 	    (r = sshbuf_put_u32(msg, status)) != 0)
542 		fatal_fr(r, "compose");
543 	if (version >= 3) {
544 		if ((r = sshbuf_put_cstring(msg,
545 		    status_to_message(status))) != 0 ||
546 		    (r = sshbuf_put_cstring(msg, "")) != 0)
547 			fatal_fr(r, "compose message");
548 	}
549 	send_msg(msg);
550 	sshbuf_free(msg);
551 }
552 static void
553 send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen)
554 {
555 	struct sshbuf *msg;
556 	int r;
557 
558 	if ((msg = sshbuf_new()) == NULL)
559 		fatal_f("sshbuf_new failed");
560 	if ((r = sshbuf_put_u8(msg, type)) != 0 ||
561 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
562 	    (r = sshbuf_put_string(msg, data, dlen)) != 0)
563 		fatal_fr(r, "compose");
564 	send_msg(msg);
565 	sshbuf_free(msg);
566 }
567 
568 static void
569 send_data(u_int32_t id, const u_char *data, int dlen)
570 {
571 	debug("request %u: sent data len %d", id, dlen);
572 	send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
573 }
574 
575 static void
576 send_handle(u_int32_t id, int handle)
577 {
578 	u_char *string;
579 	int hlen;
580 
581 	handle_to_string(handle, &string, &hlen);
582 	debug("request %u: sent handle handle %d", id, handle);
583 	send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
584 	free(string);
585 }
586 
587 static void
588 send_names(u_int32_t id, int count, const Stat *stats)
589 {
590 	struct sshbuf *msg;
591 	int i, r;
592 
593 	if ((msg = sshbuf_new()) == NULL)
594 		fatal_f("sshbuf_new failed");
595 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 ||
596 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
597 	    (r = sshbuf_put_u32(msg, count)) != 0)
598 		fatal_fr(r, "compose");
599 	debug("request %u: sent names count %d", id, count);
600 	for (i = 0; i < count; i++) {
601 		if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 ||
602 		    (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 ||
603 		    (r = encode_attrib(msg, &stats[i].attrib)) != 0)
604 			fatal_fr(r, "compose filenames/attrib");
605 	}
606 	send_msg(msg);
607 	sshbuf_free(msg);
608 }
609 
610 static void
611 send_attrib(u_int32_t id, const Attrib *a)
612 {
613 	struct sshbuf *msg;
614 	int r;
615 
616 	debug("request %u: sent attrib have 0x%x", id, a->flags);
617 	if ((msg = sshbuf_new()) == NULL)
618 		fatal_f("sshbuf_new failed");
619 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 ||
620 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
621 	    (r = encode_attrib(msg, a)) != 0)
622 		fatal_fr(r, "compose");
623 	send_msg(msg);
624 	sshbuf_free(msg);
625 }
626 
627 static void
628 send_statvfs(u_int32_t id, struct statvfs *st)
629 {
630 	struct sshbuf *msg;
631 	u_int64_t flag;
632 	int r;
633 
634 	flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
635 	flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
636 
637 	if ((msg = sshbuf_new()) == NULL)
638 		fatal_f("sshbuf_new failed");
639 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
640 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
641 	    (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 ||
642 	    (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 ||
643 	    (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 ||
644 	    (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 ||
645 	    (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 ||
646 	    (r = sshbuf_put_u64(msg, st->f_files)) != 0 ||
647 	    (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 ||
648 	    (r = sshbuf_put_u64(msg, st->f_favail)) != 0 ||
649 	    (r = sshbuf_put_u64(msg, st->f_fsid)) != 0 ||
650 	    (r = sshbuf_put_u64(msg, flag)) != 0 ||
651 	    (r = sshbuf_put_u64(msg, st->f_namemax)) != 0)
652 		fatal_fr(r, "compose");
653 	send_msg(msg);
654 	sshbuf_free(msg);
655 }
656 
657 /*
658  * Prepare SSH2_FXP_VERSION extension advertisement for a single extension.
659  * The extension is checked for permission prior to advertisment.
660  */
661 static int
662 compose_extension(struct sshbuf *msg, const char *name, const char *ver)
663 {
664 	int r;
665 	const struct sftp_handler *exthnd;
666 
667 	if ((exthnd = extended_handler_byname(name)) == NULL)
668 		fatal_f("internal error: no handler for %s", name);
669 	if (!request_permitted(exthnd)) {
670 		debug2_f("refusing to advertise disallowed extension %s", name);
671 		return 0;
672 	}
673 	if ((r = sshbuf_put_cstring(msg, name)) != 0 ||
674 	    (r = sshbuf_put_cstring(msg, ver)) != 0)
675 		fatal_fr(r, "compose %s", name);
676 	return 0;
677 }
678 
679 /* parse incoming */
680 
681 static void
682 process_init(void)
683 {
684 	struct sshbuf *msg;
685 	int r;
686 
687 	if ((r = sshbuf_get_u32(iqueue, &version)) != 0)
688 		fatal_fr(r, "parse");
689 	verbose("received client version %u", version);
690 	if ((msg = sshbuf_new()) == NULL)
691 		fatal_f("sshbuf_new failed");
692 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 ||
693 	    (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
694 		fatal_fr(r, "compose");
695 
696 	 /* extension advertisments */
697 	compose_extension(msg, "posix-rename@openssh.com", "1");
698 	compose_extension(msg, "statvfs@openssh.com", "2");
699 	compose_extension(msg, "fstatvfs@openssh.com", "2");
700 	compose_extension(msg, "hardlink@openssh.com", "1");
701 	compose_extension(msg, "fsync@openssh.com", "1");
702 	compose_extension(msg, "lsetstat@openssh.com", "1");
703 	compose_extension(msg, "limits@openssh.com", "1");
704 	compose_extension(msg, "expand-path@openssh.com", "1");
705 
706 	send_msg(msg);
707 	sshbuf_free(msg);
708 }
709 
710 static void
711 process_open(u_int32_t id)
712 {
713 	u_int32_t pflags;
714 	Attrib a;
715 	char *name;
716 	int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
717 
718 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
719 	    (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
720 	    (r = decode_attrib(iqueue, &a)) != 0)
721 		fatal_fr(r, "parse");
722 
723 	debug3("request %u: open flags %d", id, pflags);
724 	flags = flags_from_portable(pflags);
725 	mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
726 	logit("open \"%s\" flags %s mode 0%o",
727 	    name, string_from_portable(pflags), mode);
728 	if (readonly &&
729 	    ((flags & O_ACCMODE) != O_RDONLY ||
730 	    (flags & (O_CREAT|O_TRUNC)) != 0)) {
731 		verbose("Refusing open request in read-only mode");
732 		status = SSH2_FX_PERMISSION_DENIED;
733 	} else {
734 		fd = open(name, flags, mode);
735 		if (fd == -1) {
736 			status = errno_to_portable(errno);
737 		} else {
738 			handle = handle_new(HANDLE_FILE, name, fd, flags, NULL);
739 			if (handle < 0) {
740 				close(fd);
741 			} else {
742 				send_handle(id, handle);
743 				status = SSH2_FX_OK;
744 			}
745 		}
746 	}
747 	if (status != SSH2_FX_OK)
748 		send_status(id, status);
749 	free(name);
750 }
751 
752 static void
753 process_close(u_int32_t id)
754 {
755 	int r, handle, ret, status = SSH2_FX_FAILURE;
756 
757 	if ((r = get_handle(iqueue, &handle)) != 0)
758 		fatal_fr(r, "parse");
759 
760 	debug3("request %u: close handle %u", id, handle);
761 	handle_log_close(handle, NULL);
762 	ret = handle_close(handle);
763 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
764 	send_status(id, status);
765 }
766 
767 static void
768 process_read(u_int32_t id)
769 {
770 	static u_char *buf;
771 	static size_t buflen;
772 	u_int32_t len;
773 	int r, handle, fd, ret, status = SSH2_FX_FAILURE;
774 	u_int64_t off;
775 
776 	if ((r = get_handle(iqueue, &handle)) != 0 ||
777 	    (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
778 	    (r = sshbuf_get_u32(iqueue, &len)) != 0)
779 		fatal_fr(r, "parse");
780 
781 	debug("request %u: read \"%s\" (handle %d) off %llu len %u",
782 	    id, handle_to_name(handle), handle, (unsigned long long)off, len);
783 	if ((fd = handle_to_fd(handle)) == -1)
784 		goto out;
785 	if (len > SFTP_MAX_READ_LENGTH) {
786 		debug2("read change len %u to %u", len, SFTP_MAX_READ_LENGTH);
787 		len = SFTP_MAX_READ_LENGTH;
788 	}
789 	if (len > buflen) {
790 		debug3_f("allocate %zu => %u", buflen, len);
791 		if ((buf = realloc(NULL, len)) == NULL)
792 			fatal_f("realloc failed");
793 		buflen = len;
794 	}
795 	if (lseek(fd, off, SEEK_SET) == -1) {
796 		status = errno_to_portable(errno);
797 		error_f("seek \"%.100s\": %s", handle_to_name(handle),
798 		    strerror(errno));
799 		goto out;
800 	}
801 	if (len == 0) {
802 		/* weird, but not strictly disallowed */
803 		ret = 0;
804 	} else if ((ret = read(fd, buf, len)) == -1) {
805 		status = errno_to_portable(errno);
806 		error_f("read \"%.100s\": %s", handle_to_name(handle),
807 		    strerror(errno));
808 		goto out;
809 	} else if (ret == 0) {
810 		status = SSH2_FX_EOF;
811 		goto out;
812 	}
813 	send_data(id, buf, ret);
814 	handle_update_read(handle, ret);
815 	/* success */
816 	status = SSH2_FX_OK;
817  out:
818 	if (status != SSH2_FX_OK)
819 		send_status(id, status);
820 }
821 
822 static void
823 process_write(u_int32_t id)
824 {
825 	u_int64_t off;
826 	size_t len;
827 	int r, handle, fd, ret, status;
828 	u_char *data;
829 
830 	if ((r = get_handle(iqueue, &handle)) != 0 ||
831 	    (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
832 	    (r = sshbuf_get_string(iqueue, &data, &len)) != 0)
833 		fatal_fr(r, "parse");
834 
835 	debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
836 	    id, handle_to_name(handle), handle, (unsigned long long)off, len);
837 	fd = handle_to_fd(handle);
838 
839 	if (fd < 0)
840 		status = SSH2_FX_FAILURE;
841 	else {
842 		if (!(handle_to_flags(handle) & O_APPEND) &&
843 		    lseek(fd, off, SEEK_SET) == -1) {
844 			status = errno_to_portable(errno);
845 			error_f("seek \"%.100s\": %s", handle_to_name(handle),
846 			    strerror(errno));
847 		} else {
848 /* XXX ATOMICIO ? */
849 			ret = write(fd, data, len);
850 			if (ret == -1) {
851 				status = errno_to_portable(errno);
852 				error_f("write \"%.100s\": %s",
853 				    handle_to_name(handle), strerror(errno));
854 			} else if ((size_t)ret == len) {
855 				status = SSH2_FX_OK;
856 				handle_update_write(handle, ret);
857 			} else {
858 				debug2_f("nothing at all written");
859 				status = SSH2_FX_FAILURE;
860 			}
861 		}
862 	}
863 	send_status(id, status);
864 	free(data);
865 }
866 
867 static void
868 process_do_stat(u_int32_t id, int do_lstat)
869 {
870 	Attrib a;
871 	struct stat st;
872 	char *name;
873 	int r, status = SSH2_FX_FAILURE;
874 
875 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
876 		fatal_fr(r, "parse");
877 
878 	debug3("request %u: %sstat", id, do_lstat ? "l" : "");
879 	verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
880 	r = do_lstat ? lstat(name, &st) : stat(name, &st);
881 	if (r == -1) {
882 		status = errno_to_portable(errno);
883 	} else {
884 		stat_to_attrib(&st, &a);
885 		send_attrib(id, &a);
886 		status = SSH2_FX_OK;
887 	}
888 	if (status != SSH2_FX_OK)
889 		send_status(id, status);
890 	free(name);
891 }
892 
893 static void
894 process_stat(u_int32_t id)
895 {
896 	process_do_stat(id, 0);
897 }
898 
899 static void
900 process_lstat(u_int32_t id)
901 {
902 	process_do_stat(id, 1);
903 }
904 
905 static void
906 process_fstat(u_int32_t id)
907 {
908 	Attrib a;
909 	struct stat st;
910 	int fd, r, handle, status = SSH2_FX_FAILURE;
911 
912 	if ((r = get_handle(iqueue, &handle)) != 0)
913 		fatal_fr(r, "parse");
914 	debug("request %u: fstat \"%s\" (handle %u)",
915 	    id, handle_to_name(handle), handle);
916 	fd = handle_to_fd(handle);
917 	if (fd >= 0) {
918 		r = fstat(fd, &st);
919 		if (r == -1) {
920 			status = errno_to_portable(errno);
921 		} else {
922 			stat_to_attrib(&st, &a);
923 			send_attrib(id, &a);
924 			status = SSH2_FX_OK;
925 		}
926 	}
927 	if (status != SSH2_FX_OK)
928 		send_status(id, status);
929 }
930 
931 static struct timeval *
932 attrib_to_tv(const Attrib *a)
933 {
934 	static struct timeval tv[2];
935 
936 	tv[0].tv_sec = a->atime;
937 	tv[0].tv_usec = 0;
938 	tv[1].tv_sec = a->mtime;
939 	tv[1].tv_usec = 0;
940 	return tv;
941 }
942 
943 static struct timespec *
944 attrib_to_ts(const Attrib *a)
945 {
946 	static struct timespec ts[2];
947 
948 	ts[0].tv_sec = a->atime;
949 	ts[0].tv_nsec = 0;
950 	ts[1].tv_sec = a->mtime;
951 	ts[1].tv_nsec = 0;
952 	return ts;
953 }
954 
955 static void
956 process_setstat(u_int32_t id)
957 {
958 	Attrib a;
959 	char *name;
960 	int r, status = SSH2_FX_OK;
961 
962 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
963 	    (r = decode_attrib(iqueue, &a)) != 0)
964 		fatal_fr(r, "parse");
965 
966 	debug("request %u: setstat name \"%s\"", id, name);
967 	if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
968 		logit("set \"%s\" size %llu",
969 		    name, (unsigned long long)a.size);
970 		r = truncate(name, a.size);
971 		if (r == -1)
972 			status = errno_to_portable(errno);
973 	}
974 	if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
975 		logit("set \"%s\" mode %04o", name, a.perm);
976 		r = chmod(name, a.perm & 07777);
977 		if (r == -1)
978 			status = errno_to_portable(errno);
979 	}
980 	if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
981 		char buf[64];
982 		time_t t = a.mtime;
983 
984 		strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
985 		    localtime(&t));
986 		logit("set \"%s\" modtime %s", name, buf);
987 		r = utimes(name, attrib_to_tv(&a));
988 		if (r == -1)
989 			status = errno_to_portable(errno);
990 	}
991 	if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
992 		logit("set \"%s\" owner %lu group %lu", name,
993 		    (u_long)a.uid, (u_long)a.gid);
994 		r = chown(name, a.uid, a.gid);
995 		if (r == -1)
996 			status = errno_to_portable(errno);
997 	}
998 	send_status(id, status);
999 	free(name);
1000 }
1001 
1002 static void
1003 process_fsetstat(u_int32_t id)
1004 {
1005 	Attrib a;
1006 	int handle, fd, r;
1007 	int status = SSH2_FX_OK;
1008 
1009 	if ((r = get_handle(iqueue, &handle)) != 0 ||
1010 	    (r = decode_attrib(iqueue, &a)) != 0)
1011 		fatal_fr(r, "parse");
1012 
1013 	debug("request %u: fsetstat handle %d", id, handle);
1014 	fd = handle_to_fd(handle);
1015 	if (fd < 0)
1016 		status = SSH2_FX_FAILURE;
1017 	else {
1018 		char *name = handle_to_name(handle);
1019 
1020 		if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
1021 			logit("set \"%s\" size %llu",
1022 			    name, (unsigned long long)a.size);
1023 			r = ftruncate(fd, a.size);
1024 			if (r == -1)
1025 				status = errno_to_portable(errno);
1026 		}
1027 		if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1028 			logit("set \"%s\" mode %04o", name, a.perm);
1029 			r = fchmod(fd, a.perm & 07777);
1030 			if (r == -1)
1031 				status = errno_to_portable(errno);
1032 		}
1033 		if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1034 			char buf[64];
1035 			time_t t = a.mtime;
1036 
1037 			strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
1038 			    localtime(&t));
1039 			logit("set \"%s\" modtime %s", name, buf);
1040 			r = futimes(fd, attrib_to_tv(&a));
1041 			if (r == -1)
1042 				status = errno_to_portable(errno);
1043 		}
1044 		if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
1045 			logit("set \"%s\" owner %lu group %lu", name,
1046 			    (u_long)a.uid, (u_long)a.gid);
1047 			r = fchown(fd, a.uid, a.gid);
1048 			if (r == -1)
1049 				status = errno_to_portable(errno);
1050 		}
1051 	}
1052 	send_status(id, status);
1053 }
1054 
1055 static void
1056 process_opendir(u_int32_t id)
1057 {
1058 	DIR *dirp = NULL;
1059 	char *path;
1060 	int r, handle, status = SSH2_FX_FAILURE;
1061 
1062 	if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1063 		fatal_fr(r, "parse");
1064 
1065 	debug3("request %u: opendir", id);
1066 	logit("opendir \"%s\"", path);
1067 	dirp = opendir(path);
1068 	if (dirp == NULL) {
1069 		status = errno_to_portable(errno);
1070 	} else {
1071 		handle = handle_new(HANDLE_DIR, path, 0, 0, dirp);
1072 		if (handle < 0) {
1073 			closedir(dirp);
1074 		} else {
1075 			send_handle(id, handle);
1076 			status = SSH2_FX_OK;
1077 		}
1078 
1079 	}
1080 	if (status != SSH2_FX_OK)
1081 		send_status(id, status);
1082 	free(path);
1083 }
1084 
1085 static void
1086 process_readdir(u_int32_t id)
1087 {
1088 	DIR *dirp;
1089 	struct dirent *dp;
1090 	char *path;
1091 	int r, handle;
1092 
1093 	if ((r = get_handle(iqueue, &handle)) != 0)
1094 		fatal_fr(r, "parse");
1095 
1096 	debug("request %u: readdir \"%s\" (handle %d)", id,
1097 	    handle_to_name(handle), handle);
1098 	dirp = handle_to_dir(handle);
1099 	path = handle_to_name(handle);
1100 	if (dirp == NULL || path == NULL) {
1101 		send_status(id, SSH2_FX_FAILURE);
1102 	} else {
1103 		struct stat st;
1104 		char pathname[PATH_MAX];
1105 		Stat *stats;
1106 		int nstats = 10, count = 0, i;
1107 
1108 		stats = xcalloc(nstats, sizeof(Stat));
1109 		while ((dp = readdir(dirp)) != NULL) {
1110 			if (count >= nstats) {
1111 				nstats *= 2;
1112 				stats = xreallocarray(stats, nstats, sizeof(Stat));
1113 			}
1114 /* XXX OVERFLOW ? */
1115 			snprintf(pathname, sizeof pathname, "%s%s%s", path,
1116 			    strcmp(path, "/") ? "/" : "", dp->d_name);
1117 			if (lstat(pathname, &st) == -1)
1118 				continue;
1119 			stat_to_attrib(&st, &(stats[count].attrib));
1120 			stats[count].name = xstrdup(dp->d_name);
1121 			stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
1122 			count++;
1123 			/* send up to 100 entries in one message */
1124 			/* XXX check packet size instead */
1125 			if (count == 100)
1126 				break;
1127 		}
1128 		if (count > 0) {
1129 			send_names(id, count, stats);
1130 			for (i = 0; i < count; i++) {
1131 				free(stats[i].name);
1132 				free(stats[i].long_name);
1133 			}
1134 		} else {
1135 			send_status(id, SSH2_FX_EOF);
1136 		}
1137 		free(stats);
1138 	}
1139 }
1140 
1141 static void
1142 process_remove(u_int32_t id)
1143 {
1144 	char *name;
1145 	int r, status = SSH2_FX_FAILURE;
1146 
1147 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
1148 		fatal_fr(r, "parse");
1149 
1150 	debug3("request %u: remove", id);
1151 	logit("remove name \"%s\"", name);
1152 	r = unlink(name);
1153 	status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1154 	send_status(id, status);
1155 	free(name);
1156 }
1157 
1158 static void
1159 process_mkdir(u_int32_t id)
1160 {
1161 	Attrib a;
1162 	char *name;
1163 	int r, mode, status = SSH2_FX_FAILURE;
1164 
1165 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
1166 	    (r = decode_attrib(iqueue, &a)) != 0)
1167 		fatal_fr(r, "parse");
1168 
1169 	mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
1170 	    a.perm & 07777 : 0777;
1171 	debug3("request %u: mkdir", id);
1172 	logit("mkdir name \"%s\" mode 0%o", name, mode);
1173 	r = mkdir(name, mode);
1174 	status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1175 	send_status(id, status);
1176 	free(name);
1177 }
1178 
1179 static void
1180 process_rmdir(u_int32_t id)
1181 {
1182 	char *name;
1183 	int r, status;
1184 
1185 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
1186 		fatal_fr(r, "parse");
1187 
1188 	debug3("request %u: rmdir", id);
1189 	logit("rmdir name \"%s\"", name);
1190 	r = rmdir(name);
1191 	status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1192 	send_status(id, status);
1193 	free(name);
1194 }
1195 
1196 static void
1197 process_realpath(u_int32_t id)
1198 {
1199 	char resolvedname[PATH_MAX];
1200 	char *path;
1201 	int r;
1202 
1203 	if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1204 		fatal_fr(r, "parse");
1205 
1206 	if (path[0] == '\0') {
1207 		free(path);
1208 		path = xstrdup(".");
1209 	}
1210 	debug3("request %u: realpath", id);
1211 	verbose("realpath \"%s\"", path);
1212 	if (sftp_realpath(path, resolvedname) == NULL) {
1213 		send_status(id, errno_to_portable(errno));
1214 	} else {
1215 		Stat s;
1216 		attrib_clear(&s.attrib);
1217 		s.name = s.long_name = resolvedname;
1218 		send_names(id, 1, &s);
1219 	}
1220 	free(path);
1221 }
1222 
1223 static void
1224 process_rename(u_int32_t id)
1225 {
1226 	char *oldpath, *newpath;
1227 	int r, status;
1228 	struct stat sb;
1229 
1230 	if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1231 	    (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1232 		fatal_fr(r, "parse");
1233 
1234 	debug3("request %u: rename", id);
1235 	logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
1236 	status = SSH2_FX_FAILURE;
1237 	if (lstat(oldpath, &sb) == -1)
1238 		status = errno_to_portable(errno);
1239 	else if (S_ISREG(sb.st_mode)) {
1240 		/* Race-free rename of regular files */
1241 		if (link(oldpath, newpath) == -1) {
1242 			if (errno == EOPNOTSUPP) {
1243 				struct stat st;
1244 
1245 				/*
1246 				 * fs doesn't support links, so fall back to
1247 				 * stat+rename.  This is racy.
1248 				 */
1249 				if (stat(newpath, &st) == -1) {
1250 					if (rename(oldpath, newpath) == -1)
1251 						status =
1252 						    errno_to_portable(errno);
1253 					else
1254 						status = SSH2_FX_OK;
1255 				}
1256 			} else {
1257 				status = errno_to_portable(errno);
1258 			}
1259 		} else if (unlink(oldpath) == -1) {
1260 			status = errno_to_portable(errno);
1261 			/* clean spare link */
1262 			unlink(newpath);
1263 		} else
1264 			status = SSH2_FX_OK;
1265 	} else if (stat(newpath, &sb) == -1) {
1266 		if (rename(oldpath, newpath) == -1)
1267 			status = errno_to_portable(errno);
1268 		else
1269 			status = SSH2_FX_OK;
1270 	}
1271 	send_status(id, status);
1272 	free(oldpath);
1273 	free(newpath);
1274 }
1275 
1276 static void
1277 process_readlink(u_int32_t id)
1278 {
1279 	int r, len;
1280 	char buf[PATH_MAX];
1281 	char *path;
1282 
1283 	if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1284 		fatal_fr(r, "parse");
1285 
1286 	debug3("request %u: readlink", id);
1287 	verbose("readlink \"%s\"", path);
1288 	if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
1289 		send_status(id, errno_to_portable(errno));
1290 	else {
1291 		Stat s;
1292 
1293 		buf[len] = '\0';
1294 		attrib_clear(&s.attrib);
1295 		s.name = s.long_name = buf;
1296 		send_names(id, 1, &s);
1297 	}
1298 	free(path);
1299 }
1300 
1301 static void
1302 process_symlink(u_int32_t id)
1303 {
1304 	char *oldpath, *newpath;
1305 	int r, status;
1306 
1307 	if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1308 	    (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1309 		fatal_fr(r, "parse");
1310 
1311 	debug3("request %u: symlink", id);
1312 	logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
1313 	/* this will fail if 'newpath' exists */
1314 	r = symlink(oldpath, newpath);
1315 	status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1316 	send_status(id, status);
1317 	free(oldpath);
1318 	free(newpath);
1319 }
1320 
1321 static void
1322 process_extended_posix_rename(u_int32_t id)
1323 {
1324 	char *oldpath, *newpath;
1325 	int r, status;
1326 
1327 	if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1328 	    (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1329 		fatal_fr(r, "parse");
1330 
1331 	debug3("request %u: posix-rename", id);
1332 	logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1333 	r = rename(oldpath, newpath);
1334 	status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1335 	send_status(id, status);
1336 	free(oldpath);
1337 	free(newpath);
1338 }
1339 
1340 static void
1341 process_extended_statvfs(u_int32_t id)
1342 {
1343 	char *path;
1344 	struct statvfs st;
1345 	int r;
1346 
1347 	if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1348 		fatal_fr(r, "parse");
1349 	debug3("request %u: statvfs", id);
1350 	logit("statvfs \"%s\"", path);
1351 
1352 	if (statvfs(path, &st) != 0)
1353 		send_status(id, errno_to_portable(errno));
1354 	else
1355 		send_statvfs(id, &st);
1356 	free(path);
1357 }
1358 
1359 static void
1360 process_extended_fstatvfs(u_int32_t id)
1361 {
1362 	int r, handle, fd;
1363 	struct statvfs st;
1364 
1365 	if ((r = get_handle(iqueue, &handle)) != 0)
1366 		fatal_fr(r, "parse");
1367 	debug("request %u: fstatvfs \"%s\" (handle %u)",
1368 	    id, handle_to_name(handle), handle);
1369 	if ((fd = handle_to_fd(handle)) < 0) {
1370 		send_status(id, SSH2_FX_FAILURE);
1371 		return;
1372 	}
1373 	if (fstatvfs(fd, &st) != 0)
1374 		send_status(id, errno_to_portable(errno));
1375 	else
1376 		send_statvfs(id, &st);
1377 }
1378 
1379 static void
1380 process_extended_hardlink(u_int32_t id)
1381 {
1382 	char *oldpath, *newpath;
1383 	int r, status;
1384 
1385 	if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1386 	    (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1387 		fatal_fr(r, "parse");
1388 
1389 	debug3("request %u: hardlink", id);
1390 	logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
1391 	r = link(oldpath, newpath);
1392 	status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1393 	send_status(id, status);
1394 	free(oldpath);
1395 	free(newpath);
1396 }
1397 
1398 static void
1399 process_extended_fsync(u_int32_t id)
1400 {
1401 	int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
1402 
1403 	if ((r = get_handle(iqueue, &handle)) != 0)
1404 		fatal_fr(r, "parse");
1405 	debug3("request %u: fsync (handle %u)", id, handle);
1406 	verbose("fsync \"%s\"", handle_to_name(handle));
1407 	if ((fd = handle_to_fd(handle)) < 0)
1408 		status = SSH2_FX_NO_SUCH_FILE;
1409 	else if (handle_is_ok(handle, HANDLE_FILE)) {
1410 		r = fsync(fd);
1411 		status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1412 	}
1413 	send_status(id, status);
1414 }
1415 
1416 static void
1417 process_extended_lsetstat(u_int32_t id)
1418 {
1419 	Attrib a;
1420 	char *name;
1421 	int r, status = SSH2_FX_OK;
1422 
1423 	if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
1424 	    (r = decode_attrib(iqueue, &a)) != 0)
1425 		fatal_fr(r, "parse");
1426 
1427 	debug("request %u: lsetstat name \"%s\"", id, name);
1428 	if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
1429 		/* nonsensical for links */
1430 		status = SSH2_FX_BAD_MESSAGE;
1431 		goto out;
1432 	}
1433 	if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1434 		logit("set \"%s\" mode %04o", name, a.perm);
1435 		r = fchmodat(AT_FDCWD, name,
1436 		    a.perm & 07777, AT_SYMLINK_NOFOLLOW);
1437 		if (r == -1)
1438 			status = errno_to_portable(errno);
1439 	}
1440 	if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1441 		char buf[64];
1442 		time_t t = a.mtime;
1443 
1444 		strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
1445 		    localtime(&t));
1446 		logit("set \"%s\" modtime %s", name, buf);
1447 		r = utimensat(AT_FDCWD, name,
1448 		    attrib_to_ts(&a), AT_SYMLINK_NOFOLLOW);
1449 		if (r == -1)
1450 			status = errno_to_portable(errno);
1451 	}
1452 	if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
1453 		logit("set \"%s\" owner %lu group %lu", name,
1454 		    (u_long)a.uid, (u_long)a.gid);
1455 		r = fchownat(AT_FDCWD, name, a.uid, a.gid,
1456 		    AT_SYMLINK_NOFOLLOW);
1457 		if (r == -1)
1458 			status = errno_to_portable(errno);
1459 	}
1460  out:
1461 	send_status(id, status);
1462 	free(name);
1463 }
1464 
1465 static void
1466 process_extended_limits(u_int32_t id)
1467 {
1468 	struct sshbuf *msg;
1469 	int r;
1470 	uint64_t nfiles = 0;
1471 	struct rlimit rlim;
1472 
1473 	debug("request %u: limits", id);
1474 
1475 	if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5)
1476 		nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */
1477 
1478 	if ((msg = sshbuf_new()) == NULL)
1479 		fatal_f("sshbuf_new failed");
1480 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
1481 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1482 	    /* max-packet-length */
1483 	    (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH)) != 0 ||
1484 	    /* max-read-length */
1485 	    (r = sshbuf_put_u64(msg, SFTP_MAX_READ_LENGTH)) != 0 ||
1486 	    /* max-write-length */
1487 	    (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH - 1024)) != 0 ||
1488 	    /* max-open-handles */
1489 	    (r = sshbuf_put_u64(msg, nfiles)) != 0)
1490 		fatal_fr(r, "compose");
1491 	send_msg(msg);
1492 	sshbuf_free(msg);
1493 }
1494 
1495 static void
1496 process_extended_expand(u_int32_t id)
1497 {
1498 	char cwd[PATH_MAX], resolvedname[PATH_MAX];
1499 	char *path, *npath;
1500 	int r;
1501 	Stat s;
1502 
1503 	if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1504 		fatal_fr(r, "parse");
1505 	if (getcwd(cwd, sizeof(cwd)) == NULL) {
1506 		send_status(id, errno_to_portable(errno));
1507 		goto out;
1508 	}
1509 
1510 	debug3("request %u: expand, original \"%s\"", id, path);
1511 	if (path[0] == '\0') {
1512 		/* empty path */
1513 		free(path);
1514 		path = xstrdup(".");
1515 	} else if (*path == '~') {
1516 		/* ~ expand path */
1517 		/* Special-case for "~" and "~/" to respect homedir flag */
1518 		if (strcmp(path, "~") == 0) {
1519 			free(path);
1520 			path = xstrdup(cwd);
1521 		} else if (strncmp(path, "~/", 2) == 0) {
1522 			npath = xstrdup(path + 2);
1523 			free(path);
1524 			xasprintf(&path, "%s/%s", cwd, npath);
1525 		} else {
1526 			/* ~user expansions */
1527 			if (tilde_expand(path, pw->pw_uid, &npath) != 0) {
1528 				send_status(id, errno_to_portable(EINVAL));
1529 				goto out;
1530 			}
1531 			free(path);
1532 			path = npath;
1533 		}
1534 	} else if (*path != '/') {
1535 		/* relative path */
1536 		xasprintf(&npath, "%s/%s", cwd, path);
1537 		free(path);
1538 		path = npath;
1539 	}
1540 	verbose("expand \"%s\"", path);
1541 	if (sftp_realpath(path, resolvedname) == NULL) {
1542 		send_status(id, errno_to_portable(errno));
1543 		goto out;
1544 	}
1545 	attrib_clear(&s.attrib);
1546 	s.name = s.long_name = resolvedname;
1547 	send_names(id, 1, &s);
1548  out:
1549 	free(path);
1550 }
1551 
1552 static void
1553 process_extended(u_int32_t id)
1554 {
1555 	char *request;
1556 	int r;
1557 	const struct sftp_handler *exthand;
1558 
1559 	if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0)
1560 		fatal_fr(r, "parse");
1561 	if ((exthand = extended_handler_byname(request)) == NULL) {
1562 		error("Unknown extended request \"%.100s\"", request);
1563 		send_status(id, SSH2_FX_OP_UNSUPPORTED);	/* MUST */
1564 	} else {
1565 		if (!request_permitted(exthand))
1566 			send_status(id, SSH2_FX_PERMISSION_DENIED);
1567 		else
1568 			exthand->handler(id);
1569 	}
1570 	free(request);
1571 }
1572 
1573 /* stolen from ssh-agent */
1574 
1575 static void
1576 process(void)
1577 {
1578 	u_int msg_len;
1579 	u_int buf_len;
1580 	u_int consumed;
1581 	u_char type;
1582 	const u_char *cp;
1583 	int i, r;
1584 	u_int32_t id;
1585 
1586 	buf_len = sshbuf_len(iqueue);
1587 	if (buf_len < 5)
1588 		return;		/* Incomplete message. */
1589 	cp = sshbuf_ptr(iqueue);
1590 	msg_len = get_u32(cp);
1591 	if (msg_len > SFTP_MAX_MSG_LENGTH) {
1592 		error("bad message from %s local user %s",
1593 		    client_addr, pw->pw_name);
1594 		sftp_server_cleanup_exit(11);
1595 	}
1596 	if (buf_len < msg_len + 4)
1597 		return;
1598 	if ((r = sshbuf_consume(iqueue, 4)) != 0)
1599 		fatal_fr(r, "consume");
1600 	buf_len -= 4;
1601 	if ((r = sshbuf_get_u8(iqueue, &type)) != 0)
1602 		fatal_fr(r, "parse type");
1603 
1604 	switch (type) {
1605 	case SSH2_FXP_INIT:
1606 		process_init();
1607 		init_done = 1;
1608 		break;
1609 	case SSH2_FXP_EXTENDED:
1610 		if (!init_done)
1611 			fatal("Received extended request before init");
1612 		if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
1613 			fatal_fr(r, "parse extended ID");
1614 		process_extended(id);
1615 		break;
1616 	default:
1617 		if (!init_done)
1618 			fatal("Received %u request before init", type);
1619 		if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
1620 			fatal_fr(r, "parse ID");
1621 		for (i = 0; handlers[i].handler != NULL; i++) {
1622 			if (type == handlers[i].type) {
1623 				if (!request_permitted(&handlers[i])) {
1624 					send_status(id,
1625 					    SSH2_FX_PERMISSION_DENIED);
1626 				} else {
1627 					handlers[i].handler(id);
1628 				}
1629 				break;
1630 			}
1631 		}
1632 		if (handlers[i].handler == NULL)
1633 			error("Unknown message %u", type);
1634 	}
1635 	/* discard the remaining bytes from the current packet */
1636 	if (buf_len < sshbuf_len(iqueue)) {
1637 		error("iqueue grew unexpectedly");
1638 		sftp_server_cleanup_exit(255);
1639 	}
1640 	consumed = buf_len - sshbuf_len(iqueue);
1641 	if (msg_len < consumed) {
1642 		error("msg_len %u < consumed %u", msg_len, consumed);
1643 		sftp_server_cleanup_exit(255);
1644 	}
1645 	if (msg_len > consumed &&
1646 	    (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
1647 		fatal_fr(r, "consume");
1648 }
1649 
1650 /* Cleanup handler that logs active handles upon normal exit */
1651 void
1652 sftp_server_cleanup_exit(int i)
1653 {
1654 	if (pw != NULL && client_addr != NULL) {
1655 		handle_log_exit();
1656 		logit("session closed for local user %s from [%s]",
1657 		    pw->pw_name, client_addr);
1658 	}
1659 	_exit(i);
1660 }
1661 
1662 static void
1663 sftp_server_usage(void)
1664 {
1665 	extern char *__progname;
1666 
1667 	fprintf(stderr,
1668 	    "usage: %s [-ehR] [-d start_directory] [-f log_facility] "
1669 	    "[-l log_level]\n\t[-P denied_requests] "
1670 	    "[-p allowed_requests] [-u umask]\n"
1671 	    "       %s -Q protocol_feature\n",
1672 	    __progname, __progname);
1673 	exit(1);
1674 }
1675 
1676 int
1677 sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1678 {
1679 	fd_set *rset, *wset;
1680 	int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
1681 	ssize_t len, olen, set_size;
1682 	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
1683 	char *cp, *homedir = NULL, uidstr[32], buf[4*4096];
1684 	long mask;
1685 
1686 	extern char *optarg;
1687 	extern char *__progname;
1688 
1689 	log_init(__progname, log_level, log_facility, log_stderr);
1690 
1691 	pw = pwcopy(user_pw);
1692 
1693 	while (!skipargs && (ch = getopt(argc, argv,
1694 	    "d:f:l:P:p:Q:u:cehR")) != -1) {
1695 		switch (ch) {
1696 		case 'Q':
1697 			if (strcasecmp(optarg, "requests") != 0) {
1698 				fprintf(stderr, "Invalid query type\n");
1699 				exit(1);
1700 			}
1701 			for (i = 0; handlers[i].handler != NULL; i++)
1702 				printf("%s\n", handlers[i].name);
1703 			for (i = 0; extended_handlers[i].handler != NULL; i++)
1704 				printf("%s\n", extended_handlers[i].name);
1705 			exit(0);
1706 			break;
1707 		case 'R':
1708 			readonly = 1;
1709 			break;
1710 		case 'c':
1711 			/*
1712 			 * Ignore all arguments if we are invoked as a
1713 			 * shell using "sftp-server -c command"
1714 			 */
1715 			skipargs = 1;
1716 			break;
1717 		case 'e':
1718 			log_stderr = 1;
1719 			break;
1720 		case 'l':
1721 			log_level = log_level_number(optarg);
1722 			if (log_level == SYSLOG_LEVEL_NOT_SET)
1723 				error("Invalid log level \"%s\"", optarg);
1724 			break;
1725 		case 'f':
1726 			log_facility = log_facility_number(optarg);
1727 			if (log_facility == SYSLOG_FACILITY_NOT_SET)
1728 				error("Invalid log facility \"%s\"", optarg);
1729 			break;
1730 		case 'd':
1731 			cp = tilde_expand_filename(optarg, user_pw->pw_uid);
1732 			snprintf(uidstr, sizeof(uidstr), "%llu",
1733 			    (unsigned long long)pw->pw_uid);
1734 			homedir = percent_expand(cp, "d", user_pw->pw_dir,
1735 			    "u", user_pw->pw_name, "U", uidstr, (char *)NULL);
1736 			free(cp);
1737 			break;
1738 		case 'p':
1739 			if (request_allowlist != NULL)
1740 				fatal("Permitted requests already set");
1741 			request_allowlist = xstrdup(optarg);
1742 			break;
1743 		case 'P':
1744 			if (request_denylist != NULL)
1745 				fatal("Refused requests already set");
1746 			request_denylist = xstrdup(optarg);
1747 			break;
1748 		case 'u':
1749 			errno = 0;
1750 			mask = strtol(optarg, &cp, 8);
1751 			if (mask < 0 || mask > 0777 || *cp != '\0' ||
1752 			    cp == optarg || (mask == 0 && errno != 0))
1753 				fatal("Invalid umask \"%s\"", optarg);
1754 			(void)umask((mode_t)mask);
1755 			break;
1756 		case 'h':
1757 		default:
1758 			sftp_server_usage();
1759 		}
1760 	}
1761 
1762 	log_init(__progname, log_level, log_facility, log_stderr);
1763 
1764 	if ((cp = getenv("SSH_CONNECTION")) != NULL) {
1765 		client_addr = xstrdup(cp);
1766 		if ((cp = strchr(client_addr, ' ')) == NULL) {
1767 			error("Malformed SSH_CONNECTION variable: \"%s\"",
1768 			    getenv("SSH_CONNECTION"));
1769 			sftp_server_cleanup_exit(255);
1770 		}
1771 		*cp = '\0';
1772 	} else
1773 		client_addr = xstrdup("UNKNOWN");
1774 
1775 	logit("session opened for local user %s from [%s]",
1776 	    pw->pw_name, client_addr);
1777 
1778 	in = STDIN_FILENO;
1779 	out = STDOUT_FILENO;
1780 
1781 	max = 0;
1782 	if (in > max)
1783 		max = in;
1784 	if (out > max)
1785 		max = out;
1786 
1787 	if ((iqueue = sshbuf_new()) == NULL)
1788 		fatal_f("sshbuf_new failed");
1789 	if ((oqueue = sshbuf_new()) == NULL)
1790 		fatal_f("sshbuf_new failed");
1791 
1792 	rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
1793 	wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
1794 
1795 	if (homedir != NULL) {
1796 		if (chdir(homedir) != 0) {
1797 			error("chdir to \"%s\" failed: %s", homedir,
1798 			    strerror(errno));
1799 		}
1800 	}
1801 
1802 	set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
1803 	for (;;) {
1804 		memset(rset, 0, set_size);
1805 		memset(wset, 0, set_size);
1806 
1807 		/*
1808 		 * Ensure that we can read a full buffer and handle
1809 		 * the worst-case length packet it can generate,
1810 		 * otherwise apply backpressure by stopping reads.
1811 		 */
1812 		if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
1813 		    (r = sshbuf_check_reserve(oqueue,
1814 		    SFTP_MAX_MSG_LENGTH)) == 0)
1815 			FD_SET(in, rset);
1816 		else if (r != SSH_ERR_NO_BUFFER_SPACE)
1817 			fatal_fr(r, "reserve");
1818 
1819 		olen = sshbuf_len(oqueue);
1820 		if (olen > 0)
1821 			FD_SET(out, wset);
1822 
1823 		if (select(max+1, rset, wset, NULL, NULL) == -1) {
1824 			if (errno == EINTR)
1825 				continue;
1826 			error("select: %s", strerror(errno));
1827 			sftp_server_cleanup_exit(2);
1828 		}
1829 
1830 		/* copy stdin to iqueue */
1831 		if (FD_ISSET(in, rset)) {
1832 			len = read(in, buf, sizeof buf);
1833 			if (len == 0) {
1834 				debug("read eof");
1835 				sftp_server_cleanup_exit(0);
1836 			} else if (len == -1) {
1837 				error("read: %s", strerror(errno));
1838 				sftp_server_cleanup_exit(1);
1839 			} else if ((r = sshbuf_put(iqueue, buf, len)) != 0)
1840 				fatal_fr(r, "sshbuf_put");
1841 		}
1842 		/* send oqueue to stdout */
1843 		if (FD_ISSET(out, wset)) {
1844 			len = write(out, sshbuf_ptr(oqueue), olen);
1845 			if (len == -1) {
1846 				error("write: %s", strerror(errno));
1847 				sftp_server_cleanup_exit(1);
1848 			} else if ((r = sshbuf_consume(oqueue, len)) != 0)
1849 				fatal_fr(r, "consume");
1850 		}
1851 
1852 		/*
1853 		 * Process requests from client if we can fit the results
1854 		 * into the output buffer, otherwise stop processing input
1855 		 * and let the output queue drain.
1856 		 */
1857 		r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH);
1858 		if (r == 0)
1859 			process();
1860 		else if (r != SSH_ERR_NO_BUFFER_SPACE)
1861 			fatal_fr(r, "reserve");
1862 	}
1863 }
1864