rev |
line source |
shann@25666
|
1 From 8e6485a1bcb0baffdea9e55255a81270b768439c Mon Sep 17 00:00:00 2001
|
shann@25666
|
2 From: Jouni Malinen <j@w1.fi>
|
shann@25666
|
3 Date: Sat, 8 Jul 2023 19:55:32 +0300
|
shann@25666
|
4 Subject: PEAP client: Update Phase 2 authentication requirements
|
shann@25666
|
5
|
shann@25666
|
6 The previous PEAP client behavior allowed the server to skip Phase 2
|
shann@25666
|
7 authentication with the expectation that the server was authenticated
|
shann@25666
|
8 during Phase 1 through TLS server certificate validation. Various PEAP
|
shann@25666
|
9 specifications are not exactly clear on what the behavior on this front
|
shann@25666
|
10 is supposed to be and as such, this ended up being more flexible than
|
shann@25666
|
11 the TTLS/FAST/TEAP cases. However, this is not really ideal when
|
shann@25666
|
12 unfortunately common misconfiguration of PEAP is used in deployed
|
shann@25666
|
13 devices where the server trust root (ca_cert) is not configured or the
|
shann@25666
|
14 user has an easy option for allowing this validation step to be skipped.
|
shann@25666
|
15
|
shann@25666
|
16 Change the default PEAP client behavior to be to require Phase 2
|
shann@25666
|
17 authentication to be successfully completed for cases where TLS session
|
shann@25666
|
18 resumption is not used and the client certificate has not been
|
shann@25666
|
19 configured. Those two exceptions are the main cases where a deployed
|
shann@25666
|
20 authentication server might skip Phase 2 and as such, where a more
|
shann@25666
|
21 strict default behavior could result in undesired interoperability
|
shann@25666
|
22 issues. Requiring Phase 2 authentication will end up disabling TLS
|
shann@25666
|
23 session resumption automatically to avoid interoperability issues.
|
shann@25666
|
24
|
shann@25666
|
25 Allow Phase 2 authentication behavior to be configured with a new phase1
|
shann@25666
|
26 configuration parameter option:
|
shann@25666
|
27 'phase2_auth' option can be used to control Phase 2 (i.e., within TLS
|
shann@25666
|
28 tunnel) behavior for PEAP:
|
shann@25666
|
29 * 0 = do not require Phase 2 authentication
|
shann@25666
|
30 * 1 = require Phase 2 authentication when client certificate
|
shann@25666
|
31 (private_key/client_cert) is no used and TLS session resumption was
|
shann@25666
|
32 not used (default)
|
shann@25666
|
33 * 2 = require Phase 2 authentication in all cases
|
shann@25666
|
34
|
shann@25666
|
35 Signed-off-by: Jouni Malinen <j@w1.fi>
|
shann@25666
|
36 ---
|
shann@25666
|
37 src/eap_peer/eap_config.h | 8 ++++++++
|
shann@25666
|
38 src/eap_peer/eap_peap.c | 40 +++++++++++++++++++++++++++++++++++---
|
shann@25666
|
39 src/eap_peer/eap_tls_common.c | 6 ++++++
|
shann@25666
|
40 src/eap_peer/eap_tls_common.h | 5 +++++
|
shann@25666
|
41 wpa_supplicant/wpa_supplicant.conf | 7 +++++++
|
shann@25666
|
42 5 files changed, 63 insertions(+), 3 deletions(-)
|
shann@25666
|
43
|
shann@25666
|
44 diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h
|
shann@25666
|
45 index 26744ab68..58d5a1359 100644
|
shann@25666
|
46 --- a/src/eap_peer/eap_config.h
|
shann@25666
|
47 +++ b/src/eap_peer/eap_config.h
|
shann@25666
|
48 @@ -471,6 +471,14 @@ struct eap_peer_config {
|
shann@25666
|
49 * 1 = use cryptobinding if server supports it
|
shann@25666
|
50 * 2 = require cryptobinding
|
shann@25666
|
51 *
|
shann@25666
|
52 + * phase2_auth option can be used to control Phase 2 (i.e., within TLS
|
shann@25666
|
53 + * tunnel) behavior for PEAP:
|
shann@25666
|
54 + * 0 = do not require Phase 2 authentication
|
shann@25666
|
55 + * 1 = require Phase 2 authentication when client certificate
|
shann@25666
|
56 + * (private_key/client_cert) is no used and TLS session resumption was
|
shann@25666
|
57 + * not used (default)
|
shann@25666
|
58 + * 2 = require Phase 2 authentication in all cases
|
shann@25666
|
59 + *
|
shann@25666
|
60 * EAP-WSC (WPS) uses following options: pin=Device_Password and
|
shann@25666
|
61 * uuid=Device_UUID
|
shann@25666
|
62 *
|
shann@25666
|
63 diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
|
shann@25666
|
64 index 12e30df29..608069719 100644
|
shann@25666
|
65 --- a/src/eap_peer/eap_peap.c
|
shann@25666
|
66 +++ b/src/eap_peer/eap_peap.c
|
shann@25666
|
67 @@ -67,6 +67,7 @@ struct eap_peap_data {
|
shann@25666
|
68 u8 cmk[20];
|
shann@25666
|
69 int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP)
|
shann@25666
|
70 * is enabled. */
|
shann@25666
|
71 + enum { NO_AUTH, FOR_INITIAL, ALWAYS } phase2_auth;
|
shann@25666
|
72 };
|
shann@25666
|
73
|
shann@25666
|
74
|
shann@25666
|
75 @@ -114,6 +115,19 @@ static void eap_peap_parse_phase1(struct eap_peap_data *data,
|
shann@25666
|
76 wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
|
shann@25666
|
77 }
|
shann@25666
|
78
|
shann@25666
|
79 + if (os_strstr(phase1, "phase2_auth=0")) {
|
shann@25666
|
80 + data->phase2_auth = NO_AUTH;
|
shann@25666
|
81 + wpa_printf(MSG_DEBUG,
|
shann@25666
|
82 + "EAP-PEAP: Do not require Phase 2 authentication");
|
shann@25666
|
83 + } else if (os_strstr(phase1, "phase2_auth=1")) {
|
shann@25666
|
84 + data->phase2_auth = FOR_INITIAL;
|
shann@25666
|
85 + wpa_printf(MSG_DEBUG,
|
shann@25666
|
86 + "EAP-PEAP: Require Phase 2 authentication for initial connection");
|
shann@25666
|
87 + } else if (os_strstr(phase1, "phase2_auth=2")) {
|
shann@25666
|
88 + data->phase2_auth = ALWAYS;
|
shann@25666
|
89 + wpa_printf(MSG_DEBUG,
|
shann@25666
|
90 + "EAP-PEAP: Require Phase 2 authentication for all cases");
|
shann@25666
|
91 + }
|
shann@25666
|
92 #ifdef EAP_TNC
|
shann@25666
|
93 if (os_strstr(phase1, "tnc=soh2")) {
|
shann@25666
|
94 data->soh = 2;
|
shann@25666
|
95 @@ -142,6 +156,7 @@ static void * eap_peap_init(struct eap_sm *sm)
|
shann@25666
|
96 data->force_peap_version = -1;
|
shann@25666
|
97 data->peap_outer_success = 2;
|
shann@25666
|
98 data->crypto_binding = OPTIONAL_BINDING;
|
shann@25666
|
99 + data->phase2_auth = FOR_INITIAL;
|
shann@25666
|
100
|
shann@25666
|
101 if (config && config->phase1)
|
shann@25666
|
102 eap_peap_parse_phase1(data, config->phase1);
|
shann@25666
|
103 @@ -454,6 +469,20 @@ static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
|
shann@25666
|
104 }
|
shann@25666
|
105
|
shann@25666
|
106
|
shann@25666
|
107 +static bool peap_phase2_sufficient(struct eap_sm *sm,
|
shann@25666
|
108 + struct eap_peap_data *data)
|
shann@25666
|
109 +{
|
shann@25666
|
110 + if ((data->phase2_auth == ALWAYS ||
|
shann@25666
|
111 + (data->phase2_auth == FOR_INITIAL &&
|
shann@25666
|
112 + !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn) &&
|
shann@25666
|
113 + !data->ssl.client_cert_conf) ||
|
shann@25666
|
114 + data->phase2_eap_started) &&
|
shann@25666
|
115 + !data->phase2_eap_success)
|
shann@25666
|
116 + return false;
|
shann@25666
|
117 + return true;
|
shann@25666
|
118 +}
|
shann@25666
|
119 +
|
shann@25666
|
120 +
|
shann@25666
|
121 /**
|
shann@25666
|
122 * eap_tlv_process - Process a received EAP-TLV message and generate a response
|
shann@25666
|
123 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
shann@25666
|
124 @@ -568,6 +597,11 @@ static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
|
shann@25666
|
125 " - force failed Phase 2");
|
shann@25666
|
126 resp_status = EAP_TLV_RESULT_FAILURE;
|
shann@25666
|
127 ret->decision = DECISION_FAIL;
|
shann@25666
|
128 + } else if (!peap_phase2_sufficient(sm, data)) {
|
shann@25666
|
129 + wpa_printf(MSG_INFO,
|
shann@25666
|
130 + "EAP-PEAP: Server indicated Phase 2 success, but sufficient Phase 2 authentication has not been completed");
|
shann@25666
|
131 + resp_status = EAP_TLV_RESULT_FAILURE;
|
shann@25666
|
132 + ret->decision = DECISION_FAIL;
|
shann@25666
|
133 } else {
|
shann@25666
|
134 resp_status = EAP_TLV_RESULT_SUCCESS;
|
shann@25666
|
135 ret->decision = DECISION_UNCOND_SUCC;
|
shann@25666
|
136 @@ -887,8 +921,7 @@ continue_req:
|
shann@25666
|
137 /* EAP-Success within TLS tunnel is used to indicate
|
shann@25666
|
138 * shutdown of the TLS channel. The authentication has
|
shann@25666
|
139 * been completed. */
|
shann@25666
|
140 - if (data->phase2_eap_started &&
|
shann@25666
|
141 - !data->phase2_eap_success) {
|
shann@25666
|
142 + if (!peap_phase2_sufficient(sm, data)) {
|
shann@25666
|
143 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
|
shann@25666
|
144 "Success used to indicate success, "
|
shann@25666
|
145 "but Phase 2 EAP was not yet "
|
shann@25666
|
146 @@ -1199,8 +1232,9 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
shann@25666
|
147 static bool eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
|
shann@25666
|
148 {
|
shann@25666
|
149 struct eap_peap_data *data = priv;
|
shann@25666
|
150 +
|
shann@25666
|
151 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
|
shann@25666
|
152 - data->phase2_success;
|
shann@25666
|
153 + data->phase2_success && data->phase2_auth != ALWAYS;
|
shann@25666
|
154 }
|
shann@25666
|
155
|
shann@25666
|
156
|
shann@25666
|
157 diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
|
shann@25666
|
158 index 6193b4bdb..966cbd6c7 100644
|
shann@25666
|
159 --- a/src/eap_peer/eap_tls_common.c
|
shann@25666
|
160 +++ b/src/eap_peer/eap_tls_common.c
|
shann@25666
|
161 @@ -242,6 +242,12 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
|
shann@25666
|
162
|
shann@25666
|
163 sm->ext_cert_check = !!(params->flags & TLS_CONN_EXT_CERT_CHECK);
|
shann@25666
|
164
|
shann@25666
|
165 + if (!phase2)
|
shann@25666
|
166 + data->client_cert_conf = params->client_cert ||
|
shann@25666
|
167 + params->client_cert_blob ||
|
shann@25666
|
168 + params->private_key ||
|
shann@25666
|
169 + params->private_key_blob;
|
shann@25666
|
170 +
|
shann@25666
|
171 return 0;
|
shann@25666
|
172 }
|
shann@25666
|
173
|
shann@25666
|
174 diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h
|
shann@25666
|
175 index 9ac00121f..334863413 100644
|
shann@25666
|
176 --- a/src/eap_peer/eap_tls_common.h
|
shann@25666
|
177 +++ b/src/eap_peer/eap_tls_common.h
|
shann@25666
|
178 @@ -79,6 +79,11 @@ struct eap_ssl_data {
|
shann@25666
|
179 * tls_v13 - Whether TLS v1.3 or newer is used
|
shann@25666
|
180 */
|
shann@25666
|
181 int tls_v13;
|
shann@25666
|
182 +
|
shann@25666
|
183 + /**
|
shann@25666
|
184 + * client_cert_conf: Whether client certificate has been configured
|
shann@25666
|
185 + */
|
shann@25666
|
186 + bool client_cert_conf;
|
shann@25666
|
187 };
|
shann@25666
|
188
|
shann@25666
|
189
|
shann@25666
|
190 diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
|
shann@25666
|
191 index f0b82443e..1b09f57d3 100644
|
shann@25666
|
192 --- a/wpa_supplicant/wpa_supplicant.conf
|
shann@25666
|
193 +++ b/wpa_supplicant/wpa_supplicant.conf
|
shann@25666
|
194 @@ -1370,6 +1370,13 @@ fast_reauth=1
|
shann@25666
|
195 # * 0 = do not use cryptobinding (default)
|
shann@25666
|
196 # * 1 = use cryptobinding if server supports it
|
shann@25666
|
197 # * 2 = require cryptobinding
|
shann@25666
|
198 +# 'phase2_auth' option can be used to control Phase 2 (i.e., within TLS
|
shann@25666
|
199 +# tunnel) behavior for PEAP:
|
shann@25666
|
200 +# * 0 = do not require Phase 2 authentication
|
shann@25666
|
201 +# * 1 = require Phase 2 authentication when client certificate
|
shann@25666
|
202 +# (private_key/client_cert) is no used and TLS session resumption was
|
shann@25666
|
203 +# not used (default)
|
shann@25666
|
204 +# * 2 = require Phase 2 authentication in all cases
|
shann@25666
|
205 # EAP-WSC (WPS) uses following options: pin=<Device Password> or
|
shann@25666
|
206 # pbc=1.
|
shann@25666
|
207 #
|
shann@25666
|
208 --
|
shann@25666
|
209 cgit v1.2.3-18-g5258
|