From 0ac0e4df1c5bd74522afa74c6d910f9988fa571b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 18 Mar 2008 11:26:17 +0200 Subject: [PATCH] EAP-PEAP: Moved EAP-TLV processing into eap_peap.c EAP-PEAP was the only method that used the external eap_tlv.c peer implementation. This worked fine just for the simple protected result notification, but extending the TLV support for cryptobinding etc. is not trivial with such separation. With the TLV processing integrated into eap_peap.c, all the needed information is now available for using additional TLVs. --- src/eap_peer/eap_fast.c | 2 +- src/eap_peer/eap_peap.c | 172 +++++++++++++++++++++++++++++++++++- src/eap_peer/eap_tlv.c | 189 ---------------------------------------- src/eap_peer/eap_tlv.h | 26 ------ wpa_supplicant/Makefile | 8 -- 5 files changed, 172 insertions(+), 225 deletions(-) delete mode 100644 src/eap_peer/eap_tlv.c delete mode 100644 src/eap_peer/eap_tlv.h diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 33e523208..5bc1de0f0 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -19,7 +19,7 @@ #include "eap_tls_common.h" #include "eap_config.h" #include "tls.h" -#include "eap_tlv.h" +#include "eap_common/eap_tlv_common.h" #include "sha1.h" #include "eap_fast_pac.h" diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 1f77aa780..c72c79a7b 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -19,7 +19,7 @@ #include "eap_tls_common.h" #include "eap_config.h" #include "tls.h" -#include "eap_tlv.h" +#include "eap_common/eap_tlv_common.h" /* Maximum supported PEAP version @@ -154,6 +154,176 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv) } +/** + * eap_tlv_build_nak - Build EAP-TLV NAK message + * @id: EAP identifier for the header + * @nak_type: TLV type (EAP_TLV_*) + * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure + * + * This funtion builds an EAP-TLV NAK message. The caller is responsible for + * freeing the returned buffer. + */ +static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) +{ + struct wpabuf *msg; + + msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, + EAP_CODE_RESPONSE, id); + if (msg == NULL) + return NULL; + + wpabuf_put_u8(msg, 0x80); /* Mandatory */ + wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); + wpabuf_put_be16(msg, 6); /* Length */ + wpabuf_put_be32(msg, 0); /* Vendor-Id */ + wpabuf_put_be16(msg, nak_type); /* NAK-Type */ + + return msg; +} + + +/** + * eap_tlv_build_result - Build EAP-TLV Result message + * @id: EAP identifier for the header + * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) + * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure + * + * This funtion builds an EAP-TLV Result message. The caller is responsible for + * freeing the returned buffer. + */ +static struct wpabuf * eap_tlv_build_result(int id, u16 status) +{ + struct wpabuf *msg; + + msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 6, + EAP_CODE_RESPONSE, id); + if (msg == NULL) + return NULL; + + wpabuf_put_u8(msg, 0x80); /* Mandatory */ + wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); + wpabuf_put_be16(msg, 2); /* Length */ + wpabuf_put_be16(msg, status); /* Status */ + + return msg; +} + + +/** + * 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() + * @ret: Return values from EAP request validation and processing + * @req: EAP-TLV request to be processed. The caller must have validated that + * the buffer is large enough to contain full request (hdr->length bytes) and + * that the EAP type is EAP_TYPE_TLV. + * @resp: Buffer to return a pointer to the allocated response message. This + * field should be initialized to %NULL before the call. The value will be + * updated if a response message is generated. The caller is responsible for + * freeing the allocated message. + * @force_failure: Force negotiation to fail + * Returns: 0 on success, -1 on failure + */ +static int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, + const struct wpabuf *req, struct wpabuf **resp, + int force_failure) +{ + size_t left, tlv_len; + const u8 *pos; + const u8 *result_tlv = NULL; + size_t result_tlv_len = 0; + int tlv_type, mandatory; + + /* Parse TLVs */ + pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); + if (pos == NULL) + return -1; + wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); + while (left >= 4) { + mandatory = !!(pos[0] & 0x80); + tlv_type = WPA_GET_BE16(pos) & 0x3fff; + pos += 2; + tlv_len = WPA_GET_BE16(pos); + pos += 2; + left -= 4; + if (tlv_len > left) { + wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " + "(tlv_len=%lu left=%lu)", + (unsigned long) tlv_len, + (unsigned long) left); + return -1; + } + switch (tlv_type) { + case EAP_TLV_RESULT_TLV: + result_tlv = pos; + result_tlv_len = tlv_len; + break; + default: + wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " + "%d%s", tlv_type, + mandatory ? " (mandatory)" : ""); + if (mandatory) { + /* NAK TLV and ignore all TLVs in this packet. + */ + *resp = eap_tlv_build_nak(eap_get_id(req), + tlv_type); + return *resp == NULL ? -1 : 0; + } + /* Ignore this TLV, but process other TLVs */ + break; + } + + pos += tlv_len; + left -= tlv_len; + } + if (left) { + wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " + "Request (left=%lu)", (unsigned long) left); + return -1; + } + + /* Process supported TLVs */ + if (result_tlv) { + int status, resp_status; + wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", + result_tlv, result_tlv_len); + if (result_tlv_len < 2) { + wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " + "(len=%lu)", + (unsigned long) result_tlv_len); + return -1; + } + status = WPA_GET_BE16(result_tlv); + if (status == EAP_TLV_RESULT_SUCCESS) { + wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " + "- EAP-TLV/Phase2 Completed"); + if (force_failure) { + wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" + " - force failed Phase 2"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } else { + resp_status = EAP_TLV_RESULT_SUCCESS; + ret->decision = DECISION_UNCOND_SUCC; + } + } else if (status == EAP_TLV_RESULT_FAILURE) { + wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } else { + wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " + "Status %d", status); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } + ret->methodState = METHOD_DONE; + + *resp = eap_tlv_build_result(eap_get_id(req), resp_status); + } + + return 0; +} + + static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) { struct wpabuf *e; diff --git a/src/eap_peer/eap_tlv.c b/src/eap_peer/eap_tlv.c deleted file mode 100644 index e2b94833f..000000000 --- a/src/eap_peer/eap_tlv.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tlv.h" - - -/** - * eap_tlv_build_nak - Build EAP-TLV NAK message - * @id: EAP identifier for the header - * @nak_type: TLV type (EAP_TLV_*) - * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure - * - * This funtion builds an EAP-TLV NAK message. The caller is responsible for - * freeing the returned buffer. - */ -struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, - EAP_CODE_RESPONSE, id); - if (msg == NULL) - return NULL; - - wpabuf_put_u8(msg, 0x80); /* Mandatory */ - wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); - wpabuf_put_be16(msg, 6); /* Length */ - wpabuf_put_be32(msg, 0); /* Vendor-Id */ - wpabuf_put_be16(msg, nak_type); /* NAK-Type */ - - return msg; -} - - -/** - * eap_tlv_build_result - Build EAP-TLV Result message - * @id: EAP identifier for the header - * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) - * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure - * - * This funtion builds an EAP-TLV Result message. The caller is responsible for - * freeing the returned buffer. - */ -struct wpabuf * eap_tlv_build_result(int id, u16 status) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 6, - EAP_CODE_RESPONSE, id); - if (msg == NULL) - return NULL; - - wpabuf_put_u8(msg, 0x80); /* Mandatory */ - wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); - wpabuf_put_be16(msg, 2); /* Length */ - wpabuf_put_be16(msg, status); /* Status */ - - return msg; -} - - -/** - * 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() - * @ret: Return values from EAP request validation and processing - * @req: EAP-TLV request to be processed. The caller must have validated that - * the buffer is large enough to contain full request (hdr->length bytes) and - * that the EAP type is EAP_TYPE_TLV. - * @resp: Buffer to return a pointer to the allocated response message. This - * field should be initialized to %NULL before the call. The value will be - * updated if a response message is generated. The caller is responsible for - * freeing the allocated message. - * @force_failure: Force negotiation to fail - * Returns: 0 on success, -1 on failure - */ -int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - const struct wpabuf *req, struct wpabuf **resp, - int force_failure) -{ - size_t left, tlv_len; - const u8 *pos; - const u8 *result_tlv = NULL; - size_t result_tlv_len = 0; - int tlv_type, mandatory; - - /* Parse TLVs */ - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); - if (pos == NULL) - return -1; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - tlv_len = WPA_GET_BE16(pos); - pos += 2; - left -= 4; - if (tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " - "(tlv_len=%lu left=%lu)", - (unsigned long) tlv_len, - (unsigned long) left); - return -1; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - /* NAK TLV and ignore all TLVs in this packet. - */ - *resp = eap_tlv_build_nak(eap_get_id(req), - tlv_type); - return *resp == NULL ? -1 : 0; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - return -1; - } - - /* Process supported TLVs */ - if (result_tlv) { - int status, resp_status; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", - result_tlv, result_tlv_len); - if (result_tlv_len < 2) { - wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " - "(len=%lu)", - (unsigned long) result_tlv_len); - return -1; - } - status = WPA_GET_BE16(result_tlv); - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " - "- EAP-TLV/Phase2 Completed"); - if (force_failure) { - wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" - " - force failed Phase 2"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - resp_status = EAP_TLV_RESULT_SUCCESS; - ret->decision = DECISION_UNCOND_SUCC; - } - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " - "Status %d", status); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } - ret->methodState = METHOD_DONE; - - *resp = eap_tlv_build_result(eap_get_id(req), resp_status); - } - - return 0; -} diff --git a/src/eap_peer/eap_tlv.h b/src/eap_peer/eap_tlv.h deleted file mode 100644 index ce70aba77..000000000 --- a/src/eap_peer/eap_tlv.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLV_H -#define EAP_TLV_H - -#include "eap_common/eap_tlv_common.h" - -struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type); -struct wpabuf * eap_tlv_build_result(int id, u16 status); -int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - const struct wpabuf *req, struct wpabuf **resp, - int force_failure); - -#endif /* EAP_TLV_H */ diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 17c699026..f185b590e 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -274,7 +274,6 @@ OBJS_h += ../src/eap_server/eap_peap.o endif TLS_FUNCS=y CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_TLV=y endif ifdef CONFIG_EAP_TTLS @@ -417,13 +416,6 @@ NEED_AES=y NEED_FIPS186_2_PRF=y endif -ifdef CONFIG_EAP_TLV -# EAP-TLV -CFLAGS += -DEAP_TLV -OBJS += ../src/eap_peer/eap_tlv.o -OBJS_h += ../src/eap_server/eap_tlv.o -endif - ifdef CONFIG_EAP_FAST # EAP-FAST ifeq ($(CONFIG_EAP_FAST), dyn)