aboutsummaryrefslogtreecommitdiffstats
path: root/meta-networking/recipes-support/strongswan/files/CVE-2021-45079.patch
blob: 97aa6a0efcb3e6df463993bd94b8f5c8bcf14a92 (plain)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
From 76968cdd6b79f6ae40d674554e902ced192fd33e Mon Sep 17 00:00:00 2001
From: Tobias Brunner <tobias@strongswan.org>
Date: Tue, 14 Dec 2021 10:51:35 +0100
Subject: [PATCH] eap-authenticator: Enforce failure if MSK generation fails

Without this, the authentication succeeded if the server sent an early
EAP-Success message for mutual, key-generating EAP methods like EAP-TLS,
which may be used in EAP-only scenarios but would complete without server
or client authentication.  For clients configured for such EAP-only
scenarios, a rogue server could capture traffic after the tunnel is
established or even access hosts behind the client.  For non-mutual EAP
methods, public key server authentication has been enforced for a while.

A server previously could also crash a client by sending an EAP-Success
immediately without initiating an actual EAP method.

Fixes: 0706c39cda52 ("added support for EAP methods not establishing an MSK")
Fixes: CVE-2021-45079

Upstream-Status: Backport [https://download.strongswan.org/security/CVE-2021-45079/strongswan-5.5.0-5.9.4_eap_success.patch]
CVE: CVE-2021-45079
Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>

---
 src/libcharon/plugins/eap_gtc/eap_gtc.c       |  2 +-
 src/libcharon/plugins/eap_md5/eap_md5.c       |  2 +-
 src/libcharon/plugins/eap_radius/eap_radius.c |  4 ++-
 src/libcharon/sa/eap/eap_method.h             |  8 ++++-
 .../ikev2/authenticators/eap_authenticator.c  | 32 ++++++++++++++++---
 5 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c
index 95ba090b79ce..cffb6222c2f8 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc.c
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c
@@ -195,7 +195,7 @@ METHOD(eap_method_t, get_type, eap_type_t,
 METHOD(eap_method_t, get_msk, status_t,
 	private_eap_gtc_t *this, chunk_t *msk)
 {
-	return FAILED;
+	return NOT_SUPPORTED;
 }
 
 METHOD(eap_method_t, get_identifier, uint8_t,
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c
index ab5f7ff6a823..3a92ad7c0a04 100644
--- a/src/libcharon/plugins/eap_md5/eap_md5.c
+++ b/src/libcharon/plugins/eap_md5/eap_md5.c
@@ -213,7 +213,7 @@ METHOD(eap_method_t, get_type, eap_type_t,
 METHOD(eap_method_t, get_msk, status_t,
 	private_eap_md5_t *this, chunk_t *msk)
 {
-	return FAILED;
+	return NOT_SUPPORTED;
 }
 
 METHOD(eap_method_t, is_mutual, bool,
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
index 2dc7a423e702..5336dead13d9 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius.c
@@ -733,7 +733,9 @@ METHOD(eap_method_t, get_msk, status_t,
 		*out = msk;
 		return SUCCESS;
 	}
-	return FAILED;
+	/* we assume the selected method did not establish an MSK, if it failed
+	 * to establish one, process() would have failed */
+	return NOT_SUPPORTED;
 }
 
 METHOD(eap_method_t, get_identifier, uint8_t,
diff --git a/src/libcharon/sa/eap/eap_method.h b/src/libcharon/sa/eap/eap_method.h
index 0b5218dfec15..33564831f86e 100644
--- a/src/libcharon/sa/eap/eap_method.h
+++ b/src/libcharon/sa/eap/eap_method.h
@@ -114,10 +114,16 @@ struct eap_method_t {
 	 * Not all EAP methods establish a shared secret. For implementations of
 	 * the EAP-Identity method, get_msk() returns the received identity.
 	 *
+	 * @note Returning NOT_SUPPORTED is important for implementations of EAP
+	 * methods that don't establish an MSK.  In particular as client because
+	 * key-generating EAP methods MUST fail to process EAP-Success messages if
+	 * no MSK is established.
+	 *
 	 * @param msk			chunk receiving internal stored MSK
 	 * @return
-	 *						- SUCCESS, or
+	 *						- SUCCESS, if MSK is established
 	 * 						- FAILED, if MSK not established (yet)
+	 *						- NOT_SUPPORTED, for non-MSK-establishing methods
 	 */
 	status_t (*get_msk) (eap_method_t *this, chunk_t *msk);
 
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index e1e6cd7ee6f3..87548fc471a6 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -305,9 +305,17 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
 				this->method->destroy(this->method);
 				return server_initiate_eap(this, FALSE);
 			}
-			if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
+			switch (this->method->get_msk(this->method, &this->msk))
 			{
-				this->msk = chunk_clone(this->msk);
+				case SUCCESS:
+					this->msk = chunk_clone(this->msk);
+					break;
+				case NOT_SUPPORTED:
+					break;
+				case FAILED:
+				default:
+					DBG1(DBG_IKE, "failed to establish MSK");
+					goto failure;
 			}
 			if (vendor)
 			{
@@ -326,6 +334,7 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
 			return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
 		case FAILED:
 		default:
+failure:
 			/* type might have changed for virtual methods */
 			type = this->method->get_type(this->method, &vendor);
 			if (vendor)
@@ -661,9 +670,24 @@ METHOD(authenticator_t, process_client, status_t,
 				uint32_t vendor;
 				auth_cfg_t *cfg;
 
-				if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
+				if (!this->method)
 				{
-					this->msk = chunk_clone(this->msk);
+					DBG1(DBG_IKE, "received unexpected %N",
+						 eap_code_names, eap_payload->get_code(eap_payload));
+					return FAILED;
+				}
+				switch (this->method->get_msk(this->method, &this->msk))
+				{
+					case SUCCESS:
+						this->msk = chunk_clone(this->msk);
+						break;
+					case NOT_SUPPORTED:
+						break;
+					case FAILED:
+					default:
+						DBG1(DBG_IKE, "received %N but failed to establish MSK",
+							 eap_code_names, eap_payload->get_code(eap_payload));
+						return FAILED;
 				}
 				type = this->method->get_type(this->method, &vendor);
 				if (vendor)
-- 
2.25.1