diff options
author | 2021-02-18 00:30:17 +0000 | |
---|---|---|
committer | 2021-02-18 00:30:17 +0000 | |
commit | 029b49a021ec98dc51059ea4165f507a23ffbbde (patch) | |
tree | 910703e7566638112364e86dd6feb4d46bb94ac5 /usr.bin/ssh/sftp-server.c | |
parent | handle "simple-pm-bus" in simplebus (diff) | |
download | wireguard-openbsd-029b49a021ec98dc51059ea4165f507a23ffbbde.tar.xz wireguard-openbsd-029b49a021ec98dc51059ea4165f507a23ffbbde.zip |
sftp-server: implement limits@openssh.com extension
This is a simple extension that allows the server to clearly
communicate transfer limits it is imposing so the client doesn't
have to guess, or force the user to manually tune. This is
particularly useful when an attempt to use too large of a value
causes the server to abort the connection.
Patch from Mike Frysinger; ok dtucker@
Diffstat (limited to 'usr.bin/ssh/sftp-server.c')
-rw-r--r-- | usr.bin/ssh/sftp-server.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/usr.bin/ssh/sftp-server.c b/usr.bin/ssh/sftp-server.c index 222d5667d0d..18869639d24 100644 --- a/usr.bin/ssh/sftp-server.c +++ b/usr.bin/ssh/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.121 2021/02/12 03:49:09 djm Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.122 2021/02/18 00:30:17 djm Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -16,6 +16,7 @@ */ #include <sys/types.h> +#include <sys/resource.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/mount.h> @@ -45,6 +46,9 @@ char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ +/* Maximum data read that we are willing to accept */ +#define SFTP_MAX_READ_LENGTH (64 * 1024) + /* Our verbosity */ static LogLevel log_level = SYSLOG_LEVEL_ERROR; @@ -102,6 +106,7 @@ static void process_extended_fstatvfs(u_int32_t id); static void process_extended_hardlink(u_int32_t id); static void process_extended_fsync(u_int32_t id); static void process_extended_lsetstat(u_int32_t id); +static void process_extended_limits(u_int32_t id); static void process_extended(u_int32_t id); struct sftp_handler { @@ -144,6 +149,7 @@ static const struct sftp_handler extended_handlers[] = { { "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 }, { "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 }, { "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 }, + { "limits", "limits@openssh.com", 0, process_extended_limits, 1 }, { NULL, NULL, 0, NULL, 0 } }; @@ -665,6 +671,9 @@ process_init(void) (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ /* lsetstat extension */ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ + /* limits extension */ + (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ fatal_fr(r, "compose"); send_msg(msg); @@ -731,7 +740,7 @@ process_close(u_int32_t id) static void process_read(u_int32_t id) { - u_char buf[64*1024]; + u_char buf[SFTP_MAX_READ_LENGTH]; u_int32_t len; int r, handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; @@ -1411,6 +1420,36 @@ process_extended_lsetstat(u_int32_t id) } static void +process_extended_limits(u_int32_t id) +{ + struct sshbuf *msg; + int r; + uint64_t nfiles = 0; + struct rlimit rlim; + + debug("request %u: limits", id); + + if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5) + nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */ + + if ((msg = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + /* max-packet-length */ + (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH)) != 0 || + /* max-read-length */ + (r = sshbuf_put_u64(msg, SFTP_MAX_READ_LENGTH)) != 0 || + /* max-write-length */ + (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH - 1024)) != 0 || + /* max-open-handles */ + (r = sshbuf_put_u64(msg, nfiles)) != 0) + fatal_fr(r, "compose"); + send_msg(msg); + sshbuf_free(msg); +} + +static void process_extended(u_int32_t id) { char *request; |