Submitted By:            Douglas R. Reno <renodr at linuxfromscratch dot org>
Date:                    2024-02-13
Initial Package Version: 2.10
Upstream Status:         Applied
Origin:                  Upstream (commit 8e6485a1bcb0baff)
Description:             Fixes CVE-2023-52160, a security vulnerability that
                         allows an attacker to trick a victim into connecting
                         to a malicious clone of a wireless network and thus
                         intercepting all traffic. More details on this attack
                         can be found at:
                         https://www.top10vpn.com/research/wifi-vulnerabilities/

diff -Naurp wpa_supplicant-2.10.orig/src/eap_peer/eap_config.h wpa_supplicant-2.10/src/eap_peer/eap_config.h
--- wpa_supplicant-2.10.orig/src/eap_peer/eap_config.h	2024-02-13 21:17:02.175907855 -0600
+++ wpa_supplicant-2.10/src/eap_peer/eap_config.h	2024-02-13 21:17:09.000844738 -0600
@@ -469,6 +469,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 -Naurp wpa_supplicant-2.10.orig/src/eap_peer/eap_peap.c wpa_supplicant-2.10/src/eap_peer/eap_peap.c
--- wpa_supplicant-2.10.orig/src/eap_peer/eap_peap.c	2024-02-13 21:17:02.175907855 -0600
+++ wpa_supplicant-2.10/src/eap_peer/eap_peap.c	2024-02-13 21:17:09.000844738 -0600
@@ -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
 		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_s
 	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_cryptobindin
 }
 
 
+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
 					   " - 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(
 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 -Naurp wpa_supplicant-2.10.orig/src/eap_peer/eap_tls_common.c wpa_supplicant-2.10/src/eap_peer/eap_tls_common.c
--- wpa_supplicant-2.10.orig/src/eap_peer/eap_tls_common.c	2024-02-13 21:17:02.175907855 -0600
+++ wpa_supplicant-2.10/src/eap_peer/eap_tls_common.c	2024-02-13 21:17:09.001844729 -0600
@@ -239,6 +239,12 @@ static int eap_tls_params_from_conf(stru
 
 	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 -Naurp wpa_supplicant-2.10.orig/src/eap_peer/eap_tls_common.h wpa_supplicant-2.10/src/eap_peer/eap_tls_common.h
--- wpa_supplicant-2.10.orig/src/eap_peer/eap_tls_common.h	2024-02-13 21:17:02.175907855 -0600
+++ wpa_supplicant-2.10/src/eap_peer/eap_tls_common.h	2024-02-13 21:17:09.001844729 -0600
@@ -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 -Naurp wpa_supplicant-2.10.orig/wpa_supplicant/wpa_supplicant.conf wpa_supplicant-2.10/wpa_supplicant/wpa_supplicant.conf
--- wpa_supplicant-2.10.orig/wpa_supplicant/wpa_supplicant.conf	2024-02-13 21:17:02.163907965 -0600
+++ wpa_supplicant-2.10/wpa_supplicant/wpa_supplicant.conf	2024-02-13 21:17:09.001844729 -0600
@@ -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=<Device Password> or
 #	pbc=1.
 #
