]> andersk Git - openssh.git/blob - sftp-server.c
4022b93b604076f29874c5b4874a165a02d9450a
[openssh.git] / sftp-server.c
1 /* $OpenBSD: sftp-server.c,v 1.83 2008/06/09 13:02:39 dtucker 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 & 0777);
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 & 0777);
821 #else
822                         ret = chmod(name, a->perm & 0777);
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 & 0777 : 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 LINK_OPNOTSUPP_ERRNO
1046                             || errno == LINK_OPNOTSUPP_ERRNO
1047 #endif
1048                             ) {
1049                                 struct stat st;
1050
1051                                 /*
1052                                  * fs doesn't support links, so fall back to
1053                                  * stat+rename.  This is racy.
1054                                  */
1055                                 if (stat(newpath, &st) == -1) {
1056                                         if (rename(oldpath, newpath) == -1)
1057                                                 status =
1058                                                     errno_to_portable(errno);
1059                                         else
1060                                                 status = SSH2_FX_OK;
1061                                 }
1062                         } else {
1063                                 status = errno_to_portable(errno);
1064                         }
1065                 } else if (unlink(oldpath) == -1) {
1066                         status = errno_to_portable(errno);
1067                         /* clean spare link */
1068                         unlink(newpath);
1069                 } else
1070                         status = SSH2_FX_OK;
1071         } else if (stat(newpath, &sb) == -1) {
1072                 if (rename(oldpath, newpath) == -1)
1073                         status = errno_to_portable(errno);
1074                 else
1075                         status = SSH2_FX_OK;
1076         }
1077         send_status(id, status);
1078         xfree(oldpath);
1079         xfree(newpath);
1080 }
1081
1082 static void
1083 process_readlink(void)
1084 {
1085         u_int32_t id;
1086         int len;
1087         char buf[MAXPATHLEN];
1088         char *path;
1089
1090         id = get_int();
1091         path = get_string(NULL);
1092         debug3("request %u: readlink", id);
1093         verbose("readlink \"%s\"", path);
1094         if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
1095                 send_status(id, errno_to_portable(errno));
1096         else {
1097                 Stat s;
1098
1099                 buf[len] = '\0';
1100                 attrib_clear(&s.attrib);
1101                 s.name = s.long_name = buf;
1102                 send_names(id, 1, &s);
1103         }
1104         xfree(path);
1105 }
1106
1107 static void
1108 process_symlink(void)
1109 {
1110         u_int32_t id;
1111         char *oldpath, *newpath;
1112         int ret, status;
1113
1114         id = get_int();
1115         oldpath = get_string(NULL);
1116         newpath = get_string(NULL);
1117         debug3("request %u: symlink", id);
1118         logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
1119         /* this will fail if 'newpath' exists */
1120         ret = symlink(oldpath, newpath);
1121         status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1122         send_status(id, status);
1123         xfree(oldpath);
1124         xfree(newpath);
1125 }
1126
1127 static void
1128 process_extended_posix_rename(u_int32_t id)
1129 {
1130         char *oldpath, *newpath;
1131
1132         oldpath = get_string(NULL);
1133         newpath = get_string(NULL);
1134         debug3("request %u: posix-rename", id);
1135         logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1136         if (rename(oldpath, newpath) == -1)
1137                 send_status(id, errno_to_portable(errno));
1138         else
1139                 send_status(id, SSH2_FX_OK);
1140         xfree(oldpath);
1141         xfree(newpath);
1142 }
1143
1144 static void
1145 process_extended_statvfs(u_int32_t id)
1146 {
1147         char *path;
1148         struct statvfs st;
1149
1150         path = get_string(NULL);
1151         debug3("request %u: statfs", id);
1152         logit("statfs \"%s\"", path);
1153
1154         if (statvfs(path, &st) != 0)
1155                 send_status(id, errno_to_portable(errno));
1156         else
1157                 send_statvfs(id, &st);
1158         xfree(path);
1159 }
1160
1161 static void
1162 process_extended_fstatvfs(u_int32_t id)
1163 {
1164         int handle, fd;
1165         struct statvfs st;
1166
1167         handle = get_handle();
1168         debug("request %u: fstatvfs \"%s\" (handle %u)",
1169             id, handle_to_name(handle), handle);
1170         if ((fd = handle_to_fd(handle)) < 0) {
1171                 send_status(id, SSH2_FX_FAILURE);
1172                 return;
1173         }
1174         if (fstatvfs(fd, &st) != 0)
1175                 send_status(id, errno_to_portable(errno));
1176         else
1177                 send_statvfs(id, &st);
1178 }
1179
1180 static void
1181 process_extended(void)
1182 {
1183         u_int32_t id;
1184         char *request;
1185
1186         id = get_int();
1187         request = get_string(NULL);
1188         if (strcmp(request, "posix-rename@openssh.com") == 0)
1189                 process_extended_posix_rename(id);
1190         else if (strcmp(request, "statvfs@openssh.com") == 0)
1191                 process_extended_statvfs(id);
1192         else if (strcmp(request, "fstatvfs@openssh.com") == 0)
1193                 process_extended_fstatvfs(id);
1194         else
1195                 send_status(id, SSH2_FX_OP_UNSUPPORTED);        /* MUST */
1196         xfree(request);
1197 }
1198
1199 /* stolen from ssh-agent */
1200
1201 static void
1202 process(void)
1203 {
1204         u_int msg_len;
1205         u_int buf_len;
1206         u_int consumed;
1207         u_int type;
1208         u_char *cp;
1209
1210         buf_len = buffer_len(&iqueue);
1211         if (buf_len < 5)
1212                 return;         /* Incomplete message. */
1213         cp = buffer_ptr(&iqueue);
1214         msg_len = get_u32(cp);
1215         if (msg_len > SFTP_MAX_MSG_LENGTH) {
1216                 error("bad message from %s local user %s",
1217                     client_addr, pw->pw_name);
1218                 sftp_server_cleanup_exit(11);
1219         }
1220         if (buf_len < msg_len + 4)
1221                 return;
1222         buffer_consume(&iqueue, 4);
1223         buf_len -= 4;
1224         type = buffer_get_char(&iqueue);
1225         switch (type) {
1226         case SSH2_FXP_INIT:
1227                 process_init();
1228                 break;
1229         case SSH2_FXP_OPEN:
1230                 process_open();
1231                 break;
1232         case SSH2_FXP_CLOSE:
1233                 process_close();
1234                 break;
1235         case SSH2_FXP_READ:
1236                 process_read();
1237                 break;
1238         case SSH2_FXP_WRITE:
1239                 process_write();
1240                 break;
1241         case SSH2_FXP_LSTAT:
1242                 process_lstat();
1243                 break;
1244         case SSH2_FXP_FSTAT:
1245                 process_fstat();
1246                 break;
1247         case SSH2_FXP_SETSTAT:
1248                 process_setstat();
1249                 break;
1250         case SSH2_FXP_FSETSTAT:
1251                 process_fsetstat();
1252                 break;
1253         case SSH2_FXP_OPENDIR:
1254                 process_opendir();
1255                 break;
1256         case SSH2_FXP_READDIR:
1257                 process_readdir();
1258                 break;
1259         case SSH2_FXP_REMOVE:
1260                 process_remove();
1261                 break;
1262         case SSH2_FXP_MKDIR:
1263                 process_mkdir();
1264                 break;
1265         case SSH2_FXP_RMDIR:
1266                 process_rmdir();
1267                 break;
1268         case SSH2_FXP_REALPATH:
1269                 process_realpath();
1270                 break;
1271         case SSH2_FXP_STAT:
1272                 process_stat();
1273                 break;
1274         case SSH2_FXP_RENAME:
1275                 process_rename();
1276                 break;
1277         case SSH2_FXP_READLINK:
1278                 process_readlink();
1279                 break;
1280         case SSH2_FXP_SYMLINK:
1281                 process_symlink();
1282                 break;
1283         case SSH2_FXP_EXTENDED:
1284                 process_extended();
1285                 break;
1286         default:
1287                 error("Unknown message %d", type);
1288                 break;
1289         }
1290         /* discard the remaining bytes from the current packet */
1291         if (buf_len < buffer_len(&iqueue)) {
1292                 error("iqueue grew unexpectedly");
1293                 sftp_server_cleanup_exit(255);
1294         }
1295         consumed = buf_len - buffer_len(&iqueue);
1296         if (msg_len < consumed) {
1297                 error("msg_len %d < consumed %d", msg_len, consumed);
1298                 sftp_server_cleanup_exit(255);
1299         }
1300         if (msg_len > consumed)
1301                 buffer_consume(&iqueue, msg_len - consumed);
1302 }
1303
1304 /* Cleanup handler that logs active handles upon normal exit */
1305 void
1306 sftp_server_cleanup_exit(int i)
1307 {
1308         if (pw != NULL && client_addr != NULL) {
1309                 handle_log_exit();
1310                 logit("session closed for local user %s from [%s]",
1311                     pw->pw_name, client_addr);
1312         }
1313         _exit(i);
1314 }
1315
1316 static void
1317 sftp_server_usage(void)
1318 {
1319         extern char *__progname;
1320
1321         fprintf(stderr,
1322             "usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname);
1323         exit(1);
1324 }
1325
1326 int
1327 sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1328 {
1329         fd_set *rset, *wset;
1330         int in, out, max, ch, skipargs = 0, log_stderr = 0;
1331         ssize_t len, olen, set_size;
1332         SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
1333         char *cp, buf[4*4096];
1334
1335         extern char *optarg;
1336         extern char *__progname;
1337
1338         __progname = ssh_get_progname(argv[0]);
1339         log_init(__progname, log_level, log_facility, log_stderr);
1340
1341         while (!skipargs && (ch = getopt(argc, argv, "C:f:l:che")) != -1) {
1342                 switch (ch) {
1343                 case 'c':
1344                         /*
1345                          * Ignore all arguments if we are invoked as a
1346                          * shell using "sftp-server -c command"
1347                          */
1348                         skipargs = 1;
1349                         break;
1350                 case 'e':
1351                         log_stderr = 1;
1352                         break;
1353                 case 'l':
1354                         log_level = log_level_number(optarg);
1355                         if (log_level == SYSLOG_LEVEL_NOT_SET)
1356                                 error("Invalid log level \"%s\"", optarg);
1357                         break;
1358                 case 'f':
1359                         log_facility = log_facility_number(optarg);
1360                         if (log_facility == SYSLOG_FACILITY_NOT_SET)
1361                                 error("Invalid log facility \"%s\"", optarg);
1362                         break;
1363                 case 'h':
1364                 default:
1365                         sftp_server_usage();
1366                 }
1367         }
1368
1369         log_init(__progname, log_level, log_facility, log_stderr);
1370
1371         if ((cp = getenv("SSH_CONNECTION")) != NULL) {
1372                 client_addr = xstrdup(cp);
1373                 if ((cp = strchr(client_addr, ' ')) == NULL) {
1374                         error("Malformed SSH_CONNECTION variable: \"%s\"",
1375                             getenv("SSH_CONNECTION"));
1376                         sftp_server_cleanup_exit(255);
1377                 }
1378                 *cp = '\0';
1379         } else
1380                 client_addr = xstrdup("UNKNOWN");
1381
1382         pw = pwcopy(user_pw);
1383
1384         logit("session opened for local user %s from [%s]",
1385             pw->pw_name, client_addr);
1386
1387         in = dup(STDIN_FILENO);
1388         out = dup(STDOUT_FILENO);
1389
1390 #ifdef HAVE_CYGWIN
1391         setmode(in, O_BINARY);
1392         setmode(out, O_BINARY);
1393 #endif
1394
1395         max = 0;
1396         if (in > max)
1397                 max = in;
1398         if (out > max)
1399                 max = out;
1400
1401         buffer_init(&iqueue);
1402         buffer_init(&oqueue);
1403
1404         set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
1405         rset = (fd_set *)xmalloc(set_size);
1406         wset = (fd_set *)xmalloc(set_size);
1407
1408         for (;;) {
1409                 memset(rset, 0, set_size);
1410                 memset(wset, 0, set_size);
1411
1412                 /*
1413                  * Ensure that we can read a full buffer and handle
1414                  * the worst-case length packet it can generate,
1415                  * otherwise apply backpressure by stopping reads.
1416                  */
1417                 if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
1418                     buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
1419                         FD_SET(in, rset);
1420
1421                 olen = buffer_len(&oqueue);
1422                 if (olen > 0)
1423                         FD_SET(out, wset);
1424
1425                 if (select(max+1, rset, wset, NULL, NULL) < 0) {
1426                         if (errno == EINTR)
1427                                 continue;
1428                         error("select: %s", strerror(errno));
1429                         sftp_server_cleanup_exit(2);
1430                 }
1431
1432                 /* copy stdin to iqueue */
1433                 if (FD_ISSET(in, rset)) {
1434                         len = read(in, buf, sizeof buf);
1435                         if (len == 0) {
1436                                 debug("read eof");
1437                                 sftp_server_cleanup_exit(0);
1438                         } else if (len < 0) {
1439                                 error("read: %s", strerror(errno));
1440                                 sftp_server_cleanup_exit(1);
1441                         } else {
1442                                 buffer_append(&iqueue, buf, len);
1443                         }
1444                 }
1445                 /* send oqueue to stdout */
1446                 if (FD_ISSET(out, wset)) {
1447                         len = write(out, buffer_ptr(&oqueue), olen);
1448                         if (len < 0) {
1449                                 error("write: %s", strerror(errno));
1450                                 sftp_server_cleanup_exit(1);
1451                         } else {
1452                                 buffer_consume(&oqueue, len);
1453                         }
1454                 }
1455
1456                 /*
1457                  * Process requests from client if we can fit the results
1458                  * into the output buffer, otherwise stop processing input
1459                  * and let the output queue drain.
1460                  */
1461                 if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
1462                         process();
1463         }
1464 }
This page took 0.144716 seconds and 3 git commands to generate.