From 8323fbaee79d54cf61bf3ca88915969c0c007b2d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 17 Jun 2026 15:37:39 +0200 Subject: [PATCH] eap-peap: Don't allow authenticated client to skip EAP-TNC with unexpected EAP-SUCCESS EAP-PEAP transports results as separate AVPs, we expect one after the first phase 2 authentication (if not using certificates). However, with the previous caching of the result of that, the client could then send another confirmation as response to the EAP-TNC request to skip it. Since no group membership is set if EAP-TNC is not complete, it shouldn't really affect its outcome, though. Fixes: 1be296dfb2af ("implemented the PEAP tunneling protocol as an EAP plugin") --- .../plugins/eap_peap/eap_peap_server.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c index 29ab9b451..4d489a13a 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_server.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c @@ -106,7 +106,8 @@ static status_t start_phase2_auth(private_eap_peap_server_t *this) return FAILED; } DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, type); - this->ph2_method = charon->eap->create_instance(charon->eap, type, 0, + this->phase2_result = EAP_FAILURE; + this->ph2_method = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER, this->server, this->peer); if (this->ph2_method == NULL) { @@ -125,7 +126,7 @@ static status_t start_phase2_auth(private_eap_peap_server_t *this) else { DBG1(DBG_IKE, "%N method failed", eap_type_names, type); - return FAILED; + return FAILED; } } @@ -138,6 +139,7 @@ static status_t start_phase2_tnc(private_eap_peap_server_t *this) "%s.plugins.eap-peap.phase2_tnc", FALSE, lib->ns)) { DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, EAP_TNC); + this->phase2_result = EAP_FAILURE; this->ph2_method = charon->eap->create_instance(charon->eap, EAP_TNC, 0, EAP_SERVER, this->server, this->peer); if (this->ph2_method == NULL) @@ -218,9 +220,14 @@ METHOD(tls_application_t, process, status_t, DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]", eap_code_short_names, code); in->destroy(in); - /* if EAP_SUCCESS check if to continue phase2 with EAP-TNC */ - return (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS) ? - start_phase2_tnc(this) : FAILED; + + if (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS) + { + /* only accept SUCCESS once after a successful inner method */ + this->phase2_result = EAP_FAILURE; + return start_phase2_tnc(this); + } + return FAILED; } if (this->ph2_method) @@ -292,7 +299,7 @@ METHOD(tls_application_t, process, status_t, } } - if (this->ph2_method == 0) + if (this->ph2_method == NULL) { DBG1(DBG_IKE, "no %N phase2 method installed", eap_type_names, EAP_PEAP); in->destroy(in);