Browse code

auth-gen-token: Authenticate generated auth-tokens when client re-authenticates

On a server with --auth-gen-token enabled, the server will have created
a random token and pushed it to the client. When the client needs to
renegotiate the connection or otherwise reconnect, it will at this point
use the auth-token as password.

Here we check if we have a token generated and that it has been pushed
to the client, if so, then we check if the token matches the locally
stored token. If everything matches, we're done and the connection
is still authenticated.

If the auth-token authentication fails, we delete our local copy of
the token and changes the connection to not being authenticated. From
this moment of, the client needs to do a full reconnect providing
the users password again.

This token authentication also considers the token lifetime, if that
have been set via --auth-gen-token. If the token have expired, the
client is rejected and needs to do a full reconnect with a new
authentication using the users password.

v2 - Rename auth_generate_token to auth_token_generate
- Wrap lines exceeding 80 chars
- Improved several comments (rephrasing, grammar)

Signed-off-by: David Sommerseth <davids@openvpn.net>
Acked-by: Steffan Karger <steffan@karger.me>
Message-Id: <1477684124-26083-6-git-send-email-davids@openvpn.net>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg12822.html

David Sommerseth authored on 2016/10/29 04:48:44
Showing 1 changed files
... ...
@@ -1139,6 +1139,63 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
1139 1139
   string_mod_remap_name (up->username, COMMON_NAME_CHAR_CLASS);
1140 1140
   string_mod (up->password, CC_PRINT, CC_CRLF, '_');
1141 1141
 
1142
+  /* If server is configured with --auth-gen-token and we have an
1143
+   * authentication token for this client, this authentication
1144
+   * round will be done internally using the token instead of
1145
+   * calling any external authentication modules.
1146
+   */
1147
+  if (session->opt->auth_token_generate && multi->auth_token_sent
1148
+      && NULL != multi->auth_token)
1149
+    {
1150
+      unsigned int ssl_flags = session->opt->ssl_flags;
1151
+
1152
+      /* Ensure that the username has not changed */
1153
+      if (!tls_lock_username(multi, up->username))
1154
+        {
1155
+          ks->authenticated = false;
1156
+          goto done;
1157
+        }
1158
+
1159
+      /* If auth-token lifetime has been enabled,
1160
+       * ensure the token has not expired
1161
+       */
1162
+      if (session->opt->auth_token_lifetime > 0
1163
+          && (multi->auth_token_tstamp + session->opt->auth_token_lifetime) < now)
1164
+        {
1165
+          msg (D_HANDSHAKE, "Auth-token for client expired\n");
1166
+          ks->authenticated = false;
1167
+          goto done;
1168
+        }
1169
+
1170
+      /* The core authentication of the token itself */
1171
+      if (memcmp_constant_time(multi->auth_token, up->password,
1172
+                 strlen(multi->auth_token)) != 0)
1173
+        {
1174
+          memset (multi->auth_token, 0, AUTH_TOKEN_SIZE);
1175
+          free (multi->auth_token);
1176
+          multi->auth_token = NULL;
1177
+          multi->auth_token_sent = false;
1178
+          ks->authenticated = false;
1179
+          tls_deauthenticate (multi);
1180
+
1181
+          msg (D_TLS_ERRORS, "TLS Auth Error: Auth-token verification "
1182
+               "failed for username '%s' %s", up->username,
1183
+               (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : "");
1184
+        }
1185
+      else
1186
+        {
1187
+          ks->authenticated = true;
1188
+
1189
+          if (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME)
1190
+            set_common_name (session, up->username);
1191
+          msg (D_HANDSHAKE, "TLS: Username/auth-token authentication "
1192
+               "succeeded for username '%s' %s",
1193
+               up->username,
1194
+               (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : "");
1195
+        }
1196
+      goto done;
1197
+    }
1198
+
1142 1199
   /* call plugin(s) and/or script */
1143 1200
 #ifdef MANAGEMENT_DEF_AUTH
1144 1201
   if (man_def_auth == KMDA_DEF)
... ...
@@ -1232,6 +1289,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
1232 1232
       msg (D_TLS_ERRORS, "TLS Auth Error: Auth Username/Password verification failed for peer");
1233 1233
     }
1234 1234
 
1235
+ done:
1235 1236
   gc_free (&gc);
1236 1237
 }
1237 1238