1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
From 3d18e308c4e7e6f7ab7c2826c70d2d07b031c18a Mon Sep 17 00:00:00 2001
From: Arne Schwabe <arne@rfc2549.org>
Date: Sat, 27 Mar 2021 19:35:44 +0100
Subject: [PATCH] Ensure auth-token is only sent on a fully authenticated
session
This fixes the problem that if client authentication is deferred, we
send an updated token before the authentication fully finished.
Calling the new ssl_session_fully_authenticated from the two places
that do the state transition to KS_AUTH_TRUE is a bit suboptimal but
a cleaner solution requires more refactoring of the involved methods
and state machines.
This bug allows - under very specific circumstances - to trick a
server using delayed authentication (plugin or management) *and*
"--auth-gen-token" into returning a PUSH_REPLY before the AUTH_FAILED
message, which can possibly be used to gather information about a
VPN setup or even get access to a VPN with an otherwise-invalid account.
CVE-2020-15078 has been assigned to acknowledge this risk.
CVE: 2020-15078
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <d25ec73f-2ab0-31df-8cb6-7778000f4822@openvpn.net>
URL: non-public, embargoed
Signed-off-by: Gert Doering <gert@greenie.muc.de>
---
src/openvpn/ssl_verify.c | 64 +++++++++++++++++++++++++++-------------
1 file changed, 43 insertions(+), 21 deletions(-)
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
index 6fd51505e..55e7fedc0 100644
--- a/src/openvpn/ssl_verify.c
+++ b/src/openvpn/ssl_verify.c
@@ -906,6 +906,39 @@ key_state_test_auth_control_file(struct key_state *ks)
#endif /* ifdef PLUGIN_DEF_AUTH */
+/* This function is called when a session's primary key state first becomes KS_TRUE */
+void ssl_session_fully_authenticated(struct tls_multi *multi, struct tls_session* session)
+{
+ struct key_state *ks = &session->key[KS_PRIMARY];
+ if (ks->key_id == 0)
+ {
+ /* A key id of 0 indicates a new session and the client will
+ * get the auth-token as part of the initial push reply */
+ return;
+ }
+
+ /*
+ * Auth token already sent to client, update auth-token on client.
+ * The initial auth-token is sent as part of the push message, for this
+ * update we need to schedule an extra push message.
+ *
+ * Otherwise the auth-token get pushed out as part of the "normal"
+ * push-reply
+ */
+ if (multi->auth_token_initial)
+ {
+ /*
+ * We do not explicitly schedule the sending of the
+ * control message here but control message are only
+ * postponed when the control channel is not yet fully
+ * established and furthermore since this is called in
+ * the middle of authentication, there are other messages
+ * (new data channel keys) that are sent anyway and will
+ * trigger scheduling
+ */
+ send_push_reply_auth_token(multi);
+ }
+}
/*
* Return current session authentication state. Return
* value is TLS_AUTHENTICATION_x.
@@ -975,6 +1008,12 @@ tls_authentication_status(struct tls_multi *multi, const int latency)
case ACF_SUCCEEDED:
case ACF_DISABLED:
success = true;
+ /* i=0 is the TM_ACTIVE/KS_PRIMARY session */
+ if (i == 0 && ks->authenticated == KS_AUTH_DEFERRED)
+ {
+ ssl_session_fully_authenticated(multi,
+ &multi->session[TM_ACTIVE]);
+ }
ks->authenticated = KS_AUTH_TRUE;
break;
@@ -1385,31 +1424,14 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
*/
generate_auth_token(up, multi);
}
- /*
- * Auth token already sent to client, update auth-token on client.
- * The initial auth-token is sent as part of the push message, for this
- * update we need to schedule an extra push message.
- *
- * Otherwise the auth-token get pushed out as part of the "normal"
- * push-reply
- */
- if (multi->auth_token_initial)
- {
- /*
- * We do not explicitly schedule the sending of the
- * control message here but control message are only
- * postponed when the control channel is not yet fully
- * established and furthermore since this is called in
- * the middle of authentication, there are other messages
- * (new data channel keys) that are sent anyway and will
- * trigger schedueling
- */
- send_push_reply_auth_token(multi);
- }
msg(D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s",
(ks->authenticated == KS_AUTH_DEFERRED) ? "deferred" : "succeeded",
up->username,
(session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : "");
+ if (ks->authenticated == KS_AUTH_TRUE)
+ {
+ ssl_session_fully_authenticated(multi, session);
+ }
}
else
{
|