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