The caching in tls_authentication_status broke the quick reaction to
authentication status in the code paths that did not do caching like
PUSH_REQUEST reply code path.
This patch introduces exponential backoff for the caching so we still
retain the quick reaction while still keeping the benefit of caching.
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <
20210510131356.968965-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22327.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
static void
multi_connection_established(struct multi_context *m, struct multi_instance *mi)
{
- if (tls_authentication_status(mi->context.c2.tls_multi, TLS_MULTI_AUTH_STATUS_INTERVAL)
- != TLS_AUTHENTICATION_SUCCEEDED)
+ if (tls_authentication_status(mi->context.c2.tls_multi) != TLS_AUTHENTICATION_SUCCEEDED)
{
return;
}
int ret = PUSH_MSG_ERROR;
- if (tls_authentication_status(c->c2.tls_multi, TLS_MULTI_AUTH_STATUS_INTERVAL) == TLS_AUTHENTICATION_FAILED
+ if (tls_authentication_status(c->c2.tls_multi) == TLS_AUTHENTICATION_FAILED
|| c->c2.tls_multi->multi_state == CAS_FAILED)
{
const char *client_reason = tls_client_reason(c->c2.tls_multi);
update_time();
- enum tls_auth_status tas = tls_authentication_status(multi, TLS_MULTI_AUTH_STATUS_INTERVAL);
+ enum tls_auth_status tas = tls_authentication_status(multi);
/*
* If lame duck session expires, kill it.
#define TLS_MULTI_HORIZON 2 /* call tls_multi_process frequently for n seconds after
* every packet sent/received action */
-/* Interval that tls_multi_process should call tls_authentication_status */
-#define TLS_MULTI_AUTH_STATUS_INTERVAL 10
-
/*
* Buffer sizes (also see mtu.h).
*/
char *locked_username;
struct cert_hash_set *locked_cert_hash_set;
- /* Time of last when we updated the cached state of
+ /** Time of last when we updated the cached state of
* tls_authentication_status deferred files */
time_t tas_cache_last_update;
+ /** The number of times we updated the cache */
+ unsigned int tas_cache_num_updates;
+
/*
* An error message to send to client on AUTH_FAILED
*/
return ACF_DISABLED;
}
+/**
+ * The minimum times to have passed to update the cache. Older versions
+ * of OpenVPN had code path that did not do any caching, so we start
+ * with no caching (0) here as well to have the same super quick initial
+ * reaction.
+ */
+static time_t cache_intervals[] = {0, 0, 0, 0, 0, 1, 1, 2, 2, 4, 8};
+
+/**
+ * uses cache_intervals times to determine if we should update the
+ * cache.
+ */
+static bool
+tls_authentication_status_use_cache(struct tls_multi *multi)
+{
+ unsigned int idx = min_uint(multi->tas_cache_num_updates, SIZE(cache_intervals) - 1);
+ time_t latency = cache_intervals[idx];
+ return multi->tas_cache_last_update + latency >= now;
+}
+
enum tls_auth_status
-tls_authentication_status(struct tls_multi *multi, const int latency)
+tls_authentication_status(struct tls_multi *multi)
{
bool deferred = false;
/* at least one key already failed authentication */
bool failed_auth = false;
- bool cached = multi->tas_cache_last_update + latency >= now;
+ bool cached = tls_authentication_status_use_cache(multi);
for (int i = 0; i < KEY_SCAN_SIZE; ++i)
{
if (!cached)
{
multi->tas_cache_last_update = now;
+ multi->tas_cache_num_updates++;
}
#if 0
/**
* Return current session authentication state of the tls_multi structure
* This will return TLS_AUTHENTICATION_SUCCEEDED only if the session is
- * fully authenicated, i.e. VPN traffic is allowed over it.
+ * fully authenticated, i.e. VPN traffic is allowed over it.
*
* Checks the status of all active keys and checks if the deferred
* authentication has succeeded.
* from KS_AUTH_DEFERRED to KS_AUTH_FALSE/KS_AUTH_TRUE if the deferred
* authentication has succeeded after last call.
*
- * @param latency if not null, return a cached result from the last
- * call if the last call for this multi struct has
- * been less than latency seconds ago
* @param multi the tls_multi struct to operate on
*
* @return Current authentication status of the tls_multi
*/
enum tls_auth_status
-tls_authentication_status(struct tls_multi *multi, const int latency);
+tls_authentication_status(struct tls_multi *multi);
/** Check whether the \a ks \c key_state has finished the key exchange part
* of the OpenVPN hand shake. This is that the key_method_2read/write