When not using username and password (i.e. auth-user-pass) it can still
be desirable to provide the client with an auth-token, e.g. for allowing
a session to continue after a reconnect without requiring 2FA again.
However, without --auth-user-pass openvpn does not have a username and will
ignore any pushed auth-token command.
This patch adds support for auth-token-user to set the username that should
be used for auth-token
The spec of using auth-token-user base64-encoded-user are the ones that
OpenVPN3 already implements.
Patch V2: Improve style, fix comments and commit message
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20210520151148.2565578-2-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22417.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -50,6 +50,14 @@ configuration. |
50 | 50 |
after a failed auth. Older clients will keep using the token value and |
51 | 51 |
react according to ``--auth-retry`` |
52 | 52 |
|
53 |
+--auth-token-user base64username |
|
54 |
+ Companion option to ``--auth-token``. This options allows to override |
|
55 |
+ the username used by the client when reauthenticating with the ``auth-token``. |
|
56 |
+ It also allows to use ``--auth-token`` in setups that normally do not use |
|
57 |
+ username and password. |
|
58 |
+ |
|
59 |
+ The username has to be base64 encoded. |
|
60 |
+ |
|
53 | 61 |
--auth-user-pass |
54 | 62 |
Authenticate with server using username/password. |
55 | 63 |
|
... | ... |
@@ -490,22 +490,49 @@ void |
490 | 490 |
set_auth_token(struct user_pass *up, struct user_pass *tk, const char *token) |
491 | 491 |
{ |
492 | 492 |
|
493 |
- if (strlen(token) && (up->defined || tk->defined)) |
|
493 |
+ if (strlen(token)) |
|
494 | 494 |
{ |
495 |
- /* auth-token has no password, so it needs the username |
|
496 |
- * either already set or copied from up */ |
|
497 | 495 |
strncpynt(tk->password, token, USER_PASS_LEN); |
498 |
- if (up->defined) |
|
496 |
+ tk->token_defined = true; |
|
497 |
+ |
|
498 |
+ /* |
|
499 |
+ * --auth-token has no username, so it needs the username |
|
500 |
+ * either already set or copied from up, or later set by |
|
501 |
+ * --auth-token-user |
|
502 |
+ * |
|
503 |
+ * Do not overwrite the username if already set to avoid |
|
504 |
+ * overwriting an username set by --auth-token-user |
|
505 |
+ */ |
|
506 |
+ if (up->defined && !tk->defined) |
|
499 | 507 |
{ |
500 | 508 |
strncpynt(tk->username, up->username, USER_PASS_LEN); |
509 |
+ tk->defined = true; |
|
501 | 510 |
} |
502 |
- tk->defined = true; |
|
503 | 511 |
} |
504 | 512 |
|
505 | 513 |
/* Cleans user/pass for nocache */ |
506 | 514 |
purge_user_pass(up, false); |
507 | 515 |
} |
508 | 516 |
|
517 |
+void |
|
518 |
+set_auth_token_user(struct user_pass *tk, const char *username) |
|
519 |
+{ |
|
520 |
+ if (strlen(username)) |
|
521 |
+ { |
|
522 |
+ /* Clear the username before decoding to ensure no old material is left |
|
523 |
+ * and also allow decoding to not use all space to ensure the last byte is |
|
524 |
+ * always 0 */ |
|
525 |
+ CLEAR(tk->username); |
|
526 |
+ int len = openvpn_base64_decode(username, tk->username, USER_PASS_LEN - 1); |
|
527 |
+ tk->defined = len > 0; |
|
528 |
+ if (!tk->defined) |
|
529 |
+ { |
|
530 |
+ msg(D_PUSH, "Error decoding auth-token-username"); |
|
531 |
+ } |
|
532 |
+ } |
|
533 |
+} |
|
534 |
+ |
|
535 |
+ |
|
509 | 536 |
/* |
510 | 537 |
* Process string received by untrusted peer before |
511 | 538 |
* printing to console or log file. |
... | ... |
@@ -56,6 +56,9 @@ const char *hostname_randomize(const char *hostname, struct gc_arena *gc); |
56 | 56 |
struct user_pass |
57 | 57 |
{ |
58 | 58 |
bool defined; |
59 |
+ /* For auth-token username and token can be set individually, so we |
|
60 |
+ * use this second bool to track if the token (password) is defined */ |
|
61 |
+ bool token_defined; |
|
59 | 62 |
bool nocache; |
60 | 63 |
|
61 | 64 |
/* max length of username/password */ |
... | ... |
@@ -138,19 +141,31 @@ void fail_user_pass(const char *prefix, |
138 | 138 |
void purge_user_pass(struct user_pass *up, const bool force); |
139 | 139 |
|
140 | 140 |
/** |
141 |
- * Sets the auth-token to token if a username is available from either |
|
142 |
- * up or already present in tk. The method will also purge up if |
|
141 |
+ * Sets the auth-token to token. If a username is available from |
|
142 |
+ * either up or already present in tk that will be used as default |
|
143 |
+ * username for the token. The method will also purge up if |
|
143 | 144 |
* the auth-nocache option is active. |
144 | 145 |
* |
145 | 146 |
* @param up (non Auth-token) Username/password |
146 | 147 |
* @param tk auth-token userpass to set |
147 |
- * @param token token to use as password for the |
|
148 |
+ * @param token token to use as password for the auth-token |
|
148 | 149 |
* |
149 | 150 |
* @note all parameters to this function must not be null. |
150 | 151 |
*/ |
151 | 152 |
void set_auth_token(struct user_pass *up, struct user_pass *tk, |
152 | 153 |
const char *token); |
153 | 154 |
|
155 |
+/** |
|
156 |
+ * Sets the auth-token username by base64 decoding the passed |
|
157 |
+ * username |
|
158 |
+ * |
|
159 |
+ * @param tk auth-token userpass to set |
|
160 |
+ * @param username base64 encoded username to set |
|
161 |
+ * |
|
162 |
+ * @note all parameters to this function must not be null. |
|
163 |
+ */ |
|
164 |
+void set_auth_token_user(struct user_pass *tk, const char *username); |
|
165 |
+ |
|
154 | 166 |
/* |
155 | 167 |
* Process string received by untrusted peer before |
156 | 168 |
* printing to console or log file. |
... | ... |
@@ -8311,6 +8311,11 @@ add_option(struct options *options, |
8311 | 8311 |
} |
8312 | 8312 |
#endif |
8313 | 8313 |
} |
8314 |
+ else if (streq(p[0], "auth-token-user") && p[1] && !p[2]) |
|
8315 |
+ { |
|
8316 |
+ VERIFY_PERMISSION(OPT_P_ECHO); |
|
8317 |
+ ssl_set_auth_token_user(p[1]); |
|
8318 |
+ } |
|
8314 | 8319 |
else if (streq(p[0], "single-session") && !p[1]) |
8315 | 8320 |
{ |
8316 | 8321 |
VERIFY_PERMISSION(OPT_P_GENERAL); |
... | ... |
@@ -446,6 +446,12 @@ ssl_set_auth_token(const char *token) |
446 | 446 |
set_auth_token(&auth_user_pass, &auth_token, token); |
447 | 447 |
} |
448 | 448 |
|
449 |
+void |
|
450 |
+ssl_set_auth_token_user(const char *username) |
|
451 |
+{ |
|
452 |
+ set_auth_token_user(&auth_token, username); |
|
453 |
+} |
|
454 |
+ |
|
449 | 455 |
/* |
450 | 456 |
* Cleans an auth token and checks if it was active |
451 | 457 |
*/ |
... | ... |
@@ -2310,8 +2316,8 @@ key_method_2_write(struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
2310 | 2310 |
} |
2311 | 2311 |
} |
2312 | 2312 |
|
2313 |
- /* write username/password if specified */ |
|
2314 |
- if (auth_user_pass_enabled) |
|
2313 |
+ /* write username/password if specified or we are using a auth-token */ |
|
2314 |
+ if (auth_user_pass_enabled || (auth_token.token_defined && auth_token.defined)) |
|
2315 | 2315 |
{ |
2316 | 2316 |
#ifdef ENABLE_MANAGEMENT |
2317 | 2317 |
auth_user_pass_setup(session->opt->auth_user_pass_file, session->opt->sci); |
... | ... |
@@ -2324,7 +2330,7 @@ key_method_2_write(struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
2324 | 2324 |
* If we have a valid auth-token, send that instead of real |
2325 | 2325 |
* username/password |
2326 | 2326 |
*/ |
2327 |
- if (auth_token.defined) |
|
2327 |
+ if (auth_token.token_defined && auth_token.defined) |
|
2328 | 2328 |
{ |
2329 | 2329 |
up = &auth_token; |
2330 | 2330 |
} |