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