summaryrefslogtreecommitdiff
path: root/src/eap_server/eap_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eap_server/eap_server.c')
-rw-r--r--src/eap_server/eap_server.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c
index fdc26f9343fb..15f7e22846ec 100644
--- a/src/eap_server/eap_server.c
+++ b/src/eap_server/eap_server.c
@@ -2,14 +2,8 @@
* hostapd / EAP Full Authenticator state machine (RFC 4137)
* Copyright (c) 2004-2007, 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*
* This state machine is based on the full authenticator state machine defined
* in RFC 4137. However, to support backend authentication in RADIUS
@@ -136,6 +130,14 @@ SM_STATE(EAP, INITIALIZE)
{
SM_ENTRY(EAP, INITIALIZE);
+ if (sm->eap_if.eapRestart && !sm->eap_server && sm->identity) {
+ /*
+ * Need to allow internal Identity method to be used instead
+ * of passthrough at the beginning of reauthentication.
+ */
+ eap_server_clear_identity(sm);
+ }
+
sm->currentId = -1;
sm->eap_if.eapSuccess = FALSE;
sm->eap_if.eapFail = FALSE;
@@ -273,6 +275,11 @@ SM_STATE(EAP, INTEGRITY_CHECK)
{
SM_ENTRY(EAP, INTEGRITY_CHECK);
+ if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) {
+ sm->ignore = TRUE;
+ return;
+ }
+
if (sm->m->check) {
sm->ignore = sm->m->check(sm, sm->eap_method_priv,
sm->eap_if.eapRespData);
@@ -307,6 +314,9 @@ SM_STATE(EAP, METHOD_RESPONSE)
{
SM_ENTRY(EAP, METHOD_RESPONSE);
+ if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
+ return;
+
sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
if (sm->m->isDone(sm, sm->eap_method_priv)) {
eap_sm_Policy_update(sm, NULL, 0);
@@ -378,6 +388,9 @@ SM_STATE(EAP, NAK)
}
sm->m = NULL;
+ if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
+ return;
+
nak = wpabuf_head(sm->eap_if.eapRespData);
if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
len = be_to_host16(nak->length);
@@ -1028,9 +1041,12 @@ void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len)
not_found:
/* not found - remove from the list */
- os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1],
- (EAP_MAX_METHODS - i - 1) *
- sizeof(sm->user->methods[0]));
+ if (i + 1 < EAP_MAX_METHODS) {
+ os_memmove(&sm->user->methods[i],
+ &sm->user->methods[i + 1],
+ (EAP_MAX_METHODS - i - 1) *
+ sizeof(sm->user->methods[0]));
+ }
sm->user->methods[EAP_MAX_METHODS - 1].vendor =
EAP_VENDOR_IETF;
sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
@@ -1255,8 +1271,13 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
sm->wps = conf->wps;
if (conf->assoc_wps_ie)
sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
+ if (conf->assoc_p2p_ie)
+ sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie);
if (conf->peer_addr)
os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
+ sm->fragment_size = conf->fragment_size;
+ sm->pwd_group = conf->pwd_group;
+ sm->pbc_in_m1 = conf->pbc_in_m1;
wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
@@ -1291,6 +1312,7 @@ void eap_server_sm_deinit(struct eap_sm *sm)
os_free(sm->eap_if.aaaEapKeyData);
eap_user_free(sm->user);
wpabuf_free(sm->assoc_wps_ie);
+ wpabuf_free(sm->assoc_p2p_ie);
os_free(sm);
}
@@ -1362,3 +1384,18 @@ struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
{
return &sm->eap_if;
}
+
+
+/**
+ * eap_server_clear_identity - Clear EAP identity information
+ * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
+ *
+ * This function can be used to clear the EAP identity information in the EAP
+ * server context. This allows the EAP/Identity method to be used again after
+ * EAPOL-Start or EAPOL-Logoff.
+ */
+void eap_server_clear_identity(struct eap_sm *sm)
+{
+ os_free(sm->identity);
+ sm->identity = NULL;
+}