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