From: Tobias Brunner Date: Tue, 21 Aug 2012 14:54:21 +0000 (+0200) Subject: Send EAP-Nak with supported types if requested type is unsupported X-Git-Tag: 5.0.1~154^2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af04233e1451c02dcda2582cd369481b03f21974;p=thirdparty%2Fstrongswan.git Send EAP-Nak with supported types if requested type is unsupported --- diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c index 1b9a5c8028..4420f281be 100644 --- a/src/libcharon/encoding/payloads/eap_payload.c +++ b/src/libcharon/encoding/payloads/eap_payload.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +21,7 @@ #include #include +#include typedef struct private_eap_payload_t private_eap_payload_t; @@ -313,15 +315,75 @@ eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier) return eap_payload_create_data(data); } +/** + * Write the given type either expanded or not + */ +static void write_type(bio_writer_t *writer, eap_type_t type, u_int32_t vendor, + bool expanded) +{ + if (expanded) + { + writer->write_uint8(writer, EAP_EXPANDED); + writer->write_uint24(writer, vendor); + writer->write_uint32(writer, type); + } + else + { + writer->write_uint8(writer, type); + } +} + /* * Described in header */ -eap_payload_t *eap_payload_create_nak(u_int8_t identifier) +eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded) { - chunk_t data; + enumerator_t *enumerator; + eap_type_t reg_type; + u_int32_t reg_vendor; + bio_writer_t *writer; + chunk_t length, data; + bool added_any = FALSE, found_vendor = FALSE; + eap_payload_t *payload; + + writer = bio_writer_create(12); + writer->write_uint8(writer, EAP_RESPONSE); + writer->write_uint8(writer, identifier); + length = writer->skip(writer, 2); + + write_type(writer, EAP_NAK, 0, expanded); + + enumerator = charon->eap->create_enumerator(charon->eap, EAP_PEER); + while (enumerator->enumerate(enumerator, ®_type, ®_vendor)) + { + if (!reg_vendor || expanded) + { + write_type(writer, reg_type, reg_vendor, expanded); + added_any = TRUE; + } + else if (reg_vendor) + { /* found vendor specifc method, but this is not an expanded Nak */ + found_vendor = TRUE; + } + } + enumerator->destroy(enumerator); - data = chunk_from_chars(EAP_RESPONSE, identifier, 0, 0, EAP_NAK); - htoun16(data.ptr + 2, data.len); - return eap_payload_create_data(data); + if (found_vendor) + { /* request an expanded authentication type */ + write_type(writer, EAP_EXPANDED, 0, expanded); + added_any = TRUE; + } + if (!added_any) + { /* no methods added */ + write_type(writer, 0, 0, expanded); + } + + /* set length */ + data = writer->get_buf(writer); + htoun16(length.ptr, data.len); + + payload = eap_payload_create_data(data); + writer->destroy(writer); + return payload; } diff --git a/src/libcharon/encoding/payloads/eap_payload.h b/src/libcharon/encoding/payloads/eap_payload.h index 52bc7ac5ea..ad8c57de13 100644 --- a/src/libcharon/encoding/payloads/eap_payload.h +++ b/src/libcharon/encoding/payloads/eap_payload.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -126,8 +127,10 @@ 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 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); +eap_payload_t *eap_payload_create_nak(u_int8_t identifier, 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 72e201fb65..96d4d0f303 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c @@ -85,7 +85,7 @@ METHOD(tls_application_t, process, status_t, default: return FAILED; } - + in = eap_payload_create_data(data); DBG3(DBG_IKE, "%B", &data); chunk_free(&data); @@ -151,7 +151,8 @@ 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), + 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 767111b3e2..59366b4901 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c @@ -138,7 +138,7 @@ METHOD(tls_application_t, process, status_t, chunk_free(&avp_data); } while (eap_pos < eap_data.len); - + in = eap_payload_create_data(eap_data); chunk_free(&eap_data); payload = (payload_t*)in; @@ -192,7 +192,8 @@ 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), + 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 2c282dc06f..46913a7e02 100644 --- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c @@ -357,9 +357,11 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, this->method->destroy(this->method); this->method = NULL; } + /* FIXME: sending a Nak is not correct here as EAP_IDENTITY (1) is no + * 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)); + return eap_payload_create_nak(in->get_identifier(in), FALSE); } if (this->method == NULL) { @@ -377,7 +379,7 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, if (!this->method) { DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK"); - return eap_payload_create_nak(in->get_identifier(in)); + return eap_payload_create_nak(in->get_identifier(in), vendor != 0); } }