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