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