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