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