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