summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--channels.c74
-rw-r--r--ssh_config.522
-rw-r--r--sshd_config.544
3 files changed, 99 insertions, 41 deletions
diff --git a/channels.c b/channels.c
index 20f31dad..6862556b 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.435 2023/12/18 14:47:20 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.436 2024/01/09 22:19:00 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -214,6 +214,9 @@ struct ssh_channels {
/* Channel timeouts by type */
struct ssh_channel_timeout *timeouts;
size_t ntimeouts;
+ /* Global timeout for all OPEN channels */
+ int global_deadline;
+ time_t lastused;
};
/* helper */
@@ -316,6 +319,11 @@ channel_add_timeout(struct ssh *ssh, const char *type_pattern,
{
struct ssh_channels *sc = ssh->chanctxt;
+ if (strcmp(type_pattern, "global") == 0) {
+ debug2_f("global channel timeout %d seconds", timeout_secs);
+ sc->global_deadline = timeout_secs;
+ return;
+ }
debug2_f("channel type \"%s\" timeout %d seconds",
type_pattern, timeout_secs);
sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts,
@@ -377,6 +385,38 @@ channel_set_xtype(struct ssh *ssh, int id, const char *xctype)
}
/*
+ * update "last used" time on a channel.
+ * NB. nothing else should update lastused except to clear it.
+ */
+static void
+channel_set_used_time(struct ssh *ssh, Channel *c)
+{
+ ssh->chanctxt->lastused = monotime();
+ if (c != NULL)
+ c->lastused = ssh->chanctxt->lastused;
+}
+
+/*
+ * Get the time at which a channel is due to time out for inactivity.
+ * Returns 0 if the channel is not due to time out ever.
+ */
+static time_t
+channel_get_expiry(struct ssh *ssh, Channel *c)
+{
+ struct ssh_channels *sc = ssh->chanctxt;
+ time_t expiry = 0, channel_expiry;
+
+ if (sc->lastused != 0 && sc->global_deadline != 0)
+ expiry = sc->lastused + sc->global_deadline;
+ if (c->lastused != 0 && c->inactive_deadline != 0) {
+ channel_expiry = c->lastused + c->inactive_deadline;
+ if (expiry == 0 || channel_expiry < expiry)
+ expiry = channel_expiry;
+ }
+ return expiry;
+}
+
+/*
* Register filedescriptors for a channel, used when allocating a channel or
* when the channel consumer/producer is ready, e.g. shell exec'd
*/
@@ -441,6 +481,8 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
if (efd != -1)
set_nonblock(efd);
}
+ /* channel might be entering a larval state, so reset global timeout */
+ channel_set_used_time(ssh, NULL);
}
/*
@@ -1197,7 +1239,7 @@ channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd,
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty);
c->type = SSH_CHANNEL_OPEN;
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
c->local_window = c->local_window_max = window_max;
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||
@@ -1368,7 +1410,7 @@ channel_pre_x11_open(struct ssh *ssh, Channel *c)
if (ret == 1) {
c->type = SSH_CHANNEL_OPEN;
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
channel_pre_open(ssh, c);
} else if (ret == -1) {
logit("X11 connection rejected because of wrong "
@@ -2016,7 +2058,7 @@ channel_post_connecting(struct ssh *ssh, Channel *c)
c->self, c->connect_ctx.host, c->connect_ctx.port);
channel_connect_ctx_free(&c->connect_ctx);
c->type = SSH_CHANNEL_OPEN;
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
if (isopen) {
/* no message necessary */
} else {
@@ -2108,7 +2150,7 @@ channel_handle_rfd(struct ssh *ssh, Channel *c)
goto rfail;
}
if (nr != 0)
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
return 1;
}
@@ -2134,7 +2176,7 @@ channel_handle_rfd(struct ssh *ssh, Channel *c)
}
return -1;
}
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
if (c->input_filter != NULL) {
if (c->input_filter(ssh, c, buf, len) == -1) {
debug2("channel %d: filter stops", c->self);
@@ -2215,7 +2257,7 @@ channel_handle_wfd(struct ssh *ssh, Channel *c)
}
return -1;
}
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
#ifndef BROKEN_TCGETATTR_ICANON
if (c->isatty && dlen >= 1 && buf[0] != '\r') {
if (tcgetattr(c->wfd, &tio) == 0 &&
@@ -2264,7 +2306,7 @@ channel_handle_efd_write(struct ssh *ssh, Channel *c)
if ((r = sshbuf_consume(c->extended, len)) != 0)
fatal_fr(r, "channel %i: consume", c->self);
c->local_consumed += len;
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
}
return 1;
}
@@ -2291,7 +2333,7 @@ channel_handle_efd_read(struct ssh *ssh, Channel *c)
channel_close_fd(ssh, c, &c->efd);
return 1;
}
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
if (c->extended_usage == CHAN_EXTENDED_IGNORE)
debug3("channel %d: discard efd", c->self);
else if ((r = sshbuf_put(c->extended, buf, len)) != 0)
@@ -2581,10 +2623,9 @@ channel_handler(struct ssh *ssh, int table, struct timespec *timeout)
continue;
}
if (ftab[c->type] != NULL) {
- if (table == CHAN_PRE &&
- c->type == SSH_CHANNEL_OPEN &&
- c->inactive_deadline != 0 && c->lastused != 0 &&
- now >= c->lastused + c->inactive_deadline) {
+ if (table == CHAN_PRE && c->type == SSH_CHANNEL_OPEN &&
+ channel_get_expiry(ssh, c) != 0 &&
+ now >= channel_get_expiry(ssh, c)) {
/* channel closed for inactivity */
verbose("channel %d: closing after %u seconds "
"of inactivity", c->self,
@@ -2596,10 +2637,9 @@ channel_handler(struct ssh *ssh, int table, struct timespec *timeout)
/* inactivity timeouts must interrupt poll() */
if (timeout != NULL &&
c->type == SSH_CHANNEL_OPEN &&
- c->lastused != 0 &&
- c->inactive_deadline != 0) {
+ channel_get_expiry(ssh, c) != 0) {
ptimeout_deadline_monotime(timeout,
- c->lastused + c->inactive_deadline);
+ channel_get_expiry(ssh, c));
}
} else if (timeout != NULL) {
/*
@@ -3558,7 +3598,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx);
debug2_f("channel %d: callback done", c->self);
}
- c->lastused = monotime();
+ channel_set_used_time(ssh, c);
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
c->remote_window, c->remote_maxpacket);
return 0;
diff --git a/ssh_config.5 b/ssh_config.5
index 4bbdfefd..15ad012f 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.391 2023/10/12 02:18:18 djm Exp $
-.Dd $Mdocdate: October 12 2023 $
+.\" $OpenBSD: ssh_config.5,v 1.392 2024/01/09 22:19:00 djm Exp $
+.Dd $Mdocdate: January 9 2024 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -463,8 +463,10 @@ Timeouts are specified as one or more
.Dq type=interval
pairs separated by whitespace, where the
.Dq type
-must be a channel type name (as described in the table below), optionally
-containing wildcard characters.
+must be the special keyword
+.Dq global
+or a channel type name from the list below, optionally containing
+wildcard characters.
.Pp
The timeout value
.Dq interval
@@ -473,11 +475,19 @@ is specified in seconds or may use any of the units documented in the
section.
For example,
.Dq session=5m
-would cause the interactive session to terminate after five minutes of
+would cause interactive sessions to terminate after five minutes of
inactivity.
Specifying a zero value disables the inactivity timeout.
.Pp
-The available channel types include:
+The special timeout
+.Dq global
+Applies to all active channels, taken together.
+Traffic on any active channel will reset the timeout, but when the timeout
+expires then all open channels will be closed.
+Note that this global timeout is not matched by wildcards and must be
+specified explicitly.
+.Pp
+The available channel type names include:
.Bl -tag -width Ds
.It Cm agent-connection
Open connections to
diff --git a/sshd_config.5 b/sshd_config.5
index 7e1a56cd..ca5eeb59 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: sshd_config.5,v 1.350 2023/07/28 05:42:36 jmc Exp $
-.Dd $Mdocdate: July 28 2023 $
+.\" $OpenBSD: sshd_config.5,v 1.351 2024/01/09 22:19:00 djm Exp $
+.Dd $Mdocdate: January 9 2024 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@@ -409,8 +409,10 @@ Timeouts are specified as one or more
.Dq type=interval
pairs separated by whitespace, where the
.Dq type
-must be a channel type name (as described in the table below), optionally
-containing wildcard characters.
+must be the special keyword
+.Dq global
+or a channel type name from the list below, optionally containing
+wildcard characters.
.Pp
The timeout value
.Dq interval
@@ -418,11 +420,20 @@ is specified in seconds or may use any of the units documented in the
.Sx TIME FORMATS
section.
For example,
-.Dq session:*=5m
-would cause all sessions to terminate after five minutes of inactivity.
+.Dq session=5m
+would cause interactive sessions to terminate after five minutes of
+inactivity.
Specifying a zero value disables the inactivity timeout.
.Pp
-The available channel types include:
+The special timeout
+.Dq global
+Applies to all active channels, taken together.
+Traffic on any active channel will reset the timeout, but when the timeout
+expires then all open channels will be closed.
+Note that this global timeout is not matched by wildcards and must be
+specified explicitly.
+.Pp
+The available channel type names include:
.Bl -tag -width Ds
.It Cm agent-connection
Open connections to
@@ -443,15 +454,15 @@ listening on behalf of a
.Xr ssh 1
remote forwarding, i.e.\&
.Cm RemoteForward .
-.It Cm session:command
-Command execution sessions.
-.It Cm session:shell
-Interactive shell sessions.
-.It Cm session:subsystem:...
-Subsystem sessions, e.g. for
+.It Cm session
+The interactive main session, including shell session, command execution,
+.Xr scp 1 ,
.Xr sftp 1 ,
-which could be identified as
-.Cm session:subsystem:sftp .
+etc.
+.It Cm tun-connection
+Open
+.Cm TunnelForward
+connections.
.It Cm x11-connection
Open X11 forwarding sessions.
.El
@@ -465,9 +476,6 @@ close the SSH connection, nor does it prevent a client from
requesting another channel of the same type.
In particular, expiring an inactive forwarding session does not prevent
another identical forwarding from being subsequently created.
-See also
-.Cm UnusedConnectionTimeout ,
-which may be used in conjunction with this option.
.Pp
The default is not to expire channels of any type for inactivity.
.It Cm ChrootDirectory