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