[Openvpn-devel,v3] Backport stricter check for valid tokens
Commit Message
From: Arne Schwabe <arne@rfc2549.org>
OpenVPN 2.5 does not have the logic to keep a session id for the auth
token. So it does not suffer the same problem that 2.6 and 2.7 did
(CVE 2026-13122).
However the improvement that we are a lot stricter to check what might
be an auth token is a good thing to backport as well to avoid any other
potential issues that might be there.
Partial cherry pick from ee119b24b3. This drops the parts that are not
present in 2.5 and also forgoes back porting the new unit tests.
Change-Id: I16187153e5b107eb08ccb7c9c9ed4acd6377af0c
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Razvan Cojocaru <razvanc@mailbox.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1766
---
This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to release/2.5.
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1766
This mail reflects revision 3 of this Change.
Acked-by according to Gerrit (reflected above):
Razvan Cojocaru <razvanc@mailbox.org>
Comments
Thanks for backporting this to 2.5 as well, and thanks Razvan for
verifying the result. It's "the same change", but not all of it
applies, and having an extra set of eyes helps...
I have stared at the code a bit, and "make check" it, and did some light
t_client testing (which does not excercise the code, but general sanity).
Gerrit does not currently build 2.5 patches (because half the builders
would fail, and "lots of work for a basically-no-longer-maintained branch").
Your patch has been applied to the release/2.5 branch.
commit 69e40fabd902321e8d30622094d6ea7bf9992db1
Author: Arne Schwabe
Date: Wed Sep 16 18:46:43 2026 +0200
Backport stricter check for valid tokens
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Razvan Cojocaru <razvanc@mailbox.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1766
Message-Id: <20260916164648.31293-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg39256.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
--
kind regards,
Gert Doering
@@ -21,12 +21,33 @@
const char *auth_token_pem_name = "OpenVPN auth-token server key";
#define AUTH_TOKEN_SESSION_ID_LEN 12
-#if AUTH_TOKEN_SESSION_ID_LEN % 3
-#error AUTH_TOKEN_SESSION_ID_LEN needs to be multiple a 3
-#endif
+#define AUTH_TOKEN_SESSION_ID_BASE64_LEN (OPENVPN_BASE64_LENGTH(AUTH_TOKEN_SESSION_ID_LEN))
+/* We want our token to be a multiple of 3 bytes to avoid the base64 padding */
+static_assert(AUTH_TOKEN_SESSION_ID_LEN % 3 == 0, "AUTH_TOKEN_SESSION_ID_LEN needs to be multiple of 3");
+
+#define AUTH_TOKEN_HMAC_LEN SHA256_DIGEST_LENGTH
/* Size of the data of the token (not b64 encoded and without prefix) */
-#define TOKEN_DATA_LEN (2 * sizeof(int64_t) + AUTH_TOKEN_SESSION_ID_LEN + 32)
+#define TOKEN_DATA_LEN (2 * sizeof(int64_t) + AUTH_TOKEN_SESSION_ID_LEN + AUTH_TOKEN_HMAC_LEN)
+#define TOKEN_DATA_BASE64_LEN (OPENVPN_BASE64_LENGTH(TOKEN_DATA_LEN))
+
+
+#define TOTAL_SESSION_TOKEN_LEN (strlen(SESSION_ID_PREFIX) + TOKEN_DATA_BASE64_LEN)
+
+/* Ensure that TOKEN_DATA_LEN is a multiple of 3 so the we avoid the base64
+ * padding */
+static_assert(TOKEN_DATA_LEN % 3 == 0, "TOKEN_DATA_LEN is not a multiple of 3");
+
+bool
+is_auth_token(const char *password)
+{
+ if (strlen(password) != TOTAL_SESSION_TOKEN_LEN)
+ {
+ return false;
+ }
+
+ return (memcmp_constant_time(SESSION_ID_PREFIX, password, strlen(SESSION_ID_PREFIX)) == 0);
+}
static struct key_type
auth_token_kt(void)
@@ -115,18 +115,11 @@
#define SESSION_ID_PREFIX "SESS_ID_AT_"
/**
- * Return if the password string has the format of a password.
+ * Return if the password string has the format of an auth token.
*
- * This fuction will always read as many bytes as SESSION_ID_PREFIX is longer
- * the caller needs ensure that password memory is at least that long (true for
- * calling with struct user_pass)
* @param password
* @return whether the password string starts with the session token prefix
*/
-static inline bool
-is_auth_token(const char *password)
-{
- return (memcmp_constant_time(SESSION_ID_PREFIX, password,
- strlen(SESSION_ID_PREFIX)) == 0);
-}
+bool
+is_auth_token(const char *password);
#endif /* AUTH_TOKEN_H */