1 /* $OpenBSD: sftp-server.c,v 1.93 2010/12/04 00:18:01 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 #ifdef HAVE_SYS_MOUNT_H
27 #include <sys/mount.h>
29 #ifdef HAVE_SYS_STATVFS_H
30 #include <sys/statvfs.h>
52 #include "sftp-common.h"
55 #define get_int64() buffer_get_int64(&iqueue);
56 #define get_int() buffer_get_int(&iqueue);
57 #define get_string(lenp) buffer_get_string(&iqueue, lenp);
60 LogLevel log_level
= SYSLOG_LEVEL_ERROR
;
63 struct passwd
*pw
= NULL
;
64 char *client_addr
= NULL
;
66 /* input and output queue */
70 /* Version of client */
76 /* portable attributes, etc. */
78 typedef struct Stat Stat
;
87 errno_to_portable(int unixerrno
)
99 ret
= SSH2_FX_NO_SUCH_FILE
;
104 ret
= SSH2_FX_PERMISSION_DENIED
;
108 ret
= SSH2_FX_BAD_MESSAGE
;
111 ret
= SSH2_FX_OP_UNSUPPORTED
;
114 ret
= SSH2_FX_FAILURE
;
121 flags_from_portable(int pflags
)
125 if ((pflags
& SSH2_FXF_READ
) &&
126 (pflags
& SSH2_FXF_WRITE
)) {
128 } else if (pflags
& SSH2_FXF_READ
) {
130 } else if (pflags
& SSH2_FXF_WRITE
) {
133 if (pflags
& SSH2_FXF_CREAT
)
135 if (pflags
& SSH2_FXF_TRUNC
)
137 if (pflags
& SSH2_FXF_EXCL
)
143 string_from_portable(int pflags
)
145 static char ret
[128];
149 #define PAPPEND(str) { \
151 strlcat(ret, ",", sizeof(ret)); \
152 strlcat(ret, str, sizeof(ret)); \
155 if (pflags
& SSH2_FXF_READ
)
157 if (pflags
& SSH2_FXF_WRITE
)
159 if (pflags
& SSH2_FXF_CREAT
)
161 if (pflags
& SSH2_FXF_TRUNC
)
163 if (pflags
& SSH2_FXF_EXCL
)
172 return decode_attrib(&iqueue
);
177 typedef struct Handle Handle
;
183 u_int64_t bytes_read
, bytes_write
;
193 Handle
*handles
= NULL
;
194 u_int num_handles
= 0;
195 int first_unused_handle
= -1;
197 static void handle_unused(int i
)
199 handles
[i
].use
= HANDLE_UNUSED
;
200 handles
[i
].next_unused
= first_unused_handle
;
201 first_unused_handle
= i
;
205 handle_new(int use
, const char *name
, int fd
, DIR *dirp
)
209 if (first_unused_handle
== -1) {
210 if (num_handles
+ 1 <= num_handles
)
213 handles
= xrealloc(handles
, num_handles
, sizeof(Handle
));
214 handle_unused(num_handles
- 1);
217 i
= first_unused_handle
;
218 first_unused_handle
= handles
[i
].next_unused
;
220 handles
[i
].use
= use
;
221 handles
[i
].dirp
= dirp
;
223 handles
[i
].name
= xstrdup(name
);
224 handles
[i
].bytes_read
= handles
[i
].bytes_write
= 0;
230 handle_is_ok(int i
, int type
)
232 return i
>= 0 && (u_int
)i
< num_handles
&& handles
[i
].use
== type
;
236 handle_to_string(int handle
, char **stringp
, int *hlenp
)
238 if (stringp
== NULL
|| hlenp
== NULL
)
240 *stringp
= xmalloc(sizeof(int32_t));
241 put_u32(*stringp
, handle
);
242 *hlenp
= sizeof(int32_t);
247 handle_from_string(const char *handle
, u_int hlen
)
251 if (hlen
!= sizeof(int32_t))
253 val
= get_u32(handle
);
254 if (handle_is_ok(val
, HANDLE_FILE
) ||
255 handle_is_ok(val
, HANDLE_DIR
))
261 handle_to_name(int handle
)
263 if (handle_is_ok(handle
, HANDLE_DIR
)||
264 handle_is_ok(handle
, HANDLE_FILE
))
265 return handles
[handle
].name
;
270 handle_to_dir(int handle
)
272 if (handle_is_ok(handle
, HANDLE_DIR
))
273 return handles
[handle
].dirp
;
278 handle_to_fd(int handle
)
280 if (handle_is_ok(handle
, HANDLE_FILE
))
281 return handles
[handle
].fd
;
286 handle_update_read(int handle
, ssize_t bytes
)
288 if (handle_is_ok(handle
, HANDLE_FILE
) && bytes
> 0)
289 handles
[handle
].bytes_read
+= bytes
;
293 handle_update_write(int handle
, ssize_t bytes
)
295 if (handle_is_ok(handle
, HANDLE_FILE
) && bytes
> 0)
296 handles
[handle
].bytes_write
+= bytes
;
300 handle_bytes_read(int handle
)
302 if (handle_is_ok(handle
, HANDLE_FILE
))
303 return (handles
[handle
].bytes_read
);
308 handle_bytes_write(int handle
)
310 if (handle_is_ok(handle
, HANDLE_FILE
))
311 return (handles
[handle
].bytes_write
);
316 handle_close(int handle
)
320 if (handle_is_ok(handle
, HANDLE_FILE
)) {
321 ret
= close(handles
[handle
].fd
);
322 xfree(handles
[handle
].name
);
323 handle_unused(handle
);
324 } else if (handle_is_ok(handle
, HANDLE_DIR
)) {
325 ret
= closedir(handles
[handle
].dirp
);
326 xfree(handles
[handle
].name
);
327 handle_unused(handle
);
335 handle_log_close(int handle
, char *emsg
)
337 if (handle_is_ok(handle
, HANDLE_FILE
)) {
338 logit("%s%sclose \"%s\" bytes read %llu written %llu",
339 emsg
== NULL
? "" : emsg
, emsg
== NULL
? "" : " ",
340 handle_to_name(handle
),
341 (unsigned long long)handle_bytes_read(handle
),
342 (unsigned long long)handle_bytes_write(handle
));
344 logit("%s%sclosedir \"%s\"",
345 emsg
== NULL
? "" : emsg
, emsg
== NULL
? "" : " ",
346 handle_to_name(handle
));
351 handle_log_exit(void)
355 for (i
= 0; i
< num_handles
; i
++)
356 if (handles
[i
].use
!= HANDLE_UNUSED
)
357 handle_log_close(i
, "forced");
367 handle
= get_string(&hlen
);
369 val
= handle_from_string(handle
, hlen
);
379 int mlen
= buffer_len(m
);
381 buffer_put_int(&oqueue
, mlen
);
382 buffer_append(&oqueue
, buffer_ptr(m
), mlen
);
383 buffer_consume(m
, mlen
);
387 status_to_message(u_int32_t status
)
389 const char *status_messages
[] = {
390 "Success", /* SSH_FX_OK */
391 "End of file", /* SSH_FX_EOF */
392 "No such file", /* SSH_FX_NO_SUCH_FILE */
393 "Permission denied", /* SSH_FX_PERMISSION_DENIED */
394 "Failure", /* SSH_FX_FAILURE */
395 "Bad message", /* SSH_FX_BAD_MESSAGE */
396 "No connection", /* SSH_FX_NO_CONNECTION */
397 "Connection lost", /* SSH_FX_CONNECTION_LOST */
398 "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
399 "Unknown error" /* Others */
401 return (status_messages
[MIN(status
,SSH2_FX_MAX
)]);
405 send_status(u_int32_t id
, u_int32_t status
)
409 debug3("request %u: sent status %u", id
, status
);
410 if (log_level
> SYSLOG_LEVEL_VERBOSE
||
411 (status
!= SSH2_FX_OK
&& status
!= SSH2_FX_EOF
))
412 logit("sent status %s", status_to_message(status
));
414 buffer_put_char(&msg
, SSH2_FXP_STATUS
);
415 buffer_put_int(&msg
, id
);
416 buffer_put_int(&msg
, status
);
418 buffer_put_cstring(&msg
, status_to_message(status
));
419 buffer_put_cstring(&msg
, "");
425 send_data_or_handle(char type
, u_int32_t id
, const char *data
, int dlen
)
430 buffer_put_char(&msg
, type
);
431 buffer_put_int(&msg
, id
);
432 buffer_put_string(&msg
, data
, dlen
);
438 send_data(u_int32_t id
, const char *data
, int dlen
)
440 debug("request %u: sent data len %d", id
, dlen
);
441 send_data_or_handle(SSH2_FXP_DATA
, id
, data
, dlen
);
445 send_handle(u_int32_t id
, int handle
)
450 handle_to_string(handle
, &string
, &hlen
);
451 debug("request %u: sent handle handle %d", id
, handle
);
452 send_data_or_handle(SSH2_FXP_HANDLE
, id
, string
, hlen
);
457 send_names(u_int32_t id
, int count
, const Stat
*stats
)
463 buffer_put_char(&msg
, SSH2_FXP_NAME
);
464 buffer_put_int(&msg
, id
);
465 buffer_put_int(&msg
, count
);
466 debug("request %u: sent names count %d", id
, count
);
467 for (i
= 0; i
< count
; i
++) {
468 buffer_put_cstring(&msg
, stats
[i
].name
);
469 buffer_put_cstring(&msg
, stats
[i
].long_name
);
470 encode_attrib(&msg
, &stats
[i
].attrib
);
477 send_attrib(u_int32_t id
, const Attrib
*a
)
481 debug("request %u: sent attrib have 0x%x", id
, a
->flags
);
483 buffer_put_char(&msg
, SSH2_FXP_ATTRS
);
484 buffer_put_int(&msg
, id
);
485 encode_attrib(&msg
, a
);
491 send_statvfs(u_int32_t id
, struct statvfs
*st
)
496 flag
= (st
->f_flag
& ST_RDONLY
) ? SSH2_FXE_STATVFS_ST_RDONLY
: 0;
497 flag
|= (st
->f_flag
& ST_NOSUID
) ? SSH2_FXE_STATVFS_ST_NOSUID
: 0;
500 buffer_put_char(&msg
, SSH2_FXP_EXTENDED_REPLY
);
501 buffer_put_int(&msg
, id
);
502 buffer_put_int64(&msg
, st
->f_bsize
);
503 buffer_put_int64(&msg
, st
->f_frsize
);
504 buffer_put_int64(&msg
, st
->f_blocks
);
505 buffer_put_int64(&msg
, st
->f_bfree
);
506 buffer_put_int64(&msg
, st
->f_bavail
);
507 buffer_put_int64(&msg
, st
->f_files
);
508 buffer_put_int64(&msg
, st
->f_ffree
);
509 buffer_put_int64(&msg
, st
->f_favail
);
510 buffer_put_int64(&msg
, FSID_TO_ULONG(st
->f_fsid
));
511 buffer_put_int64(&msg
, flag
);
512 buffer_put_int64(&msg
, st
->f_namemax
);
525 verbose("received client version %d", version
);
527 buffer_put_char(&msg
, SSH2_FXP_VERSION
);
528 buffer_put_int(&msg
, SSH2_FILEXFER_VERSION
);
529 /* POSIX rename extension */
530 buffer_put_cstring(&msg
, "posix-rename@openssh.com");
531 buffer_put_cstring(&msg
, "1"); /* version */
532 /* statvfs extension */
533 buffer_put_cstring(&msg
, "statvfs@openssh.com");
534 buffer_put_cstring(&msg
, "2"); /* version */
535 /* fstatvfs extension */
536 buffer_put_cstring(&msg
, "fstatvfs@openssh.com");
537 buffer_put_cstring(&msg
, "2"); /* version */
538 /* hardlink extension */
539 buffer_put_cstring(&msg
, "hardlink@openssh.com");
540 buffer_put_cstring(&msg
, "1"); /* version */
548 u_int32_t id
, pflags
;
551 int handle
, fd
, flags
, mode
, status
= SSH2_FX_FAILURE
;
554 name
= get_string(NULL
);
555 pflags
= get_int(); /* portable flags */
556 debug3("request %u: open flags %d", id
, pflags
);
558 flags
= flags_from_portable(pflags
);
559 mode
= (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) ? a
->perm
: 0666;
560 logit("open \"%s\" flags %s mode 0%o",
561 name
, string_from_portable(pflags
), mode
);
563 ((flags
& O_ACCMODE
) == O_WRONLY
|| (flags
& O_ACCMODE
) == O_RDWR
))
564 status
= SSH2_FX_PERMISSION_DENIED
;
566 fd
= open(name
, flags
, mode
);
568 status
= errno_to_portable(errno
);
570 handle
= handle_new(HANDLE_FILE
, name
, fd
, NULL
);
574 send_handle(id
, handle
);
579 if (status
!= SSH2_FX_OK
)
580 send_status(id
, status
);
588 int handle
, ret
, status
= SSH2_FX_FAILURE
;
591 handle
= get_handle();
592 debug3("request %u: close handle %u", id
, handle
);
593 handle_log_close(handle
, NULL
);
594 ret
= handle_close(handle
);
595 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
596 send_status(id
, status
);
604 int handle
, fd
, ret
, status
= SSH2_FX_FAILURE
;
608 handle
= get_handle();
612 debug("request %u: read \"%s\" (handle %d) off %llu len %d",
613 id
, handle_to_name(handle
), handle
, (unsigned long long)off
, len
);
614 if (len
> sizeof buf
) {
616 debug2("read change len %d", len
);
618 fd
= handle_to_fd(handle
);
620 if (lseek(fd
, off
, SEEK_SET
) < 0) {
621 error("process_read: seek failed");
622 status
= errno_to_portable(errno
);
624 ret
= read(fd
, buf
, len
);
626 status
= errno_to_portable(errno
);
627 } else if (ret
== 0) {
628 status
= SSH2_FX_EOF
;
630 send_data(id
, buf
, ret
);
632 handle_update_read(handle
, ret
);
636 if (status
!= SSH2_FX_OK
)
637 send_status(id
, status
);
646 int handle
, fd
, ret
, status
;
650 handle
= get_handle();
652 data
= get_string(&len
);
654 debug("request %u: write \"%s\" (handle %d) off %llu len %d",
655 id
, handle_to_name(handle
), handle
, (unsigned long long)off
, len
);
656 fd
= handle_to_fd(handle
);
659 status
= SSH2_FX_FAILURE
;
661 status
= SSH2_FX_PERMISSION_DENIED
;
663 if (lseek(fd
, off
, SEEK_SET
) < 0) {
664 status
= errno_to_portable(errno
);
665 error("process_write: seek failed");
668 ret
= write(fd
, data
, len
);
670 error("process_write: write failed");
671 status
= errno_to_portable(errno
);
672 } else if ((size_t)ret
== len
) {
674 handle_update_write(handle
, ret
);
676 debug2("nothing at all written");
677 status
= SSH2_FX_FAILURE
;
681 send_status(id
, status
);
686 process_do_stat(int do_lstat
)
692 int ret
, status
= SSH2_FX_FAILURE
;
695 name
= get_string(NULL
);
696 debug3("request %u: %sstat", id
, do_lstat
? "l" : "");
697 verbose("%sstat name \"%s\"", do_lstat
? "l" : "", name
);
698 ret
= do_lstat
? lstat(name
, &st
) : stat(name
, &st
);
700 status
= errno_to_portable(errno
);
702 stat_to_attrib(&st
, &a
);
706 if (status
!= SSH2_FX_OK
)
707 send_status(id
, status
);
729 int fd
, ret
, handle
, status
= SSH2_FX_FAILURE
;
732 handle
= get_handle();
733 debug("request %u: fstat \"%s\" (handle %u)",
734 id
, handle_to_name(handle
), handle
);
735 fd
= handle_to_fd(handle
);
737 ret
= fstat(fd
, &st
);
739 status
= errno_to_portable(errno
);
741 stat_to_attrib(&st
, &a
);
746 if (status
!= SSH2_FX_OK
)
747 send_status(id
, status
);
750 static struct timeval
*
751 attrib_to_tv(const Attrib
*a
)
753 static struct timeval tv
[2];
755 tv
[0].tv_sec
= a
->atime
;
757 tv
[1].tv_sec
= a
->mtime
;
763 process_setstat(void)
768 int status
= SSH2_FX_OK
, ret
;
771 name
= get_string(NULL
);
773 debug("request %u: setstat name \"%s\"", id
, name
);
775 status
= SSH2_FX_PERMISSION_DENIED
;
778 if (a
->flags
& SSH2_FILEXFER_ATTR_SIZE
) {
779 logit("set \"%s\" size %llu",
780 name
, (unsigned long long)a
->size
);
781 ret
= truncate(name
, a
->size
);
783 status
= errno_to_portable(errno
);
785 if (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) {
786 logit("set \"%s\" mode %04o", name
, a
->perm
);
787 ret
= chmod(name
, a
->perm
& 07777);
789 status
= errno_to_portable(errno
);
791 if (a
->flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
795 strftime(buf
, sizeof(buf
), "%Y%m%d-%H:%M:%S",
797 logit("set \"%s\" modtime %s", name
, buf
);
798 ret
= utimes(name
, attrib_to_tv(a
));
800 status
= errno_to_portable(errno
);
802 if (a
->flags
& SSH2_FILEXFER_ATTR_UIDGID
) {
803 logit("set \"%s\" owner %lu group %lu", name
,
804 (u_long
)a
->uid
, (u_long
)a
->gid
);
805 ret
= chown(name
, a
->uid
, a
->gid
);
807 status
= errno_to_portable(errno
);
809 send_status(id
, status
);
814 process_fsetstat(void)
819 int status
= SSH2_FX_OK
;
822 handle
= get_handle();
824 debug("request %u: fsetstat handle %d", id
, handle
);
825 fd
= handle_to_fd(handle
);
827 status
= SSH2_FX_FAILURE
;
829 status
= SSH2_FX_PERMISSION_DENIED
;
831 char *name
= handle_to_name(handle
);
833 if (a
->flags
& SSH2_FILEXFER_ATTR_SIZE
) {
834 logit("set \"%s\" size %llu",
835 name
, (unsigned long long)a
->size
);
836 ret
= ftruncate(fd
, a
->size
);
838 status
= errno_to_portable(errno
);
840 if (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) {
841 logit("set \"%s\" mode %04o", name
, a
->perm
);
843 ret
= fchmod(fd
, a
->perm
& 07777);
845 ret
= chmod(name
, a
->perm
& 07777);
848 status
= errno_to_portable(errno
);
850 if (a
->flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
854 strftime(buf
, sizeof(buf
), "%Y%m%d-%H:%M:%S",
856 logit("set \"%s\" modtime %s", name
, buf
);
858 ret
= futimes(fd
, attrib_to_tv(a
));
860 ret
= utimes(name
, attrib_to_tv(a
));
863 status
= errno_to_portable(errno
);
865 if (a
->flags
& SSH2_FILEXFER_ATTR_UIDGID
) {
866 logit("set \"%s\" owner %lu group %lu", name
,
867 (u_long
)a
->uid
, (u_long
)a
->gid
);
869 ret
= fchown(fd
, a
->uid
, a
->gid
);
871 ret
= chown(name
, a
->uid
, a
->gid
);
874 status
= errno_to_portable(errno
);
877 send_status(id
, status
);
881 process_opendir(void)
885 int handle
, status
= SSH2_FX_FAILURE
;
889 path
= get_string(NULL
);
890 debug3("request %u: opendir", id
);
891 logit("opendir \"%s\"", path
);
892 dirp
= opendir(path
);
894 status
= errno_to_portable(errno
);
896 handle
= handle_new(HANDLE_DIR
, path
, 0, dirp
);
900 send_handle(id
, handle
);
905 if (status
!= SSH2_FX_OK
)
906 send_status(id
, status
);
911 process_readdir(void)
920 handle
= get_handle();
921 debug("request %u: readdir \"%s\" (handle %d)", id
,
922 handle_to_name(handle
), handle
);
923 dirp
= handle_to_dir(handle
);
924 path
= handle_to_name(handle
);
925 if (dirp
== NULL
|| path
== NULL
) {
926 send_status(id
, SSH2_FX_FAILURE
);
929 char pathname
[MAXPATHLEN
];
931 int nstats
= 10, count
= 0, i
;
933 stats
= xcalloc(nstats
, sizeof(Stat
));
934 while ((dp
= readdir(dirp
)) != NULL
) {
935 if (count
>= nstats
) {
937 stats
= xrealloc(stats
, nstats
, sizeof(Stat
));
940 snprintf(pathname
, sizeof pathname
, "%s%s%s", path
,
941 strcmp(path
, "/") ? "/" : "", dp
->d_name
);
942 if (lstat(pathname
, &st
) < 0)
944 stat_to_attrib(&st
, &(stats
[count
].attrib
));
945 stats
[count
].name
= xstrdup(dp
->d_name
);
946 stats
[count
].long_name
= ls_file(dp
->d_name
, &st
, 0, 0);
948 /* send up to 100 entries in one message */
949 /* XXX check packet size instead */
954 send_names(id
, count
, stats
);
955 for (i
= 0; i
< count
; i
++) {
956 xfree(stats
[i
].name
);
957 xfree(stats
[i
].long_name
);
960 send_status(id
, SSH2_FX_EOF
);
971 int status
= SSH2_FX_FAILURE
;
975 name
= get_string(NULL
);
976 debug3("request %u: remove", id
);
977 logit("remove name \"%s\"", name
);
979 status
= SSH2_FX_PERMISSION_DENIED
;
982 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
984 send_status(id
, status
);
994 int ret
, mode
, status
= SSH2_FX_FAILURE
;
997 name
= get_string(NULL
);
999 mode
= (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) ?
1000 a
->perm
& 07777 : 0777;
1001 debug3("request %u: mkdir", id
);
1002 logit("mkdir name \"%s\" mode 0%o", name
, mode
);
1004 status
= SSH2_FX_PERMISSION_DENIED
;
1006 ret
= mkdir(name
, mode
);
1007 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1009 send_status(id
, status
);
1021 name
= get_string(NULL
);
1022 debug3("request %u: rmdir", id
);
1023 logit("rmdir name \"%s\"", name
);
1025 status
= SSH2_FX_PERMISSION_DENIED
;
1028 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1030 send_status(id
, status
);
1035 process_realpath(void)
1037 char resolvedname
[MAXPATHLEN
];
1042 path
= get_string(NULL
);
1043 if (path
[0] == '\0') {
1045 path
= xstrdup(".");
1047 debug3("request %u: realpath", id
);
1048 verbose("realpath \"%s\"", path
);
1049 if (realpath(path
, resolvedname
) == NULL
) {
1050 send_status(id
, errno_to_portable(errno
));
1053 attrib_clear(&s
.attrib
);
1054 s
.name
= s
.long_name
= resolvedname
;
1055 send_names(id
, 1, &s
);
1061 process_rename(void)
1064 char *oldpath
, *newpath
;
1069 oldpath
= get_string(NULL
);
1070 newpath
= get_string(NULL
);
1071 debug3("request %u: rename", id
);
1072 logit("rename old \"%s\" new \"%s\"", oldpath
, newpath
);
1073 status
= SSH2_FX_FAILURE
;
1075 status
= SSH2_FX_PERMISSION_DENIED
;
1076 else if (lstat(oldpath
, &sb
) == -1)
1077 status
= errno_to_portable(errno
);
1078 else if (S_ISREG(sb
.st_mode
)) {
1079 /* Race-free rename of regular files */
1080 if (link(oldpath
, newpath
) == -1) {
1081 if (errno
== EOPNOTSUPP
|| errno
== ENOSYS
1085 #ifdef LINK_OPNOTSUPP_ERRNO
1086 || errno
== LINK_OPNOTSUPP_ERRNO
1092 * fs doesn't support links, so fall back to
1093 * stat+rename. This is racy.
1095 if (stat(newpath
, &st
) == -1) {
1096 if (rename(oldpath
, newpath
) == -1)
1098 errno_to_portable(errno
);
1100 status
= SSH2_FX_OK
;
1103 status
= errno_to_portable(errno
);
1105 } else if (unlink(oldpath
) == -1) {
1106 status
= errno_to_portable(errno
);
1107 /* clean spare link */
1110 status
= SSH2_FX_OK
;
1111 } else if (stat(newpath
, &sb
) == -1) {
1112 if (rename(oldpath
, newpath
) == -1)
1113 status
= errno_to_portable(errno
);
1115 status
= SSH2_FX_OK
;
1117 send_status(id
, status
);
1123 process_readlink(void)
1127 char buf
[MAXPATHLEN
];
1131 path
= get_string(NULL
);
1132 debug3("request %u: readlink", id
);
1133 verbose("readlink \"%s\"", path
);
1134 if ((len
= readlink(path
, buf
, sizeof(buf
) - 1)) == -1)
1135 send_status(id
, errno_to_portable(errno
));
1140 attrib_clear(&s
.attrib
);
1141 s
.name
= s
.long_name
= buf
;
1142 send_names(id
, 1, &s
);
1148 process_symlink(void)
1151 char *oldpath
, *newpath
;
1155 oldpath
= get_string(NULL
);
1156 newpath
= get_string(NULL
);
1157 debug3("request %u: symlink", id
);
1158 logit("symlink old \"%s\" new \"%s\"", oldpath
, newpath
);
1159 /* this will fail if 'newpath' exists */
1161 status
= SSH2_FX_PERMISSION_DENIED
;
1163 ret
= symlink(oldpath
, newpath
);
1164 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1166 send_status(id
, status
);
1172 process_extended_posix_rename(u_int32_t id
)
1174 char *oldpath
, *newpath
;
1177 oldpath
= get_string(NULL
);
1178 newpath
= get_string(NULL
);
1179 debug3("request %u: posix-rename", id
);
1180 logit("posix-rename old \"%s\" new \"%s\"", oldpath
, newpath
);
1182 status
= SSH2_FX_PERMISSION_DENIED
;
1184 ret
= rename(oldpath
, newpath
);
1185 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1187 send_status(id
, status
);
1193 process_extended_statvfs(u_int32_t id
)
1198 path
= get_string(NULL
);
1199 debug3("request %u: statfs", id
);
1200 logit("statfs \"%s\"", path
);
1202 if (statvfs(path
, &st
) != 0)
1203 send_status(id
, errno_to_portable(errno
));
1205 send_statvfs(id
, &st
);
1210 process_extended_fstatvfs(u_int32_t id
)
1215 handle
= get_handle();
1216 debug("request %u: fstatvfs \"%s\" (handle %u)",
1217 id
, handle_to_name(handle
), handle
);
1218 if ((fd
= handle_to_fd(handle
)) < 0) {
1219 send_status(id
, SSH2_FX_FAILURE
);
1222 if (fstatvfs(fd
, &st
) != 0)
1223 send_status(id
, errno_to_portable(errno
));
1225 send_statvfs(id
, &st
);
1229 process_extended_hardlink(u_int32_t id
)
1231 char *oldpath
, *newpath
;
1234 oldpath
= get_string(NULL
);
1235 newpath
= get_string(NULL
);
1236 debug3("request %u: hardlink", id
);
1237 logit("hardlink old \"%s\" new \"%s\"", oldpath
, newpath
);
1239 status
= SSH2_FX_PERMISSION_DENIED
;
1241 ret
= link(oldpath
, newpath
);
1242 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1244 send_status(id
, status
);
1250 process_extended(void)
1256 request
= get_string(NULL
);
1257 if (strcmp(request
, "posix-rename@openssh.com") == 0)
1258 process_extended_posix_rename(id
);
1259 else if (strcmp(request
, "statvfs@openssh.com") == 0)
1260 process_extended_statvfs(id
);
1261 else if (strcmp(request
, "fstatvfs@openssh.com") == 0)
1262 process_extended_fstatvfs(id
);
1263 else if (strcmp(request
, "hardlink@openssh.com") == 0)
1264 process_extended_hardlink(id
);
1266 send_status(id
, SSH2_FX_OP_UNSUPPORTED
); /* MUST */
1270 /* stolen from ssh-agent */
1281 buf_len
= buffer_len(&iqueue
);
1283 return; /* Incomplete message. */
1284 cp
= buffer_ptr(&iqueue
);
1285 msg_len
= get_u32(cp
);
1286 if (msg_len
> SFTP_MAX_MSG_LENGTH
) {
1287 error("bad message from %s local user %s",
1288 client_addr
, pw
->pw_name
);
1289 sftp_server_cleanup_exit(11);
1291 if (buf_len
< msg_len
+ 4)
1293 buffer_consume(&iqueue
, 4);
1295 type
= buffer_get_char(&iqueue
);
1303 case SSH2_FXP_CLOSE
:
1309 case SSH2_FXP_WRITE
:
1312 case SSH2_FXP_LSTAT
:
1315 case SSH2_FXP_FSTAT
:
1318 case SSH2_FXP_SETSTAT
:
1321 case SSH2_FXP_FSETSTAT
:
1324 case SSH2_FXP_OPENDIR
:
1327 case SSH2_FXP_READDIR
:
1330 case SSH2_FXP_REMOVE
:
1333 case SSH2_FXP_MKDIR
:
1336 case SSH2_FXP_RMDIR
:
1339 case SSH2_FXP_REALPATH
:
1345 case SSH2_FXP_RENAME
:
1348 case SSH2_FXP_READLINK
:
1351 case SSH2_FXP_SYMLINK
:
1354 case SSH2_FXP_EXTENDED
:
1358 error("Unknown message %d", type
);
1361 /* discard the remaining bytes from the current packet */
1362 if (buf_len
< buffer_len(&iqueue
)) {
1363 error("iqueue grew unexpectedly");
1364 sftp_server_cleanup_exit(255);
1366 consumed
= buf_len
- buffer_len(&iqueue
);
1367 if (msg_len
< consumed
) {
1368 error("msg_len %d < consumed %d", msg_len
, consumed
);
1369 sftp_server_cleanup_exit(255);
1371 if (msg_len
> consumed
)
1372 buffer_consume(&iqueue
, msg_len
- consumed
);
1375 /* Cleanup handler that logs active handles upon normal exit */
1377 sftp_server_cleanup_exit(int i
)
1379 if (pw
!= NULL
&& client_addr
!= NULL
) {
1381 logit("session closed for local user %s from [%s]",
1382 pw
->pw_name
, client_addr
);
1388 sftp_server_usage(void)
1390 extern char *__progname
;
1393 "usage: %s [-ehR] [-f log_facility] [-l log_level] [-u umask]\n",
1399 sftp_server_main(int argc
, char **argv
, struct passwd
*user_pw
)
1401 fd_set
*rset
, *wset
;
1402 int in
, out
, max
, ch
, skipargs
= 0, log_stderr
= 0;
1403 ssize_t len
, olen
, set_size
;
1404 SyslogFacility log_facility
= SYSLOG_FACILITY_AUTH
;
1405 char *cp
, buf
[4*4096];
1408 extern char *optarg
;
1409 extern char *__progname
;
1411 __progname
= ssh_get_progname(argv
[0]);
1412 log_init(__progname
, log_level
, log_facility
, log_stderr
);
1414 while (!skipargs
&& (ch
= getopt(argc
, argv
, "f:l:u:cehR")) != -1) {
1421 * Ignore all arguments if we are invoked as a
1422 * shell using "sftp-server -c command"
1430 log_level
= log_level_number(optarg
);
1431 if (log_level
== SYSLOG_LEVEL_NOT_SET
)
1432 error("Invalid log level \"%s\"", optarg
);
1435 log_facility
= log_facility_number(optarg
);
1436 if (log_facility
== SYSLOG_FACILITY_NOT_SET
)
1437 error("Invalid log facility \"%s\"", optarg
);
1441 mask
= strtol(optarg
, &cp
, 8);
1442 if (mask
< 0 || mask
> 0777 || *cp
!= '\0' ||
1443 cp
== optarg
|| (mask
== 0 && errno
!= 0))
1444 fatal("Invalid umask \"%s\"", optarg
);
1445 (void)umask((mode_t
)mask
);
1449 sftp_server_usage();
1453 log_init(__progname
, log_level
, log_facility
, log_stderr
);
1455 if ((cp
= getenv("SSH_CONNECTION")) != NULL
) {
1456 client_addr
= xstrdup(cp
);
1457 if ((cp
= strchr(client_addr
, ' ')) == NULL
) {
1458 error("Malformed SSH_CONNECTION variable: \"%s\"",
1459 getenv("SSH_CONNECTION"));
1460 sftp_server_cleanup_exit(255);
1464 client_addr
= xstrdup("UNKNOWN");
1466 pw
= pwcopy(user_pw
);
1468 logit("session opened for local user %s from [%s]",
1469 pw
->pw_name
, client_addr
);
1472 out
= STDOUT_FILENO
;
1475 setmode(in
, O_BINARY
);
1476 setmode(out
, O_BINARY
);
1485 buffer_init(&iqueue
);
1486 buffer_init(&oqueue
);
1488 set_size
= howmany(max
+ 1, NFDBITS
) * sizeof(fd_mask
);
1489 rset
= (fd_set
*)xmalloc(set_size
);
1490 wset
= (fd_set
*)xmalloc(set_size
);
1493 memset(rset
, 0, set_size
);
1494 memset(wset
, 0, set_size
);
1497 * Ensure that we can read a full buffer and handle
1498 * the worst-case length packet it can generate,
1499 * otherwise apply backpressure by stopping reads.
1501 if (buffer_check_alloc(&iqueue
, sizeof(buf
)) &&
1502 buffer_check_alloc(&oqueue
, SFTP_MAX_MSG_LENGTH
))
1505 olen
= buffer_len(&oqueue
);
1509 if (select(max
+1, rset
, wset
, NULL
, NULL
) < 0) {
1512 error("select: %s", strerror(errno
));
1513 sftp_server_cleanup_exit(2);
1516 /* copy stdin to iqueue */
1517 if (FD_ISSET(in
, rset
)) {
1518 len
= read(in
, buf
, sizeof buf
);
1521 sftp_server_cleanup_exit(0);
1522 } else if (len
< 0) {
1523 error("read: %s", strerror(errno
));
1524 sftp_server_cleanup_exit(1);
1526 buffer_append(&iqueue
, buf
, len
);
1529 /* send oqueue to stdout */
1530 if (FD_ISSET(out
, wset
)) {
1531 len
= write(out
, buffer_ptr(&oqueue
), olen
);
1533 error("write: %s", strerror(errno
));
1534 sftp_server_cleanup_exit(1);
1536 buffer_consume(&oqueue
, len
);
1541 * Process requests from client if we can fit the results
1542 * into the output buffer, otherwise stop processing input
1543 * and let the output queue drain.
1545 if (buffer_check_alloc(&oqueue
, SFTP_MAX_MSG_LENGTH
))