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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-01-05 14:13:50 +02:00
parent 7271ee8769
commit 5f01c3c84a

View file

@ -1,6 +1,6 @@
/*
* EAP peer state machines (RFC 4137)
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* 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;