1 /* $OpenBSD: sftp-server.c,v 1.80 2008/05/18 21:29:05 djm Exp $ */
3 * Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
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.
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.
20 #include <sys/types.h>
21 #include <sys/param.h>
23 #ifdef HAVE_SYS_TIME_H
24 # include <sys/time.h>
26 #include <sys/mount.h>
27 #include <sys/statvfs.h>
48 #include "sftp-common.h"
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);
56 LogLevel log_level = SYSLOG_LEVEL_ERROR;
59 struct passwd *pw = NULL;
60 char *client_addr = NULL;
62 /* input and output queue */
66 /* Version of client */
69 /* portable attributes, etc. */
71 typedef struct Stat Stat;
80 errno_to_portable(int unixerrno)
92 ret = SSH2_FX_NO_SUCH_FILE;
97 ret = SSH2_FX_PERMISSION_DENIED;
101 ret = SSH2_FX_BAD_MESSAGE;
104 ret = SSH2_FX_FAILURE;
111 flags_from_portable(int pflags)
115 if ((pflags & SSH2_FXF_READ) &&
116 (pflags & SSH2_FXF_WRITE)) {
118 } else if (pflags & SSH2_FXF_READ) {
120 } else if (pflags & SSH2_FXF_WRITE) {
123 if (pflags & SSH2_FXF_CREAT)
125 if (pflags & SSH2_FXF_TRUNC)
127 if (pflags & SSH2_FXF_EXCL)
133 string_from_portable(int pflags)
135 static char ret[128];
139 #define PAPPEND(str) { \
141 strlcat(ret, ",", sizeof(ret)); \
142 strlcat(ret, str, sizeof(ret)); \
145 if (pflags & SSH2_FXF_READ)
147 if (pflags & SSH2_FXF_WRITE)
149 if (pflags & SSH2_FXF_CREAT)
151 if (pflags & SSH2_FXF_TRUNC)
153 if (pflags & SSH2_FXF_EXCL)
162 return decode_attrib(&iqueue);
167 typedef struct Handle Handle;
173 u_int64_t bytes_read, bytes_write;
183 Handle *handles = NULL;
184 u_int num_handles = 0;
185 int first_unused_handle = -1;
187 static void handle_unused(int i)
189 handles[i].use = HANDLE_UNUSED;
190 handles[i].next_unused = first_unused_handle;
191 first_unused_handle = i;
195 handle_new(int use, const char *name, int fd, DIR *dirp)
199 if (first_unused_handle == -1) {
200 if (num_handles + 1 <= num_handles)
203 handles = xrealloc(handles, num_handles, sizeof(Handle));
204 handle_unused(num_handles - 1);
207 i = first_unused_handle;
208 first_unused_handle = handles[i].next_unused;
210 handles[i].use = use;
211 handles[i].dirp = dirp;
213 handles[i].name = xstrdup(name);
214 handles[i].bytes_read = handles[i].bytes_write = 0;
220 handle_is_ok(int i, int type)
222 return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
226 handle_to_string(int handle, char **stringp, int *hlenp)
228 if (stringp == NULL || hlenp == NULL)
230 *stringp = xmalloc(sizeof(int32_t));
231 put_u32(*stringp, handle);
232 *hlenp = sizeof(int32_t);
237 handle_from_string(const char *handle, u_int hlen)
241 if (hlen != sizeof(int32_t))
243 val = get_u32(handle);
244 if (handle_is_ok(val, HANDLE_FILE) ||
245 handle_is_ok(val, HANDLE_DIR))
251 handle_to_name(int handle)
253 if (handle_is_ok(handle, HANDLE_DIR)||
254 handle_is_ok(handle, HANDLE_FILE))
255 return handles[handle].name;
260 handle_to_dir(int handle)
262 if (handle_is_ok(handle, HANDLE_DIR))
263 return handles[handle].dirp;
268 handle_to_fd(int handle)
270 if (handle_is_ok(handle, HANDLE_FILE))
271 return handles[handle].fd;
276 handle_update_read(int handle, ssize_t bytes)
278 if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
279 handles[handle].bytes_read += bytes;
283 handle_update_write(int handle, ssize_t bytes)
285 if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
286 handles[handle].bytes_write += bytes;
290 handle_bytes_read(int handle)
292 if (handle_is_ok(handle, HANDLE_FILE))
293 return (handles[handle].bytes_read);
298 handle_bytes_write(int handle)
300 if (handle_is_ok(handle, HANDLE_FILE))
301 return (handles[handle].bytes_write);
306 handle_close(int handle)
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);
325 handle_log_close(int handle, char *emsg)
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));
334 logit("%s%sclosedir \"%s\"",
335 emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
336 handle_to_name(handle));
341 handle_log_exit(void)
345 for (i = 0; i < num_handles; i++)
346 if (handles[i].use != HANDLE_UNUSED)
347 handle_log_close(i, "forced");
357 handle = get_string(&hlen);
359 val = handle_from_string(handle, hlen);
369 int mlen = buffer_len(m);
371 buffer_put_int(&oqueue, mlen);
372 buffer_append(&oqueue, buffer_ptr(m), mlen);
373 buffer_consume(m, mlen);
377 status_to_message(u_int32_t status)
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 */
391 return (status_messages[MIN(status,SSH2_FX_MAX)]);
395 send_status(u_int32_t id, u_int32_t status)
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));
404 buffer_put_char(&msg, SSH2_FXP_STATUS);
405 buffer_put_int(&msg, id);
406 buffer_put_int(&msg, status);
408 buffer_put_cstring(&msg, status_to_message(status));
409 buffer_put_cstring(&msg, "");
415 send_data_or_handle(char type, u_int32_t id, const char *data, int dlen)
420 buffer_put_char(&msg, type);
421 buffer_put_int(&msg, id);
422 buffer_put_string(&msg, data, dlen);
428 send_data(u_int32_t id, const char *data, int dlen)
430 debug("request %u: sent data len %d", id, dlen);
431 send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
435 send_handle(u_int32_t id, int handle)
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);
447 send_names(u_int32_t id, int count, const Stat *stats)
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);
467 send_attrib(u_int32_t id, const Attrib *a)
471 debug("request %u: sent attrib have 0x%x", id, a->flags);
473 buffer_put_char(&msg, SSH2_FXP_ATTRS);
474 buffer_put_int(&msg, id);
475 encode_attrib(&msg, a);
481 send_statvfs(u_int32_t id, struct statvfs *st)
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;
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);
515 verbose("received client version %d", version);
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 */
535 u_int32_t id, pflags;
538 int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
541 name = get_string(NULL);
542 pflags = get_int(); /* portable flags */
543 debug3("request %u: open flags %d", id, pflags);
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);
551 status = errno_to_portable(errno);
553 handle = handle_new(HANDLE_FILE, name, fd, NULL);
557 send_handle(id, handle);
561 if (status != SSH2_FX_OK)
562 send_status(id, status);
570 int handle, ret, status = SSH2_FX_FAILURE;
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);
586 int handle, fd, ret, status = SSH2_FX_FAILURE;
590 handle = get_handle();
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) {
598 debug2("read change len %d", len);
600 fd = handle_to_fd(handle);
602 if (lseek(fd, off, SEEK_SET) < 0) {
603 error("process_read: seek failed");
604 status = errno_to_portable(errno);
606 ret = read(fd, buf, len);
608 status = errno_to_portable(errno);
609 } else if (ret == 0) {
610 status = SSH2_FX_EOF;
612 send_data(id, buf, ret);
614 handle_update_read(handle, ret);
618 if (status != SSH2_FX_OK)
619 send_status(id, status);
628 int handle, fd, ret, status = SSH2_FX_FAILURE;
632 handle = get_handle();
634 data = get_string(&len);
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);
640 if (lseek(fd, off, SEEK_SET) < 0) {
641 status = errno_to_portable(errno);
642 error("process_write: seek failed");
645 ret = write(fd, data, len);
647 error("process_write: write failed");
648 status = errno_to_portable(errno);
649 } else if ((size_t)ret == len) {
651 handle_update_write(handle, ret);
653 debug2("nothing at all written");
657 send_status(id, status);
662 process_do_stat(int do_lstat)
668 int ret, status = SSH2_FX_FAILURE;
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);
676 status = errno_to_portable(errno);
678 stat_to_attrib(&st, &a);
682 if (status != SSH2_FX_OK)
683 send_status(id, status);
705 int fd, ret, handle, status = SSH2_FX_FAILURE;
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);
713 ret = fstat(fd, &st);
715 status = errno_to_portable(errno);
717 stat_to_attrib(&st, &a);
722 if (status != SSH2_FX_OK)
723 send_status(id, status);
726 static struct timeval *
727 attrib_to_tv(const Attrib *a)
729 static struct timeval tv[2];
731 tv[0].tv_sec = a->atime;
733 tv[1].tv_sec = a->mtime;
739 process_setstat(void)
744 int status = SSH2_FX_OK, ret;
747 name = get_string(NULL);
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);
755 status = errno_to_portable(errno);
757 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
758 logit("set \"%s\" mode %04o", name, a->perm);
759 ret = chmod(name, a->perm & 0777);
761 status = errno_to_portable(errno);
763 if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
767 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
769 logit("set \"%s\" modtime %s", name, buf);
770 ret = utimes(name, attrib_to_tv(a));
772 status = errno_to_portable(errno);
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);
779 status = errno_to_portable(errno);
781 send_status(id, status);
786 process_fsetstat(void)
791 int status = SSH2_FX_OK;
794 handle = get_handle();
796 debug("request %u: fsetstat handle %d", id, handle);
797 fd = handle_to_fd(handle);
799 status = SSH2_FX_FAILURE;
801 char *name = handle_to_name(handle);
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);
808 status = errno_to_portable(errno);
810 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
811 logit("set \"%s\" mode %04o", name, a->perm);
813 ret = fchmod(fd, a->perm & 0777);
815 ret = chmod(name, a->perm & 0777);
818 status = errno_to_portable(errno);
820 if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
824 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
826 logit("set \"%s\" modtime %s", name, buf);
828 ret = futimes(fd, attrib_to_tv(a));
830 ret = utimes(name, attrib_to_tv(a));
833 status = errno_to_portable(errno);
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);
839 ret = fchown(fd, a->uid, a->gid);
841 ret = chown(name, a->uid, a->gid);
844 status = errno_to_portable(errno);
847 send_status(id, status);
851 process_opendir(void)
855 int handle, status = SSH2_FX_FAILURE;
859 path = get_string(NULL);
860 debug3("request %u: opendir", id);
861 logit("opendir \"%s\"", path);
862 dirp = opendir(path);
864 status = errno_to_portable(errno);
866 handle = handle_new(HANDLE_DIR, path, 0, dirp);
870 send_handle(id, handle);
875 if (status != SSH2_FX_OK)
876 send_status(id, status);
881 process_readdir(void)
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);
899 char pathname[MAXPATHLEN];
901 int nstats = 10, count = 0, i;
903 stats = xcalloc(nstats, sizeof(Stat));
904 while ((dp = readdir(dirp)) != NULL) {
905 if (count >= nstats) {
907 stats = xrealloc(stats, nstats, sizeof(Stat));
910 snprintf(pathname, sizeof pathname, "%s%s%s", path,
911 strcmp(path, "/") ? "/" : "", dp->d_name);
912 if (lstat(pathname, &st) < 0)
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);
918 /* send up to 100 entries in one message */
919 /* XXX check packet size instead */
924 send_names(id, count, stats);
925 for (i = 0; i < count; i++) {
926 xfree(stats[i].name);
927 xfree(stats[i].long_name);
930 send_status(id, SSH2_FX_EOF);
941 int status = SSH2_FX_FAILURE;
945 name = get_string(NULL);
946 debug3("request %u: remove", id);
947 logit("remove name \"%s\"", name);
949 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
950 send_status(id, status);
960 int ret, mode, status = SSH2_FX_FAILURE;
963 name = get_string(NULL);
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);
983 name = get_string(NULL);
984 debug3("request %u: rmdir", id);
985 logit("rmdir name \"%s\"", name);
987 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
988 send_status(id, status);
993 process_realpath(void)
995 char resolvedname[MAXPATHLEN];
1000 path = get_string(NULL);
1001 if (path[0] == '\0') {
1003 path = xstrdup(".");
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));
1011 attrib_clear(&s.attrib);
1012 s.name = s.long_name = resolvedname;
1013 send_names(id, 1, &s);
1019 process_rename(void)
1022 char *oldpath, *newpath;
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
1045 * fs doesn't support links, so fall back to
1046 * stat+rename. This is racy.
1048 if (stat(newpath, &st) == -1) {
1049 if (rename(oldpath, newpath) == -1)
1051 errno_to_portable(errno);
1053 status = SSH2_FX_OK;
1056 status = errno_to_portable(errno);
1058 } else if (unlink(oldpath) == -1) {
1059 status = errno_to_portable(errno);
1060 /* clean spare link */
1063 status = SSH2_FX_OK;
1064 } else if (stat(newpath, &sb) == -1) {
1065 if (rename(oldpath, newpath) == -1)
1066 status = errno_to_portable(errno);
1068 status = SSH2_FX_OK;
1070 send_status(id, status);
1076 process_readlink(void)
1080 char buf[MAXPATHLEN];
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));
1093 attrib_clear(&s.attrib);
1094 s.name = s.long_name = buf;
1095 send_names(id, 1, &s);
1101 process_symlink(void)
1104 char *oldpath, *newpath;
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);
1121 process_extended_posix_rename(u_int32_t id)
1123 char *oldpath, *newpath;
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));
1132 send_status(id, SSH2_FX_OK);
1138 process_extended_statvfs(u_int32_t id)
1143 path = get_string(NULL);
1144 debug3("request %u: statfs", id);
1145 logit("statfs \"%s\"", path);
1147 if (statvfs(path, &st) != 0)
1148 send_status(id, errno_to_portable(errno));
1150 send_statvfs(id, &st);
1155 process_extended_fstatvfs(u_int32_t id)
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);
1167 if (fstatvfs(fd, &st) != 0)
1168 send_status(id, errno_to_portable(errno));
1170 send_statvfs(id, &st);
1174 process_extended(void)
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);
1188 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
1192 /* stolen from ssh-agent */
1203 buf_len = buffer_len(&iqueue);
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);
1213 if (buf_len < msg_len + 4)
1215 buffer_consume(&iqueue, 4);
1217 type = buffer_get_char(&iqueue);
1225 case SSH2_FXP_CLOSE:
1231 case SSH2_FXP_WRITE:
1234 case SSH2_FXP_LSTAT:
1237 case SSH2_FXP_FSTAT:
1240 case SSH2_FXP_SETSTAT:
1243 case SSH2_FXP_FSETSTAT:
1246 case SSH2_FXP_OPENDIR:
1249 case SSH2_FXP_READDIR:
1252 case SSH2_FXP_REMOVE:
1255 case SSH2_FXP_MKDIR:
1258 case SSH2_FXP_RMDIR:
1261 case SSH2_FXP_REALPATH:
1267 case SSH2_FXP_RENAME:
1270 case SSH2_FXP_READLINK:
1273 case SSH2_FXP_SYMLINK:
1276 case SSH2_FXP_EXTENDED:
1280 error("Unknown message %d", type);
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);
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);
1293 if (msg_len > consumed)
1294 buffer_consume(&iqueue, msg_len - consumed);
1297 /* Cleanup handler that logs active handles upon normal exit */
1299 sftp_server_cleanup_exit(int i)
1301 if (pw != NULL && client_addr != NULL) {
1303 logit("session closed for local user %s from [%s]",
1304 pw->pw_name, client_addr);
1310 sftp_server_usage(void)
1312 extern char *__progname;
1315 "usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname);
1320 sftp_server_main(int argc, char **argv, struct passwd *user_pw)
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];
1328 extern char *optarg;
1329 extern char *__progname;
1331 __progname = ssh_get_progname(argv[0]);
1332 log_init(__progname, log_level, log_facility, log_stderr);
1334 while (!skipargs && (ch = getopt(argc, argv, "C:f:l:che")) != -1) {
1338 * Ignore all arguments if we are invoked as a
1339 * shell using "sftp-server -c command"
1347 log_level = log_level_number(optarg);
1348 if (log_level == SYSLOG_LEVEL_NOT_SET)
1349 error("Invalid log level \"%s\"", optarg);
1352 log_facility = log_facility_number(optarg);
1353 if (log_facility == SYSLOG_FACILITY_NOT_SET)
1354 error("Invalid log facility \"%s\"", optarg);
1358 sftp_server_usage();
1362 log_init(__progname, log_level, log_facility, log_stderr);
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);
1373 client_addr = xstrdup("UNKNOWN");
1375 pw = pwcopy(user_pw);
1377 logit("session opened for local user %s from [%s]",
1378 pw->pw_name, client_addr);
1380 in = dup(STDIN_FILENO);
1381 out = dup(STDOUT_FILENO);
1384 setmode(in, O_BINARY);
1385 setmode(out, O_BINARY);
1394 buffer_init(&iqueue);
1395 buffer_init(&oqueue);
1397 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
1398 rset = (fd_set *)xmalloc(set_size);
1399 wset = (fd_set *)xmalloc(set_size);
1402 memset(rset, 0, set_size);
1403 memset(wset, 0, set_size);
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.
1410 if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
1411 buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
1414 olen = buffer_len(&oqueue);
1418 if (select(max+1, rset, wset, NULL, NULL) < 0) {
1421 error("select: %s", strerror(errno));
1422 sftp_server_cleanup_exit(2);
1425 /* copy stdin to iqueue */
1426 if (FD_ISSET(in, rset)) {
1427 len = read(in, buf, sizeof buf);
1430 sftp_server_cleanup_exit(0);
1431 } else if (len < 0) {
1432 error("read: %s", strerror(errno));
1433 sftp_server_cleanup_exit(1);
1435 buffer_append(&iqueue, buf, len);
1438 /* send oqueue to stdout */
1439 if (FD_ISSET(out, wset)) {
1440 len = write(out, buffer_ptr(&oqueue), olen);
1442 error("write: %s", strerror(errno));
1443 sftp_server_cleanup_exit(1);
1445 buffer_consume(&oqueue, len);
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.
1454 if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))