-/* $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
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;
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);
}
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;
-/* $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.
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)
-/* $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>
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 *);
-/* $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
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
- oEnableEscapeCommandline, oObscureKeystrokeTiming,
+ oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout,
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
{ "requiredrsasize", oRequiredRSASize },
{ "enableescapecommandline", oEnableEscapeCommandline },
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
+ { "channeltimeout", oChannelTimeout },
{ NULL, oBadOption }
};
*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);
options->enable_escape_commandline = -1;
options->obscure_keystroke_timing_interval = -1;
options->tag = NULL;
+ options->channel_timeouts = NULL;
+ options->num_channel_timeouts = 0;
}
/*
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);
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) {
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 */
-/* $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>
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;
-/* $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
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)
{
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]);
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);
}
-/* $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
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,
.\" (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
.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 ,