HAMMER 60I/Many: Mirroring
[dragonfly.git] / contrib / hostapd-0.5.8 / eapol_sm.c
blobf4f575298e9f3b1462c4a8dc8e00ee6928bec537
1 /*
2 * hostapd / IEEE 802.1X Authenticator - EAPOL state machine
3 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "hostapd.h"
18 #include "ieee802_1x.h"
19 #include "eapol_sm.h"
20 #include "eloop.h"
21 #include "wpa.h"
22 #include "preauth.h"
23 #include "sta_info.h"
24 #include "eap.h"
25 #include "state_machine.h"
27 #define STATE_MACHINE_DATA struct eapol_state_machine
28 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
29 #define STATE_MACHINE_ADDR sm->addr
31 static struct eapol_callbacks eapol_cb;
33 /* EAPOL state machines are described in IEEE Std 802.1X-REV-d11, Chap. 8.2 */
35 #define setPortAuthorized() \
36 ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 1)
37 #define setPortUnauthorized() \
38 ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 0)
40 /* procedures */
41 #define txCannedFail() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 0)
42 #define txCannedSuccess() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 1)
43 #define txReq() ieee802_1x_tx_req(sm->hapd, sm->sta)
44 #define sendRespToServer() ieee802_1x_send_resp_to_server(sm->hapd, sm->sta)
45 #define abortAuth() ieee802_1x_abort_auth(sm->hapd, sm->sta)
46 #define txKey() ieee802_1x_tx_key(sm->hapd, sm->sta)
47 #define processKey() do { } while (0)
50 static void eapol_sm_step_run(struct eapol_state_machine *sm);
51 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
54 /* Port Timers state machine - implemented as a function that will be called
55 * once a second as a registered event loop timeout */
57 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
59 struct eapol_state_machine *state = timeout_ctx;
61 if (state->aWhile > 0) {
62 state->aWhile--;
63 if (state->aWhile == 0) {
64 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
65 " - aWhile --> 0",
66 MAC2STR(state->addr));
70 if (state->quietWhile > 0) {
71 state->quietWhile--;
72 if (state->quietWhile == 0) {
73 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
74 " - quietWhile --> 0",
75 MAC2STR(state->addr));
79 if (state->reAuthWhen > 0) {
80 state->reAuthWhen--;
81 if (state->reAuthWhen == 0) {
82 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
83 " - reAuthWhen --> 0",
84 MAC2STR(state->addr));
88 eapol_sm_step_run(state);
90 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
95 /* Authenticator PAE state machine */
97 SM_STATE(AUTH_PAE, INITIALIZE)
99 SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
100 sm->portMode = Auto;
102 sm->currentId = 255;
106 SM_STATE(AUTH_PAE, DISCONNECTED)
108 int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
110 if (sm->eapolLogoff) {
111 if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
112 sm->authEapLogoffsWhileConnecting++;
113 else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)
114 sm->authAuthEapLogoffWhileAuthenticated++;
117 SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
119 sm->authPortStatus = Unauthorized;
120 setPortUnauthorized();
121 sm->reAuthCount = 0;
122 sm->eapolLogoff = FALSE;
123 if (!from_initialize) {
124 if (sm->flags & EAPOL_SM_PREAUTH)
125 rsn_preauth_finished(sm->hapd, sm->sta, 0);
126 else
127 ieee802_1x_finished(sm->hapd, sm->sta, 0);
132 SM_STATE(AUTH_PAE, RESTART)
134 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
135 if (sm->reAuthenticate)
136 sm->authAuthReauthsWhileAuthenticated++;
137 if (sm->eapolStart)
138 sm->authAuthEapStartsWhileAuthenticated++;
139 if (sm->eapolLogoff)
140 sm->authAuthEapLogoffWhileAuthenticated++;
143 SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
145 sm->eapRestart = TRUE;
146 ieee802_1x_request_identity(sm->hapd, sm->sta);
150 SM_STATE(AUTH_PAE, CONNECTING)
152 if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
153 sm->authEntersConnecting++;
155 SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
157 sm->reAuthenticate = FALSE;
158 sm->reAuthCount++;
162 SM_STATE(AUTH_PAE, HELD)
164 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
165 sm->authAuthFailWhileAuthenticating++;
167 SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
169 sm->authPortStatus = Unauthorized;
170 setPortUnauthorized();
171 sm->quietWhile = sm->quietPeriod;
172 sm->eapolLogoff = FALSE;
174 hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
175 HOSTAPD_LEVEL_WARNING, "authentication failed - "
176 "EAP type: %d (%s)",
177 sm->eap_type_authsrv,
178 eap_type_text(sm->eap_type_authsrv));
179 if (sm->eap_type_authsrv != sm->eap_type_supp) {
180 hostapd_logger(sm->hapd, sm->addr,
181 HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_INFO,
182 "Supplicant used different EAP type: %d (%s)",
183 sm->eap_type_supp,
184 eap_type_text(sm->eap_type_supp));
186 if (sm->flags & EAPOL_SM_PREAUTH)
187 rsn_preauth_finished(sm->hapd, sm->sta, 0);
188 else
189 ieee802_1x_finished(sm->hapd, sm->sta, 0);
193 SM_STATE(AUTH_PAE, AUTHENTICATED)
195 char *extra = "";
197 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
198 sm->authAuthSuccessesWhileAuthenticating++;
200 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
202 sm->authPortStatus = Authorized;
203 setPortAuthorized();
204 sm->reAuthCount = 0;
205 if (sm->flags & EAPOL_SM_PREAUTH)
206 extra = " (pre-authentication)";
207 else if (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm))
208 extra = " (PMKSA cache)";
209 hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
210 HOSTAPD_LEVEL_INFO, "authenticated - EAP type: %d (%s)"
211 "%s", sm->eap_type_authsrv,
212 eap_type_text(sm->eap_type_authsrv), extra);
213 if (sm->flags & EAPOL_SM_PREAUTH)
214 rsn_preauth_finished(sm->hapd, sm->sta, 1);
215 else
216 ieee802_1x_finished(sm->hapd, sm->sta, 1);
220 SM_STATE(AUTH_PAE, AUTHENTICATING)
222 if (sm->auth_pae_state == AUTH_PAE_CONNECTING && sm->rx_identity) {
223 sm->authEntersAuthenticating++;
224 sm->rx_identity = FALSE;
227 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
229 sm->eapolStart = FALSE;
230 sm->authSuccess = FALSE;
231 sm->authFail = FALSE;
232 sm->authTimeout = FALSE;
233 sm->authStart = TRUE;
234 sm->keyRun = FALSE;
235 sm->keyDone = FALSE;
239 SM_STATE(AUTH_PAE, ABORTING)
241 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
242 if (sm->authTimeout)
243 sm->authAuthTimeoutsWhileAuthenticating++;
244 if (sm->eapolStart)
245 sm->authAuthEapStartsWhileAuthenticating++;
246 if (sm->eapolLogoff)
247 sm->authAuthEapLogoffWhileAuthenticating++;
250 SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
252 sm->authAbort = TRUE;
253 sm->keyRun = FALSE;
254 sm->keyDone = FALSE;
258 SM_STATE(AUTH_PAE, FORCE_AUTH)
260 SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
262 sm->authPortStatus = Authorized;
263 setPortAuthorized();
264 sm->portMode = ForceAuthorized;
265 sm->eapolStart = FALSE;
266 txCannedSuccess();
270 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
272 SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
274 sm->authPortStatus = Unauthorized;
275 setPortUnauthorized();
276 sm->portMode = ForceUnauthorized;
277 sm->eapolStart = FALSE;
278 txCannedFail();
282 SM_STEP(AUTH_PAE)
284 if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
285 sm->initialize || !sm->portEnabled)
286 SM_ENTER(AUTH_PAE, INITIALIZE);
287 else if (sm->portControl == ForceAuthorized &&
288 sm->portMode != sm->portControl &&
289 !(sm->initialize || !sm->portEnabled))
290 SM_ENTER(AUTH_PAE, FORCE_AUTH);
291 else if (sm->portControl == ForceUnauthorized &&
292 sm->portMode != sm->portControl &&
293 !(sm->initialize || !sm->portEnabled))
294 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
295 else {
296 switch (sm->auth_pae_state) {
297 case AUTH_PAE_INITIALIZE:
298 SM_ENTER(AUTH_PAE, DISCONNECTED);
299 break;
300 case AUTH_PAE_DISCONNECTED:
301 SM_ENTER(AUTH_PAE, RESTART);
302 break;
303 case AUTH_PAE_RESTART:
304 if (!sm->eapRestart)
305 SM_ENTER(AUTH_PAE, CONNECTING);
306 break;
307 case AUTH_PAE_HELD:
308 if (sm->quietWhile == 0)
309 SM_ENTER(AUTH_PAE, RESTART);
310 break;
311 case AUTH_PAE_CONNECTING:
312 if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
313 SM_ENTER(AUTH_PAE, DISCONNECTED);
314 else if ((sm->eapReq &&
315 sm->reAuthCount <= sm->reAuthMax) ||
316 sm->eapSuccess || sm->eapFail)
317 SM_ENTER(AUTH_PAE, AUTHENTICATING);
318 break;
319 case AUTH_PAE_AUTHENTICATED:
320 if (sm->eapolStart || sm->reAuthenticate)
321 SM_ENTER(AUTH_PAE, RESTART);
322 else if (sm->eapolLogoff || !sm->portValid)
323 SM_ENTER(AUTH_PAE, DISCONNECTED);
324 break;
325 case AUTH_PAE_AUTHENTICATING:
326 if (sm->authSuccess && sm->portValid)
327 SM_ENTER(AUTH_PAE, AUTHENTICATED);
328 else if (sm->authFail ||
329 (sm->keyDone && !sm->portValid))
330 SM_ENTER(AUTH_PAE, HELD);
331 else if (sm->eapolStart || sm->eapolLogoff ||
332 sm->authTimeout)
333 SM_ENTER(AUTH_PAE, ABORTING);
334 break;
335 case AUTH_PAE_ABORTING:
336 if (sm->eapolLogoff && !sm->authAbort)
337 SM_ENTER(AUTH_PAE, DISCONNECTED);
338 else if (!sm->eapolLogoff && !sm->authAbort)
339 SM_ENTER(AUTH_PAE, RESTART);
340 break;
341 case AUTH_PAE_FORCE_AUTH:
342 if (sm->eapolStart)
343 SM_ENTER(AUTH_PAE, FORCE_AUTH);
344 break;
345 case AUTH_PAE_FORCE_UNAUTH:
346 if (sm->eapolStart)
347 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
348 break;
355 /* Backend Authentication state machine */
357 SM_STATE(BE_AUTH, INITIALIZE)
359 SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
361 abortAuth();
362 sm->eapNoReq = FALSE;
363 sm->authAbort = FALSE;
367 SM_STATE(BE_AUTH, REQUEST)
369 SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
371 txReq();
372 sm->eapReq = FALSE;
373 sm->backendOtherRequestsToSupplicant++;
376 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
377 * it looks like this would be logical thing to do there since the old
378 * EAP response would not be valid anymore after the new EAP request
379 * was sent out.
381 * A race condition has been reported, in which hostapd ended up
382 * sending out EAP-Response/Identity as a response to the first
383 * EAP-Request from the main EAP method. This can be avoided by
384 * clearing eapolEap here.
386 sm->eapolEap = FALSE;
390 SM_STATE(BE_AUTH, RESPONSE)
392 SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
394 sm->authTimeout = FALSE;
395 sm->eapolEap = FALSE;
396 sm->eapNoReq = FALSE;
397 sm->aWhile = sm->serverTimeout;
398 sm->eapResp = TRUE;
399 sendRespToServer();
400 sm->backendResponses++;
404 SM_STATE(BE_AUTH, SUCCESS)
406 SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
408 txReq();
409 sm->authSuccess = TRUE;
410 sm->keyRun = TRUE;
414 SM_STATE(BE_AUTH, FAIL)
416 SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
418 /* Note: IEEE 802.1X-REV-d11 has unconditional txReq() here.
419 * txCannelFail() is used as a workaround for the case where
420 * authentication server does not include EAP-Message with
421 * Access-Reject. */
422 if (sm->last_eap_radius == NULL)
423 txCannedFail();
424 else
425 txReq();
426 sm->authFail = TRUE;
430 SM_STATE(BE_AUTH, TIMEOUT)
432 SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
434 sm->authTimeout = TRUE;
438 SM_STATE(BE_AUTH, IDLE)
440 SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
442 sm->authStart = FALSE;
446 SM_STATE(BE_AUTH, IGNORE)
448 SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
450 sm->eapNoReq = FALSE;
454 SM_STEP(BE_AUTH)
456 if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
457 SM_ENTER(BE_AUTH, INITIALIZE);
458 return;
461 switch (sm->be_auth_state) {
462 case BE_AUTH_INITIALIZE:
463 SM_ENTER(BE_AUTH, IDLE);
464 break;
465 case BE_AUTH_REQUEST:
466 if (sm->eapolEap)
467 SM_ENTER(BE_AUTH, RESPONSE);
468 else if (sm->eapReq)
469 SM_ENTER(BE_AUTH, REQUEST);
470 else if (sm->eapTimeout)
471 SM_ENTER(BE_AUTH, TIMEOUT);
472 break;
473 case BE_AUTH_RESPONSE:
474 if (sm->eapNoReq)
475 SM_ENTER(BE_AUTH, IGNORE);
476 if (sm->eapReq) {
477 sm->backendAccessChallenges++;
478 SM_ENTER(BE_AUTH, REQUEST);
479 } else if (sm->aWhile == 0)
480 SM_ENTER(BE_AUTH, TIMEOUT);
481 else if (sm->eapFail) {
482 sm->backendAuthFails++;
483 SM_ENTER(BE_AUTH, FAIL);
484 } else if (sm->eapSuccess) {
485 sm->backendAuthSuccesses++;
486 SM_ENTER(BE_AUTH, SUCCESS);
488 break;
489 case BE_AUTH_SUCCESS:
490 SM_ENTER(BE_AUTH, IDLE);
491 break;
492 case BE_AUTH_FAIL:
493 SM_ENTER(BE_AUTH, IDLE);
494 break;
495 case BE_AUTH_TIMEOUT:
496 SM_ENTER(BE_AUTH, IDLE);
497 break;
498 case BE_AUTH_IDLE:
499 if (sm->eapFail && sm->authStart)
500 SM_ENTER(BE_AUTH, FAIL);
501 else if (sm->eapReq && sm->authStart)
502 SM_ENTER(BE_AUTH, REQUEST);
503 else if (sm->eapSuccess && sm->authStart)
504 SM_ENTER(BE_AUTH, SUCCESS);
505 break;
506 case BE_AUTH_IGNORE:
507 if (sm->eapolEap)
508 SM_ENTER(BE_AUTH, RESPONSE);
509 else if (sm->eapReq)
510 SM_ENTER(BE_AUTH, REQUEST);
511 else if (sm->eapTimeout)
512 SM_ENTER(BE_AUTH, TIMEOUT);
513 break;
519 /* Reauthentication Timer state machine */
521 SM_STATE(REAUTH_TIMER, INITIALIZE)
523 SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
525 sm->reAuthWhen = sm->reAuthPeriod;
529 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
531 SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
533 sm->reAuthenticate = TRUE;
534 wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL);
538 SM_STEP(REAUTH_TIMER)
540 if (sm->portControl != Auto || sm->initialize ||
541 sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
542 SM_ENTER(REAUTH_TIMER, INITIALIZE);
543 return;
546 switch (sm->reauth_timer_state) {
547 case REAUTH_TIMER_INITIALIZE:
548 if (sm->reAuthWhen == 0)
549 SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
550 break;
551 case REAUTH_TIMER_REAUTHENTICATE:
552 SM_ENTER(REAUTH_TIMER, INITIALIZE);
553 break;
559 /* Authenticator Key Transmit state machine */
561 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
563 SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
567 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
569 SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
571 txKey();
572 sm->keyAvailable = FALSE;
573 sm->keyDone = TRUE;
577 SM_STEP(AUTH_KEY_TX)
579 if (sm->initialize || sm->portControl != Auto) {
580 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
581 return;
584 switch (sm->auth_key_tx_state) {
585 case AUTH_KEY_TX_NO_KEY_TRANSMIT:
586 if (sm->keyTxEnabled && sm->keyAvailable && sm->keyRun &&
587 !wpa_auth_sta_wpa_version(sm->sta->wpa_sm))
588 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
589 break;
590 case AUTH_KEY_TX_KEY_TRANSMIT:
591 if (!sm->keyTxEnabled || !sm->keyRun)
592 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
593 else if (sm->keyAvailable)
594 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
595 break;
601 /* Key Receive state machine */
603 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
605 SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
609 SM_STATE(KEY_RX, KEY_RECEIVE)
611 SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
613 processKey();
614 sm->rxKey = FALSE;
618 SM_STEP(KEY_RX)
620 if (sm->initialize || !sm->portEnabled) {
621 SM_ENTER(KEY_RX, NO_KEY_RECEIVE);
622 return;
625 switch (sm->key_rx_state) {
626 case KEY_RX_NO_KEY_RECEIVE:
627 if (sm->rxKey)
628 SM_ENTER(KEY_RX, KEY_RECEIVE);
629 break;
630 case KEY_RX_KEY_RECEIVE:
631 if (sm->rxKey)
632 SM_ENTER(KEY_RX, KEY_RECEIVE);
633 break;
639 /* Controlled Directions state machine */
641 SM_STATE(CTRL_DIR, FORCE_BOTH)
643 SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
644 sm->operControlledDirections = Both;
648 SM_STATE(CTRL_DIR, IN_OR_BOTH)
650 SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
651 sm->operControlledDirections = sm->adminControlledDirections;
655 SM_STEP(CTRL_DIR)
657 if (sm->initialize) {
658 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
659 return;
662 switch (sm->ctrl_dir_state) {
663 case CTRL_DIR_FORCE_BOTH:
664 if (sm->portEnabled && sm->operEdge)
665 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
666 break;
667 case CTRL_DIR_IN_OR_BOTH:
668 if (sm->operControlledDirections !=
669 sm->adminControlledDirections)
670 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
671 if (!sm->portEnabled || !sm->operEdge)
672 SM_ENTER(CTRL_DIR, FORCE_BOTH);
673 break;
679 struct eapol_state_machine *
680 eapol_sm_alloc(struct hostapd_data *hapd, struct sta_info *sta)
682 struct eapol_state_machine *sm;
684 sm = wpa_zalloc(sizeof(*sm));
685 if (sm == NULL) {
686 printf("IEEE 802.1X port state allocation failed\n");
687 return NULL;
689 sm->radius_identifier = -1;
690 memcpy(sm->addr, sta->addr, ETH_ALEN);
691 if (sta->flags & WLAN_STA_PREAUTH)
692 sm->flags |= EAPOL_SM_PREAUTH;
694 sm->hapd = hapd;
695 sm->sta = sta;
697 /* Set default values for state machine constants */
698 sm->auth_pae_state = AUTH_PAE_INITIALIZE;
699 sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
700 sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
702 sm->be_auth_state = BE_AUTH_INITIALIZE;
703 sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
705 sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
706 sm->reAuthPeriod = hapd->conf->eap_reauth_period;
707 sm->reAuthEnabled = hapd->conf->eap_reauth_period > 0 ? TRUE : FALSE;
709 sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
711 sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
713 sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
715 sm->portEnabled = FALSE;
716 sm->portControl = Auto;
718 sm->keyAvailable = FALSE;
719 if (!hapd->conf->wpa &&
720 (hapd->default_wep_key || hapd->conf->individual_wep_key_len > 0))
721 sm->keyTxEnabled = TRUE;
722 else
723 sm->keyTxEnabled = FALSE;
724 if (hapd->conf->wpa)
725 sm->portValid = FALSE;
726 else
727 sm->portValid = TRUE;
729 if (hapd->conf->eap_server) {
730 struct eap_config eap_conf;
731 memset(&eap_conf, 0, sizeof(eap_conf));
732 eap_conf.ssl_ctx = hapd->ssl_ctx;
733 eap_conf.eap_sim_db_priv = hapd->eap_sim_db_priv;
734 sm->eap = eap_sm_init(sm, &eapol_cb, &eap_conf);
735 if (sm->eap == NULL) {
736 eapol_sm_free(sm);
737 return NULL;
741 eapol_sm_initialize(sm);
743 return sm;
747 void eapol_sm_free(struct eapol_state_machine *sm)
749 if (sm == NULL)
750 return;
752 eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
753 eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
754 if (sm->eap)
755 eap_sm_deinit(sm->eap);
756 free(sm);
760 static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr)
762 struct sta_info *sta;
763 sta = ap_get_sta(hapd, addr);
764 if (sta == NULL || sta->eapol_sm == NULL)
765 return 0;
766 return 1;
770 static void eapol_sm_step_run(struct eapol_state_machine *sm)
772 struct hostapd_data *hapd = sm->hapd;
773 u8 addr[ETH_ALEN];
774 unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
775 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
776 int max_steps = 100;
778 memcpy(addr, sm->sta->addr, ETH_ALEN);
781 * Allow EAPOL state machines to run as long as there are state
782 * changes, but exit and return here through event loop if more than
783 * 100 steps is needed as a precaution against infinite loops inside
784 * eloop callback.
786 restart:
787 prev_auth_pae = sm->auth_pae_state;
788 prev_be_auth = sm->be_auth_state;
789 prev_reauth_timer = sm->reauth_timer_state;
790 prev_auth_key_tx = sm->auth_key_tx_state;
791 prev_key_rx = sm->key_rx_state;
792 prev_ctrl_dir = sm->ctrl_dir_state;
794 SM_STEP_RUN(AUTH_PAE);
795 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
796 SM_STEP_RUN(BE_AUTH);
797 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
798 SM_STEP_RUN(REAUTH_TIMER);
799 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
800 SM_STEP_RUN(AUTH_KEY_TX);
801 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
802 SM_STEP_RUN(KEY_RX);
803 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
804 SM_STEP_RUN(CTRL_DIR);
806 if (prev_auth_pae != sm->auth_pae_state ||
807 prev_be_auth != sm->be_auth_state ||
808 prev_reauth_timer != sm->reauth_timer_state ||
809 prev_auth_key_tx != sm->auth_key_tx_state ||
810 prev_key_rx != sm->key_rx_state ||
811 prev_ctrl_dir != sm->ctrl_dir_state) {
812 if (--max_steps > 0)
813 goto restart;
814 /* Re-run from eloop timeout */
815 eapol_sm_step(sm);
816 return;
819 if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) {
820 if (eap_sm_step(sm->eap)) {
821 if (--max_steps > 0)
822 goto restart;
823 /* Re-run from eloop timeout */
824 eapol_sm_step(sm);
825 return;
829 if (eapol_sm_sta_entry_alive(hapd, addr))
830 wpa_auth_sm_notify(sm->sta->wpa_sm);
834 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
836 struct eapol_state_machine *sm = eloop_ctx;
837 eapol_sm_step_run(sm);
841 void eapol_sm_step(struct eapol_state_machine *sm)
844 * Run eapol_sm_step_run from a registered timeout to make sure that
845 * other possible timeouts/events are processed and to avoid long
846 * function call chains.
849 eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
853 void eapol_sm_initialize(struct eapol_state_machine *sm)
855 sm->initializing = TRUE;
856 /* Initialize the state machines by asserting initialize and then
857 * deasserting it after one step */
858 sm->initialize = TRUE;
859 eapol_sm_step_run(sm);
860 sm->initialize = FALSE;
861 eapol_sm_step_run(sm);
862 sm->initializing = FALSE;
864 /* Start one second tick for port timers state machine */
865 eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
866 eloop_register_timeout(1, 0, eapol_port_timers_tick, sm->hapd, sm);
870 #ifdef HOSTAPD_DUMP_STATE
871 static inline const char * port_type_txt(PortTypes pt)
873 switch (pt) {
874 case ForceUnauthorized: return "ForceUnauthorized";
875 case ForceAuthorized: return "ForceAuthorized";
876 case Auto: return "Auto";
877 default: return "Unknown";
882 static inline const char * port_state_txt(PortState ps)
884 switch (ps) {
885 case Unauthorized: return "Unauthorized";
886 case Authorized: return "Authorized";
887 default: return "Unknown";
892 static inline const char * ctrl_dir_txt(ControlledDirection dir)
894 switch (dir) {
895 case Both: return "Both";
896 case In: return "In";
897 default: return "Unknown";
902 static inline const char * auth_pae_state_txt(int s)
904 switch (s) {
905 case AUTH_PAE_INITIALIZE: return "INITIALIZE";
906 case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
907 case AUTH_PAE_CONNECTING: return "CONNECTING";
908 case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
909 case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
910 case AUTH_PAE_ABORTING: return "ABORTING";
911 case AUTH_PAE_HELD: return "HELD";
912 case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
913 case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
914 case AUTH_PAE_RESTART: return "RESTART";
915 default: return "Unknown";
920 static inline const char * be_auth_state_txt(int s)
922 switch (s) {
923 case BE_AUTH_REQUEST: return "REQUEST";
924 case BE_AUTH_RESPONSE: return "RESPONSE";
925 case BE_AUTH_SUCCESS: return "SUCCESS";
926 case BE_AUTH_FAIL: return "FAIL";
927 case BE_AUTH_TIMEOUT: return "TIMEOUT";
928 case BE_AUTH_IDLE: return "IDLE";
929 case BE_AUTH_INITIALIZE: return "INITIALIZE";
930 case BE_AUTH_IGNORE: return "IGNORE";
931 default: return "Unknown";
936 static inline const char * reauth_timer_state_txt(int s)
938 switch (s) {
939 case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
940 case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
941 default: return "Unknown";
946 static inline const char * auth_key_tx_state_txt(int s)
948 switch (s) {
949 case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
950 case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
951 default: return "Unknown";
956 static inline const char * key_rx_state_txt(int s)
958 switch (s) {
959 case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
960 case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
961 default: return "Unknown";
966 static inline const char * ctrl_dir_state_txt(int s)
968 switch (s) {
969 case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
970 case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
971 default: return "Unknown";
976 void eapol_sm_dump_state(FILE *f, const char *prefix,
977 struct eapol_state_machine *sm)
979 fprintf(f, "%sEAPOL state machine:\n", prefix);
980 fprintf(f, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
981 sm->aWhile, sm->quietWhile, sm->reAuthWhen);
982 #define _SB(b) ((b) ? "TRUE" : "FALSE")
983 fprintf(f,
984 "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
985 "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
986 "%s eapSuccess=%s eapTimeout=%s initialize=%s "
987 "keyAvailable=%s\n"
988 "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
989 "%s portEnabled=%s portValid=%s reAuthenticate=%s\n",
990 prefix, _SB(sm->authAbort), _SB(sm->authFail),
991 port_state_txt(sm->authPortStatus), _SB(sm->authStart),
992 prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
993 _SB(sm->eapFail), _SB(sm->eapolEap),
994 prefix, _SB(sm->eapSuccess), _SB(sm->eapTimeout),
995 _SB(sm->initialize), _SB(sm->keyAvailable),
996 prefix, _SB(sm->keyDone), _SB(sm->keyRun),
997 _SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
998 prefix, _SB(sm->portEnabled), _SB(sm->portValid),
999 _SB(sm->reAuthenticate));
1001 fprintf(f, "%s Authenticator PAE:\n"
1002 "%s state=%s\n"
1003 "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
1004 "%s portMode=%s reAuthCount=%d\n"
1005 "%s quietPeriod=%d reAuthMax=%d\n"
1006 "%s authEntersConnecting=%d\n"
1007 "%s authEapLogoffsWhileConnecting=%d\n"
1008 "%s authEntersAuthenticating=%d\n"
1009 "%s authAuthSuccessesWhileAuthenticating=%d\n"
1010 "%s authAuthTimeoutsWhileAuthenticating=%d\n"
1011 "%s authAuthFailWhileAuthenticating=%d\n"
1012 "%s authAuthEapStartsWhileAuthenticating=%d\n"
1013 "%s authAuthEapLogoffWhileAuthenticating=%d\n"
1014 "%s authAuthReauthsWhileAuthenticated=%d\n"
1015 "%s authAuthEapStartsWhileAuthenticated=%d\n"
1016 "%s authAuthEapLogoffWhileAuthenticated=%d\n",
1017 prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
1018 _SB(sm->eapolLogoff), _SB(sm->eapolStart), _SB(sm->eapRestart),
1019 prefix, port_type_txt(sm->portMode), sm->reAuthCount,
1020 prefix, sm->quietPeriod, sm->reAuthMax,
1021 prefix, sm->authEntersConnecting,
1022 prefix, sm->authEapLogoffsWhileConnecting,
1023 prefix, sm->authEntersAuthenticating,
1024 prefix, sm->authAuthSuccessesWhileAuthenticating,
1025 prefix, sm->authAuthTimeoutsWhileAuthenticating,
1026 prefix, sm->authAuthFailWhileAuthenticating,
1027 prefix, sm->authAuthEapStartsWhileAuthenticating,
1028 prefix, sm->authAuthEapLogoffWhileAuthenticating,
1029 prefix, sm->authAuthReauthsWhileAuthenticated,
1030 prefix, sm->authAuthEapStartsWhileAuthenticated,
1031 prefix, sm->authAuthEapLogoffWhileAuthenticated);
1033 fprintf(f, "%s Backend Authentication:\n"
1034 "%s state=%s\n"
1035 "%s eapNoReq=%s eapReq=%s eapResp=%s\n"
1036 "%s serverTimeout=%d\n"
1037 "%s backendResponses=%d\n"
1038 "%s backendAccessChallenges=%d\n"
1039 "%s backendOtherRequestsToSupplicant=%d\n"
1040 "%s backendAuthSuccesses=%d\n"
1041 "%s backendAuthFails=%d\n",
1042 prefix, prefix,
1043 be_auth_state_txt(sm->be_auth_state),
1044 prefix, _SB(sm->eapNoReq), _SB(sm->eapReq), _SB(sm->eapResp),
1045 prefix, sm->serverTimeout,
1046 prefix, sm->backendResponses,
1047 prefix, sm->backendAccessChallenges,
1048 prefix, sm->backendOtherRequestsToSupplicant,
1049 prefix, sm->backendAuthSuccesses,
1050 prefix, sm->backendAuthFails);
1052 fprintf(f, "%s Reauthentication Timer:\n"
1053 "%s state=%s\n"
1054 "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
1055 reauth_timer_state_txt(sm->reauth_timer_state), prefix,
1056 sm->reAuthPeriod, _SB(sm->reAuthEnabled));
1058 fprintf(f, "%s Authenticator Key Transmit:\n"
1059 "%s state=%s\n", prefix, prefix,
1060 auth_key_tx_state_txt(sm->auth_key_tx_state));
1062 fprintf(f, "%s Key Receive:\n"
1063 "%s state=%s\n"
1064 "%s rxKey=%s\n", prefix, prefix,
1065 key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
1067 fprintf(f, "%s Controlled Directions:\n"
1068 "%s state=%s\n"
1069 "%s adminControlledDirections=%s "
1070 "operControlledDirections=%s\n"
1071 "%s operEdge=%s\n", prefix, prefix,
1072 ctrl_dir_state_txt(sm->ctrl_dir_state),
1073 prefix, ctrl_dir_txt(sm->adminControlledDirections),
1074 ctrl_dir_txt(sm->operControlledDirections),
1075 prefix, _SB(sm->operEdge));
1076 #undef _SB
1078 #endif /* HOSTAPD_DUMP_STATE */
1081 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1083 struct eapol_state_machine *sm = ctx;
1084 if (sm == NULL)
1085 return FALSE;
1086 switch (variable) {
1087 case EAPOL_eapSuccess:
1088 return sm->eapSuccess;
1089 case EAPOL_eapRestart:
1090 return sm->eapRestart;
1091 case EAPOL_eapFail:
1092 return sm->eapFail;
1093 case EAPOL_eapResp:
1094 return sm->eapResp;
1095 case EAPOL_eapReq:
1096 return sm->eapReq;
1097 case EAPOL_eapNoReq:
1098 return sm->eapNoReq;
1099 case EAPOL_portEnabled:
1100 return sm->portEnabled;
1101 case EAPOL_eapTimeout:
1102 return sm->eapTimeout;
1104 return FALSE;
1108 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1109 Boolean value)
1111 struct eapol_state_machine *sm = ctx;
1112 if (sm == NULL)
1113 return;
1114 switch (variable) {
1115 case EAPOL_eapSuccess:
1116 sm->eapSuccess = value;
1117 break;
1118 case EAPOL_eapRestart:
1119 sm->eapRestart = value;
1120 break;
1121 case EAPOL_eapFail:
1122 sm->eapFail = value;
1123 break;
1124 case EAPOL_eapResp:
1125 sm->eapResp = value;
1126 break;
1127 case EAPOL_eapReq:
1128 sm->eapReq = value;
1129 break;
1130 case EAPOL_eapNoReq:
1131 sm->eapNoReq = value;
1132 break;
1133 case EAPOL_portEnabled:
1134 sm->portEnabled = value;
1135 break;
1136 case EAPOL_eapTimeout:
1137 sm->eapTimeout = value;
1138 break;
1143 static void eapol_sm_set_eapReqData(void *ctx, const u8 *eapReqData,
1144 size_t eapReqDataLen)
1146 struct eapol_state_machine *sm = ctx;
1147 if (sm == NULL)
1148 return;
1150 free(sm->last_eap_radius);
1151 sm->last_eap_radius = malloc(eapReqDataLen);
1152 if (sm->last_eap_radius == NULL)
1153 return;
1154 memcpy(sm->last_eap_radius, eapReqData, eapReqDataLen);
1155 sm->last_eap_radius_len = eapReqDataLen;
1159 static void eapol_sm_set_eapKeyData(void *ctx, const u8 *eapKeyData,
1160 size_t eapKeyDataLen)
1162 struct eapol_state_machine *sm = ctx;
1163 struct hostapd_data *hapd;
1165 if (sm == NULL)
1166 return;
1168 hapd = sm->hapd;
1170 if (eapKeyData && eapKeyDataLen >= 64) {
1171 free(sm->eapol_key_sign);
1172 free(sm->eapol_key_crypt);
1173 sm->eapol_key_crypt = malloc(32);
1174 if (sm->eapol_key_crypt) {
1175 memcpy(sm->eapol_key_crypt, eapKeyData, 32);
1176 sm->eapol_key_crypt_len = 32;
1178 sm->eapol_key_sign = malloc(32);
1179 if (sm->eapol_key_sign) {
1180 memcpy(sm->eapol_key_sign, eapKeyData + 32, 32);
1181 sm->eapol_key_sign_len = 32;
1183 if (hapd->default_wep_key ||
1184 hapd->conf->individual_wep_key_len > 0 ||
1185 hapd->conf->wpa)
1186 sm->keyAvailable = TRUE;
1187 } else {
1188 free(sm->eapol_key_sign);
1189 free(sm->eapol_key_crypt);
1190 sm->eapol_key_sign = NULL;
1191 sm->eapol_key_crypt = NULL;
1192 sm->eapol_key_sign_len = 0;
1193 sm->eapol_key_crypt_len = 0;
1194 sm->keyAvailable = FALSE;
1199 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
1200 size_t identity_len, int phase2,
1201 struct eap_user *user)
1203 struct eapol_state_machine *sm = ctx;
1204 const struct hostapd_eap_user *eap_user;
1205 int i, count;
1207 eap_user = hostapd_get_eap_user(sm->hapd->conf, identity,
1208 identity_len, phase2);
1209 if (eap_user == NULL)
1210 return -1;
1212 memset(user, 0, sizeof(*user));
1213 user->phase2 = phase2;
1214 count = EAP_USER_MAX_METHODS;
1215 if (count > EAP_MAX_METHODS)
1216 count = EAP_MAX_METHODS;
1217 for (i = 0; i < count; i++) {
1218 user->methods[i].vendor = eap_user->methods[i].vendor;
1219 user->methods[i].method = eap_user->methods[i].method;
1222 if (eap_user->password) {
1223 user->password = malloc(eap_user->password_len);
1224 if (user->password == NULL)
1225 return -1;
1226 memcpy(user->password, eap_user->password,
1227 eap_user->password_len);
1228 user->password_len = eap_user->password_len;
1230 user->force_version = eap_user->force_version;
1232 return 0;
1236 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
1238 struct eapol_state_machine *sm = ctx;
1239 *len = sm->hapd->conf->eap_req_id_text_len;
1240 return sm->hapd->conf->eap_req_id_text;
1244 static struct eapol_callbacks eapol_cb =
1246 .get_bool = eapol_sm_get_bool,
1247 .set_bool = eapol_sm_set_bool,
1248 .set_eapReqData = eapol_sm_set_eapReqData,
1249 .set_eapKeyData = eapol_sm_set_eapKeyData,
1250 .get_eap_user = eapol_sm_get_eap_user,
1251 .get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
1255 int eapol_sm_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
1257 if (sm == NULL || ctx != sm->eap)
1258 return -1;
1260 eap_sm_pending_cb(sm->eap);
1261 eapol_sm_step(sm);
1263 return 0;