From c70e847bc40cb58c8be90410f1b59cad04cfc703 Mon Sep 17 00:00:00 2001 From: SubmarinePhantom Date: Tue, 16 Apr 2024 14:09:46 +0800 Subject: [PATCH] =?UTF-8?q?CVE-2024-25670=20wpa=20=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E6=BC=8F=E6=B4=9Epatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SubmarinePhantom Change-Id: If7369fa8792363570d115cd48b870f9b6e1edcfc --- .../src/eap_peer/eap_config.h | 8 ++++ .../src/eap_peer/eap_peap.c | 40 +++++++++++++++++-- .../src/eap_peer/eap_tls_common.c | 6 +++ .../src/eap_peer/eap_tls_common.h | 5 +++ .../wpa_supplicant/wpa_supplicant.conf | 7 ++++ 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant-2.9_standard/src/eap_peer/eap_config.h b/wpa_supplicant-2.9_standard/src/eap_peer/eap_config.h index 583e16a..1321541 100644 --- a/wpa_supplicant-2.9_standard/src/eap_peer/eap_config.h +++ b/wpa_supplicant-2.9_standard/src/eap_peer/eap_config.h @@ -484,6 +484,14 @@ struct eap_peer_config { * 1 = use cryptobinding if server supports it * 2 = require cryptobinding * + * phase2_auth option can be used to control Phase 2 (i.e., within TLS + * tunnel) behavior for PEAP: + * 0 = do not require Phase 2 authentication + * 1 = require Phase 2 authentication when client certificate + * (private_key/client_cert) is no used and TLS session resumption was + * not used (default) + * 2 = require Phase 2 authentication in all cases + * * EAP-WSC (WPS) uses following options: pin=Device_Password and * uuid=Device_UUID * diff --git a/wpa_supplicant-2.9_standard/src/eap_peer/eap_peap.c b/wpa_supplicant-2.9_standard/src/eap_peer/eap_peap.c index 12e30df..6080697 100644 --- a/wpa_supplicant-2.9_standard/src/eap_peer/eap_peap.c +++ b/wpa_supplicant-2.9_standard/src/eap_peer/eap_peap.c @@ -67,6 +67,7 @@ struct eap_peap_data { u8 cmk[20]; int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) * is enabled. */ + enum { NO_AUTH, FOR_INITIAL, ALWAYS } phase2_auth; }; @@ -114,6 +115,19 @@ static void eap_peap_parse_phase1(struct eap_peap_data *data, wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); } + if (os_strstr(phase1, "phase2_auth=0")) { + data->phase2_auth = NO_AUTH; + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Do not require Phase 2 authentication"); + } else if (os_strstr(phase1, "phase2_auth=1")) { + data->phase2_auth = FOR_INITIAL; + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Require Phase 2 authentication for initial connection"); + } else if (os_strstr(phase1, "phase2_auth=2")) { + data->phase2_auth = ALWAYS; + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Require Phase 2 authentication for all cases"); + } #ifdef EAP_TNC if (os_strstr(phase1, "tnc=soh2")) { data->soh = 2; @@ -142,6 +156,7 @@ static void * eap_peap_init(struct eap_sm *sm) data->force_peap_version = -1; data->peap_outer_success = 2; data->crypto_binding = OPTIONAL_BINDING; + data->phase2_auth = FOR_INITIAL; if (config && config->phase1) eap_peap_parse_phase1(data, config->phase1); @@ -454,6 +469,20 @@ static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, } +static bool peap_phase2_sufficient(struct eap_sm *sm, + struct eap_peap_data *data) +{ + if ((data->phase2_auth == ALWAYS || + (data->phase2_auth == FOR_INITIAL && + !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn) && + !data->ssl.client_cert_conf) || + data->phase2_eap_started) && + !data->phase2_eap_success) + return false; + return true; +} + + /** * eap_tlv_process - Process a received EAP-TLV message and generate a response * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() @@ -568,6 +597,11 @@ static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, " - force failed Phase 2"); resp_status = EAP_TLV_RESULT_FAILURE; ret->decision = DECISION_FAIL; + } else if (!peap_phase2_sufficient(sm, data)) { + wpa_printf(MSG_INFO, + "EAP-PEAP: Server indicated Phase 2 success, but sufficient Phase 2 authentication has not been completed"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; } else { resp_status = EAP_TLV_RESULT_SUCCESS; ret->decision = DECISION_UNCOND_SUCC; @@ -887,8 +921,7 @@ continue_req: /* EAP-Success within TLS tunnel is used to indicate * shutdown of the TLS channel. The authentication has * been completed. */ - if (data->phase2_eap_started && - !data->phase2_eap_success) { + if (!peap_phase2_sufficient(sm, data)) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " "Success used to indicate success, " "but Phase 2 EAP was not yet " @@ -1199,8 +1232,9 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, static bool eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; + return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; + data->phase2_success && data->phase2_auth != ALWAYS; } diff --git a/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.c b/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.c index c1837db..a53eeb1 100644 --- a/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.c +++ b/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.c @@ -239,6 +239,12 @@ static int eap_tls_params_from_conf(struct eap_sm *sm, sm->ext_cert_check = !!(params->flags & TLS_CONN_EXT_CERT_CHECK); + if (!phase2) + data->client_cert_conf = params->client_cert || + params->client_cert_blob || + params->private_key || + params->private_key_blob; + return 0; } diff --git a/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.h b/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.h index 9ac0012..3348634 100644 --- a/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.h +++ b/wpa_supplicant-2.9_standard/src/eap_peer/eap_tls_common.h @@ -79,6 +79,11 @@ struct eap_ssl_data { * tls_v13 - Whether TLS v1.3 or newer is used */ int tls_v13; + + /** + * client_cert_conf: Whether client certificate has been configured + */ + bool client_cert_conf; }; diff --git a/wpa_supplicant-2.9_standard/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant-2.9_standard/wpa_supplicant/wpa_supplicant.conf index 6619d6b..d63f73c 100644 --- a/wpa_supplicant-2.9_standard/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant-2.9_standard/wpa_supplicant/wpa_supplicant.conf @@ -1321,6 +1321,13 @@ fast_reauth=1 # * 0 = do not use cryptobinding (default) # * 1 = use cryptobinding if server supports it # * 2 = require cryptobinding +# 'phase2_auth' option can be used to control Phase 2 (i.e., within TLS +# tunnel) behavior for PEAP: +# * 0 = do not require Phase 2 authentication +# * 1 = require Phase 2 authentication when client certificate +# (private_key/client_cert) is no used and TLS session resumption was +# not used (default) +# * 2 = require Phase 2 authentication in all cases # EAP-WSC (WPS) uses following options: pin= or # pbc=1. # -- Gitee