@@ -2596,8 +2596,7 @@ static const multi_client_connect_handler client_connect_handlers[] = {
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;
}
@@ -864,7 +864,7 @@ process_incoming_push_request(struct context *c)
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);
@@ -3133,7 +3133,7 @@ tls_multi_process(struct tls_multi *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.
@@ -91,9 +91,6 @@
#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).
*/
@@ -570,10 +570,13 @@ struct tls_multi
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
*/
@@ -1073,8 +1073,28 @@ key_state_test_auth_control_file(struct auth_deferred_status *ads, bool cached)
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;
@@ -1087,7 +1107,7 @@ tls_authentication_status(struct tls_multi *multi, const int latency)
/* 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)
{
@@ -1143,6 +1163,7 @@ tls_authentication_status(struct tls_multi *multi, const int latency)
if (!cached)
{
multi->tas_cache_last_update = now;
+ multi->tas_cache_num_updates++;
}
#if 0
@@ -75,7 +75,7 @@ enum tls_auth_status
/**
* 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.
@@ -84,15 +84,13 @@ enum tls_auth_status
* 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 TLS_AUTHENTICATION_UNDEFINED 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
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> --- src/openvpn/multi.c | 3 +-- src/openvpn/push.c | 2 +- src/openvpn/ssl.c | 2 +- src/openvpn/ssl.h | 3 --- src/openvpn/ssl_common.h | 5 ++++- src/openvpn/ssl_verify.c | 25 +++++++++++++++++++++++-- src/openvpn/ssl_verify.h | 8 +++----- 7 files changed, 33 insertions(+), 15 deletions(-)