From 5f01c3c84a9c11c2b58c35a4e7264de43f524bc8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Jan 2014 14:13:50 +0200 Subject: [PATCH] EAP peer: Improve failure reporting from METHOD with no eapRespData One of the RFC 4137 state transitions (METHOD -> FAILURE) had been forgotten and this could result in EAP peer method processing not reporting failure immediately and instead, remain stuck waiting for the connection to time out. Fix this by adding the methodState == DONE && decision == FAIL case to allow immediate reporting of failures. The condition from RFC 4137 as-is would cause problems for number of the existing EAP method implementations since they use that in places where the final message before EAP-Failure should really be sent to the EAP server (e.g., WSC_Done in EAP-WSC). Address this by includng eapRespData == NULL as an additional constraint for entering FAILURE state directly from METHOD. Signed-hostap: Jouni Malinen --- src/eap_peer/eap.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index 3439c2dfc..98abd4ef7 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -1,6 +1,6 @@ /* * EAP peer state machines (RFC 4137) - * Copyright (c) 2004-2012, Jouni Malinen + * Copyright (c) 2004-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -388,10 +388,11 @@ SM_STATE(EAP, METHOD) sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret, eapReqData); wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s " - "methodState=%s decision=%s", + "methodState=%s decision=%s eapRespData=%p", ret.ignore ? "TRUE" : "FALSE", eap_sm_method_state_txt(ret.methodState), - eap_sm_decision_txt(ret.decision)); + eap_sm_decision_txt(ret.decision), + sm->eapRespData); sm->ignore = ret.ignore; if (sm->ignore) @@ -432,8 +433,10 @@ SM_STATE(EAP, SEND_RESPONSE) sm->lastId = sm->reqId; sm->lastRespData = wpabuf_dup(sm->eapRespData); eapol_set_bool(sm, EAPOL_eapResp, TRUE); - } else + } else { + wpa_printf(MSG_DEBUG, "EAP: No eapRespData available"); sm->lastRespData = NULL; + } eapol_set_bool(sm, EAPOL_eapReq, FALSE); eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); } @@ -724,8 +727,19 @@ static void eap_peer_sm_step_local(struct eap_sm *sm) SM_ENTER(EAP, SEND_RESPONSE); break; case EAP_METHOD: + /* + * Note: RFC 4137 uses methodState == DONE && decision == FAIL + * as the condition. eapRespData == NULL here is used to allow + * final EAP method response to be sent without having to change + * all methods to either use methodState MAY_CONT or leaving + * decision to something else than FAIL in cases where the only + * expected response is EAP-Failure. + */ if (sm->ignore) SM_ENTER(EAP, DISCARD); + else if (sm->methodState == METHOD_DONE && + sm->decision == DECISION_FAIL && !sm->eapRespData) + SM_ENTER(EAP, FAILURE); else SM_ENTER(EAP, SEND_RESPONSE); break;