upstream: add ChannelTimeout support to the client, mirroring the
same option in the server. ok markus@ OpenBSD-Commit-ID: 55630b26f390ac063980cfe7ad8c54b03284ef02
This commit is contained in:
parent
76e91e7238
commit
a752a6c0e1
|
@ -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;
|
||||
|
||||
|
|
39
misc.c
39
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)
|
||||
|
|
3
misc.h
3
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 *);
|
||||
|
|
47
readconf.c
47
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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
40
servconf.c
40
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);
|
||||
}
|
||||
|
|
16
ssh.c
16
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,
|
||||
|
|
69
ssh_config.5
69
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 ,
|
||||
|
|
Loading…
Reference in New Issue