[prev in list] [next in list] [prev in thread] [next in thread]
List: hostap
Subject: [patch] Disconnect the STA if EAP timeout is reached
From: Andriy Tkachuk <andriy.v.tkachuk () globallogic ! com>
Date: 2009-03-23 16:16:12
Message-ID: 49C7B5CC.6010604 () globallogic ! com
[Download RAW message or body]
Hi all.
Attached patch is the merge of Jouni's two fixes to EAP state machine
from 0.6 branch to 0.5:
1. Fixed retransmission of EAP requests if no response is received
(http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap-06.git;a=commit;h=8e09c6d25306135106c12a013966102ab01ddc38)
2. Disconnect the STA if EAP timeout is reached
(http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap-06.git;a=commit;h=805e6dc66326764b3d20c5113fb538b2be6aa662)
Jouni, I would appreciate your review. Also I have a question - is it
possible to commit this to 0.5 branch?
Thank you,
Andriy
["eap-timeout.patch" (text/plain)]
Index: ChangeLog
===================================================================
--- ChangeLog (revision 3621)
+++ ChangeLog (working copy)
@@ -1,10 +1,12 @@
ChangeLog for hostapd
+ * fixed retransmission of EAP requests if no response is received
+
2008-11-28 - v0.5.11
* driver_madwifi: Fixed NULL pointer dereference on error path
[Bug 273]
* avoid possible NULL pointer dereference on SIGHUP with MAC ACLs
* update previous BSSID into STA data only after full validation of the
reassociation request
* avoid NULL pointer dereference if initialization of EAP-TTLS Phase 2
EAP method fails
Index: eap.c
===================================================================
--- eap.c (revision 3621)
+++ eap.c (working copy)
@@ -199,18 +199,21 @@ SM_STATE(EAP, IDLE)
sm->methodTimeout);
}
SM_STATE(EAP, RETRANSMIT)
{
SM_ENTRY(EAP, RETRANSMIT);
- /* TODO: Is this needed since EAPOL state machines take care of
- * retransmit? */
+ sm->retransCount++;
+ if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
+ eapol_set_eapReqData(sm, sm->lastReqData, sm->lastReqDataLen);
+ eapol_set_bool(sm, EAPOL_eapReq, TRUE);
+ }
}
SM_STATE(EAP, RECEIVED)
{
SM_ENTRY(EAP, RECEIVED);
/* parse rxResp, respId, respMethod */
@@ -606,20 +609,61 @@ SM_STEP(EAP)
}
}
static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
int eapSRTT, int eapRTTVAR,
int methodTimeout)
{
- /* For now, retransmission is done in EAPOL state machines, so make
- * sure EAP state machine does not end up trying to retransmit packets.
+ int rto, i;
+
+ if (methodTimeout) {
+ /*
+ * EAP method (either internal or through AAA server, provided
+ * timeout hint. Use that as-is as a timeout for retransmitting
+ * the EAP request if no response is received.
+ */
+ wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
+ "(from EAP method hint)", methodTimeout);
+ return methodTimeout;
+ }
+
+ /*
+ * RFC 3748 recommends algorithms described in RFC 2988 for estimation
+ * of the retransmission timeout. This should be implemented once
+ * round-trip time measurements are available. For nowm a simple
+ * backoff mechanism is used instead if there are no EAP method
+ * specific hints.
+ *
+ * SRTT = smoothed round-trip time
+ * RTTVAR = round-trip time variation
+ * RTO = retransmission timeout
*/
- return 1;
+
+ /*
+ * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
+ * initial retransmission and then double the RTO to provide back off
+ * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
+ * modified RTOmax.
+ */
+ rto = 3;
+ for (i = 0; i < retransCount; i++) {
+ rto *= 2;
+ if (rto >= 20) {
+ rto = 20;
+ break;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
+ "(from dynamic back off; retransCount=%d)",
+ rto, retransCount);
+
+ return rto;
}
static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len)
{
struct eap_hdr *hdr;
size_t plen;
@@ -955,17 +999,17 @@ struct eap_sm * eap_sm_init(void *eapol_
{
struct eap_sm *sm;
sm = wpa_zalloc(sizeof(*sm));
if (sm == NULL)
return NULL;
sm->eapol_ctx = eapol_ctx;
sm->eapol_cb = eapol_cb;
- sm->MaxRetrans = 10;
+ sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
sm->ssl_ctx = conf->ssl_ctx;
sm->eap_sim_db_priv = conf->eap_sim_db_priv;
sm->backend_auth = conf->backend_auth;
wpa_printf(MSG_DEBUG, "EAP: State machine created");
return sm;
}
Index: eapol_sm.c
===================================================================
--- eapol_sm.c (revision 3621)
+++ eapol_sm.c (working copy)
@@ -80,16 +80,25 @@ static void eapol_port_timers_tick(void
state->reAuthWhen--;
if (state->reAuthWhen == 0) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
" - reAuthWhen --> 0",
MAC2STR(state->addr));
}
}
+ if (state->eap->retransWhile > 0) {
+ state->eap->retransWhile--;
+ if (state->eap->retransWhile == 0) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
+ " - (EAP) retransWhile --> 0",
+ MAC2STR(state->addr));
+ }
+ }
+
eapol_sm_step_run(state);
eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
}
/* Authenticator PAE state machine */
Index: eapol_sm.h
===================================================================
--- eapol_sm.h (revision 3621)
+++ eapol_sm.h (working copy)
@@ -11,27 +11,26 @@
*
* See README and COPYING for more details.
*/
#ifndef EAPOL_SM_H
#define EAPOL_SM_H
#include "defs.h"
+#include "eap_i.h"
/* IEEE Std 802.1X-2004, Ch. 8.2 */
typedef enum { ForceUnauthorized = 1, ForceAuthorized = 3, Auto = 2 }
PortTypes;
typedef enum { Unauthorized = 2, Authorized = 1 } PortState;
typedef enum { Both = 0, In = 1 } ControlledDirection;
typedef unsigned int Counter;
-struct eap_sm;
-
struct radius_attr_data {
u8 *data;
size_t len;
};
struct radius_class_data {
struct radius_attr_data *attr;
size_t count;
Index: ieee802_1x.c
===================================================================
--- ieee802_1x.c (revision 3621)
+++ ieee802_1x.c (working copy)
@@ -27,16 +27,17 @@
#include "sta_info.h"
#include "wpa.h"
#include "preauth.h"
#include "pmksa_cache.h"
#include "driver.h"
#include "hw_features.h"
#include "eap.h"
#include "eap_wsc.h"
+#include "ieee802_11.h"
static void ieee802_1x_new_auth_session(struct hostapd_data *hapd,
struct sta_info *sta);
void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
u8 type, u8 *data, size_t datalen)
@@ -1478,20 +1479,17 @@ ieee802_1x_receive_auth(struct radius_ms
eap_timeout = session_timeout;
} else
eap_timeout = 30;
hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG,
"using EAP timeout of %d seconds%s",
eap_timeout,
session_timeout_set ? " (from RADIUS)" : "");
- eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
- eloop_register_timeout(eap_timeout, 0, ieee802_1x_eap_timeout,
- sta, NULL);
- sm->eapTimeout = FALSE;
+ sm->eap->methodTimeout = eap_timeout;
break;
}
ieee802_1x_decapsulate_radius(hapd, sta);
if (override_eapReq)
sm->eapReq = FALSE;
eapol_sm_step(sm);
@@ -1534,16 +1532,32 @@ void ieee802_1x_abort_auth(struct hostap
sm->last_recv_radius = NULL;
}
free(sm->last_eap_supp);
sm->last_eap_supp = NULL;
sm->last_eap_supp_len = 0;
free(sm->last_eap_radius);
sm->last_eap_radius = NULL;
sm->last_eap_radius_len = 0;
+
+ if (sm->eapTimeout) {
+ /*
+ * Disconnect the STA since it did not reply to the last EAP
+ * request and we cannot continue EAP processing (EAP-Failure
+ * could only be sent if the EAP peer actually replied).
+ */
+ sm->portEnabled = FALSE;
+ hostapd_sta_deauth(hapd, sta->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
+ WLAN_STA_AUTHORIZED);
+ eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+ eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
+ sta->timeout_next = STA_REMOVE;
+ }
}
#ifdef HOSTAPD_DUMP_STATE
static void fprint_char(FILE *f, char c)
{
if (c >= 32 && c < 127)
fprintf(f, "%c", c);
_______________________________________________
HostAP mailing list
HostAP@lists.shmoo.com
http://lists.shmoo.com/mailman/listinfo/hostap
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic