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