summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2023-01-17 09:44:48 +0000
committerDamien Miller <djm@mindrot.org>2023-01-17 20:50:41 +1100
commit0293c19807f83141cdf33b443154459f9ee471f6 (patch)
treeb24a66100ba0d93f33bd420e40cb2fb8b30477a5 /serverloop.c
parent8ec2e3123802d2beeca06c1644b0b647f6d36dab (diff)
downloadopenssh-git-0293c19807f83141cdf33b443154459f9ee471f6.tar.gz
upstream: Add a sshd_config UnusedConnectionTimeout option to terminate
client connections that have no open channels for some length of time. This complements the recently-added ChannelTimeout option that terminates inactive channels after a timeout. ok markus@ OpenBSD-Commit-ID: ca983be74c0350364c11f8ba3bd692f6f24f5da9
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/serverloop.c b/serverloop.c
index 2d46feb9..6db0916d 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.233 2023/01/06 02:38:23 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.234 2023/01/17 09:44:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -172,17 +172,19 @@ wait_until_can_do_something(struct ssh *ssh,
int *conn_in_readyp, int *conn_out_readyp)
{
struct timespec timeout;
+ char remote_id[512];
int ret;
int client_alive_scheduled = 0;
u_int p;
- /* time we last heard from the client OR sent a keepalive */
- static time_t last_client_time;
+ time_t now;
+ static time_t last_client_time, unused_connection_expiry;
*conn_in_readyp = *conn_out_readyp = 0;
/* Prepare channel poll. First two pollfd entries are reserved */
ptimeout_init(&timeout);
channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2, &timeout);
+ now = monotime();
if (*npfd_activep < 2)
fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */
if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) {
@@ -191,6 +193,18 @@ wait_until_can_do_something(struct ssh *ssh,
}
/*
+ * If no channels are open and UnusedConnectionTimeout is set, then
+ * start the clock to terminate the connection.
+ */
+ if (options.unused_connection_timeout != 0) {
+ if (channel_still_open(ssh) || unused_connection_expiry == 0) {
+ unused_connection_expiry = now +
+ options.unused_connection_timeout;
+ }
+ ptimeout_deadline_monotime(&timeout, unused_connection_expiry);
+ }
+
+ /*
* if using client_alive, set the max timeout accordingly,
* and indicate that this particular timeout was for client
* alive by setting the client_alive_scheduled flag.
@@ -199,8 +213,9 @@ wait_until_can_do_something(struct ssh *ssh,
* analysis more difficult, but we're not doing it yet.
*/
if (options.client_alive_interval) {
+ /* Time we last heard from the client OR sent a keepalive */
if (last_client_time == 0)
- last_client_time = monotime();
+ last_client_time = now;
ptimeout_deadline_sec(&timeout, options.client_alive_interval);
/* XXX ? deadline_monotime(last_client_time + alive_interval) */
client_alive_scheduled = 1;
@@ -237,9 +252,9 @@ wait_until_can_do_something(struct ssh *ssh,
*conn_in_readyp = (*pfdp)[0].revents != 0;
*conn_out_readyp = (*pfdp)[1].revents != 0;
+ now = monotime(); /* need to reset after ppoll() */
/* ClientAliveInterval probing */
if (client_alive_scheduled) {
- time_t now = monotime();
if (ret == 0 &&
now > last_client_time + options.client_alive_interval) {
/* ppoll timed out and we're due to probe */
@@ -250,6 +265,14 @@ wait_until_can_do_something(struct ssh *ssh,
last_client_time = now;
}
}
+
+ /* UnusedConnectionTimeout handling */
+ if (unused_connection_expiry != 0 &&
+ now > unused_connection_expiry && !channel_still_open(ssh)) {
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
+ logit("terminating inactive connection from %s", remote_id);
+ cleanup_exit(255);
+ }
}
/*