sftp-server.c revision 248619
1/* $OpenBSD: sftp-server.c,v 1.96 2013/01/04 19:26:38 jmc 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 */
60LogLevel log_level = SYSLOG_LEVEL_ERROR;
61
62/* Our client */
63struct passwd *pw = NULL;
64char *client_addr = NULL;
65
66/* input and output queue */
67Buffer iqueue;
68Buffer oqueue;
69
70/* Version of client */
71u_int version;
72
73/* Disable writes */
74int readonly;
75
76/* portable attributes, etc. */
77
78typedef struct Stat Stat;
79
80struct Stat {
81	char *name;
82	char *long_name;
83	Attrib attrib;
84};
85
86static int
87errno_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
120static int
121flags_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
142static const char *
143string_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
169static Attrib *
170get_attrib(void)
171{
172	return decode_attrib(&iqueue);
173}
174
175/* handle handles */
176
177typedef struct Handle Handle;
178struct 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
187enum {
188	HANDLE_UNUSED,
189	HANDLE_DIR,
190	HANDLE_FILE
191};
192
193Handle *handles = NULL;
194u_int num_handles = 0;
195int first_unused_handle = -1;
196
197static 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
204static int
205handle_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
229static int
230handle_is_ok(int i, int type)
231{
232	return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
233}
234
235static int
236handle_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
246static int
247handle_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
260static char *
261handle_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
269static DIR *
270handle_to_dir(int handle)
271{
272	if (handle_is_ok(handle, HANDLE_DIR))
273		return handles[handle].dirp;
274	return NULL;
275}
276
277static int
278handle_to_fd(int handle)
279{
280	if (handle_is_ok(handle, HANDLE_FILE))
281		return handles[handle].fd;
282	return -1;
283}
284
285static void
286handle_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
292static void
293handle_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
299static u_int64_t
300handle_bytes_read(int handle)
301{
302	if (handle_is_ok(handle, HANDLE_FILE))
303		return (handles[handle].bytes_read);
304	return 0;
305}
306
307static u_int64_t
308handle_bytes_write(int handle)
309{
310	if (handle_is_ok(handle, HANDLE_FILE))
311		return (handles[handle].bytes_write);
312	return 0;
313}
314
315static int
316handle_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
334static void
335handle_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
350static void
351handle_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
360static int
361get_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
376static void
377send_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
386static const char *
387status_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
404static void
405send_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}
424static void
425send_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
437static void
438send_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
444static void
445send_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
456static void
457send_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
476static void
477send_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
490static void
491send_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
519static void
520process_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@openssh.com");
531	buffer_put_cstring(&msg, "1"); /* version */
532	/* statvfs extension */
533	buffer_put_cstring(&msg, "statvfs@openssh.com");
534	buffer_put_cstring(&msg, "2"); /* version */
535	/* fstatvfs extension */
536	buffer_put_cstring(&msg, "fstatvfs@openssh.com");
537	buffer_put_cstring(&msg, "2"); /* version */
538	/* hardlink extension */
539	buffer_put_cstring(&msg, "hardlink@openssh.com");
540	buffer_put_cstring(&msg, "1"); /* version */
541	send_msg(&msg);
542	buffer_free(&msg);
543}
544
545static void
546process_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
584static void
585process_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
599static void
600process_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
640static void
641process_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
685static void
686process_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
711static void
712process_stat(void)
713{
714	process_do_stat(0);
715}
716
717static void
718process_lstat(void)
719{
720	process_do_stat(1);
721}
722
723static void
724process_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
750static struct timeval *
751attrib_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
762static void
763process_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
813static void
814process_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
880static void
881process_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
910static void
911process_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
966static void
967process_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
988static void
989process_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
1013static void
1014process_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
1034static void
1035process_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
1060static void
1061process_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
1122static void
1123process_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
1147static void
1148process_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
1171static void
1172process_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
1192static void
1193process_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
1209static void
1210process_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
1228static void
1229process_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
1249static void
1250process_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@openssh.com") == 0)
1258		process_extended_posix_rename(id);
1259	else if (strcmp(request, "statvfs@openssh.com") == 0)
1260		process_extended_statvfs(id);
1261	else if (strcmp(request, "fstatvfs@openssh.com") == 0)
1262		process_extended_fstatvfs(id);
1263	else if (strcmp(request, "hardlink@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
1272static void
1273process(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 */
1376void
1377sftp_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
1387static void
1388sftp_server_usage(void)
1389{
1390	extern char *__progname;
1391
1392	fprintf(stderr,
1393	    "usage: %s [-ehR] [-d start_directory] [-f log_facility] "
1394	    "[-l log_level]\n\t[-u umask]\n",
1395	    __progname);
1396	exit(1);
1397}
1398
1399int
1400sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1401{
1402	fd_set *rset, *wset;
1403	int in, out, max, ch, skipargs = 0, log_stderr = 0;
1404	ssize_t len, olen, set_size;
1405	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
1406	char *cp, *homedir = NULL, buf[4*4096];
1407	long mask;
1408
1409	extern char *optarg;
1410	extern char *__progname;
1411
1412	__progname = ssh_get_progname(argv[0]);
1413	log_init(__progname, log_level, log_facility, log_stderr);
1414
1415	pw = pwcopy(user_pw);
1416
1417	while (!skipargs && (ch = getopt(argc, argv, "d:f:l:u:cehR")) != -1) {
1418		switch (ch) {
1419		case 'R':
1420			readonly = 1;
1421			break;
1422		case 'c':
1423			/*
1424			 * Ignore all arguments if we are invoked as a
1425			 * shell using "sftp-server -c command"
1426			 */
1427			skipargs = 1;
1428			break;
1429		case 'e':
1430			log_stderr = 1;
1431			break;
1432		case 'l':
1433			log_level = log_level_number(optarg);
1434			if (log_level == SYSLOG_LEVEL_NOT_SET)
1435				error("Invalid log level \"%s\"", optarg);
1436			break;
1437		case 'f':
1438			log_facility = log_facility_number(optarg);
1439			if (log_facility == SYSLOG_FACILITY_NOT_SET)
1440				error("Invalid log facility \"%s\"", optarg);
1441			break;
1442		case 'd':
1443			cp = tilde_expand_filename(optarg, user_pw->pw_uid);
1444			homedir = percent_expand(cp, "d", user_pw->pw_dir,
1445			    "u", user_pw->pw_name, (char *)NULL);
1446			free(cp);
1447			break;
1448		case 'u':
1449			errno = 0;
1450			mask = strtol(optarg, &cp, 8);
1451			if (mask < 0 || mask > 0777 || *cp != '\0' ||
1452			    cp == optarg || (mask == 0 && errno != 0))
1453				fatal("Invalid umask \"%s\"", optarg);
1454			(void)umask((mode_t)mask);
1455			break;
1456		case 'h':
1457		default:
1458			sftp_server_usage();
1459		}
1460	}
1461
1462	log_init(__progname, log_level, log_facility, log_stderr);
1463
1464	if ((cp = getenv("SSH_CONNECTION")) != NULL) {
1465		client_addr = xstrdup(cp);
1466		if ((cp = strchr(client_addr, ' ')) == NULL) {
1467			error("Malformed SSH_CONNECTION variable: \"%s\"",
1468			    getenv("SSH_CONNECTION"));
1469			sftp_server_cleanup_exit(255);
1470		}
1471		*cp = '\0';
1472	} else
1473		client_addr = xstrdup("UNKNOWN");
1474
1475	logit("session opened for local user %s from [%s]",
1476	    pw->pw_name, client_addr);
1477
1478	in = STDIN_FILENO;
1479	out = STDOUT_FILENO;
1480
1481#ifdef HAVE_CYGWIN
1482	setmode(in, O_BINARY);
1483	setmode(out, O_BINARY);
1484#endif
1485
1486	max = 0;
1487	if (in > max)
1488		max = in;
1489	if (out > max)
1490		max = out;
1491
1492	buffer_init(&iqueue);
1493	buffer_init(&oqueue);
1494
1495	set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
1496	rset = (fd_set *)xmalloc(set_size);
1497	wset = (fd_set *)xmalloc(set_size);
1498
1499	if (homedir != NULL) {
1500		if (chdir(homedir) != 0) {
1501			error("chdir to \"%s\" failed: %s", homedir,
1502			    strerror(errno));
1503		}
1504	}
1505
1506	for (;;) {
1507		memset(rset, 0, set_size);
1508		memset(wset, 0, set_size);
1509
1510		/*
1511		 * Ensure that we can read a full buffer and handle
1512		 * the worst-case length packet it can generate,
1513		 * otherwise apply backpressure by stopping reads.
1514		 */
1515		if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
1516		    buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
1517			FD_SET(in, rset);
1518
1519		olen = buffer_len(&oqueue);
1520		if (olen > 0)
1521			FD_SET(out, wset);
1522
1523		if (select(max+1, rset, wset, NULL, NULL) < 0) {
1524			if (errno == EINTR)
1525				continue;
1526			error("select: %s", strerror(errno));
1527			sftp_server_cleanup_exit(2);
1528		}
1529
1530		/* copy stdin to iqueue */
1531		if (FD_ISSET(in, rset)) {
1532			len = read(in, buf, sizeof buf);
1533			if (len == 0) {
1534				debug("read eof");
1535				sftp_server_cleanup_exit(0);
1536			} else if (len < 0) {
1537				error("read: %s", strerror(errno));
1538				sftp_server_cleanup_exit(1);
1539			} else {
1540				buffer_append(&iqueue, buf, len);
1541			}
1542		}
1543		/* send oqueue to stdout */
1544		if (FD_ISSET(out, wset)) {
1545			len = write(out, buffer_ptr(&oqueue), olen);
1546			if (len < 0) {
1547				error("write: %s", strerror(errno));
1548				sftp_server_cleanup_exit(1);
1549			} else {
1550				buffer_consume(&oqueue, len);
1551			}
1552		}
1553
1554		/*
1555		 * Process requests from client if we can fit the results
1556		 * into the output buffer, otherwise stop processing input
1557		 * and let the output queue drain.
1558		 */
1559		if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
1560			process();
1561	}
1562}
1563