Mailing List Archive

[openssh] 02/02: upstream: add ChannelTimeout support to the client, mirroring the
This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit a752a6c0e1001f93696d7025f0c867f0376e2ecf
Author: djm@openbsd.org <djm@openbsd.org>
Date: Wed Oct 11 22:42:26 2023 +0000

upstream: add ChannelTimeout support to the client, mirroring the

same option in the server. ok markus@

OpenBSD-Commit-ID: 55630b26f390ac063980cfe7ad8c54b03284ef02
---
clientloop.c | 8 +++----
misc.c | 39 +++++++++++++++++++++++++++++++++-
misc.h | 3 ++-
readconf.c | 47 +++++++++++++++++++++++++++++++++++++++--
readconf.h | 5 ++++-
servconf.c | 40 ++++-------------------------------
ssh.c | 16 +++++++++++++-
ssh_config.5 | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
8 files changed, 180 insertions(+), 47 deletions(-)

diff --git a/clientloop.c b/clientloop.c
index 3e9fa322..e8131637 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.398 2023/09/10 03:51:55 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.399 2023/10/11 22:42:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1801,7 +1801,7 @@ client_request_x11(struct ssh *ssh, const char *request_type, int rchan)
sock = x11_connect_display(ssh);
if (sock < 0)
return NULL;
- c = channel_new(ssh, "x11",
+ c = channel_new(ssh, "x11-connection",
SSH_CHANNEL_X11_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
c->force_drain = 1;
@@ -1836,7 +1836,7 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
else
debug2_fr(r, "ssh_agent_bind_hostkey");

- c = channel_new(ssh, "authentication agent connection",
+ c = channel_new(ssh, "agent-connection",
SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
"authentication agent connection", 1);
@@ -1864,7 +1864,7 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode,
}
debug("Tunnel forwarding using interface %s", ifname);

- c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+ c = channel_new(ssh, "tun-connection", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;

diff --git a/misc.c b/misc.c
index 42582c61..662b7c67 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.187 2023/08/28 03:31:16 djm Exp $ */
+/* $OpenBSD: misc.c,v 1.188 2023/10/11 22:42:26 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
@@ -2493,6 +2493,43 @@ format_absolute_time(uint64_t t, char *buf, size_t len)
strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
}

+/*
+ * Parse a "pattern=interval" clause (e.g. a ChannelTimeout).
+ * Returns 0 on success or non-zero on failure.
+ * Caller must free *typep.
+ */
+int
+parse_pattern_interval(const char *s, char **typep, int *secsp)
+{
+ char *cp, *sdup;
+ int secs;
+
+ if (typep != NULL)
+ *typep = NULL;
+ if (secsp != NULL)
+ *secsp = 0;
+ if (s == NULL)
+ return -1;
+ sdup = xstrdup(s);
+
+ if ((cp = strchr(sdup, '=')) == NULL || cp == sdup) {
+ free(sdup);
+ return -1;
+ }
+ *cp++ = '\0';
+ if ((secs = convtime(cp)) < 0) {
+ free(sdup);
+ return -1;
+ }
+ /* success */
+ if (typep != NULL)
+ *typep = xstrdup(sdup);
+ if (secsp != NULL)
+ *secsp = secs;
+ free(sdup);
+ return 0;
+}
+
/* check if path is absolute */
int
path_absolute(const char *path)
diff --git a/misc.h b/misc.h
index 4f941597..74c6f832 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.105 2023/08/28 03:31:16 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.106 2023/10/11 22:42:26 djm Exp $ */

/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -95,6 +95,7 @@ int valid_env_name(const char *);
const char *atoi_err(const char *, int *);
int parse_absolute_time(const char *, uint64_t *);
void format_absolute_time(uint64_t, char *, size_t);
+int parse_pattern_interval(const char *, char **, int *);
int path_absolute(const char *);
int stdfd_devnull(int, int, int);
int lib_contains_symbol(const char *, const char *);
diff --git a/readconf.c b/readconf.c
index 131c24f5..23fb604d 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.381 2023/08/28 03:31:16 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.382 2023/10/11 22:42:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -178,7 +178,7 @@ typedef enum {
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
- oEnableEscapeCommandline, oObscureKeystrokeTiming,
+ oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout,
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;

@@ -328,6 +328,7 @@ static struct {
{ "requiredrsasize", oRequiredRSASize },
{ "enableescapecommandline", oEnableEscapeCommandline },
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
+ { "channeltimeout", oChannelTimeout },

{ NULL, oBadOption }
};
@@ -2323,6 +2324,31 @@ parse_pubkey_algos:
*intptr = value;
break;

+ case oChannelTimeout:
+ uvalue = options->num_channel_timeouts;
+ i = 0;
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ /* Allow "none" only in first position */
+ if (strcasecmp(arg, "none") == 0) {
+ if (i > 0 || ac > 0) {
+ error("%s line %d: keyword %s \"none\" "
+ "argument must appear alone.",
+ filename, linenum, keyword);
+ goto out;
+ }
+ } else if (parse_pattern_interval(arg,
+ NULL, NULL) != 0) {
+ fatal("%s line %d: invalid channel timeout %s",
+ filename, linenum, arg);
+ }
+ if (!*activep || uvalue != 0)
+ continue;
+ opt_array_append(filename, linenum, keyword,
+ &options->channel_timeouts,
+ &options->num_channel_timeouts, arg);
+ }
+ break;
+
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@@ -2575,6 +2601,8 @@ initialize_options(Options * options)
options->enable_escape_commandline = -1;
options->obscure_keystroke_timing_interval = -1;
options->tag = NULL;
+ options->channel_timeouts = NULL;
+ options->num_channel_timeouts = 0;
}

/*
@@ -2815,6 +2843,16 @@ fill_default_options(Options * options)
v = NULL; \
} \
} while(0)
+#define CLEAR_ON_NONE_ARRAY(v, nv, none) \
+ do { \
+ if (options->nv == 1 && \
+ strcasecmp(options->v[0], none) == 0) { \
+ free(options->v[0]); \
+ free(options->v); \
+ options->v = NULL; \
+ options->nv = 0; \
+ } \
+ } while (0)
CLEAR_ON_NONE(options->local_command);
CLEAR_ON_NONE(options->remote_command);
CLEAR_ON_NONE(options->proxy_command);
@@ -2823,6 +2861,9 @@ fill_default_options(Options * options)
CLEAR_ON_NONE(options->pkcs11_provider);
CLEAR_ON_NONE(options->sk_provider);
CLEAR_ON_NONE(options->known_hosts_command);
+ CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
+#undef CLEAR_ON_NONE
+#undef CLEAR_ON_NONE_ARRAY
if (options->jump_host != NULL &&
strcmp(options->jump_host, "none") == 0 &&
options->jump_port == 0 && options->jump_user == NULL) {
@@ -3527,6 +3568,8 @@ dump_client_config(Options *o, const char *host)
dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
dump_cfg_strarray_oneline(oLogVerbose,
o->num_log_verbose, o->log_verbose);
+ dump_cfg_strarray_oneline(oChannelTimeout,
+ o->num_channel_timeouts, o->channel_timeouts);

/* Special cases */

diff --git a/readconf.h b/readconf.h
index ce261bd6..702b027d 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.152 2023/08/28 03:31:16 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.153 2023/10/11 22:42:26 djm Exp $ */

/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -182,6 +182,9 @@ typedef struct {
int enable_escape_commandline; /* ~C commandline */
int obscure_keystroke_timing_interval;

+ char **channel_timeouts; /* inactivity timeout by channel type */
+ u_int num_channel_timeouts;
+
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;

diff --git a/servconf.c b/servconf.c
index 49f7f732..86c29793 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.402 2023/09/08 06:34:24 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.403 2023/10/11 22:42:26 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -956,39 +956,6 @@ process_permitopen(struct ssh *ssh, ServerOptions *options)
options->num_permitted_listens);
}

-/* Parse a ChannelTimeout clause "pattern=interval" */
-static int
-parse_timeout(const char *s, char **typep, int *secsp)
-{
- char *cp, *sdup;
- int secs;
-
- if (typep != NULL)
- *typep = NULL;
- if (secsp != NULL)
- *secsp = 0;
- if (s == NULL)
- return -1;
- sdup = xstrdup(s);
-
- if ((cp = strchr(sdup, '=')) == NULL || cp == sdup) {
- free(sdup);
- return -1;
- }
- *cp++ = '\0';
- if ((secs = convtime(cp)) < 0) {
- free(sdup);
- return -1;
- }
- /* success */
- if (typep != NULL)
- *typep = xstrdup(sdup);
- if (secsp != NULL)
- *secsp = secs;
- free(sdup);
- return 0;
-}
-
void
process_channel_timeouts(struct ssh *ssh, ServerOptions *options)
{
@@ -999,7 +966,7 @@ process_channel_timeouts(struct ssh *ssh, ServerOptions *options)
debug3_f("setting %u timeouts", options->num_channel_timeouts);
channel_clear_timeouts(ssh);
for (i = 0; i < options->num_channel_timeouts; i++) {
- if (parse_timeout(options->channel_timeouts[i],
+ if (parse_pattern_interval(options->channel_timeouts[i],
&type, &secs) != 0) {
fatal_f("internal error: bad timeout %s",
options->channel_timeouts[i]);
@@ -2549,7 +2516,8 @@ process_server_config_line_depth(ServerOptions *options, char *line,
filename, linenum, keyword);
goto out;
}
- } else if (parse_timeout(arg, NULL, NULL) != 0) {
+ } else if (parse_pattern_interval(arg,
+ NULL, NULL) != 0) {
fatal("%s line %d: invalid channel timeout %s",
filename, linenum, arg);
}
diff --git a/ssh.c b/ssh.c
index 1dbbda7d..8b8c595e 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.594 2023/09/03 23:59:32 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.595 2023/10/11 22:42:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1573,6 +1573,20 @@ main(int ac, char **av)
else
timeout_ms = options.connection_timeout * 1000;

+ /* Apply channels timeouts, if set */
+ channel_clear_timeouts(ssh);
+ for (j = 0; j < options.num_channel_timeouts; j++) {
+ debug3("applying channel timeout %s",
+ options.channel_timeouts[j]);
+ if (parse_pattern_interval(options.channel_timeouts[j],
+ &cp, &i) != 0) {
+ fatal_f("internal error: bad timeout %s",
+ options.channel_timeouts[j]);
+ }
+ channel_add_timeout(ssh, cp, i);
+ free(cp);
+ }
+
/* Open a connection to the remote host. */
if (ssh_connect(ssh, host, options.host_arg, addrs, &hostaddr,
options.port, options.connection_attempts,
diff --git a/ssh_config.5 b/ssh_config.5
index dd72a98f..d1c7037d 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,7 +33,7 @@
.\" (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.389 2023/10/11 06:40:54 djm Exp $
+.\" $OpenBSD: ssh_config.5,v 1.390 2023/10/11 22:42:26 djm Exp $
.Dd $Mdocdate: October 11 2023 $
.Dt SSH_CONFIG 5
.Os
@@ -455,6 +455,73 @@ Multiple
.Cm CertificateFile
directives will add to the list of certificates used for
authentication.
+.It Cm ChannelTimeout
+Specifies whether and how quickly
+.Xr ssh 1
+should close inactive channels.
+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.
+.Pp
+The timeout value
+.Dq interval
+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 the interactive session to terminate after five minutes of
+inactivity.
+Specifying a zero value disables the inactivity timeout.
+.Pp
+The available channel types include:
+.Bl -tag -width Ds
+.It Cm agent-connection
+Open connections to
+.Xr ssh-agent 1 .
+.It Cm direct-tcpip , Cm direct-streamlocal@openssh.com
+Open TCP or Unix socket (respectively) connections that have
+been established from a
+.Xr ssh 1
+local forwarding, i.e.\&
+.Cm LocalForward
+or
+.Cm DynamicForward .
+.It Cm forwarded-tcpip , Cm forwarded-streamlocal@openssh.com
+Open TCP or Unix socket (respectively) connections that have been
+established to a
+.Xr sshd 8
+listening on behalf of a
+.Xr ssh 1
+remote forwarding, i.e.\&
+.Cm RemoteForward .
+.It Cm session
+The interactive main session, including shell session, command execution,
+.Xr scp 1 ,
+.Xr sftp 1 ,
+etc.
+.It Cm tun-connection
+Open
+.Cm TunnelForward
+connections.
+.It Cm x11-connection
+Open X11 forwarding sessions.
+.El
+.Pp
+Note that in all the above cases, terminating an inactive session does not
+guarantee to remove all resources associated with the session, e.g. shell
+processes or X11 clients relating to the session may continue to execute.
+.Pp
+Moreover, terminating an inactive channel or session does not necessarily
+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.
+.Pp
+The default is not to expire channels of any type for inactivity.
.It Cm CheckHostIP
If set to
.Cm yes ,

--
To stop receiving notification emails like this one, please contact
djm@mindrot.org.
_______________________________________________
openssh-commits mailing list
openssh-commits@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-commits