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