upstream: Only reset the serveralive check when we receive traffic from
the server and ignore traffic from a port forwarding client, preventing a client from keeping a connection alive when it should be terminated. Based on a patch from jxraynor at gmail.com via openssh-unix-dev and bz#2265, ok djm@ OpenBSD-Commit-ID: a941a575a5cbc244c0ef5d7abd0422bbf02c2dcd
This commit is contained in:
parent
adfdbf1211
commit
f11b233463
36
clientloop.c
36
clientloop.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: clientloop.c,v 1.344 2020/04/24 02:19:40 dtucker Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.345 2020/07/03 05:09:06 dtucker Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -162,6 +162,7 @@ static int connection_out; /* Connection to server (output). */
|
||||||
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
|
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
|
||||||
static int session_closed; /* In SSH2: login session closed. */
|
static int session_closed; /* In SSH2: login session closed. */
|
||||||
static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
|
static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
|
||||||
|
static time_t server_alive_time; /* Time to do server_alive_check */
|
||||||
|
|
||||||
static void client_init_dispatch(struct ssh *ssh);
|
static void client_init_dispatch(struct ssh *ssh);
|
||||||
int session_ident = -1;
|
int session_ident = -1;
|
||||||
|
@ -466,6 +467,13 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
schedule_server_alive_check(void)
|
||||||
|
{
|
||||||
|
if (options.server_alive_interval > 0)
|
||||||
|
server_alive_time = monotime() + options.server_alive_interval;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
server_alive_check(struct ssh *ssh)
|
server_alive_check(struct ssh *ssh)
|
||||||
{
|
{
|
||||||
|
@ -482,6 +490,7 @@ server_alive_check(struct ssh *ssh)
|
||||||
fatal("%s: send packet: %s", __func__, ssh_err(r));
|
fatal("%s: send packet: %s", __func__, ssh_err(r));
|
||||||
/* Insert an empty placeholder to maintain ordering */
|
/* Insert an empty placeholder to maintain ordering */
|
||||||
client_register_global_confirm(NULL, NULL);
|
client_register_global_confirm(NULL, NULL);
|
||||||
|
schedule_server_alive_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -495,7 +504,7 @@ client_wait_until_can_do_something(struct ssh *ssh,
|
||||||
{
|
{
|
||||||
struct timeval tv, *tvp;
|
struct timeval tv, *tvp;
|
||||||
int timeout_secs;
|
int timeout_secs;
|
||||||
time_t minwait_secs = 0, server_alive_time = 0, now = monotime();
|
time_t minwait_secs = 0, now = monotime();
|
||||||
int r, ret;
|
int r, ret;
|
||||||
|
|
||||||
/* Add any selections by the channel mechanism. */
|
/* Add any selections by the channel mechanism. */
|
||||||
|
@ -524,10 +533,8 @@ client_wait_until_can_do_something(struct ssh *ssh,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
|
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
|
||||||
if (options.server_alive_interval > 0) {
|
if (options.server_alive_interval > 0)
|
||||||
timeout_secs = options.server_alive_interval;
|
timeout_secs = MAXIMUM(server_alive_time - now, 0);
|
||||||
server_alive_time = now + options.server_alive_interval;
|
|
||||||
}
|
|
||||||
if (options.rekey_interval > 0 && !rekeying)
|
if (options.rekey_interval > 0 && !rekeying)
|
||||||
timeout_secs = MINIMUM(timeout_secs,
|
timeout_secs = MINIMUM(timeout_secs,
|
||||||
ssh_packet_get_rekey_timeout(ssh));
|
ssh_packet_get_rekey_timeout(ssh));
|
||||||
|
@ -557,7 +564,6 @@ client_wait_until_can_do_something(struct ssh *ssh,
|
||||||
*/
|
*/
|
||||||
memset(*readsetp, 0, *nallocp);
|
memset(*readsetp, 0, *nallocp);
|
||||||
memset(*writesetp, 0, *nallocp);
|
memset(*writesetp, 0, *nallocp);
|
||||||
|
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
return;
|
return;
|
||||||
/* Note: we might still have data in the buffers. */
|
/* Note: we might still have data in the buffers. */
|
||||||
|
@ -565,15 +571,14 @@ client_wait_until_can_do_something(struct ssh *ssh,
|
||||||
"select: %s\r\n", strerror(errno))) != 0)
|
"select: %s\r\n", strerror(errno))) != 0)
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
quit_pending = 1;
|
quit_pending = 1;
|
||||||
} else if (ret == 0) {
|
} else if (options.server_alive_interval > 0 && !FD_ISSET(connection_in,
|
||||||
|
*readsetp) && monotime() >= server_alive_time)
|
||||||
/*
|
/*
|
||||||
* Timeout. Could have been either keepalive or rekeying.
|
* ServerAlive check is needed. We can't rely on the select
|
||||||
* Keepalive we check here, rekeying is checked in clientloop.
|
* timing out since traffic on the client side such as port
|
||||||
|
* forwards can keep waking it up.
|
||||||
*/
|
*/
|
||||||
if (server_alive_time != 0 && server_alive_time <= monotime())
|
server_alive_check(ssh);
|
||||||
server_alive_check(ssh);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -613,6 +618,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset)
|
||||||
* the packet subsystem.
|
* the packet subsystem.
|
||||||
*/
|
*/
|
||||||
if (FD_ISSET(connection_in, readset)) {
|
if (FD_ISSET(connection_in, readset)) {
|
||||||
|
schedule_server_alive_check();
|
||||||
/* Read as much as possible. */
|
/* Read as much as possible. */
|
||||||
len = read(connection_in, buf, sizeof(buf));
|
len = read(connection_in, buf, sizeof(buf));
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
|
@ -1314,6 +1320,8 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
|
||||||
client_channel_closed, 0);
|
client_channel_closed, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
schedule_server_alive_check();
|
||||||
|
|
||||||
/* Main loop of the client for the interactive session mode. */
|
/* Main loop of the client for the interactive session mode. */
|
||||||
while (!quit_pending) {
|
while (!quit_pending) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue