1 /* $OpenBSD: sftp-server.c,v 1.109 2016/02/15 09:47:49 dtucker 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/param.h> /* MIN */
21 #include <sys/types.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>
53 #include "sftp-common.h"
56 static LogLevel log_level
= SYSLOG_LEVEL_ERROR
;
59 static struct passwd
*pw
= NULL
;
60 static char *client_addr
= NULL
;
62 /* input and output queue */
63 struct sshbuf
*iqueue
;
64 struct sshbuf
*oqueue
;
66 /* Version of client */
69 /* SSH2_FXP_INIT received */
75 /* Requests that are allowed/denied */
76 static char *request_whitelist
, *request_blacklist
;
78 /* portable attributes, etc. */
79 typedef struct Stat Stat
;
88 static void process_open(u_int32_t id
);
89 static void process_close(u_int32_t id
);
90 static void process_read(u_int32_t id
);
91 static void process_write(u_int32_t id
);
92 static void process_stat(u_int32_t id
);
93 static void process_lstat(u_int32_t id
);
94 static void process_fstat(u_int32_t id
);
95 static void process_setstat(u_int32_t id
);
96 static void process_fsetstat(u_int32_t id
);
97 static void process_opendir(u_int32_t id
);
98 static void process_readdir(u_int32_t id
);
99 static void process_remove(u_int32_t id
);
100 static void process_mkdir(u_int32_t id
);
101 static void process_rmdir(u_int32_t id
);
102 static void process_realpath(u_int32_t id
);
103 static void process_rename(u_int32_t id
);
104 static void process_readlink(u_int32_t id
);
105 static void process_symlink(u_int32_t id
);
106 static void process_extended_posix_rename(u_int32_t id
);
107 static void process_extended_statvfs(u_int32_t id
);
108 static void process_extended_fstatvfs(u_int32_t id
);
109 static void process_extended_hardlink(u_int32_t id
);
110 static void process_extended_fsync(u_int32_t id
);
111 static void process_extended(u_int32_t id
);
113 struct sftp_handler
{
114 const char *name
; /* user-visible name for fine-grained perms */
115 const char *ext_name
; /* extended request name */
116 u_int type
; /* packet type, for non extended packets */
117 void (*handler
)(u_int32_t
);
118 int does_write
; /* if nonzero, banned for readonly mode */
121 struct sftp_handler handlers
[] = {
122 /* NB. SSH2_FXP_OPEN does the readonly check in the handler itself */
123 { "open", NULL
, SSH2_FXP_OPEN
, process_open
, 0 },
124 { "close", NULL
, SSH2_FXP_CLOSE
, process_close
, 0 },
125 { "read", NULL
, SSH2_FXP_READ
, process_read
, 0 },
126 { "write", NULL
, SSH2_FXP_WRITE
, process_write
, 1 },
127 { "lstat", NULL
, SSH2_FXP_LSTAT
, process_lstat
, 0 },
128 { "fstat", NULL
, SSH2_FXP_FSTAT
, process_fstat
, 0 },
129 { "setstat", NULL
, SSH2_FXP_SETSTAT
, process_setstat
, 1 },
130 { "fsetstat", NULL
, SSH2_FXP_FSETSTAT
, process_fsetstat
, 1 },
131 { "opendir", NULL
, SSH2_FXP_OPENDIR
, process_opendir
, 0 },
132 { "readdir", NULL
, SSH2_FXP_READDIR
, process_readdir
, 0 },
133 { "remove", NULL
, SSH2_FXP_REMOVE
, process_remove
, 1 },
134 { "mkdir", NULL
, SSH2_FXP_MKDIR
, process_mkdir
, 1 },
135 { "rmdir", NULL
, SSH2_FXP_RMDIR
, process_rmdir
, 1 },
136 { "realpath", NULL
, SSH2_FXP_REALPATH
, process_realpath
, 0 },
137 { "stat", NULL
, SSH2_FXP_STAT
, process_stat
, 0 },
138 { "rename", NULL
, SSH2_FXP_RENAME
, process_rename
, 1 },
139 { "readlink", NULL
, SSH2_FXP_READLINK
, process_readlink
, 0 },
140 { "symlink", NULL
, SSH2_FXP_SYMLINK
, process_symlink
, 1 },
141 { NULL
, NULL
, 0, NULL
, 0 }
144 /* SSH2_FXP_EXTENDED submessages */
145 struct sftp_handler extended_handlers
[] = {
146 { "posix-rename", "posix-rename@openssh.com", 0,
147 process_extended_posix_rename
, 1 },
148 { "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs
, 0 },
149 { "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs
, 0 },
150 { "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink
, 1 },
151 { "fsync", "fsync@openssh.com", 0, process_extended_fsync
, 1 },
152 { NULL
, NULL
, 0, NULL
, 0 }
156 request_permitted(struct sftp_handler
*h
)
160 if (readonly
&& h
->does_write
) {
161 verbose("Refusing %s request in read-only mode", h
->name
);
164 if (request_blacklist
!= NULL
&&
165 ((result
= match_list(h
->name
, request_blacklist
, NULL
))) != NULL
) {
167 verbose("Refusing blacklisted %s request", h
->name
);
170 if (request_whitelist
!= NULL
&&
171 ((result
= match_list(h
->name
, request_whitelist
, NULL
))) != NULL
) {
173 debug2("Permitting whitelisted %s request", h
->name
);
176 if (request_whitelist
!= NULL
) {
177 verbose("Refusing non-whitelisted %s request", h
->name
);
184 errno_to_portable(int unixerrno
)
196 ret
= SSH2_FX_NO_SUCH_FILE
;
201 ret
= SSH2_FX_PERMISSION_DENIED
;
205 ret
= SSH2_FX_BAD_MESSAGE
;
208 ret
= SSH2_FX_OP_UNSUPPORTED
;
211 ret
= SSH2_FX_FAILURE
;
218 flags_from_portable(int pflags
)
222 if ((pflags
& SSH2_FXF_READ
) &&
223 (pflags
& SSH2_FXF_WRITE
)) {
225 } else if (pflags
& SSH2_FXF_READ
) {
227 } else if (pflags
& SSH2_FXF_WRITE
) {
230 if (pflags
& SSH2_FXF_APPEND
)
232 if (pflags
& SSH2_FXF_CREAT
)
234 if (pflags
& SSH2_FXF_TRUNC
)
236 if (pflags
& SSH2_FXF_EXCL
)
242 string_from_portable(int pflags
)
244 static char ret
[128];
248 #define PAPPEND(str) { \
250 strlcat(ret, ",", sizeof(ret)); \
251 strlcat(ret, str, sizeof(ret)); \
254 if (pflags
& SSH2_FXF_READ
)
256 if (pflags
& SSH2_FXF_WRITE
)
258 if (pflags
& SSH2_FXF_APPEND
)
260 if (pflags
& SSH2_FXF_CREAT
)
262 if (pflags
& SSH2_FXF_TRUNC
)
264 if (pflags
& SSH2_FXF_EXCL
)
272 typedef struct Handle Handle
;
279 u_int64_t bytes_read
, bytes_write
;
289 Handle
*handles
= NULL
;
290 u_int num_handles
= 0;
291 int first_unused_handle
= -1;
293 static void handle_unused(int i
)
295 handles
[i
].use
= HANDLE_UNUSED
;
296 handles
[i
].next_unused
= first_unused_handle
;
297 first_unused_handle
= i
;
301 handle_new(int use
, const char *name
, int fd
, int flags
, DIR *dirp
)
305 if (first_unused_handle
== -1) {
306 if (num_handles
+ 1 <= num_handles
)
309 handles
= xreallocarray(handles
, num_handles
, sizeof(Handle
));
310 handle_unused(num_handles
- 1);
313 i
= first_unused_handle
;
314 first_unused_handle
= handles
[i
].next_unused
;
316 handles
[i
].use
= use
;
317 handles
[i
].dirp
= dirp
;
319 handles
[i
].flags
= flags
;
320 handles
[i
].name
= xstrdup(name
);
321 handles
[i
].bytes_read
= handles
[i
].bytes_write
= 0;
327 handle_is_ok(int i
, int type
)
329 return i
>= 0 && (u_int
)i
< num_handles
&& handles
[i
].use
== type
;
333 handle_to_string(int handle
, u_char
**stringp
, int *hlenp
)
335 if (stringp
== NULL
|| hlenp
== NULL
)
337 *stringp
= xmalloc(sizeof(int32_t));
338 put_u32(*stringp
, handle
);
339 *hlenp
= sizeof(int32_t);
344 handle_from_string(const u_char
*handle
, u_int hlen
)
348 if (hlen
!= sizeof(int32_t))
350 val
= get_u32(handle
);
351 if (handle_is_ok(val
, HANDLE_FILE
) ||
352 handle_is_ok(val
, HANDLE_DIR
))
358 handle_to_name(int handle
)
360 if (handle_is_ok(handle
, HANDLE_DIR
)||
361 handle_is_ok(handle
, HANDLE_FILE
))
362 return handles
[handle
].name
;
367 handle_to_dir(int handle
)
369 if (handle_is_ok(handle
, HANDLE_DIR
))
370 return handles
[handle
].dirp
;
375 handle_to_fd(int handle
)
377 if (handle_is_ok(handle
, HANDLE_FILE
))
378 return handles
[handle
].fd
;
383 handle_to_flags(int handle
)
385 if (handle_is_ok(handle
, HANDLE_FILE
))
386 return handles
[handle
].flags
;
391 handle_update_read(int handle
, ssize_t bytes
)
393 if (handle_is_ok(handle
, HANDLE_FILE
) && bytes
> 0)
394 handles
[handle
].bytes_read
+= bytes
;
398 handle_update_write(int handle
, ssize_t bytes
)
400 if (handle_is_ok(handle
, HANDLE_FILE
) && bytes
> 0)
401 handles
[handle
].bytes_write
+= bytes
;
405 handle_bytes_read(int handle
)
407 if (handle_is_ok(handle
, HANDLE_FILE
))
408 return (handles
[handle
].bytes_read
);
413 handle_bytes_write(int handle
)
415 if (handle_is_ok(handle
, HANDLE_FILE
))
416 return (handles
[handle
].bytes_write
);
421 handle_close(int handle
)
425 if (handle_is_ok(handle
, HANDLE_FILE
)) {
426 ret
= close(handles
[handle
].fd
);
427 free(handles
[handle
].name
);
428 handle_unused(handle
);
429 } else if (handle_is_ok(handle
, HANDLE_DIR
)) {
430 ret
= closedir(handles
[handle
].dirp
);
431 free(handles
[handle
].name
);
432 handle_unused(handle
);
440 handle_log_close(int handle
, char *emsg
)
442 if (handle_is_ok(handle
, HANDLE_FILE
)) {
443 logit("%s%sclose \"%s\" bytes read %llu written %llu",
444 emsg
== NULL
? "" : emsg
, emsg
== NULL
? "" : " ",
445 handle_to_name(handle
),
446 (unsigned long long)handle_bytes_read(handle
),
447 (unsigned long long)handle_bytes_write(handle
));
449 logit("%s%sclosedir \"%s\"",
450 emsg
== NULL
? "" : emsg
, emsg
== NULL
? "" : " ",
451 handle_to_name(handle
));
456 handle_log_exit(void)
460 for (i
= 0; i
< num_handles
; i
++)
461 if (handles
[i
].use
!= HANDLE_UNUSED
)
462 handle_log_close(i
, "forced");
466 get_handle(struct sshbuf
*queue
, int *hp
)
473 if ((r
= sshbuf_get_string(queue
, &handle
, &hlen
)) != 0)
476 *hp
= handle_from_string(handle
, hlen
);
484 send_msg(struct sshbuf
*m
)
488 if ((r
= sshbuf_put_stringb(oqueue
, m
)) != 0)
489 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
494 status_to_message(u_int32_t status
)
496 const char *status_messages
[] = {
497 "Success", /* SSH_FX_OK */
498 "End of file", /* SSH_FX_EOF */
499 "No such file", /* SSH_FX_NO_SUCH_FILE */
500 "Permission denied", /* SSH_FX_PERMISSION_DENIED */
501 "Failure", /* SSH_FX_FAILURE */
502 "Bad message", /* SSH_FX_BAD_MESSAGE */
503 "No connection", /* SSH_FX_NO_CONNECTION */
504 "Connection lost", /* SSH_FX_CONNECTION_LOST */
505 "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
506 "Unknown error" /* Others */
508 return (status_messages
[MIN(status
,SSH2_FX_MAX
)]);
512 send_status(u_int32_t id
, u_int32_t status
)
517 debug3("request %u: sent status %u", id
, status
);
518 if (log_level
> SYSLOG_LEVEL_VERBOSE
||
519 (status
!= SSH2_FX_OK
&& status
!= SSH2_FX_EOF
))
520 logit("sent status %s", status_to_message(status
));
521 if ((msg
= sshbuf_new()) == NULL
)
522 fatal("%s: sshbuf_new failed", __func__
);
523 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_STATUS
)) != 0 ||
524 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
525 (r
= sshbuf_put_u32(msg
, status
)) != 0)
526 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
528 if ((r
= sshbuf_put_cstring(msg
,
529 status_to_message(status
))) != 0 ||
530 (r
= sshbuf_put_cstring(msg
, "")) != 0)
531 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
537 send_data_or_handle(char type
, u_int32_t id
, const u_char
*data
, int dlen
)
542 if ((msg
= sshbuf_new()) == NULL
)
543 fatal("%s: sshbuf_new failed", __func__
);
544 if ((r
= sshbuf_put_u8(msg
, type
)) != 0 ||
545 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
546 (r
= sshbuf_put_string(msg
, data
, dlen
)) != 0)
547 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
553 send_data(u_int32_t id
, const u_char
*data
, int dlen
)
555 debug("request %u: sent data len %d", id
, dlen
);
556 send_data_or_handle(SSH2_FXP_DATA
, id
, data
, dlen
);
560 send_handle(u_int32_t id
, int handle
)
565 handle_to_string(handle
, &string
, &hlen
);
566 debug("request %u: sent handle handle %d", id
, handle
);
567 send_data_or_handle(SSH2_FXP_HANDLE
, id
, string
, hlen
);
572 send_names(u_int32_t id
, int count
, const Stat
*stats
)
577 if ((msg
= sshbuf_new()) == NULL
)
578 fatal("%s: sshbuf_new failed", __func__
);
579 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_NAME
)) != 0 ||
580 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
581 (r
= sshbuf_put_u32(msg
, count
)) != 0)
582 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
583 debug("request %u: sent names count %d", id
, count
);
584 for (i
= 0; i
< count
; i
++) {
585 if ((r
= sshbuf_put_cstring(msg
, stats
[i
].name
)) != 0 ||
586 (r
= sshbuf_put_cstring(msg
, stats
[i
].long_name
)) != 0 ||
587 (r
= encode_attrib(msg
, &stats
[i
].attrib
)) != 0)
588 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
595 send_attrib(u_int32_t id
, const Attrib
*a
)
600 debug("request %u: sent attrib have 0x%x", id
, a
->flags
);
601 if ((msg
= sshbuf_new()) == NULL
)
602 fatal("%s: sshbuf_new failed", __func__
);
603 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_ATTRS
)) != 0 ||
604 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
605 (r
= encode_attrib(msg
, a
)) != 0)
606 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
612 send_statvfs(u_int32_t id
, struct statvfs
*st
)
618 flag
= (st
->f_flag
& ST_RDONLY
) ? SSH2_FXE_STATVFS_ST_RDONLY
: 0;
619 flag
|= (st
->f_flag
& ST_NOSUID
) ? SSH2_FXE_STATVFS_ST_NOSUID
: 0;
621 if ((msg
= sshbuf_new()) == NULL
)
622 fatal("%s: sshbuf_new failed", __func__
);
623 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_EXTENDED_REPLY
)) != 0 ||
624 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
625 (r
= sshbuf_put_u64(msg
, st
->f_bsize
)) != 0 ||
626 (r
= sshbuf_put_u64(msg
, st
->f_frsize
)) != 0 ||
627 (r
= sshbuf_put_u64(msg
, st
->f_blocks
)) != 0 ||
628 (r
= sshbuf_put_u64(msg
, st
->f_bfree
)) != 0 ||
629 (r
= sshbuf_put_u64(msg
, st
->f_bavail
)) != 0 ||
630 (r
= sshbuf_put_u64(msg
, st
->f_files
)) != 0 ||
631 (r
= sshbuf_put_u64(msg
, st
->f_ffree
)) != 0 ||
632 (r
= sshbuf_put_u64(msg
, st
->f_favail
)) != 0 ||
633 (r
= sshbuf_put_u64(msg
, FSID_TO_ULONG(st
->f_fsid
))) != 0 ||
634 (r
= sshbuf_put_u64(msg
, flag
)) != 0 ||
635 (r
= sshbuf_put_u64(msg
, st
->f_namemax
)) != 0)
636 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
649 if ((r
= sshbuf_get_u32(iqueue
, &version
)) != 0)
650 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
651 verbose("received client version %u", version
);
652 if ((msg
= sshbuf_new()) == NULL
)
653 fatal("%s: sshbuf_new failed", __func__
);
654 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_VERSION
)) != 0 ||
655 (r
= sshbuf_put_u32(msg
, SSH2_FILEXFER_VERSION
)) != 0 ||
656 /* POSIX rename extension */
657 (r
= sshbuf_put_cstring(msg
, "posix-rename@openssh.com")) != 0 ||
658 (r
= sshbuf_put_cstring(msg
, "1")) != 0 || /* version */
659 /* statvfs extension */
660 (r
= sshbuf_put_cstring(msg
, "statvfs@openssh.com")) != 0 ||
661 (r
= sshbuf_put_cstring(msg
, "2")) != 0 || /* version */
662 /* fstatvfs extension */
663 (r
= sshbuf_put_cstring(msg
, "fstatvfs@openssh.com")) != 0 ||
664 (r
= sshbuf_put_cstring(msg
, "2")) != 0 || /* version */
665 /* hardlink extension */
666 (r
= sshbuf_put_cstring(msg
, "hardlink@openssh.com")) != 0 ||
667 (r
= sshbuf_put_cstring(msg
, "1")) != 0 || /* version */
668 /* fsync extension */
669 (r
= sshbuf_put_cstring(msg
, "fsync@openssh.com")) != 0 ||
670 (r
= sshbuf_put_cstring(msg
, "1")) != 0) /* version */
671 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
677 process_open(u_int32_t id
)
682 int r
, handle
, fd
, flags
, mode
, status
= SSH2_FX_FAILURE
;
684 if ((r
= sshbuf_get_cstring(iqueue
, &name
, NULL
)) != 0 ||
685 (r
= sshbuf_get_u32(iqueue
, &pflags
)) != 0 || /* portable flags */
686 (r
= decode_attrib(iqueue
, &a
)) != 0)
687 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
689 debug3("request %u: open flags %d", id
, pflags
);
690 flags
= flags_from_portable(pflags
);
691 mode
= (a
.flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) ? a
.perm
: 0666;
692 logit("open \"%s\" flags %s mode 0%o",
693 name
, string_from_portable(pflags
), mode
);
695 ((flags
& O_ACCMODE
) == O_WRONLY
||
696 (flags
& O_ACCMODE
) == O_RDWR
)) {
697 verbose("Refusing open request in read-only mode");
698 status
= SSH2_FX_PERMISSION_DENIED
;
700 fd
= open(name
, flags
, mode
);
702 status
= errno_to_portable(errno
);
704 handle
= handle_new(HANDLE_FILE
, name
, fd
, flags
, NULL
);
708 send_handle(id
, handle
);
713 if (status
!= SSH2_FX_OK
)
714 send_status(id
, status
);
719 process_close(u_int32_t id
)
721 int r
, handle
, ret
, status
= SSH2_FX_FAILURE
;
723 if ((r
= get_handle(iqueue
, &handle
)) != 0)
724 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
726 debug3("request %u: close handle %u", id
, handle
);
727 handle_log_close(handle
, NULL
);
728 ret
= handle_close(handle
);
729 status
= (ret
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
730 send_status(id
, status
);
734 process_read(u_int32_t id
)
738 int r
, handle
, fd
, ret
, status
= SSH2_FX_FAILURE
;
741 if ((r
= get_handle(iqueue
, &handle
)) != 0 ||
742 (r
= sshbuf_get_u64(iqueue
, &off
)) != 0 ||
743 (r
= sshbuf_get_u32(iqueue
, &len
)) != 0)
744 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
746 debug("request %u: read \"%s\" (handle %d) off %llu len %d",
747 id
, handle_to_name(handle
), handle
, (unsigned long long)off
, len
);
748 if (len
> sizeof buf
) {
750 debug2("read change len %d", len
);
752 fd
= handle_to_fd(handle
);
754 if (lseek(fd
, off
, SEEK_SET
) < 0) {
755 error("process_read: seek failed");
756 status
= errno_to_portable(errno
);
758 ret
= read(fd
, buf
, len
);
760 status
= errno_to_portable(errno
);
761 } else if (ret
== 0) {
762 status
= SSH2_FX_EOF
;
764 send_data(id
, buf
, ret
);
766 handle_update_read(handle
, ret
);
770 if (status
!= SSH2_FX_OK
)
771 send_status(id
, status
);
775 process_write(u_int32_t id
)
779 int r
, handle
, fd
, ret
, status
;
782 if ((r
= get_handle(iqueue
, &handle
)) != 0 ||
783 (r
= sshbuf_get_u64(iqueue
, &off
)) != 0 ||
784 (r
= sshbuf_get_string(iqueue
, &data
, &len
)) != 0)
785 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
787 debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
788 id
, handle_to_name(handle
), handle
, (unsigned long long)off
, len
);
789 fd
= handle_to_fd(handle
);
792 status
= SSH2_FX_FAILURE
;
794 if (!(handle_to_flags(handle
) & O_APPEND
) &&
795 lseek(fd
, off
, SEEK_SET
) < 0) {
796 status
= errno_to_portable(errno
);
797 error("process_write: seek failed");
800 ret
= write(fd
, data
, len
);
802 error("process_write: write failed");
803 status
= errno_to_portable(errno
);
804 } else if ((size_t)ret
== len
) {
806 handle_update_write(handle
, ret
);
808 debug2("nothing at all written");
809 status
= SSH2_FX_FAILURE
;
813 send_status(id
, status
);
818 process_do_stat(u_int32_t id
, int do_lstat
)
823 int r
, status
= SSH2_FX_FAILURE
;
825 if ((r
= sshbuf_get_cstring(iqueue
, &name
, NULL
)) != 0)
826 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
828 debug3("request %u: %sstat", id
, do_lstat
? "l" : "");
829 verbose("%sstat name \"%s\"", do_lstat
? "l" : "", name
);
830 r
= do_lstat
? lstat(name
, &st
) : stat(name
, &st
);
832 status
= errno_to_portable(errno
);
834 stat_to_attrib(&st
, &a
);
838 if (status
!= SSH2_FX_OK
)
839 send_status(id
, status
);
844 process_stat(u_int32_t id
)
846 process_do_stat(id
, 0);
850 process_lstat(u_int32_t id
)
852 process_do_stat(id
, 1);
856 process_fstat(u_int32_t id
)
860 int fd
, r
, handle
, status
= SSH2_FX_FAILURE
;
862 if ((r
= get_handle(iqueue
, &handle
)) != 0)
863 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
864 debug("request %u: fstat \"%s\" (handle %u)",
865 id
, handle_to_name(handle
), handle
);
866 fd
= handle_to_fd(handle
);
870 status
= errno_to_portable(errno
);
872 stat_to_attrib(&st
, &a
);
877 if (status
!= SSH2_FX_OK
)
878 send_status(id
, status
);
881 static struct timeval
*
882 attrib_to_tv(const Attrib
*a
)
884 static struct timeval tv
[2];
886 tv
[0].tv_sec
= a
->atime
;
888 tv
[1].tv_sec
= a
->mtime
;
894 process_setstat(u_int32_t id
)
898 int r
, status
= SSH2_FX_OK
;
900 if ((r
= sshbuf_get_cstring(iqueue
, &name
, NULL
)) != 0 ||
901 (r
= decode_attrib(iqueue
, &a
)) != 0)
902 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
904 debug("request %u: setstat name \"%s\"", id
, name
);
905 if (a
.flags
& SSH2_FILEXFER_ATTR_SIZE
) {
906 logit("set \"%s\" size %llu",
907 name
, (unsigned long long)a
.size
);
908 r
= truncate(name
, a
.size
);
910 status
= errno_to_portable(errno
);
912 if (a
.flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) {
913 logit("set \"%s\" mode %04o", name
, a
.perm
);
914 r
= chmod(name
, a
.perm
& 07777);
916 status
= errno_to_portable(errno
);
918 if (a
.flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
922 strftime(buf
, sizeof(buf
), "%Y%m%d-%H:%M:%S",
924 logit("set \"%s\" modtime %s", name
, buf
);
925 r
= utimes(name
, attrib_to_tv(&a
));
927 status
= errno_to_portable(errno
);
929 if (a
.flags
& SSH2_FILEXFER_ATTR_UIDGID
) {
930 logit("set \"%s\" owner %lu group %lu", name
,
931 (u_long
)a
.uid
, (u_long
)a
.gid
);
932 r
= chown(name
, a
.uid
, a
.gid
);
934 status
= errno_to_portable(errno
);
936 send_status(id
, status
);
941 process_fsetstat(u_int32_t id
)
945 int status
= SSH2_FX_OK
;
947 if ((r
= get_handle(iqueue
, &handle
)) != 0 ||
948 (r
= decode_attrib(iqueue
, &a
)) != 0)
949 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
951 debug("request %u: fsetstat handle %d", id
, handle
);
952 fd
= handle_to_fd(handle
);
954 status
= SSH2_FX_FAILURE
;
956 char *name
= handle_to_name(handle
);
958 if (a
.flags
& SSH2_FILEXFER_ATTR_SIZE
) {
959 logit("set \"%s\" size %llu",
960 name
, (unsigned long long)a
.size
);
961 r
= ftruncate(fd
, a
.size
);
963 status
= errno_to_portable(errno
);
965 if (a
.flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) {
966 logit("set \"%s\" mode %04o", name
, a
.perm
);
968 r
= fchmod(fd
, a
.perm
& 07777);
970 r
= chmod(name
, a
.perm
& 07777);
973 status
= errno_to_portable(errno
);
975 if (a
.flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
979 strftime(buf
, sizeof(buf
), "%Y%m%d-%H:%M:%S",
981 logit("set \"%s\" modtime %s", name
, buf
);
983 r
= futimes(fd
, attrib_to_tv(&a
));
985 r
= utimes(name
, attrib_to_tv(&a
));
988 status
= errno_to_portable(errno
);
990 if (a
.flags
& SSH2_FILEXFER_ATTR_UIDGID
) {
991 logit("set \"%s\" owner %lu group %lu", name
,
992 (u_long
)a
.uid
, (u_long
)a
.gid
);
994 r
= fchown(fd
, a
.uid
, a
.gid
);
996 r
= chown(name
, a
.uid
, a
.gid
);
999 status
= errno_to_portable(errno
);
1002 send_status(id
, status
);
1006 process_opendir(u_int32_t id
)
1010 int r
, handle
, status
= SSH2_FX_FAILURE
;
1012 if ((r
= sshbuf_get_cstring(iqueue
, &path
, NULL
)) != 0)
1013 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1015 debug3("request %u: opendir", id
);
1016 logit("opendir \"%s\"", path
);
1017 dirp
= opendir(path
);
1019 status
= errno_to_portable(errno
);
1021 handle
= handle_new(HANDLE_DIR
, path
, 0, 0, dirp
);
1025 send_handle(id
, handle
);
1026 status
= SSH2_FX_OK
;
1030 if (status
!= SSH2_FX_OK
)
1031 send_status(id
, status
);
1036 process_readdir(u_int32_t id
)
1043 if ((r
= get_handle(iqueue
, &handle
)) != 0)
1044 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1046 debug("request %u: readdir \"%s\" (handle %d)", id
,
1047 handle_to_name(handle
), handle
);
1048 dirp
= handle_to_dir(handle
);
1049 path
= handle_to_name(handle
);
1050 if (dirp
== NULL
|| path
== NULL
) {
1051 send_status(id
, SSH2_FX_FAILURE
);
1054 char pathname
[PATH_MAX
];
1056 int nstats
= 10, count
= 0, i
;
1058 stats
= xcalloc(nstats
, sizeof(Stat
));
1059 while ((dp
= readdir(dirp
)) != NULL
) {
1060 if (count
>= nstats
) {
1062 stats
= xreallocarray(stats
, nstats
, sizeof(Stat
));
1064 /* XXX OVERFLOW ? */
1065 snprintf(pathname
, sizeof pathname
, "%s%s%s", path
,
1066 strcmp(path
, "/") ? "/" : "", dp
->d_name
);
1067 if (lstat(pathname
, &st
) < 0)
1069 stat_to_attrib(&st
, &(stats
[count
].attrib
));
1070 stats
[count
].name
= xstrdup(dp
->d_name
);
1071 stats
[count
].long_name
= ls_file(dp
->d_name
, &st
, 0, 0);
1073 /* send up to 100 entries in one message */
1074 /* XXX check packet size instead */
1079 send_names(id
, count
, stats
);
1080 for (i
= 0; i
< count
; i
++) {
1081 free(stats
[i
].name
);
1082 free(stats
[i
].long_name
);
1085 send_status(id
, SSH2_FX_EOF
);
1092 process_remove(u_int32_t id
)
1095 int r
, status
= SSH2_FX_FAILURE
;
1097 if ((r
= sshbuf_get_cstring(iqueue
, &name
, NULL
)) != 0)
1098 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1100 debug3("request %u: remove", id
);
1101 logit("remove name \"%s\"", name
);
1103 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1104 send_status(id
, status
);
1109 process_mkdir(u_int32_t id
)
1113 int r
, mode
, status
= SSH2_FX_FAILURE
;
1115 if ((r
= sshbuf_get_cstring(iqueue
, &name
, NULL
)) != 0 ||
1116 (r
= decode_attrib(iqueue
, &a
)) != 0)
1117 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1119 mode
= (a
.flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) ?
1120 a
.perm
& 07777 : 0777;
1121 debug3("request %u: mkdir", id
);
1122 logit("mkdir name \"%s\" mode 0%o", name
, mode
);
1123 r
= mkdir(name
, mode
);
1124 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1125 send_status(id
, status
);
1130 process_rmdir(u_int32_t id
)
1135 if ((r
= sshbuf_get_cstring(iqueue
, &name
, NULL
)) != 0)
1136 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1138 debug3("request %u: rmdir", id
);
1139 logit("rmdir name \"%s\"", name
);
1141 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1142 send_status(id
, status
);
1147 process_realpath(u_int32_t id
)
1149 char resolvedname
[PATH_MAX
];
1153 if ((r
= sshbuf_get_cstring(iqueue
, &path
, NULL
)) != 0)
1154 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1156 if (path
[0] == '\0') {
1158 path
= xstrdup(".");
1160 debug3("request %u: realpath", id
);
1161 verbose("realpath \"%s\"", path
);
1162 if (realpath(path
, resolvedname
) == NULL
) {
1163 send_status(id
, errno_to_portable(errno
));
1166 attrib_clear(&s
.attrib
);
1167 s
.name
= s
.long_name
= resolvedname
;
1168 send_names(id
, 1, &s
);
1174 process_rename(u_int32_t id
)
1176 char *oldpath
, *newpath
;
1180 if ((r
= sshbuf_get_cstring(iqueue
, &oldpath
, NULL
)) != 0 ||
1181 (r
= sshbuf_get_cstring(iqueue
, &newpath
, NULL
)) != 0)
1182 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1184 debug3("request %u: rename", id
);
1185 logit("rename old \"%s\" new \"%s\"", oldpath
, newpath
);
1186 status
= SSH2_FX_FAILURE
;
1187 if (lstat(oldpath
, &sb
) == -1)
1188 status
= errno_to_portable(errno
);
1189 else if (S_ISREG(sb
.st_mode
)) {
1190 /* Race-free rename of regular files */
1191 if (link(oldpath
, newpath
) == -1) {
1192 if (errno
== EOPNOTSUPP
|| errno
== ENOSYS
1196 #ifdef LINK_OPNOTSUPP_ERRNO
1197 || errno
== LINK_OPNOTSUPP_ERRNO
1203 * fs doesn't support links, so fall back to
1204 * stat+rename. This is racy.
1206 if (stat(newpath
, &st
) == -1) {
1207 if (rename(oldpath
, newpath
) == -1)
1209 errno_to_portable(errno
);
1211 status
= SSH2_FX_OK
;
1214 status
= errno_to_portable(errno
);
1216 } else if (unlink(oldpath
) == -1) {
1217 status
= errno_to_portable(errno
);
1218 /* clean spare link */
1221 status
= SSH2_FX_OK
;
1222 } else if (stat(newpath
, &sb
) == -1) {
1223 if (rename(oldpath
, newpath
) == -1)
1224 status
= errno_to_portable(errno
);
1226 status
= SSH2_FX_OK
;
1228 send_status(id
, status
);
1234 process_readlink(u_int32_t id
)
1240 if ((r
= sshbuf_get_cstring(iqueue
, &path
, NULL
)) != 0)
1241 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1243 debug3("request %u: readlink", id
);
1244 verbose("readlink \"%s\"", path
);
1245 if ((len
= readlink(path
, buf
, sizeof(buf
) - 1)) == -1)
1246 send_status(id
, errno_to_portable(errno
));
1251 attrib_clear(&s
.attrib
);
1252 s
.name
= s
.long_name
= buf
;
1253 send_names(id
, 1, &s
);
1259 process_symlink(u_int32_t id
)
1261 char *oldpath
, *newpath
;
1264 if ((r
= sshbuf_get_cstring(iqueue
, &oldpath
, NULL
)) != 0 ||
1265 (r
= sshbuf_get_cstring(iqueue
, &newpath
, NULL
)) != 0)
1266 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1268 debug3("request %u: symlink", id
);
1269 logit("symlink old \"%s\" new \"%s\"", oldpath
, newpath
);
1270 /* this will fail if 'newpath' exists */
1271 r
= symlink(oldpath
, newpath
);
1272 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1273 send_status(id
, status
);
1279 process_extended_posix_rename(u_int32_t id
)
1281 char *oldpath
, *newpath
;
1284 if ((r
= sshbuf_get_cstring(iqueue
, &oldpath
, NULL
)) != 0 ||
1285 (r
= sshbuf_get_cstring(iqueue
, &newpath
, NULL
)) != 0)
1286 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1288 debug3("request %u: posix-rename", id
);
1289 logit("posix-rename old \"%s\" new \"%s\"", oldpath
, newpath
);
1290 r
= rename(oldpath
, newpath
);
1291 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1292 send_status(id
, status
);
1298 process_extended_statvfs(u_int32_t id
)
1304 if ((r
= sshbuf_get_cstring(iqueue
, &path
, NULL
)) != 0)
1305 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1306 debug3("request %u: statvfs", id
);
1307 logit("statvfs \"%s\"", path
);
1309 if (statvfs(path
, &st
) != 0)
1310 send_status(id
, errno_to_portable(errno
));
1312 send_statvfs(id
, &st
);
1317 process_extended_fstatvfs(u_int32_t id
)
1322 if ((r
= get_handle(iqueue
, &handle
)) != 0)
1323 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1324 debug("request %u: fstatvfs \"%s\" (handle %u)",
1325 id
, handle_to_name(handle
), handle
);
1326 if ((fd
= handle_to_fd(handle
)) < 0) {
1327 send_status(id
, SSH2_FX_FAILURE
);
1330 if (fstatvfs(fd
, &st
) != 0)
1331 send_status(id
, errno_to_portable(errno
));
1333 send_statvfs(id
, &st
);
1337 process_extended_hardlink(u_int32_t id
)
1339 char *oldpath
, *newpath
;
1342 if ((r
= sshbuf_get_cstring(iqueue
, &oldpath
, NULL
)) != 0 ||
1343 (r
= sshbuf_get_cstring(iqueue
, &newpath
, NULL
)) != 0)
1344 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1346 debug3("request %u: hardlink", id
);
1347 logit("hardlink old \"%s\" new \"%s\"", oldpath
, newpath
);
1348 r
= link(oldpath
, newpath
);
1349 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1350 send_status(id
, status
);
1356 process_extended_fsync(u_int32_t id
)
1358 int handle
, fd
, r
, status
= SSH2_FX_OP_UNSUPPORTED
;
1360 if ((r
= get_handle(iqueue
, &handle
)) != 0)
1361 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1362 debug3("request %u: fsync (handle %u)", id
, handle
);
1363 verbose("fsync \"%s\"", handle_to_name(handle
));
1364 if ((fd
= handle_to_fd(handle
)) < 0)
1365 status
= SSH2_FX_NO_SUCH_FILE
;
1366 else if (handle_is_ok(handle
, HANDLE_FILE
)) {
1368 status
= (r
== -1) ? errno_to_portable(errno
) : SSH2_FX_OK
;
1370 send_status(id
, status
);
1374 process_extended(u_int32_t id
)
1379 if ((r
= sshbuf_get_cstring(iqueue
, &request
, NULL
)) != 0)
1380 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1381 for (i
= 0; extended_handlers
[i
].handler
!= NULL
; i
++) {
1382 if (strcmp(request
, extended_handlers
[i
].ext_name
) == 0) {
1383 if (!request_permitted(&extended_handlers
[i
]))
1384 send_status(id
, SSH2_FX_PERMISSION_DENIED
);
1386 extended_handlers
[i
].handler(id
);
1390 if (extended_handlers
[i
].handler
== NULL
) {
1391 error("Unknown extended request \"%.100s\"", request
);
1392 send_status(id
, SSH2_FX_OP_UNSUPPORTED
); /* MUST */
1397 /* stolen from ssh-agent */
1410 buf_len
= sshbuf_len(iqueue
);
1412 return; /* Incomplete message. */
1413 cp
= sshbuf_ptr(iqueue
);
1414 msg_len
= get_u32(cp
);
1415 if (msg_len
> SFTP_MAX_MSG_LENGTH
) {
1416 error("bad message from %s local user %s",
1417 client_addr
, pw
->pw_name
);
1418 sftp_server_cleanup_exit(11);
1420 if (buf_len
< msg_len
+ 4)
1422 if ((r
= sshbuf_consume(iqueue
, 4)) != 0)
1423 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1425 if ((r
= sshbuf_get_u8(iqueue
, &type
)) != 0)
1426 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1433 case SSH2_FXP_EXTENDED
:
1435 fatal("Received extended request before init");
1436 if ((r
= sshbuf_get_u32(iqueue
, &id
)) != 0)
1437 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1438 process_extended(id
);
1442 fatal("Received %u request before init", type
);
1443 if ((r
= sshbuf_get_u32(iqueue
, &id
)) != 0)
1444 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1445 for (i
= 0; handlers
[i
].handler
!= NULL
; i
++) {
1446 if (type
== handlers
[i
].type
) {
1447 if (!request_permitted(&handlers
[i
])) {
1449 SSH2_FX_PERMISSION_DENIED
);
1451 handlers
[i
].handler(id
);
1456 if (handlers
[i
].handler
== NULL
)
1457 error("Unknown message %u", type
);
1459 /* discard the remaining bytes from the current packet */
1460 if (buf_len
< sshbuf_len(iqueue
)) {
1461 error("iqueue grew unexpectedly");
1462 sftp_server_cleanup_exit(255);
1464 consumed
= buf_len
- sshbuf_len(iqueue
);
1465 if (msg_len
< consumed
) {
1466 error("msg_len %u < consumed %u", msg_len
, consumed
);
1467 sftp_server_cleanup_exit(255);
1469 if (msg_len
> consumed
&&
1470 (r
= sshbuf_consume(iqueue
, msg_len
- consumed
)) != 0)
1471 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1474 /* Cleanup handler that logs active handles upon normal exit */
1476 sftp_server_cleanup_exit(int i
)
1478 if (pw
!= NULL
&& client_addr
!= NULL
) {
1480 logit("session closed for local user %s from [%s]",
1481 pw
->pw_name
, client_addr
);
1487 sftp_server_usage(void)
1489 extern char *__progname
;
1492 "usage: %s [-ehR] [-d start_directory] [-f log_facility] "
1493 "[-l log_level]\n\t[-P blacklisted_requests] "
1494 "[-p whitelisted_requests] [-u umask]\n"
1495 " %s -Q protocol_feature\n",
1496 __progname
, __progname
);
1501 sftp_server_main(int argc
, char **argv
, struct passwd
*user_pw
)
1503 fd_set
*rset
, *wset
;
1504 int i
, r
, in
, out
, max
, ch
, skipargs
= 0, log_stderr
= 0;
1505 ssize_t len
, olen
, set_size
;
1506 SyslogFacility log_facility
= SYSLOG_FACILITY_AUTH
;
1507 char *cp
, *homedir
= NULL
, buf
[4*4096];
1510 extern char *optarg
;
1511 extern char *__progname
;
1513 ssh_malloc_init(); /* must be called before any mallocs */
1514 __progname
= ssh_get_progname(argv
[0]);
1515 log_init(__progname
, log_level
, log_facility
, log_stderr
);
1517 pw
= pwcopy(user_pw
);
1519 while (!skipargs
&& (ch
= getopt(argc
, argv
,
1520 "d:f:l:P:p:Q:u:cehR")) != -1) {
1523 if (strcasecmp(optarg
, "requests") != 0) {
1524 fprintf(stderr
, "Invalid query type\n");
1527 for (i
= 0; handlers
[i
].handler
!= NULL
; i
++)
1528 printf("%s\n", handlers
[i
].name
);
1529 for (i
= 0; extended_handlers
[i
].handler
!= NULL
; i
++)
1530 printf("%s\n", extended_handlers
[i
].name
);
1538 * Ignore all arguments if we are invoked as a
1539 * shell using "sftp-server -c command"
1547 log_level
= log_level_number(optarg
);
1548 if (log_level
== SYSLOG_LEVEL_NOT_SET
)
1549 error("Invalid log level \"%s\"", optarg
);
1552 log_facility
= log_facility_number(optarg
);
1553 if (log_facility
== SYSLOG_FACILITY_NOT_SET
)
1554 error("Invalid log facility \"%s\"", optarg
);
1557 cp
= tilde_expand_filename(optarg
, user_pw
->pw_uid
);
1558 homedir
= percent_expand(cp
, "d", user_pw
->pw_dir
,
1559 "u", user_pw
->pw_name
, (char *)NULL
);
1563 if (request_whitelist
!= NULL
)
1564 fatal("Permitted requests already set");
1565 request_whitelist
= xstrdup(optarg
);
1568 if (request_blacklist
!= NULL
)
1569 fatal("Refused requests already set");
1570 request_blacklist
= xstrdup(optarg
);
1574 mask
= strtol(optarg
, &cp
, 8);
1575 if (mask
< 0 || mask
> 0777 || *cp
!= '\0' ||
1576 cp
== optarg
|| (mask
== 0 && errno
!= 0))
1577 fatal("Invalid umask \"%s\"", optarg
);
1578 (void)umask((mode_t
)mask
);
1582 sftp_server_usage();
1586 log_init(__progname
, log_level
, log_facility
, log_stderr
);
1589 * On platforms where we can, avoid making /proc/self/{mem,maps}
1590 * available to the user so that sftp access doesn't automatically
1591 * imply arbitrary code execution access that will break
1592 * restricted configurations.
1594 platform_disable_tracing(1); /* strict */
1596 /* Drop any fine-grained privileges we don't need */
1597 platform_pledge_sftp_server();
1599 if ((cp
= getenv("SSH_CONNECTION")) != NULL
) {
1600 client_addr
= xstrdup(cp
);
1601 if ((cp
= strchr(client_addr
, ' ')) == NULL
) {
1602 error("Malformed SSH_CONNECTION variable: \"%s\"",
1603 getenv("SSH_CONNECTION"));
1604 sftp_server_cleanup_exit(255);
1608 client_addr
= xstrdup("UNKNOWN");
1610 logit("session opened for local user %s from [%s]",
1611 pw
->pw_name
, client_addr
);
1614 out
= STDOUT_FILENO
;
1617 setmode(in
, O_BINARY
);
1618 setmode(out
, O_BINARY
);
1627 if ((iqueue
= sshbuf_new()) == NULL
)
1628 fatal("%s: sshbuf_new failed", __func__
);
1629 if ((oqueue
= sshbuf_new()) == NULL
)
1630 fatal("%s: sshbuf_new failed", __func__
);
1632 rset
= xcalloc(howmany(max
+ 1, NFDBITS
), sizeof(fd_mask
));
1633 wset
= xcalloc(howmany(max
+ 1, NFDBITS
), sizeof(fd_mask
));
1635 if (homedir
!= NULL
) {
1636 if (chdir(homedir
) != 0) {
1637 error("chdir to \"%s\" failed: %s", homedir
,
1642 set_size
= howmany(max
+ 1, NFDBITS
) * sizeof(fd_mask
);
1644 memset(rset
, 0, set_size
);
1645 memset(wset
, 0, set_size
);
1648 * Ensure that we can read a full buffer and handle
1649 * the worst-case length packet it can generate,
1650 * otherwise apply backpressure by stopping reads.
1652 if ((r
= sshbuf_check_reserve(iqueue
, sizeof(buf
))) == 0 &&
1653 (r
= sshbuf_check_reserve(oqueue
,
1654 SFTP_MAX_MSG_LENGTH
)) == 0)
1656 else if (r
!= SSH_ERR_NO_BUFFER_SPACE
)
1657 fatal("%s: sshbuf_check_reserve failed: %s",
1658 __func__
, ssh_err(r
));
1660 olen
= sshbuf_len(oqueue
);
1664 if (select(max
+1, rset
, wset
, NULL
, NULL
) < 0) {
1667 error("select: %s", strerror(errno
));
1668 sftp_server_cleanup_exit(2);
1671 /* copy stdin to iqueue */
1672 if (FD_ISSET(in
, rset
)) {
1673 len
= read(in
, buf
, sizeof buf
);
1676 sftp_server_cleanup_exit(0);
1677 } else if (len
< 0) {
1678 error("read: %s", strerror(errno
));
1679 sftp_server_cleanup_exit(1);
1680 } else if ((r
= sshbuf_put(iqueue
, buf
, len
)) != 0) {
1681 fatal("%s: buffer error: %s",
1682 __func__
, ssh_err(r
));
1685 /* send oqueue to stdout */
1686 if (FD_ISSET(out
, wset
)) {
1687 len
= write(out
, sshbuf_ptr(oqueue
), olen
);
1689 error("write: %s", strerror(errno
));
1690 sftp_server_cleanup_exit(1);
1691 } else if ((r
= sshbuf_consume(oqueue
, len
)) != 0) {
1692 fatal("%s: buffer error: %s",
1693 __func__
, ssh_err(r
));
1698 * Process requests from client if we can fit the results
1699 * into the output buffer, otherwise stop processing input
1700 * and let the output queue drain.
1702 r
= sshbuf_check_reserve(oqueue
, SFTP_MAX_MSG_LENGTH
);
1705 else if (r
!= SSH_ERR_NO_BUFFER_SPACE
)
1706 fatal("%s: sshbuf_check_reserve: %s",
1707 __func__
, ssh_err(r
));