Skip to contentSkip to conversation

auth-token: Ensure tokens are always wiped on de-auth

PATCH Superseded David Sommerseth 4 participants 6 messages Mar 28, 2017 – Mar 29, 2017

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 auth-token: Ensure tokens are always wiped on de-auth

If tls_deauthenticate() was called, it could in some scenarios leave the authentication token for a session in memory. This change just ensures auth-tokens are always wiped as soon as a TLS session is considered broken.

---

The wipe_auth_token() function is otherwise moved to be declared before tls_deauthenticate() and the latter function is also slightly modified to make use of the C99 feature of inline declaration - mostly to have a more reasonable coding style when adding the wipe_auth_token() call.

---
 src/openvpn/ssl_verify.c | 44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)
src/openvpn/ssl_verify.c +24 -20
index a6e9be3..008a60d 100644
@@ -80,6 +80,26 @@ setenv_untrusted(struct tls_session *session)
     setenv_link_socket_actual(session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
 }
 
+
+/**
+ *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
+ *
+ *  @param multi  Pointer to a multi object holding the auth_token variables
+ */
+static void
+wipe_auth_token(struct tls_multi *multi)
+{
+    if( multi ) {
+	if (multi->auth_token ) {
+	    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
+	    free(multi->auth_token);
+	}
+	multi->auth_token = NULL;
+	multi->auth_token_sent = false;
+    }
+}
+
+
 /*
  * Remove authenticated state from all sessions in the given tunnel
  */
