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