mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-19 19:42:30 +02:00
Only schedule_exit() once
If an exit has already been scheduled we should not schedule it again. Otherwise, the exit signal is never emitted if the peer reschedules the exit before the timeout occurs. schedule_exit() now only takes the context as argument. The signal is hard coded to SIGTERM, and the interval is read directly from the context options. Furthermore, schedule_exit() now returns a bool signifying whether an exit was scheduled; false if exit is already scheduled. The call sites are updated accordingly. A notable difference is that management is only notified *once* when an exit is scheduled - we no longer notify management on redundant exit. This patch was assigned a CVE number after already reviewed and ACKed, because it was discovered that a misbehaving client can use the (now fixed) server behaviour to avoid being disconnected by means of a managment interface "client-kill" command - the security issue here is "client can circumvent security policy set by management interface". This only affects previously authenticated clients, and only management client-kill, so normal renegotion / AUTH_FAIL ("your session ends") is not affected. CVE: 2024-28882 Change-Id: I9457f005f4ba970502e6b667d9dc4299a588d661 Signed-off-by: Reynir Björnsson <reynir@reynir.dk> Acked-by: Arne Schwabe <arne-openvpn@rfc2549.org> Message-Id: <20240516120434.23499-1-gert@greenie.muc.de> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28679.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
763b35f652
commit
55bb3260c1
@ -514,17 +514,24 @@ check_server_poll_timeout(struct context *c)
|
||||
}
|
||||
|
||||
/*
|
||||
* Schedule a signal n_seconds from now.
|
||||
* Schedule a SIGTERM signal c->options.scheduled_exit_interval seconds from now.
|
||||
*/
|
||||
void
|
||||
schedule_exit(struct context *c, const int n_seconds, const int signal)
|
||||
bool
|
||||
schedule_exit(struct context *c)
|
||||
{
|
||||
const int n_seconds = c->options.scheduled_exit_interval;
|
||||
/* don't reschedule if already scheduled. */
|
||||
if (event_timeout_defined(&c->c2.scheduled_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tls_set_single_session(c->c2.tls_multi);
|
||||
update_time();
|
||||
reset_coarse_timers(c);
|
||||
event_timeout_init(&c->c2.scheduled_exit, n_seconds, now);
|
||||
c->c2.scheduled_exit_signal = signal;
|
||||
c->c2.scheduled_exit_signal = SIGTERM;
|
||||
msg(D_SCHED_EXIT, "Delayed exit in %d seconds", n_seconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -303,7 +303,7 @@ void reschedule_multi_process(struct context *c);
|
||||
|
||||
void process_ip_header(struct context *c, unsigned int flags, struct buffer *buf);
|
||||
|
||||
void schedule_exit(struct context *c, const int n_seconds, const int signal);
|
||||
bool schedule_exit(struct context *c);
|
||||
|
||||
static inline struct link_socket_info *
|
||||
get_link_socket_info(struct context *c)
|
||||
|
@ -204,7 +204,11 @@ receive_exit_message(struct context *c)
|
||||
* */
|
||||
if (c->options.mode == MODE_SERVER)
|
||||
{
|
||||
schedule_exit(c, c->options.scheduled_exit_interval, SIGTERM);
|
||||
if (!schedule_exit(c))
|
||||
{
|
||||
/* Return early when we don't need to notify management */
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -391,7 +395,7 @@ __attribute__ ((format(__printf__, 4, 5)))
|
||||
void
|
||||
send_auth_failed(struct context *c, const char *client_reason)
|
||||
{
|
||||
if (event_timeout_defined(&c->c2.scheduled_exit))
|
||||
if (!schedule_exit(c))
|
||||
{
|
||||
msg(D_TLS_DEBUG, "exit already scheduled for context");
|
||||
return;
|
||||
@ -401,8 +405,6 @@ send_auth_failed(struct context *c, const char *client_reason)
|
||||
static const char auth_failed[] = "AUTH_FAILED";
|
||||
size_t len;
|
||||
|
||||
schedule_exit(c, c->options.scheduled_exit_interval, SIGTERM);
|
||||
|
||||
len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
|
||||
if (len > PUSH_BUNDLE_SIZE)
|
||||
{
|
||||
@ -492,7 +494,7 @@ send_auth_pending_messages(struct tls_multi *tls_multi,
|
||||
void
|
||||
send_restart(struct context *c, const char *kill_msg)
|
||||
{
|
||||
schedule_exit(c, c->options.scheduled_exit_interval, SIGTERM);
|
||||
schedule_exit(c);
|
||||
send_control_channel_string(c, kill_msg ? kill_msg : "RESTART", D_PUSH);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user