@@ -88,10 +108,10 @@ tls_deauthenticate(struct tls_multi *multi)
 {
     if (multi)
     {
-        int i, j;
-        for (i = 0; i < TM_SIZE; ++i)
+        wipe_auth_token(multi);
+        for (int i = 0; i < TM_SIZE; ++i)
         {
-            for (j = 0; j < KS_SIZE; ++j)
+            for (int j = 0; j < KS_SIZE; ++j)
             {
                 multi->session[i].key[j].authenticated = false;
             }
@@ -1219,21 +1239,6 @@ verify_user_pass_management(struct tls_session *session, const struct user_pass
 }
 #endif /* ifdef MANAGEMENT_DEF_AUTH */
 
-/**
- *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
- *
- *  @param multi  Pointer to a multi object holding the auth_token variables
- */
-static void
-wipe_auth_token(struct tls_multi *multi)
-{
-    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
-    free(multi->auth_token);
-    multi->auth_token = NULL;
-    multi->auth_token_sent = false;
-}
-
-
 /*
  * Main username/password verification entry point
  */
@@ -1285,7 +1290,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         /* Ensure that the username has not changed */
         if (!tls_lock_username(multi, up->username))
         {
-            wipe_auth_token(multi);
+            /* auth-token cleared in tls_lock_username() on failure */
             ks->authenticated = false;
             goto done;
         }
@@ -1306,7 +1311,6 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         if (memcmp_constant_time(multi->auth_token, up->password,
                                  strlen(multi->auth_token)) != 0)
         {
-            wipe_auth_token(multi);
             ks->authenticated = false;
             tls_deauthenticate(multi);
 
Signature · 1 line
2.11.0
#1 lore raw

Hi,

Quoted 26 lines · David Sommerseth

If tls_deauthenticate() was called, it could in some scenarios leave the authentication token for a session in memory. This change just ensures auth-tokens are always wiped as soon as a TLS session is considered broken.

---

The wipe_auth_token() function is otherwise moved to be declared before tls_deauthenticate() and the latter function is also slightly modified to make use of the C99 feature of inline declaration - mostly to have a more reasonable coding style when adding the wipe_auth_token() call.

---
 src/openvpn/ssl_verify.c | 44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)
src/openvpn/ssl_verify.c +1 -0
index a6e9be3..008a60d 100644
@@ -80,6 +80,26 @@ setenv_untrusted(struct tls_session *session)
     setenv_link_socket_actual(session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
 }
 
+

src/openvpn/ssl_verify.c setenv_untrusted(struct tls_session *session) · line 93

Quoted 10 lines
src/openvpn/ssl_verify.c +10 -0
+/**
+ *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
+ *
+ *  @param multi  Pointer to a multi object holding the auth_token variables
+ */
+static void
+wipe_auth_token(struct tls_multi *multi)
+{
+    if( multi ) {
+	if (multi->auth_token ) {

The spaces in theses lines look a bit odd.

Quoted 59 lines
src/openvpn/ssl_verify.c +13 -19
+	    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
+	    free(multi->auth_token);
+	}
+	multi->auth_token = NULL;
+	multi->auth_token_sent = false;
+    }
+}
+
+
 /*
  * Remove authenticated state from all sessions in the given tunnel
  */
@@ -88,10 +108,10 @@ tls_deauthenticate(struct tls_multi *multi)
 {
     if (multi)
     {
-        int i, j;
-        for (i = 0; i < TM_SIZE; ++i)
+        wipe_auth_token(multi);
+        for (int i = 0; i < TM_SIZE; ++i)
         {
-            for (j = 0; j < KS_SIZE; ++j)
+            for (int j = 0; j < KS_SIZE; ++j)
             {
                 multi->session[i].key[j].authenticated = false;
             }
@@ -1219,21 +1239,6 @@ verify_user_pass_management(struct tls_session *session, const struct user_pass
 }
 #endif /* ifdef MANAGEMENT_DEF_AUTH */
 
-/**
- *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
- *
- *  @param multi  Pointer to a multi object holding the auth_token variables
- */
-static void
-wipe_auth_token(struct tls_multi *multi)
-{
-    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
-    free(multi->auth_token);
-    multi->auth_token = NULL;
-    multi->auth_token_sent = false;
-}
-
-
 /*
  * Main username/password verification entry point
  */
@@ -1285,7 +1290,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         /* Ensure that the username has not changed */
         if (!tls_lock_username(multi, up->username))
         {
-            wipe_auth_token(multi);
+            /* auth-token cleared in tls_lock_username() on failure */
             ks->authenticated = false;
             goto done;
         }

src/openvpn/ssl_verify.c verify_user_pass(struct user_pass *up, struct tls_multi *multi, · line 1316

Quoted 7 lines
src/openvpn/ssl_verify.c +0 -1
@@ -1306,7 +1311,6 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         if (memcmp_constant_time(multi->auth_token, up->password,
                                  strlen(multi->auth_token)) != 0)
         {
-            wipe_auth_token(multi);
             ks->authenticated = false;
             tls_deauthenticate(multi);
 

Shouldn't we also clear the token if the ccd authentication check in verify_final_auth_checks() fails?

-Steffan

#2 lore raw
Quoted 20 lines · Steffan Karger

Hi,

Quoted 17 lines · David Sommerseth

If tls_deauthenticate() was called, it could in some scenarios leave the authentication token for a session in memory. This change just ensures auth-tokens are always wiped as soon as a TLS session is considered broken.

---

The wipe_auth_token() function is otherwise moved to be declared before tls_deauthenticate() and the latter function is also slightly modified to make use of the C99 feature of inline declaration - mostly to have a more reasonable coding style when adding the wipe_auth_token() call.

---
 src/openvpn/ssl_verify.c | 44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)

[...snip...]

Quoted 5 lines
Quoted 5 lines
src/openvpn/ssl_verify.c +5 -0
+
+/**
+ *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
+ *
+ *  @param multi  Pointer to a multi object holding the auth_token variables
Quoted 8 lines

src/openvpn/ssl_verify.c setenv_untrusted(struct tls_session *session) · line 93

Quoted 6 lines

+ */

src/openvpn/ssl_verify.c +5 -0
+static void
+wipe_auth_token(struct tls_multi *multi)
+{
+    if( multi ) {
+	if (multi->auth_token ) {

The spaces in theses lines look a bit odd.

Sigh ... seems my Emacs config have re-decided on tabs vs spaces :/ Fixed!

[...snip...]

Quoted 3 lines

Shouldn't we also clear the token if the ccd authentication check in verify_final_auth_checks() fails?

Thanks! I didn't consider that so much, as in my mind this check happened before the user/password auth ... but it seems it actually happens afterwards. So you're right, as this is really happening after we have generated a token, this should be wiped here too.

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc
#3 lore raw

PATCH v2 1/1 auth-token: Ensure tokens are always wiped on de-auth

In reply to David Sommerseth

If tls_deauthenticate() was called, it could in some scenarios leave the authentication token for a session in memory. This change just ensures auth-tokens are always wiped as soon as a TLS session is considered broken.

---

The wipe_auth_token() function is otherwise moved to be declared before tls_deauthenticate() and the latter function is also slightly modified to make use of the C99 feature of inline declaration - mostly to have a more reasonable coding style when adding the wipe_auth_token() call.

v2 - Fixed coding style issues after changes in wipe_auth_token()
- Added wipe_auth_token() call when --ccd-exclusive auth fails

---
 src/openvpn/ssl_verify.c | 47 +++++++++++++++++++++++++++--------------------
 1 file changed, 27 insertions(+), 20 deletions(-)
src/openvpn/ssl_verify.c +27 -20
index a6e9be3..bc578fa 100644
@@ -80,6 +80,28 @@ setenv_untrusted(struct tls_session *session)
     setenv_link_socket_actual(session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
 }
 
+
+/**
+ *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
+ *
+ *  @param multi  Pointer to a multi object holding the auth_token variables
+ */
+static void
+wipe_auth_token(struct tls_multi *multi)
+{
+    if( multi )
+    {
+        if (multi->auth_token )
+        {
+            secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
+            free(multi->auth_token);
+        }
+        multi->auth_token = NULL;
+        multi->auth_token_sent = false;
+    }
+}
+
+
 /*
  * Remove authenticated state from all sessions in the given tunnel
  */
@@ -88,10 +110,10 @@ tls_deauthenticate(struct tls_multi *multi)
 {
     if (multi)
     {
-        int i, j;
-        for (i = 0; i < TM_SIZE; ++i)
+        wipe_auth_token(multi);
+        for (int i = 0; i < TM_SIZE; ++i)
         {
-            for (j = 0; j < KS_SIZE; ++j)
+            for (int j = 0; j < KS_SIZE; ++j)
             {
                 multi->session[i].key[j].authenticated = false;
             }
@@ -1219,21 +1241,6 @@ verify_user_pass_management(struct tls_session *session, const struct user_pass
 }
 #endif /* ifdef MANAGEMENT_DEF_AUTH */
 
-/**
- *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
- *
- *  @param multi  Pointer to a multi object holding the auth_token variables
- */
-static void
-wipe_auth_token(struct tls_multi *multi)
-{
-    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
-    free(multi->auth_token);
-    multi->auth_token = NULL;
-    multi->auth_token_sent = false;
-}
-
-
 /*
  * Main username/password verification entry point
  */
@@ -1285,7 +1292,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         /* Ensure that the username has not changed */
         if (!tls_lock_username(multi, up->username))
         {
-            wipe_auth_token(multi);
+            /* auth-token cleared in tls_lock_username() on failure */
             ks->authenticated = false;
             goto done;
         }
@@ -1306,7 +1313,6 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         if (memcmp_constant_time(multi->auth_token, up->password,
                                  strlen(multi->auth_token)) != 0)
         {
-            wipe_auth_token(multi);
             ks->authenticated = false;
             tls_deauthenticate(multi);
 
@@ -1478,6 +1484,7 @@ verify_final_auth_checks(struct tls_multi *multi, struct tls_session *session)
         if (!cn || !strcmp(cn, CCD_DEFAULT) || !test_file(path))
         {
             ks->authenticated = false;
+            wipe_auth_tokens(multi);
             msg(D_TLS_ERRORS, "TLS Auth Error: --client-config-dir authentication failed for common name '%s' file='%s'",
                 session->common_name,
                 path ? path : "UNDEF");
Signature · 1 line
2.11.0
#4 lore raw

Hi,

Quoted 31 lines · David Sommerseth

If tls_deauthenticate() was called, it could in some scenarios leave the authentication token for a session in memory. This change just ensures auth-tokens are always wiped as soon as a TLS session is considered broken.

---

The wipe_auth_token() function is otherwise moved to be declared before tls_deauthenticate() and the latter function is also slightly modified to make use of the C99 feature of inline declaration - mostly to have a more reasonable coding style when adding the wipe_auth_token() call.

v2 - Fixed coding style issues after changes in wipe_auth_token()
- Added wipe_auth_token() call when --ccd-exclusive auth fails

---
 src/openvpn/ssl_verify.c | 47 +++++++++++++++++++++++++++--------------------
 1 file changed, 27 insertions(+), 20 deletions(-)
src/openvpn/ssl_verify.c +3 -0
index a6e9be3..bc578fa 100644
@@ -80,6 +80,28 @@ setenv_untrusted(struct tls_session *session)
     setenv_link_socket_actual(session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
 }
 
+
+/**
+ *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags

src/openvpn/ssl_verify.c setenv_untrusted(struct tls_session *session) · line 95

Quoted 10 lines
src/openvpn/ssl_verify.c +10 -0
+ *
+ *  @param multi  Pointer to a multi object holding the auth_token variables
+ */
+static void
+wipe_auth_token(struct tls_multi *multi)
+{
+    if( multi )
+    {
+        if (multi->auth_token )
+        {

This still has weird spaces: "if( multi )" should be "if (multi)", and "if (multi->auth_token )" should be "if (multi->auth_token)".

Quoted 66 lines
src/openvpn/ssl_verify.c +13 -20
+            secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
+            free(multi->auth_token);
+        }
+        multi->auth_token = NULL;
+        multi->auth_token_sent = false;
+    }
+}
+
+
 /*
  * Remove authenticated state from all sessions in the given tunnel
  */
@@ -88,10 +110,10 @@ tls_deauthenticate(struct tls_multi *multi)
 {
     if (multi)
     {
-        int i, j;
-        for (i = 0; i < TM_SIZE; ++i)
+        wipe_auth_token(multi);
+        for (int i = 0; i < TM_SIZE; ++i)
         {
-            for (j = 0; j < KS_SIZE; ++j)
+            for (int j = 0; j < KS_SIZE; ++j)
             {
                 multi->session[i].key[j].authenticated = false;
             }
@@ -1219,21 +1241,6 @@ verify_user_pass_management(struct tls_session *session, const struct user_pass
 }
 #endif /* ifdef MANAGEMENT_DEF_AUTH */
 
-/**
- *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
- *
- *  @param multi  Pointer to a multi object holding the auth_token variables
- */
-static void
-wipe_auth_token(struct tls_multi *multi)
-{
-    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
-    free(multi->auth_token);
-    multi->auth_token = NULL;
-    multi->auth_token_sent = false;
-}
-
-
 /*
  * Main username/password verification entry point
  */
@@ -1285,7 +1292,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         /* Ensure that the username has not changed */
         if (!tls_lock_username(multi, up->username))
         {
-            wipe_auth_token(multi);
+            /* auth-token cleared in tls_lock_username() on failure */
             ks->authenticated = false;
             goto done;
         }
@@ -1306,7 +1313,6 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
         if (memcmp_constant_time(multi->auth_token, up->password,
                                  strlen(multi->auth_token)) != 0)
         {
-            wipe_auth_token(multi);
             ks->authenticated = false;
             tls_deauthenticate(multi);
 

src/openvpn/ssl_verify.c verify_final_auth_checks(struct tls_multi *multi, struct tls_session *session) · line 1487

Quoted 4 lines
src/openvpn/ssl_verify.c +1 -0
@@ -1478,6 +1484,7 @@ verify_final_auth_checks(struct tls_multi *multi, struct tls_session *session)
         if (!cn || !strcmp(cn, CCD_DEFAULT) || !test_file(path))
         {
             ks->authenticated = false;
+            wipe_auth_tokens(multi);

This should be wipe_auth_token(), not wipe_auth_tokens().

src/openvpn/ssl_verify.c verify_final_auth_checks(struct tls_multi *multi, struct tls_session *session) · line 1490

Quoted 4 lines
src/openvpn/ssl_verify.c +0 -0
             msg(D_TLS_ERRORS, "TLS Auth Error: --client-config-dir authentication failed for common name '%s' file='%s'",
                 session->common_name,
                 path ? path : "UNDEF");

Otherwise this looks good. So if the above two comments are processed, ACK. I'm fine with you doing that on-the-fly.

-Steffan

#5 lore raw
In reply to David Sommerseth

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

The embarrassing mistakes in the v2 patch to the ML was corrected on the fly.

Your patch has been applied to the following branches

commit daab0a9fa8ff4f40e8a34707db0ac156d49fbfcb (master) commit 79b93b6e421637fcd3de5cebd08d28fdfc6bdc1e (release/2.4)

Author: David Sommerseth
Date:   Tue Mar 28 22:53:46 2017 +0200
     auth-token: Ensure tokens are always wiped on de-auth

     Signed-off-by: David Sommerseth <[email protected]...>
     Acked-by: Steffan Karger <[email protected]...>
     Message-Id: <[email protected]...>
     URL: https://www.mail-archive.com/[email protected]/msg14344.html
     Signed-off-by: David Sommerseth <[email protected]...>

- --
kind regards,

David Sommerseth

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBCAAGBQJY249fAAoJEIbPlEyWcf3yQF8P/RHHvrJ7dyxPdHnDj3nVTZRA QroQ/nbs8a3BNd17zqoxlRbdbYGb+P2zbSk+cPge9JqANAV1u++SUfsATjwnASer pCQ6JtETGmbyqBC4lhmvJrtc+t/4U2LcenEEWLtTTWLEO89QoFGzzLQUgS5N/MOz YHT11k0+P5Tcwf/DexQViqJwM3LRIIkZXnSV6xeBiIl0YeEKSht+14bUMhkqYnw9 SLNNBRDT8RweHpcZhsi6Gj2GAo+yRyXTXtniSp1A+N36QzngsbPEODVbH6RQ10Fl r0CFcTqmj46hGJ4Q9ofkXNry0W5f/Zq0hxuiVonZmYbdev20zYIRab9m/8yi2zMn PDJQ2fvPEHqmCHI+7BCd7RTZWyWMnSYD2SjpLXUHZmjvaMMZp8v9VPLJaKdD3GJN M7f++wb34Ho/eVSjqlcmuIddw8ttQeyUUI0btpwZ03DuUHpALZKNkUUcnJPqA7nO OFLym/dutUcImM/8S9AYRJ6ymDY+RIpZOsNZ9gy/eVND6oE9GfiTREwc7JYE+Z6Q yTlExnng61KMtfMusYPz1HR0epKhCkzIIlWuQZGDkgNTyYzlqD2rUsQMMflhfkZ2 T/9G5hrgfKmGbOvZVBnBSmbSsuzqg6A2Ksz6H1Qwz2UvinF3Aquds1REAES2TCYP IElHZ1Fee6ho5MOLQiZb
=mj0h
-----END PGP SIGNATURE-----