Commit 6a7210731f for strongswan.org
commit 6a7210731f6dd2889d22bf20310ab0ed7274d0d8
Author: Tobias Brunner <tobias@strongswan.org>
Date: Mon Jul 27 15:24:53 2026 +0200
eap-peap: Return auth-cfg with details on TLS and inner EAP method
For some reason this plugin was not changed with the first referenced
merge commit. So this commit adds the missing `get_auth` method and
basically the same implementation as the previous commit to expose
details on the inner EAP method including the EAP-Identity.
It also forwards the phase 2 EAP method type to EAP-TNC like the eap-ttls
plugin does to allow a more informed decision on the client's identity.
This was overlooked in the second referenced commit.
Fixes: ec5752747557 ("Merge branch 'eap-constraints'")
Fixes: 2a421163bf4f ("make TNC client authentication type available to IMVs")
Fixes: 1be296dfb2af ("implemented the PEAP tunneling protocol as an EAP plugin")
Fixes: CVE-2026-78134
diff --git a/src/libcharon/plugins/eap_peap/eap_peap.c b/src/libcharon/plugins/eap_peap/eap_peap.c
index 3573cba7c6..cd942f135d 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap.c
@@ -40,6 +40,25 @@ struct private_eap_peap_t {
* TLS stack, wrapped by EAP helper
*/
tls_eap_t *tls_eap;
+
+ /**
+ * Role
+ */
+ bool is_server;
+
+ /**
+ * Actual server/client implementation
+ */
+ union {
+ tls_application_t *application;
+ eap_peap_server_t *server;
+ eap_peap_peer_t *client;
+ } impl;
+
+ /**
+ * Cached auth data for TLS and inner EAP methods
+ */
+ auth_cfg_t *auth;
};
/** Maximum number of EAP-PEAP messages/fragments allowed */
@@ -113,10 +132,34 @@ METHOD(eap_method_t, is_mutual, bool,
return TRUE;
}
+METHOD(eap_method_t, get_auth, auth_cfg_t*,
+ private_eap_peap_t *this)
+{
+ if (!this->auth)
+ {
+ auth_cfg_t *inner;
+
+ this->auth = auth_cfg_create();
+ this->auth->merge(this->auth,
+ this->tls_eap->get_auth(this->tls_eap), FALSE);
+ if (this->is_server)
+ {
+ inner = this->impl.server->get_auth(this->impl.server);
+ }
+ else
+ {
+ inner = this->impl.client->get_auth(this->impl.client);
+ }
+ this->auth->merge(this->auth, inner, FALSE);
+ }
+ return this->auth;
+}
+
METHOD(eap_method_t, destroy, void,
private_eap_peap_t *this)
{
this->tls_eap->destroy(this->tls_eap);
+ DESTROY_IF(this->auth);
free(this);
}
@@ -135,6 +178,7 @@ static private_eap_peap_t *eap_peap_create_empty(void)
.get_type = _get_type,
.is_mutual = _is_mutual,
.get_msk = _get_msk,
+ .get_auth = _get_auth,
.get_identifier = _get_identifier,
.set_identifier = _set_identifier,
.destroy = _destroy,
@@ -147,7 +191,7 @@ static private_eap_peap_t *eap_peap_create_empty(void)
/**
* Generic private constructor
*/
-static eap_peap_t *eap_peap_create(private_eap_peap_t * this,
+static eap_peap_t *eap_peap_create(private_eap_peap_t *this,
identification_t *server,
identification_t *peer, bool is_server,
tls_application_t *application)
@@ -157,6 +201,9 @@ static eap_peap_t *eap_peap_create(private_eap_peap_t * this,
bool include_length;
tls_t *tls;
+ this->is_server = is_server;
+ this->impl.application = application;
+
if (is_server && !lib->settings->get_bool(lib->settings,
"%s.plugins.eap-peap.request_peer_auth", FALSE,
lib->ns))
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.c b/src/libcharon/plugins/eap_peap/eap_peap_peer.c
index 95213a3286..f6c087ab2b 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c
@@ -52,6 +52,11 @@ struct private_eap_peap_peer_t {
*/
eap_method_t *ph2_method;
+ /**
+ * Auth data for phase 2 methods
+ */
+ auth_cfg_t *auth;
+
/**
* Pending outbound EAP message
*/
@@ -166,6 +171,12 @@ METHOD(tls_application_t, process, status_t,
switch (status)
{
case SUCCESS:
+ if (this->ph2_method->get_auth)
+ {
+ this->auth->merge(this->auth,
+ this->ph2_method->get_auth(this->ph2_method),
+ FALSE);
+ }
this->ph2_method->destroy(this->ph2_method);
this->ph2_method = NULL;
/* fall through to NEED_MORE */
@@ -220,11 +231,18 @@ METHOD(tls_application_t, build, status_t,
return INVALID_STATE;
}
+METHOD(eap_peap_peer_t, get_auth, auth_cfg_t*,
+ private_eap_peap_peer_t *this)
+{
+ return this->auth;
+}
+
METHOD(tls_application_t, destroy, void,
private_eap_peap_peer_t *this)
{
this->server->destroy(this->server);
this->peer->destroy(this->peer);
+ this->auth->destroy(this->auth);
DESTROY_IF(this->ph2_method);
DESTROY_IF(this->out);
this->avp->destroy(this->avp);
@@ -247,10 +265,12 @@ eap_peap_peer_t *eap_peap_peer_create(identification_t *server,
.build = _build,
.destroy = _destroy,
},
+ .get_auth = _get_auth,
},
.server = server->clone(server),
.peer = peer->clone(peer),
.ph1_method = eap_method,
+ .auth = auth_cfg_create(),
.avp = eap_peap_avp_create(FALSE),
);
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.h b/src/libcharon/plugins/eap_peap/eap_peap_peer.h
index 53c25cdd6b..7d16957432 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.h
+++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.h
@@ -38,6 +38,13 @@ struct eap_peap_peer_t {
* Implements the TLS application data handler.
*/
tls_application_t application;
+
+ /**
+ * Get authentication details of this EAP method and its inner method(s).
+ *
+ * @return auth method, internal data
+ */
+ auth_cfg_t *(*get_auth)(eap_peap_peer_t *this);
};
/**
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c
index 4d489a13a3..010fee447b 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_server.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c
@@ -20,6 +20,8 @@
#include <utils/debug.h>
#include <daemon.h>
+#include <sa/eap/eap_inner_method.h>
+
typedef struct private_eap_peap_server_t private_eap_peap_server_t;
/**
@@ -77,6 +79,16 @@ struct private_eap_peap_server_t {
*/
eap_method_t *ph2_method;
+ /**
+ * Type of the completed phase 2 EAP method
+ */
+ eap_type_t phase2_type;
+
+ /**
+ * Auth data for phase 2 method
+ */
+ auth_cfg_t *auth;
+
/**
* Pending outbound EAP message
*/
@@ -133,8 +145,11 @@ static status_t start_phase2_auth(private_eap_peap_server_t *this)
/**
* If configured, start EAP-TNC protocol
*/
-static status_t start_phase2_tnc(private_eap_peap_server_t *this)
+static status_t start_phase2_tnc(private_eap_peap_server_t *this,
+ eap_type_t auth_type)
{
+ eap_inner_method_t *inner_method;
+
if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
"%s.plugins.eap-peap.phase2_tnc", FALSE, lib->ns))
{
@@ -147,6 +162,8 @@ static status_t start_phase2_tnc(private_eap_peap_server_t *this)
DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC);
return FAILED;
}
+ inner_method = (eap_inner_method_t *)this->ph2_method;
+ inner_method->set_auth_type(inner_method, auth_type);
this->start_phase2_tnc = FALSE;
/* synchronize EAP message identifiers of inner protocol with outer */
@@ -225,7 +242,7 @@ METHOD(tls_application_t, process, status_t,
{
/* only accept SUCCESS once after a successful inner method */
this->phase2_result = EAP_FAILURE;
- return start_phase2_tnc(this);
+ return start_phase2_tnc(this, this->phase2_type);
}
return FAILED;
}
@@ -252,6 +269,10 @@ METHOD(tls_application_t, process, status_t,
if (!received_vendor && received_type == EAP_IDENTITY)
{
chunk_t eap_id;
+ bool peer_auth;
+
+ peer_auth = lib->settings->get_bool(lib->settings,
+ "%s.plugins.eap-peap.request_peer_auth", FALSE, lib->ns);
if (this->ph2_method == NULL)
{
@@ -278,9 +299,22 @@ METHOD(tls_application_t, process, status_t,
if (this->ph2_method->get_msk(this->ph2_method, &eap_id) == SUCCESS)
{
- this->peer->destroy(this->peer);
- this->peer = identification_create_from_data(eap_id);
- DBG1(DBG_IKE, "received EAP identity '%Y'", this->peer);
+ identification_t *id;
+
+ id = identification_create_from_data(eap_id);
+ if (peer_auth && !id->equals(id, this->peer))
+ {
+ DBG1(DBG_IKE, "received tunneled EAP identity '%Y', keeping "
+ "certificate-authenticated identity '%Y'", id, this->peer);
+ id->destroy(id);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received EAP identity '%Y'", id);
+ this->auth->add(this->auth, AUTH_RULE_EAP_IDENTITY, id);
+ this->peer->destroy(this->peer);
+ this->peer = id->clone(id);
+ }
}
in->destroy(in);
@@ -288,10 +322,9 @@ METHOD(tls_application_t, process, status_t,
this->ph2_method = NULL;
/* Start Phase 2 of EAP-PEAP authentication */
- if (lib->settings->get_bool(lib->settings,
- "%s.plugins.eap-peap.request_peer_auth", FALSE, lib->ns))
+ if (peer_auth)
{
- return start_phase2_tnc(this);
+ return start_phase2_tnc(this, EAP_TLS);
}
else
{
@@ -312,11 +345,26 @@ METHOD(tls_application_t, process, status_t,
switch (status)
{
case SUCCESS:
+ if (this->ph2_method->get_auth)
+ {
+ identification_t *id;
+ auth_cfg_t *auth;
+
+ auth = this->ph2_method->get_auth(this->ph2_method);
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ this->peer->destroy(this->peer);
+ this->peer = id->clone(id);
+ }
+ this->auth->merge(this->auth, auth, FALSE);
+ }
DBG1(DBG_IKE, "%N phase2 authentication of '%Y' with %N successful",
eap_type_names, EAP_PEAP, this->peer,
eap_type_names, type);
this->ph2_method->destroy(this->ph2_method);
this->ph2_method = NULL;
+ this->phase2_type = type;
/* EAP-PEAP requires the sending of an inner EAP_SUCCESS message */
this->phase2_result = EAP_SUCCESS;
@@ -414,11 +462,18 @@ METHOD(eap_peap_server_t, set_tls, void,
this->tls = tls;
}
+METHOD(eap_peap_server_t, get_auth, auth_cfg_t*,
+ private_eap_peap_server_t *this)
+{
+ return this->auth;
+}
+
METHOD(tls_application_t, destroy, void,
private_eap_peap_server_t *this)
{
this->server->destroy(this->server);
this->peer->destroy(this->peer);
+ this->auth->destroy(this->auth);
DESTROY_IF(this->ph2_method);
DESTROY_IF(this->out);
this->avp->destroy(this->avp);
@@ -442,10 +497,12 @@ eap_peap_server_t *eap_peap_server_create(identification_t *server,
.destroy = _destroy,
},
.set_tls = _set_tls,
+ .get_auth = _get_auth,
},
.server = server->clone(server),
.peer = peer->clone(peer),
.ph1_method = eap_method,
+ .auth = auth_cfg_create(),
.start_phase2 = TRUE,
.start_phase2_tnc = TRUE,
.start_phase2_id = lib->settings->get_bool(lib->settings,
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.h b/src/libcharon/plugins/eap_peap/eap_peap_server.h
index 3abe88bea6..8080e9f23b 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_server.h
+++ b/src/libcharon/plugins/eap_peap/eap_peap_server.h
@@ -47,6 +47,13 @@ struct eap_peap_server_t {
* @param tls TLS connection
*/
void (*set_tls)(eap_peap_server_t *this, tls_t *tls);
+
+ /**
+ * Get authentication details of this EAP method and its inner method(s).
+ *
+ * @return auth method, internal data
+ */
+ auth_cfg_t *(*get_auth)(eap_peap_server_t *this);
};
/**