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.
This commit is contained in:
Jouni Malinen 2008-03-18 11:26:17 +02:00
parent 06726f0bdd
commit 0ac0e4df1c
5 changed files with 172 additions and 225 deletions

View file

@ -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"

View file

@ -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;

View file

@ -1,189 +0,0 @@
/*
* EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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;
}

View file

@ -1,26 +0,0 @@
/*
* EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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 */

View file

@ -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)