diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c index 4420f281b..15a9972f2 100644 --- a/src/libcharon/encoding/payloads/eap_payload.c +++ b/src/libcharon/encoding/payloads/eap_payload.c @@ -336,7 +336,8 @@ static void write_type(bio_writer_t *writer, eap_type_t type, u_int32_t vendor, /* * Described in header */ -eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded) +eap_payload_t *eap_payload_create_nak(u_int8_t identifier, eap_type_t type, + u_int32_t vendor, bool expanded) { enumerator_t *enumerator; eap_type_t reg_type; @@ -356,6 +357,11 @@ eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded) enumerator = charon->eap->create_enumerator(charon->eap, EAP_PEER); while (enumerator->enumerate(enumerator, ®_type, ®_vendor)) { + if ((type && type != reg_type) || + (type && vendor && vendor != reg_vendor)) + { /* the preferred type is only sent if we actually find it */ + continue; + } if (!reg_vendor || expanded) { write_type(writer, reg_type, reg_vendor, expanded); diff --git a/src/libcharon/encoding/payloads/eap_payload.h b/src/libcharon/encoding/payloads/eap_payload.h index ad8c57de1..d3c3fae28 100644 --- a/src/libcharon/encoding/payloads/eap_payload.h +++ b/src/libcharon/encoding/payloads/eap_payload.h @@ -127,10 +127,13 @@ eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier); * Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK. * * @param identifier EAP identifier to use in payload + * @param type preferred auth type, 0 to send all supported types + * @param vendor vendor identifier for auth type, 0 for default * @param expanded TRUE to send an expanded Nak (as response to an expanded * request, i.e. one with vendor specific type) * @return eap_payload_t object */ -eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded); +eap_payload_t *eap_payload_create_nak(u_int8_t identifier, eap_type_t type, + u_int32_t vendor, bool expanded); #endif /** EAP_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.c b/src/libcharon/plugins/eap_peap/eap_peap_peer.c index 96d4d0f30..5e1972672 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c @@ -151,7 +151,7 @@ METHOD(tls_application_t, process, status_t, if (!this->ph2_method) { DBG1(DBG_IKE, "EAP method not supported"); - this->out = eap_payload_create_nak(in->get_identifier(in), + this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0, received_vendor != 0); in->destroy(in); return NEED_MORE; diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c index 59366b490..811fe051b 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c @@ -192,7 +192,7 @@ METHOD(tls_application_t, process, status_t, if (!this->method) { DBG1(DBG_IKE, "EAP method not supported"); - this->out = eap_payload_create_nak(in->get_identifier(in), + this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0, received_vendor != 0); in->destroy(in); return NEED_MORE; diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c index 7cc862538..c9178d061 100644 --- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c @@ -336,8 +336,8 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, eap_payload_t *in) { - eap_type_t type; - u_int32_t vendor; + eap_type_t type, conf_type; + u_int32_t vendor, conf_vendor; auth_cfg_t *auth; eap_payload_t *out; identification_t *id; @@ -373,7 +373,7 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, * EAP method (types 3-253, 255) */ DBG1(DBG_IKE, "%N not supported, sending EAP_NAK", eap_type_names, type); - return eap_payload_create_nak(in->get_identifier(in), FALSE); + return eap_payload_create_nak(in->get_identifier(in), 0, 0, FALSE); } if (this->method == NULL) { @@ -387,11 +387,31 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", eap_type_names, type, in->get_identifier(in)); } + auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); + conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE); + conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR); + if (conf_type != EAP_NAK && + (conf_type != type || conf_vendor != vendor)) + { + if (conf_vendor) + { + DBG1(DBG_IKE, "requesting EAP method %d-%d, sending EAP_NAK", + conf_type, conf_vendor); + } + else + { + DBG1(DBG_IKE, "requesting %N authentication, sending EAP_NAK", + eap_type_names, conf_type); + } + return eap_payload_create_nak(in->get_identifier(in), conf_type, + conf_vendor, vendor != 0); + } this->method = load_method(this, type, vendor, EAP_PEER); if (!this->method) { DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK"); - return eap_payload_create_nak(in->get_identifier(in), vendor != 0); + return eap_payload_create_nak(in->get_identifier(in), 0, 0, + vendor != 0); } }