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