1 /* $OpenBSD: sftp-server.c,v 1.69 2006/08/01 23:22:47 stevesk 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.
19 #include <sys/types.h>
20 #include <sys/param.h>
22 #ifdef HAVE_SYS_TIME_H
23 # include <sys/time.h>
44 #include "sftp-common.h"
47 #define get_int64() buffer_get_int64(&iqueue);
48 #define get_int() buffer_get_int(&iqueue);
49 #define get_string(lenp) buffer_get_string(&iqueue, lenp);
52 LogLevel log_level
= SYSLOG_LEVEL_ERROR
;
55 struct passwd
*pw
= NULL
;
56 char *client_addr
= NULL
;
58 /* input and output queue */
62 /* Version of client */
65 /* portable attributes, etc. */
67 typedef struct Stat Stat
;
76 errno_to_portable(int unixerrno
)
88 ret
= SSH2_FX_NO_SUCH_FILE
;
93 ret
= SSH2_FX_PERMISSION_DENIED
;
97 ret
= SSH2_FX_BAD_MESSAGE
;
100 ret
= SSH2_FX_FAILURE
;
107 flags_from_portable(int pflags
)
111 if ((pflags
& SSH2_FXF_READ
) &&
112 (pflags
& SSH2_FXF_WRITE
)) {
114 } else if (pflags
& SSH2_FXF_READ
) {
116 } else if (pflags
& SSH2_FXF_WRITE
) {
119 if (pflags
& SSH2_FXF_CREAT
)
121 if (pflags
& SSH2_FXF_TRUNC
)
123 if (pflags
& SSH2_FXF_EXCL
)
129 string_from_portable(int pflags
)
131 static char ret
[128];
135 #define PAPPEND(str) { \
137 strlcat(ret, ",", sizeof(ret)); \
138 strlcat(ret, str, sizeof(ret)); \
141 if (pflags
& SSH2_FXF_READ
)
143 if (pflags
& SSH2_FXF_WRITE
)
145 if (pflags
& SSH2_FXF_CREAT
)
147 if (pflags
& SSH2_FXF_TRUNC
)
149 if (pflags
& SSH2_FXF_EXCL
)
158 return decode_attrib(&iqueue
);
163 typedef struct Handle Handle
;
169 u_int64_t bytes_read
, bytes_write
;
185 for (i
= 0; i
< sizeof(handles
)/sizeof(Handle
); i
++)
186 handles
[i
].use
= HANDLE_UNUSED
;
190 handle_new(int use
, const char *name
, int fd
, DIR *dirp
)
194 for (i
= 0; i
< sizeof(handles
)/sizeof(Handle
); i
++) {
195 if (handles
[i
].use
== HANDLE_UNUSED
) {
196 handles
[i
].use
= use
;
197 handles
[i
].dirp
= dirp
;
199 handles
[i
].name
= xstrdup(name
);
200 handles
[i
].bytes_read
= handles
[i
].bytes_write
= 0;
208 handle_is_ok(int i
, int type
)
210 return i
>= 0 && (u_int
)i
< sizeof(handles
)/sizeof(Handle
) &&
211 handles
[i
].use
== type
;
215 handle_to_string(int handle
, char **stringp
, int *hlenp
)
217 if (stringp
== NULL
|| hlenp
== NULL
)
219 *stringp
= xmalloc(sizeof(int32_t));
220 put_u32(*stringp
, handle
);
221 *hlenp
= sizeof(int32_t);
226 handle_from_string(const char *handle
, u_int hlen
)
230 if (hlen
!= sizeof(int32_t))
232 val
= get_u32(handle
);
233 if (handle_is_ok(val
, HANDLE_FILE
) ||
234 handle_is_ok(val
, HANDLE_DIR
))
240 handle_to_name(int handle
)
242 if (handle_is_ok(handle
, HANDLE_DIR
)||
243 handle_is_ok(handle
, HANDLE_FILE
))
244 return handles
[handle
].name
;
249 handle_to_dir(int handle
)
251 if (handle_is_ok(handle
, HANDLE_DIR
))
252 return handles
[handle
].dirp
;
257 handle_to_fd(int handle
)
259 if (handle_is_ok(handle
, HANDLE_FILE
))
260 return handles
[handle
].fd
;
265 handle_update_read(int handle
, ssize_t bytes
)
267 if (handle_is_ok(handle
, HANDLE_FILE
) && bytes
> 0)
268 handles
[handle
].bytes_read
+= bytes
;
272 handle_update_write(int handle
, ssize_t bytes
)
274 if (handle_is_ok(handle
, HANDLE_FILE
) && bytes
> 0)
275 handles
[handle
].bytes_write
+= bytes
;
279 handle_bytes_read(int handle
)
281 if (handle_is_ok(handle
, HANDLE_FILE
))
282 return (handles
[handle
].bytes_read
);
287 handle_bytes_write(int handle
)
289 if (handle_is_ok(handle
, HANDLE_FILE
))
290 return (handles
[handle
].bytes_write
);
295 handle_close(int handle
)
299 if (handle_is_ok(handle
, HANDLE_FILE
)) {
300 ret
= close(handles
[handle
].fd
);
301 handles
[handle
].use
= HANDLE_UNUSED
;
302 xfree(handles
[handle
].name
);
303 } else if (handle_is_ok(handle
, HANDLE_DIR
)) {
304 ret
= closedir(handles
[handle
].dirp
);
305 handles
[handle
].use
= HANDLE_UNUSED
;
306 xfree(handles
[handle
].name
);
314 handle_log_close(int handle
, char *emsg
)
316 if (handle_is_ok(handle
, HANDLE_FILE
)) {
317 logit("%s%sclose \"%s\" bytes read %llu written %llu",
318 emsg
== NULL
? "" : emsg
, emsg
== NULL
? "" : " ",
319 handle_to_name(handle
),
320 handle_bytes_read(handle
), handle_bytes_write(handle
));
322 logit("%s%sclosedir \"%s\"",
323 emsg
== NULL
? "" : emsg
, emsg
== NULL
? "" : " ",
324 handle_to_name(handle
));
329 handle_log_exit(void)
333 for (i
= 0; i
< sizeof(handles
)/sizeof(Handle
); i
++)
334 if (handles
[i
].use
!= HANDLE_UNUSED
)
335 handle_log_close(i
, "forced");
345 handle
= get_string(&hlen
);
347 val
= handle_from_string(handle
, hlen
);
357 int mlen
= buffer_len(m
);
359 buffer_put_int(&oqueue
, mlen
);
360 buffer_append(&oqueue
, buffer_ptr(m
), mlen
);
361 buffer_consume(m
, mlen
);
365 status_to_message(u_int32_t status
)
367 const char *status_messages
[] = {
368 "Success", /* SSH_FX_OK */
369 "End of file", /* SSH_FX_EOF */
370 "No such file", /* SSH_FX_NO_SUCH_FILE */
371 "Permission denied", /* SSH_FX_PERMISSION_DENIED */
372 "Failure", /* SSH_FX_FAILURE */
373 "Bad message", /* SSH_FX_BAD_MESSAGE */
374 "No connection", /* SSH_FX_NO_CONNECTION */
375 "Connection lost", /* SSH_FX_CONNECTION_LOST */
376 "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
377 "Unknown error" /* Others */
379 return (status_messages
[MIN(status
,SSH2_FX_MAX
)]);
383 send_status(u_int32_t id
, u_int32_t status
)
387 debug3("request %u: sent status %u", id
, status
);
388 if (log_level
> SYSLOG_LEVEL_VERBOSE
||
389 (status
!= SSH2_FX_OK
&& status
!= SSH2_FX_EOF
))
390 logit("sent status %s", status_to_message(status
));
392 buffer_put_char(&msg
, SSH2_FXP_STATUS
);
393 buffer_put_int(&msg
, id
);
394 buffer_put_int(&msg
, status
);
396 buffer_put_cstring(&msg
, status_to_message(status
));
397 buffer_put_cstring(&msg
, "");
403 send_data_or_handle(char type
, u_int32_t id
, const char *data
, int dlen
)
408 buffer_put_char(&msg
, type
);
409 buffer_put_int(&msg
, id
);
410 buffer_put_string(&msg
, data
, dlen
);
416 send_data(u_int32_t id
, const char *data
, int dlen
)
418 debug("request %u: sent data len %d", id
, dlen
);
419 send_data_or_handle(SSH2_FXP_DATA
, id
, data
, dlen
);
423 send_handle(u_int32_t id
, int handle
)
428 handle_to_string(handle
, &string
, &hlen
);
429 debug("request %u: sent handle handle %d", id
, handle
);
430 send_data_or_handle(SSH2_FXP_HANDLE
, id
, string
, hlen
);
435 send_names(u_int32_t id
, int count
, const Stat
*stats
)
441 buffer_put_char(&msg
, SSH2_FXP_NAME
);
442 buffer_put_int(&msg
, id
);
443 buffer_put_int(&msg
, count
);
444 debug("request %u: sent names count %d", id
, count
);
445 for (i
= 0; i
< count
; i
++) {
446 buffer_put_cstring(&msg
, stats
[i
].name
);
447 buffer_put_cstring(&msg
, stats
[i
].long_name
);
448 encode_attrib(&msg
, &stats
[i
].attrib
);
455 send_attrib(u_int32_t id
, const Attrib
*a
)
459 debug("request %u: sent attrib have 0x%x", id
, a
->flags
);
461 buffer_put_char(&msg
, SSH2_FXP_ATTRS
);
462 buffer_put_int(&msg
, id
);
463 encode_attrib(&msg
, a
);
476 verbose("received client version %d", version
);
478 buffer_put_char(&msg
, SSH2_FXP_VERSION
);
479 buffer_put_int(&msg
, SSH2_FILEXFER_VERSION
);
487 u_int32_t id
, pflags
;
490 int handle
, fd
, flags
, mode
, status
= SSH2_FX_FAILURE
;
493 name
= get_string(NULL
);
494 pflags
= get_int(); /* portable flags */
495 debug3("request %u: open flags %d", id
, pflags
);
497 flags
= flags_from_portable(pflags
);
498 mode
= (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) ? a
->perm
: 0666;
499 logit("open \"%s\" flags %s mode 0%o",
500 name
, string_from_portable(pflags
), mode
);
501 fd
= open(name
, flags
, mode
);
503 status
= errno_to_portable(errno
);
505 handle
= handle_new(HANDLE_FILE
, name
, fd
, NULL
);
509 send_handle(id
, handle
);
513 if (status
!= SSH2_FX_OK
)
514 send_status(id
, status
);
522 int handle
, ret
, status
= SSH2_FX_FAILURE
;
525 handle
= get_handle();
526 debug3("request %u: close handle %u", id
, handle
);
527 handle_log_close(handle
, NULL
);
528 ret
= handle_close(handle
);
529 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
530 send_status(id
, status
);
538 int handle
, fd
, ret
, status
= SSH2_FX_FAILURE
;
542 handle
= get_handle();
546 debug("request %u: read \"%s\" (handle %d) off %llu len %d",
547 id
, handle_to_name(handle
), handle
, (unsigned long long)off
, len
);
548 if (len
> sizeof buf
) {
550 debug2("read change len %d", len
);
552 fd
= handle_to_fd(handle
);
554 if (lseek(fd
, off
, SEEK_SET
) < 0) {
555 error("process_read: seek failed");
556 status
= errno_to_portable(errno
);
558 ret
= read(fd
, buf
, len
);
560 status
= errno_to_portable(errno
);
561 } else if (ret
== 0) {
562 status
= SSH2_FX_EOF
;
564 send_data(id
, buf
, ret
);
566 handle_update_read(handle
, ret
);
570 if (status
!= SSH2_FX_OK
)
571 send_status(id
, status
);
580 int handle
, fd
, ret
, status
= SSH2_FX_FAILURE
;
584 handle
= get_handle();
586 data
= get_string(&len
);
588 debug("request %u: write \"%s\" (handle %d) off %llu len %d",
589 id
, handle_to_name(handle
), handle
, (unsigned long long)off
, len
);
590 fd
= handle_to_fd(handle
);
592 if (lseek(fd
, off
, SEEK_SET
) < 0) {
593 status
= errno_to_portable(errno
);
594 error("process_write: seek failed");
597 ret
= write(fd
, data
, len
);
599 error("process_write: write failed");
600 status
= errno_to_portable(errno
);
601 } else if ((size_t)ret
== len
) {
603 handle_update_write(handle
, ret
);
605 debug2("nothing at all written");
609 send_status(id
, status
);
614 process_do_stat(int do_lstat
)
620 int ret
, status
= SSH2_FX_FAILURE
;
623 name
= get_string(NULL
);
624 debug3("request %u: %sstat", id
, do_lstat
? "l" : "");
625 verbose("%sstat name \"%s\"", do_lstat
? "l" : "", name
);
626 ret
= do_lstat
? lstat(name
, &st
) : stat(name
, &st
);
628 status
= errno_to_portable(errno
);
630 stat_to_attrib(&st
, &a
);
634 if (status
!= SSH2_FX_OK
)
635 send_status(id
, status
);
657 int fd
, ret
, handle
, status
= SSH2_FX_FAILURE
;
660 handle
= get_handle();
661 debug("request %u: fstat \"%s\" (handle %u)",
662 id
, handle_to_name(handle
), handle
);
663 fd
= handle_to_fd(handle
);
665 ret
= fstat(fd
, &st
);
667 status
= errno_to_portable(errno
);
669 stat_to_attrib(&st
, &a
);
674 if (status
!= SSH2_FX_OK
)
675 send_status(id
, status
);
678 static struct timeval
*
679 attrib_to_tv(const Attrib
*a
)
681 static struct timeval tv
[2];
683 tv
[0].tv_sec
= a
->atime
;
685 tv
[1].tv_sec
= a
->mtime
;
691 process_setstat(void)
696 int status
= SSH2_FX_OK
, ret
;
699 name
= get_string(NULL
);
701 debug("request %u: setstat name \"%s\"", id
, name
);
702 if (a
->flags
& SSH2_FILEXFER_ATTR_SIZE
) {
703 logit("set \"%s\" size %llu", name
, a
->size
);
704 ret
= truncate(name
, a
->size
);
706 status
= errno_to_portable(errno
);
708 if (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) {
709 logit("set \"%s\" mode %04o", name
, a
->perm
);
710 ret
= chmod(name
, a
->perm
& 0777);
712 status
= errno_to_portable(errno
);
714 if (a
->flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
718 strftime(buf
, sizeof(buf
), "%Y%m%d-%H:%M:%S",
720 logit("set \"%s\" modtime %s", name
, buf
);
721 ret
= utimes(name
, attrib_to_tv(a
));
723 status
= errno_to_portable(errno
);
725 if (a
->flags
& SSH2_FILEXFER_ATTR_UIDGID
) {
726 logit("set \"%s\" owner %lu group %lu", name
,
727 (u_long
)a
->uid
, (u_long
)a
->gid
);
728 ret
= chown(name
, a
->uid
, a
->gid
);
730 status
= errno_to_portable(errno
);
732 send_status(id
, status
);
737 process_fsetstat(void)
742 int status
= SSH2_FX_OK
;
745 handle
= get_handle();
747 debug("request %u: fsetstat handle %d", id
, handle
);
748 fd
= handle_to_fd(handle
);
750 status
= SSH2_FX_FAILURE
;
752 char *name
= handle_to_name(handle
);
754 if (a
->flags
& SSH2_FILEXFER_ATTR_SIZE
) {
755 logit("set \"%s\" size %llu", name
, a
->size
);
756 ret
= ftruncate(fd
, a
->size
);
758 status
= errno_to_portable(errno
);
760 if (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) {
761 logit("set \"%s\" mode %04o", name
, a
->perm
);
763 ret
= fchmod(fd
, a
->perm
& 0777);
765 ret
= chmod(name
, a
->perm
& 0777);
768 status
= errno_to_portable(errno
);
770 if (a
->flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
774 strftime(buf
, sizeof(buf
), "%Y%m%d-%H:%M:%S",
776 logit("set \"%s\" modtime %s", name
, buf
);
778 ret
= futimes(fd
, attrib_to_tv(a
));
780 ret
= utimes(name
, attrib_to_tv(a
));
783 status
= errno_to_portable(errno
);
785 if (a
->flags
& SSH2_FILEXFER_ATTR_UIDGID
) {
786 logit("set \"%s\" owner %lu group %lu", name
,
787 (u_long
)a
->uid
, (u_long
)a
->gid
);
789 ret
= fchown(fd
, a
->uid
, a
->gid
);
791 ret
= chown(name
, a
->uid
, a
->gid
);
794 status
= errno_to_portable(errno
);
797 send_status(id
, status
);
801 process_opendir(void)
805 int handle
, status
= SSH2_FX_FAILURE
;
809 path
= get_string(NULL
);
810 debug3("request %u: opendir", id
);
811 logit("opendir \"%s\"", path
);
812 dirp
= opendir(path
);
814 status
= errno_to_portable(errno
);
816 handle
= handle_new(HANDLE_DIR
, path
, 0, dirp
);
820 send_handle(id
, handle
);
825 if (status
!= SSH2_FX_OK
)
826 send_status(id
, status
);
831 process_readdir(void)
840 handle
= get_handle();
841 debug("request %u: readdir \"%s\" (handle %d)", id
,
842 handle_to_name(handle
), handle
);
843 dirp
= handle_to_dir(handle
);
844 path
= handle_to_name(handle
);
845 if (dirp
== NULL
|| path
== NULL
) {
846 send_status(id
, SSH2_FX_FAILURE
);
849 char pathname
[MAXPATHLEN
];
851 int nstats
= 10, count
= 0, i
;
853 stats
= xcalloc(nstats
, sizeof(Stat
));
854 while ((dp
= readdir(dirp
)) != NULL
) {
855 if (count
>= nstats
) {
857 stats
= xrealloc(stats
, nstats
, sizeof(Stat
));
860 snprintf(pathname
, sizeof pathname
, "%s%s%s", path
,
861 strcmp(path
, "/") ? "/" : "", dp
->d_name
);
862 if (lstat(pathname
, &st
) < 0)
864 stat_to_attrib(&st
, &(stats
[count
].attrib
));
865 stats
[count
].name
= xstrdup(dp
->d_name
);
866 stats
[count
].long_name
= ls_file(dp
->d_name
, &st
, 0);
868 /* send up to 100 entries in one message */
869 /* XXX check packet size instead */
874 send_names(id
, count
, stats
);
875 for (i
= 0; i
< count
; i
++) {
876 xfree(stats
[i
].name
);
877 xfree(stats
[i
].long_name
);
880 send_status(id
, SSH2_FX_EOF
);
891 int status
= SSH2_FX_FAILURE
;
895 name
= get_string(NULL
);
896 debug3("request %u: remove", id
);
897 logit("remove name \"%s\"", name
);
899 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
900 send_status(id
, status
);
910 int ret
, mode
, status
= SSH2_FX_FAILURE
;
913 name
= get_string(NULL
);
915 mode
= (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) ?
916 a
->perm
& 0777 : 0777;
917 debug3("request %u: mkdir", id
);
918 logit("mkdir name \"%s\" mode 0%o", name
, mode
);
919 ret
= mkdir(name
, mode
);
920 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
921 send_status(id
, status
);
933 name
= get_string(NULL
);
934 debug3("request %u: rmdir", id
);
935 logit("rmdir name \"%s\"", name
);
937 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
938 send_status(id
, status
);
943 process_realpath(void)
945 char resolvedname
[MAXPATHLEN
];
950 path
= get_string(NULL
);
951 if (path
[0] == '\0') {
955 debug3("request %u: realpath", id
);
956 verbose("realpath \"%s\"", path
);
957 if (realpath(path
, resolvedname
) == NULL
) {
958 send_status(id
, errno_to_portable(errno
));
961 attrib_clear(&s
.attrib
);
962 s
.name
= s
.long_name
= resolvedname
;
963 send_names(id
, 1, &s
);
972 char *oldpath
, *newpath
;
977 oldpath
= get_string(NULL
);
978 newpath
= get_string(NULL
);
979 debug3("request %u: rename", id
);
980 logit("rename old \"%s\" new \"%s\"", oldpath
, newpath
);
981 status
= SSH2_FX_FAILURE
;
982 if (lstat(oldpath
, &sb
) == -1)
983 status
= errno_to_portable(errno
);
984 else if (S_ISREG(sb
.st_mode
)) {
985 /* Race-free rename of regular files */
986 if (link(oldpath
, newpath
) == -1) {
987 if (errno
== EOPNOTSUPP
988 #ifdef LINK_OPNOTSUPP_ERRNO
989 || errno
== LINK_OPNOTSUPP_ERRNO
995 * fs doesn't support links, so fall back to
996 * stat+rename. This is racy.
998 if (stat(newpath
, &st
) == -1) {
999 if (rename(oldpath
, newpath
) == -1)
1001 errno_to_portable(errno
);
1003 status
= SSH2_FX_OK
;
1006 status
= errno_to_portable(errno
);
1008 } else if (unlink(oldpath
) == -1) {
1009 status
= errno_to_portable(errno
);
1010 /* clean spare link */
1013 status
= SSH2_FX_OK
;
1014 } else if (stat(newpath
, &sb
) == -1) {
1015 if (rename(oldpath
, newpath
) == -1)
1016 status
= errno_to_portable(errno
);
1018 status
= SSH2_FX_OK
;
1020 send_status(id
, status
);
1026 process_readlink(void)
1030 char buf
[MAXPATHLEN
];
1034 path
= get_string(NULL
);
1035 debug3("request %u: readlink", id
);
1036 verbose("readlink \"%s\"", path
);
1037 if ((len
= readlink(path
, buf
, sizeof(buf
) - 1)) == -1)
1038 send_status(id
, errno_to_portable(errno
));
1043 attrib_clear(&s
.attrib
);
1044 s
.name
= s
.long_name
= buf
;
1045 send_names(id
, 1, &s
);
1051 process_symlink(void)
1054 char *oldpath
, *newpath
;
1058 oldpath
= get_string(NULL
);
1059 newpath
= get_string(NULL
);
1060 debug3("request %u: symlink", id
);
1061 logit("symlink old \"%s\" new \"%s\"", oldpath
, newpath
);
1062 /* this will fail if 'newpath' exists */
1063 ret
= symlink(oldpath
, newpath
);
1064 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1065 send_status(id
, status
);
1071 process_extended(void)
1077 request
= get_string(NULL
);
1078 send_status(id
, SSH2_FX_OP_UNSUPPORTED
); /* MUST */
1082 /* stolen from ssh-agent */
1093 buf_len
= buffer_len(&iqueue
);
1095 return; /* Incomplete message. */
1096 cp
= buffer_ptr(&iqueue
);
1097 msg_len
= get_u32(cp
);
1098 if (msg_len
> SFTP_MAX_MSG_LENGTH
) {
1099 error("bad message from %s local user %s",
1100 client_addr
, pw
->pw_name
);
1103 if (buf_len
< msg_len
+ 4)
1105 buffer_consume(&iqueue
, 4);
1107 type
= buffer_get_char(&iqueue
);
1115 case SSH2_FXP_CLOSE
:
1121 case SSH2_FXP_WRITE
:
1124 case SSH2_FXP_LSTAT
:
1127 case SSH2_FXP_FSTAT
:
1130 case SSH2_FXP_SETSTAT
:
1133 case SSH2_FXP_FSETSTAT
:
1136 case SSH2_FXP_OPENDIR
:
1139 case SSH2_FXP_READDIR
:
1142 case SSH2_FXP_REMOVE
:
1145 case SSH2_FXP_MKDIR
:
1148 case SSH2_FXP_RMDIR
:
1151 case SSH2_FXP_REALPATH
:
1157 case SSH2_FXP_RENAME
:
1160 case SSH2_FXP_READLINK
:
1163 case SSH2_FXP_SYMLINK
:
1166 case SSH2_FXP_EXTENDED
:
1170 error("Unknown message %d", type
);
1173 /* discard the remaining bytes from the current packet */
1174 if (buf_len
< buffer_len(&iqueue
))
1175 fatal("iqueue grew unexpectedly");
1176 consumed
= buf_len
- buffer_len(&iqueue
);
1177 if (msg_len
< consumed
)
1178 fatal("msg_len %d < consumed %d", msg_len
, consumed
);
1179 if (msg_len
> consumed
)
1180 buffer_consume(&iqueue
, msg_len
- consumed
);
1183 /* Cleanup handler that logs active handles upon normal exit */
1187 if (pw
!= NULL
&& client_addr
!= NULL
) {
1189 logit("session closed for local user %s from [%s]",
1190 pw
->pw_name
, client_addr
);
1198 extern char *__progname
;
1201 "usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname
);
1206 main(int argc
, char **argv
)
1208 fd_set
*rset
, *wset
;
1209 int in
, out
, max
, ch
, skipargs
= 0, log_stderr
= 0;
1210 ssize_t len
, olen
, set_size
;
1211 SyslogFacility log_facility
= SYSLOG_FACILITY_AUTH
;
1214 extern char *optarg
;
1215 extern char *__progname
;
1217 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1220 __progname
= ssh_get_progname(argv
[0]);
1221 log_init(__progname
, log_level
, log_facility
, log_stderr
);
1223 while (!skipargs
&& (ch
= getopt(argc
, argv
, "C:f:l:che")) != -1) {
1227 * Ignore all arguments if we are invoked as a
1228 * shell using "sftp-server -c command"
1236 log_level
= log_level_number(optarg
);
1237 if (log_level
== SYSLOG_LEVEL_NOT_SET
)
1238 error("Invalid log level \"%s\"", optarg
);
1241 log_facility
= log_facility_number(optarg
);
1242 if (log_level
== SYSLOG_FACILITY_NOT_SET
)
1243 error("Invalid log facility \"%s\"", optarg
);
1251 log_init(__progname
, log_level
, log_facility
, log_stderr
);
1253 if ((cp
= getenv("SSH_CONNECTION")) != NULL
) {
1254 client_addr
= xstrdup(cp
);
1255 if ((cp
= strchr(client_addr
, ' ')) == NULL
)
1256 fatal("Malformed SSH_CONNECTION variable: \"%s\"",
1257 getenv("SSH_CONNECTION"));
1260 client_addr
= xstrdup("UNKNOWN");
1262 if ((pw
= getpwuid(getuid())) == NULL
)
1263 fatal("No user found for uid %lu", (u_long
)getuid());
1266 logit("session opened for local user %s from [%s]",
1267 pw
->pw_name
, client_addr
);
1271 in
= dup(STDIN_FILENO
);
1272 out
= dup(STDOUT_FILENO
);
1275 setmode(in
, O_BINARY
);
1276 setmode(out
, O_BINARY
);
1285 buffer_init(&iqueue
);
1286 buffer_init(&oqueue
);
1288 set_size
= howmany(max
+ 1, NFDBITS
) * sizeof(fd_mask
);
1289 rset
= (fd_set
*)xmalloc(set_size
);
1290 wset
= (fd_set
*)xmalloc(set_size
);
1293 memset(rset
, 0, set_size
);
1294 memset(wset
, 0, set_size
);
1297 olen
= buffer_len(&oqueue
);
1301 if (select(max
+1, rset
, wset
, NULL
, NULL
) < 0) {
1304 error("select: %s", strerror(errno
));
1308 /* copy stdin to iqueue */
1309 if (FD_ISSET(in
, rset
)) {
1311 len
= read(in
, buf
, sizeof buf
);
1315 } else if (len
< 0) {
1316 error("read: %s", strerror(errno
));
1319 buffer_append(&iqueue
, buf
, len
);
1322 /* send oqueue to stdout */
1323 if (FD_ISSET(out
, wset
)) {
1324 len
= write(out
, buffer_ptr(&oqueue
), olen
);
1326 error("write: %s", strerror(errno
));
1329 buffer_consume(&oqueue
, len
);
1332 /* process requests from client */