Sync usage with man page.
[netbsd-mini2440.git] / dist / wpa / hostapd / eapol_sm.c
blob2b3d16ef0469783f0cb56cd8f58ed469d861e59a
1 /*
2 * hostapd / IEEE 802.1X-2004 Authenticator - EAPOL state machine
3 * Copyright (c) 2002-2008, 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_server/eap.h"
25 #include "state_machine.h"
26 #include "eap_common/eap_common.h"
28 #define STATE_MACHINE_DATA struct eapol_state_machine
29 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
30 #define STATE_MACHINE_ADDR sm->addr
32 static struct eapol_callbacks eapol_cb;
34 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
36 #define setPortAuthorized() \
37 sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 1)
38 #define setPortUnauthorized() \
39 sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 0)
41 /* procedures */
42 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
43 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
44 #define txReq() eapol_auth_tx_req(sm)
45 #define abortAuth() sm->eapol->cb.abort_auth(sm->hapd, sm->sta)
46 #define txKey() sm->eapol->cb.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 static void eapol_auth_logger(struct eapol_authenticator *eapol,
55 const u8 *addr, logger_level level,
56 const char *txt)
58 if (eapol->cb.logger == NULL)
59 return;
60 eapol->cb.logger(eapol->conf.hapd, addr, level, txt);
64 static void eapol_auth_vlogger(struct eapol_authenticator *eapol,
65 const u8 *addr, logger_level level,
66 const char *fmt, ...)
68 char *format;
69 int maxlen;
70 va_list ap;
72 if (eapol->cb.logger == NULL)
73 return;
75 maxlen = os_strlen(fmt) + 100;
76 format = os_malloc(maxlen);
77 if (!format)
78 return;
80 va_start(ap, fmt);
81 vsnprintf(format, maxlen, fmt, ap);
82 va_end(ap);
84 eapol_auth_logger(eapol, addr, level, format);
86 os_free(format);
90 static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
91 int success)
93 struct eap_hdr eap;
95 os_memset(&eap, 0, sizeof(eap));
97 eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
98 eap.identifier = ++sm->last_eap_id;
99 eap.length = host_to_be16(sizeof(eap));
101 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
102 "Sending canned EAP packet %s (identifier %d)",
103 success ? "SUCCESS" : "FAILURE", eap.identifier);
104 sm->eapol->cb.eapol_send(sm->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET,
105 (u8 *) &eap, sizeof(eap));
106 sm->dot1xAuthEapolFramesTx++;
110 static void eapol_auth_tx_req(struct eapol_state_machine *sm)
112 if (sm->eap_if->eapReqData == NULL ||
113 wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) {
114 eapol_auth_logger(sm->eapol, sm->addr,
115 EAPOL_LOGGER_DEBUG,
116 "TxReq called, but there is no EAP request "
117 "from authentication server");
118 return;
121 if (sm->flags & EAPOL_SM_WAIT_START) {
122 wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR
123 " while waiting for EAPOL-Start",
124 MAC2STR(sm->addr));
125 return;
128 sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData);
129 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
130 "Sending EAP Packet (identifier %d)",
131 sm->last_eap_id);
132 sm->eapol->cb.eapol_send(sm->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET,
133 wpabuf_head(sm->eap_if->eapReqData),
134 wpabuf_len(sm->eap_if->eapReqData));
135 sm->dot1xAuthEapolFramesTx++;
136 if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY)
137 sm->dot1xAuthEapolReqIdFramesTx++;
138 else
139 sm->dot1xAuthEapolReqFramesTx++;
143 /* Port Timers state machine - implemented as a function that will be called
144 * once a second as a registered event loop timeout */
146 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
148 struct eapol_state_machine *state = timeout_ctx;
150 if (state->aWhile > 0) {
151 state->aWhile--;
152 if (state->aWhile == 0) {
153 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
154 " - aWhile --> 0",
155 MAC2STR(state->addr));
159 if (state->quietWhile > 0) {
160 state->quietWhile--;
161 if (state->quietWhile == 0) {
162 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
163 " - quietWhile --> 0",
164 MAC2STR(state->addr));
168 if (state->reAuthWhen > 0) {
169 state->reAuthWhen--;
170 if (state->reAuthWhen == 0) {
171 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
172 " - reAuthWhen --> 0",
173 MAC2STR(state->addr));
177 eapol_sm_step_run(state);
179 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
184 /* Authenticator PAE state machine */
186 SM_STATE(AUTH_PAE, INITIALIZE)
188 SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
189 sm->portMode = Auto;
193 SM_STATE(AUTH_PAE, DISCONNECTED)
195 int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
197 if (sm->eapolLogoff) {
198 if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
199 sm->authEapLogoffsWhileConnecting++;
200 else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)
201 sm->authAuthEapLogoffWhileAuthenticated++;
204 SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
206 sm->authPortStatus = Unauthorized;
207 setPortUnauthorized();
208 sm->reAuthCount = 0;
209 sm->eapolLogoff = FALSE;
210 if (!from_initialize) {
211 sm->eapol->cb.finished(sm->hapd, sm->sta, 0,
212 sm->flags & EAPOL_SM_PREAUTH);
217 SM_STATE(AUTH_PAE, RESTART)
219 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
220 if (sm->reAuthenticate)
221 sm->authAuthReauthsWhileAuthenticated++;
222 if (sm->eapolStart)
223 sm->authAuthEapStartsWhileAuthenticated++;
224 if (sm->eapolLogoff)
225 sm->authAuthEapLogoffWhileAuthenticated++;
228 SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
230 sm->eap_if->eapRestart = TRUE;
234 SM_STATE(AUTH_PAE, CONNECTING)
236 if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
237 sm->authEntersConnecting++;
239 SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
241 sm->reAuthenticate = FALSE;
242 sm->reAuthCount++;
246 SM_STATE(AUTH_PAE, HELD)
248 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
249 sm->authAuthFailWhileAuthenticating++;
251 SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
253 sm->authPortStatus = Unauthorized;
254 setPortUnauthorized();
255 sm->quietWhile = sm->quietPeriod;
256 sm->eapolLogoff = FALSE;
258 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING,
259 "authentication failed - EAP type: %d (%s)",
260 sm->eap_type_authsrv,
261 eap_type_text(sm->eap_type_authsrv));
262 if (sm->eap_type_authsrv != sm->eap_type_supp) {
263 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
264 "Supplicant used different EAP type: "
265 "%d (%s)", sm->eap_type_supp,
266 eap_type_text(sm->eap_type_supp));
268 sm->eapol->cb.finished(sm->hapd, sm->sta, 0,
269 sm->flags & EAPOL_SM_PREAUTH);
273 SM_STATE(AUTH_PAE, AUTHENTICATED)
275 char *extra = "";
277 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
278 sm->authAuthSuccessesWhileAuthenticating++;
280 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
282 sm->authPortStatus = Authorized;
283 setPortAuthorized();
284 sm->reAuthCount = 0;
285 if (sm->flags & EAPOL_SM_PREAUTH)
286 extra = " (pre-authentication)";
287 else if (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm))
288 extra = " (PMKSA cache)";
289 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
290 "authenticated - EAP type: %d (%s)%s",
291 sm->eap_type_authsrv,
292 eap_type_text(sm->eap_type_authsrv), extra);
293 sm->eapol->cb.finished(sm->hapd, sm->sta, 1,
294 sm->flags & EAPOL_SM_PREAUTH);
298 SM_STATE(AUTH_PAE, AUTHENTICATING)
300 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
302 sm->eapolStart = FALSE;
303 sm->authSuccess = FALSE;
304 sm->authFail = FALSE;
305 sm->authTimeout = FALSE;
306 sm->authStart = TRUE;
307 sm->keyRun = FALSE;
308 sm->keyDone = FALSE;
312 SM_STATE(AUTH_PAE, ABORTING)
314 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
315 if (sm->authTimeout)
316 sm->authAuthTimeoutsWhileAuthenticating++;
317 if (sm->eapolStart)
318 sm->authAuthEapStartsWhileAuthenticating++;
319 if (sm->eapolLogoff)
320 sm->authAuthEapLogoffWhileAuthenticating++;
323 SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
325 sm->authAbort = TRUE;
326 sm->keyRun = FALSE;
327 sm->keyDone = FALSE;
331 SM_STATE(AUTH_PAE, FORCE_AUTH)
333 SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
335 sm->authPortStatus = Authorized;
336 setPortAuthorized();
337 sm->portMode = ForceAuthorized;
338 sm->eapolStart = FALSE;
339 txCannedSuccess();
343 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
345 SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
347 sm->authPortStatus = Unauthorized;
348 setPortUnauthorized();
349 sm->portMode = ForceUnauthorized;
350 sm->eapolStart = FALSE;
351 txCannedFail();
355 SM_STEP(AUTH_PAE)
357 if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
358 sm->initialize || !sm->eap_if->portEnabled)
359 SM_ENTER(AUTH_PAE, INITIALIZE);
360 else if (sm->portControl == ForceAuthorized &&
361 sm->portMode != sm->portControl &&
362 !(sm->initialize || !sm->eap_if->portEnabled))
363 SM_ENTER(AUTH_PAE, FORCE_AUTH);
364 else if (sm->portControl == ForceUnauthorized &&
365 sm->portMode != sm->portControl &&
366 !(sm->initialize || !sm->eap_if->portEnabled))
367 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
368 else {
369 switch (sm->auth_pae_state) {
370 case AUTH_PAE_INITIALIZE:
371 SM_ENTER(AUTH_PAE, DISCONNECTED);
372 break;
373 case AUTH_PAE_DISCONNECTED:
374 SM_ENTER(AUTH_PAE, RESTART);
375 break;
376 case AUTH_PAE_RESTART:
377 if (!sm->eap_if->eapRestart)
378 SM_ENTER(AUTH_PAE, CONNECTING);
379 break;
380 case AUTH_PAE_HELD:
381 if (sm->quietWhile == 0)
382 SM_ENTER(AUTH_PAE, RESTART);
383 break;
384 case AUTH_PAE_CONNECTING:
385 if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
386 SM_ENTER(AUTH_PAE, DISCONNECTED);
387 else if ((sm->eap_if->eapReq &&
388 sm->reAuthCount <= sm->reAuthMax) ||
389 sm->eap_if->eapSuccess || sm->eap_if->eapFail)
390 SM_ENTER(AUTH_PAE, AUTHENTICATING);
391 break;
392 case AUTH_PAE_AUTHENTICATED:
393 if (sm->eapolStart || sm->reAuthenticate)
394 SM_ENTER(AUTH_PAE, RESTART);
395 else if (sm->eapolLogoff || !sm->portValid)
396 SM_ENTER(AUTH_PAE, DISCONNECTED);
397 break;
398 case AUTH_PAE_AUTHENTICATING:
399 if (sm->authSuccess && sm->portValid)
400 SM_ENTER(AUTH_PAE, AUTHENTICATED);
401 else if (sm->authFail ||
402 (sm->keyDone && !sm->portValid))
403 SM_ENTER(AUTH_PAE, HELD);
404 else if (sm->eapolStart || sm->eapolLogoff ||
405 sm->authTimeout)
406 SM_ENTER(AUTH_PAE, ABORTING);
407 break;
408 case AUTH_PAE_ABORTING:
409 if (sm->eapolLogoff && !sm->authAbort)
410 SM_ENTER(AUTH_PAE, DISCONNECTED);
411 else if (!sm->eapolLogoff && !sm->authAbort)
412 SM_ENTER(AUTH_PAE, RESTART);
413 break;
414 case AUTH_PAE_FORCE_AUTH:
415 if (sm->eapolStart)
416 SM_ENTER(AUTH_PAE, FORCE_AUTH);
417 break;
418 case AUTH_PAE_FORCE_UNAUTH:
419 if (sm->eapolStart)
420 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
421 break;
428 /* Backend Authentication state machine */
430 SM_STATE(BE_AUTH, INITIALIZE)
432 SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
434 abortAuth();
435 sm->eap_if->eapNoReq = FALSE;
436 sm->authAbort = FALSE;
440 SM_STATE(BE_AUTH, REQUEST)
442 SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
444 txReq();
445 sm->eap_if->eapReq = FALSE;
446 sm->backendOtherRequestsToSupplicant++;
449 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
450 * it looks like this would be logical thing to do there since the old
451 * EAP response would not be valid anymore after the new EAP request
452 * was sent out.
454 * A race condition has been reported, in which hostapd ended up
455 * sending out EAP-Response/Identity as a response to the first
456 * EAP-Request from the main EAP method. This can be avoided by
457 * clearing eapolEap here.
459 sm->eapolEap = FALSE;
463 SM_STATE(BE_AUTH, RESPONSE)
465 SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
467 sm->authTimeout = FALSE;
468 sm->eapolEap = FALSE;
469 sm->eap_if->eapNoReq = FALSE;
470 sm->aWhile = sm->serverTimeout;
471 sm->eap_if->eapResp = TRUE;
472 /* sendRespToServer(); */
473 sm->backendResponses++;
477 SM_STATE(BE_AUTH, SUCCESS)
479 SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
481 txReq();
482 sm->authSuccess = TRUE;
483 sm->keyRun = TRUE;
487 SM_STATE(BE_AUTH, FAIL)
489 SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
491 txReq();
492 sm->authFail = TRUE;
496 SM_STATE(BE_AUTH, TIMEOUT)
498 SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
500 sm->authTimeout = TRUE;
504 SM_STATE(BE_AUTH, IDLE)
506 SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
508 sm->authStart = FALSE;
512 SM_STATE(BE_AUTH, IGNORE)
514 SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
516 sm->eap_if->eapNoReq = FALSE;
520 SM_STEP(BE_AUTH)
522 if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
523 SM_ENTER(BE_AUTH, INITIALIZE);
524 return;
527 switch (sm->be_auth_state) {
528 case BE_AUTH_INITIALIZE:
529 SM_ENTER(BE_AUTH, IDLE);
530 break;
531 case BE_AUTH_REQUEST:
532 if (sm->eapolEap)
533 SM_ENTER(BE_AUTH, RESPONSE);
534 else if (sm->eap_if->eapReq)
535 SM_ENTER(BE_AUTH, REQUEST);
536 else if (sm->eap_if->eapTimeout)
537 SM_ENTER(BE_AUTH, TIMEOUT);
538 break;
539 case BE_AUTH_RESPONSE:
540 if (sm->eap_if->eapNoReq)
541 SM_ENTER(BE_AUTH, IGNORE);
542 if (sm->eap_if->eapReq) {
543 sm->backendAccessChallenges++;
544 SM_ENTER(BE_AUTH, REQUEST);
545 } else if (sm->aWhile == 0)
546 SM_ENTER(BE_AUTH, TIMEOUT);
547 else if (sm->eap_if->eapFail) {
548 sm->backendAuthFails++;
549 SM_ENTER(BE_AUTH, FAIL);
550 } else if (sm->eap_if->eapSuccess) {
551 sm->backendAuthSuccesses++;
552 SM_ENTER(BE_AUTH, SUCCESS);
554 break;
555 case BE_AUTH_SUCCESS:
556 SM_ENTER(BE_AUTH, IDLE);
557 break;
558 case BE_AUTH_FAIL:
559 SM_ENTER(BE_AUTH, IDLE);
560 break;
561 case BE_AUTH_TIMEOUT:
562 SM_ENTER(BE_AUTH, IDLE);
563 break;
564 case BE_AUTH_IDLE:
565 if (sm->eap_if->eapFail && sm->authStart)
566 SM_ENTER(BE_AUTH, FAIL);
567 else if (sm->eap_if->eapReq && sm->authStart)
568 SM_ENTER(BE_AUTH, REQUEST);
569 else if (sm->eap_if->eapSuccess && sm->authStart)
570 SM_ENTER(BE_AUTH, SUCCESS);
571 break;
572 case BE_AUTH_IGNORE:
573 if (sm->eapolEap)
574 SM_ENTER(BE_AUTH, RESPONSE);
575 else if (sm->eap_if->eapReq)
576 SM_ENTER(BE_AUTH, REQUEST);
577 else if (sm->eap_if->eapTimeout)
578 SM_ENTER(BE_AUTH, TIMEOUT);
579 break;
585 /* Reauthentication Timer state machine */
587 SM_STATE(REAUTH_TIMER, INITIALIZE)
589 SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
591 sm->reAuthWhen = sm->reAuthPeriod;
595 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
597 SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
599 sm->reAuthenticate = TRUE;
600 wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL);
604 SM_STEP(REAUTH_TIMER)
606 if (sm->portControl != Auto || sm->initialize ||
607 sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
608 SM_ENTER(REAUTH_TIMER, INITIALIZE);
609 return;
612 switch (sm->reauth_timer_state) {
613 case REAUTH_TIMER_INITIALIZE:
614 if (sm->reAuthWhen == 0)
615 SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
616 break;
617 case REAUTH_TIMER_REAUTHENTICATE:
618 SM_ENTER(REAUTH_TIMER, INITIALIZE);
619 break;
625 /* Authenticator Key Transmit state machine */
627 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
629 SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
633 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
635 SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
637 txKey();
638 sm->eap_if->eapKeyAvailable = FALSE;
639 sm->keyDone = TRUE;
643 SM_STEP(AUTH_KEY_TX)
645 if (sm->initialize || sm->portControl != Auto) {
646 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
647 return;
650 switch (sm->auth_key_tx_state) {
651 case AUTH_KEY_TX_NO_KEY_TRANSMIT:
652 if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
653 sm->keyRun && !wpa_auth_sta_wpa_version(sm->sta->wpa_sm))
654 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
655 break;
656 case AUTH_KEY_TX_KEY_TRANSMIT:
657 if (!sm->keyTxEnabled || !sm->keyRun)
658 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
659 else if (sm->eap_if->eapKeyAvailable)
660 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
661 break;
667 /* Key Receive state machine */
669 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
671 SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
675 SM_STATE(KEY_RX, KEY_RECEIVE)
677 SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
679 processKey();
680 sm->rxKey = FALSE;
684 SM_STEP(KEY_RX)
686 if (sm->initialize || !sm->eap_if->portEnabled) {
687 SM_ENTER(KEY_RX, NO_KEY_RECEIVE);
688 return;
691 switch (sm->key_rx_state) {
692 case KEY_RX_NO_KEY_RECEIVE:
693 if (sm->rxKey)
694 SM_ENTER(KEY_RX, KEY_RECEIVE);
695 break;
696 case KEY_RX_KEY_RECEIVE:
697 if (sm->rxKey)
698 SM_ENTER(KEY_RX, KEY_RECEIVE);
699 break;
705 /* Controlled Directions state machine */
707 SM_STATE(CTRL_DIR, FORCE_BOTH)
709 SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
710 sm->operControlledDirections = Both;
714 SM_STATE(CTRL_DIR, IN_OR_BOTH)
716 SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
717 sm->operControlledDirections = sm->adminControlledDirections;
721 SM_STEP(CTRL_DIR)
723 if (sm->initialize) {
724 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
725 return;
728 switch (sm->ctrl_dir_state) {
729 case CTRL_DIR_FORCE_BOTH:
730 if (sm->eap_if->portEnabled && sm->operEdge)
731 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
732 break;
733 case CTRL_DIR_IN_OR_BOTH:
734 if (sm->operControlledDirections !=
735 sm->adminControlledDirections)
736 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
737 if (!sm->eap_if->portEnabled || !sm->operEdge)
738 SM_ENTER(CTRL_DIR, FORCE_BOTH);
739 break;
745 struct eapol_state_machine *
746 eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
747 int preauth, struct sta_info *sta)
749 struct eapol_state_machine *sm;
750 struct hostapd_data *hapd; /* TODO: to be removed */
751 struct eap_config eap_conf;
753 if (eapol == NULL)
754 return NULL;
755 hapd = eapol->conf.hapd;
757 sm = os_zalloc(sizeof(*sm));
758 if (sm == NULL) {
759 wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation "
760 "failed");
761 return NULL;
763 sm->radius_identifier = -1;
764 os_memcpy(sm->addr, addr, ETH_ALEN);
765 if (preauth)
766 sm->flags |= EAPOL_SM_PREAUTH;
768 sm->hapd = hapd;
769 sm->eapol = eapol;
770 sm->sta = sta;
772 /* Set default values for state machine constants */
773 sm->auth_pae_state = AUTH_PAE_INITIALIZE;
774 sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
775 sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
777 sm->be_auth_state = BE_AUTH_INITIALIZE;
778 sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
780 sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
781 sm->reAuthPeriod = eapol->conf.eap_reauth_period;
782 sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE;
784 sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
786 sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
788 sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
790 sm->portControl = Auto;
792 if (!eapol->conf.wpa &&
793 (hapd->default_wep_key || eapol->conf.individual_wep_key_len > 0))
794 sm->keyTxEnabled = TRUE;
795 else
796 sm->keyTxEnabled = FALSE;
797 if (eapol->conf.wpa)
798 sm->portValid = FALSE;
799 else
800 sm->portValid = TRUE;
802 os_memset(&eap_conf, 0, sizeof(eap_conf));
803 eap_conf.eap_server = eapol->conf.eap_server;
804 eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
805 eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
806 eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
807 eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
808 eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
809 eap_conf.tnc = eapol->conf.tnc;
810 sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
811 if (sm->eap == NULL) {
812 eapol_auth_free(sm);
813 return NULL;
815 sm->eap_if = eap_get_interface(sm->eap);
817 eapol_auth_initialize(sm);
819 return sm;
823 void eapol_auth_free(struct eapol_state_machine *sm)
825 if (sm == NULL)
826 return;
828 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
829 eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
830 if (sm->eap)
831 eap_server_sm_deinit(sm->eap);
832 os_free(sm);
836 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
837 const u8 *addr)
839 return eapol->cb.sta_entry_alive(eapol->conf.hapd, addr);
843 static void eapol_sm_step_run(struct eapol_state_machine *sm)
845 struct eapol_authenticator *eapol = sm->eapol;
846 u8 addr[ETH_ALEN];
847 unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
848 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
849 int max_steps = 100;
851 os_memcpy(addr, sm->addr, ETH_ALEN);
854 * Allow EAPOL state machines to run as long as there are state
855 * changes, but exit and return here through event loop if more than
856 * 100 steps is needed as a precaution against infinite loops inside
857 * eloop callback.
859 restart:
860 prev_auth_pae = sm->auth_pae_state;
861 prev_be_auth = sm->be_auth_state;
862 prev_reauth_timer = sm->reauth_timer_state;
863 prev_auth_key_tx = sm->auth_key_tx_state;
864 prev_key_rx = sm->key_rx_state;
865 prev_ctrl_dir = sm->ctrl_dir_state;
867 SM_STEP_RUN(AUTH_PAE);
868 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
869 SM_STEP_RUN(BE_AUTH);
870 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
871 SM_STEP_RUN(REAUTH_TIMER);
872 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
873 SM_STEP_RUN(AUTH_KEY_TX);
874 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
875 SM_STEP_RUN(KEY_RX);
876 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
877 SM_STEP_RUN(CTRL_DIR);
879 if (prev_auth_pae != sm->auth_pae_state ||
880 prev_be_auth != sm->be_auth_state ||
881 prev_reauth_timer != sm->reauth_timer_state ||
882 prev_auth_key_tx != sm->auth_key_tx_state ||
883 prev_key_rx != sm->key_rx_state ||
884 prev_ctrl_dir != sm->ctrl_dir_state) {
885 if (--max_steps > 0)
886 goto restart;
887 /* Re-run from eloop timeout */
888 eapol_auth_step(sm);
889 return;
892 if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
893 if (eap_server_sm_step(sm->eap)) {
894 if (--max_steps > 0)
895 goto restart;
896 /* Re-run from eloop timeout */
897 eapol_auth_step(sm);
898 return;
901 /* TODO: find a better location for this */
902 if (sm->eap_if->aaaEapResp) {
903 sm->eap_if->aaaEapResp = FALSE;
904 if (sm->eap_if->aaaEapRespData == NULL) {
905 wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
906 "but no aaaEapRespData available");
907 return;
909 sm->eapol->cb.aaa_send(
910 sm->hapd, sm->sta,
911 wpabuf_head(sm->eap_if->aaaEapRespData),
912 wpabuf_len(sm->eap_if->aaaEapRespData));
916 if (eapol_sm_sta_entry_alive(eapol, addr))
917 wpa_auth_sm_notify(sm->sta->wpa_sm);
921 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
923 struct eapol_state_machine *sm = eloop_ctx;
924 eapol_sm_step_run(sm);
928 void eapol_auth_step(struct eapol_state_machine *sm)
931 * Run eapol_sm_step_run from a registered timeout to make sure that
932 * other possible timeouts/events are processed and to avoid long
933 * function call chains.
936 eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
940 void eapol_auth_initialize(struct eapol_state_machine *sm)
942 sm->initializing = TRUE;
943 /* Initialize the state machines by asserting initialize and then
944 * deasserting it after one step */
945 sm->initialize = TRUE;
946 eapol_sm_step_run(sm);
947 sm->initialize = FALSE;
948 eapol_sm_step_run(sm);
949 sm->initializing = FALSE;
951 /* Start one second tick for port timers state machine */
952 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
953 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
957 #ifdef HOSTAPD_DUMP_STATE
958 static inline const char * port_type_txt(PortTypes pt)
960 switch (pt) {
961 case ForceUnauthorized: return "ForceUnauthorized";
962 case ForceAuthorized: return "ForceAuthorized";
963 case Auto: return "Auto";
964 default: return "Unknown";
969 static inline const char * port_state_txt(PortState ps)
971 switch (ps) {
972 case Unauthorized: return "Unauthorized";
973 case Authorized: return "Authorized";
974 default: return "Unknown";
979 static inline const char * ctrl_dir_txt(ControlledDirection dir)
981 switch (dir) {
982 case Both: return "Both";
983 case In: return "In";
984 default: return "Unknown";
989 static inline const char * auth_pae_state_txt(int s)
991 switch (s) {
992 case AUTH_PAE_INITIALIZE: return "INITIALIZE";
993 case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
994 case AUTH_PAE_CONNECTING: return "CONNECTING";
995 case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
996 case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
997 case AUTH_PAE_ABORTING: return "ABORTING";
998 case AUTH_PAE_HELD: return "HELD";
999 case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
1000 case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
1001 case AUTH_PAE_RESTART: return "RESTART";
1002 default: return "Unknown";
1007 static inline const char * be_auth_state_txt(int s)
1009 switch (s) {
1010 case BE_AUTH_REQUEST: return "REQUEST";
1011 case BE_AUTH_RESPONSE: return "RESPONSE";
1012 case BE_AUTH_SUCCESS: return "SUCCESS";
1013 case BE_AUTH_FAIL: return "FAIL";
1014 case BE_AUTH_TIMEOUT: return "TIMEOUT";
1015 case BE_AUTH_IDLE: return "IDLE";
1016 case BE_AUTH_INITIALIZE: return "INITIALIZE";
1017 case BE_AUTH_IGNORE: return "IGNORE";
1018 default: return "Unknown";
1023 static inline const char * reauth_timer_state_txt(int s)
1025 switch (s) {
1026 case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
1027 case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
1028 default: return "Unknown";
1033 static inline const char * auth_key_tx_state_txt(int s)
1035 switch (s) {
1036 case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
1037 case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
1038 default: return "Unknown";
1043 static inline const char * key_rx_state_txt(int s)
1045 switch (s) {
1046 case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
1047 case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
1048 default: return "Unknown";
1053 static inline const char * ctrl_dir_state_txt(int s)
1055 switch (s) {
1056 case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
1057 case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
1058 default: return "Unknown";
1063 void eapol_auth_dump_state(FILE *f, const char *prefix,
1064 struct eapol_state_machine *sm)
1066 fprintf(f, "%sEAPOL state machine:\n", prefix);
1067 fprintf(f, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
1068 sm->aWhile, sm->quietWhile, sm->reAuthWhen);
1069 #define _SB(b) ((b) ? "TRUE" : "FALSE")
1070 fprintf(f,
1071 "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
1072 "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
1073 "%s eapSuccess=%s eapTimeout=%s initialize=%s "
1074 "keyAvailable=%s\n"
1075 "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
1076 "%s portEnabled=%s portValid=%s reAuthenticate=%s\n",
1077 prefix, _SB(sm->authAbort), _SB(sm->authFail),
1078 port_state_txt(sm->authPortStatus), _SB(sm->authStart),
1079 prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
1080 _SB(sm->eap_if->eapFail), _SB(sm->eapolEap),
1081 prefix, _SB(sm->eap_if->eapSuccess),
1082 _SB(sm->eap_if->eapTimeout),
1083 _SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable),
1084 prefix, _SB(sm->keyDone), _SB(sm->keyRun),
1085 _SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
1086 prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid),
1087 _SB(sm->reAuthenticate));
1089 fprintf(f, "%s Authenticator PAE:\n"
1090 "%s state=%s\n"
1091 "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
1092 "%s portMode=%s reAuthCount=%d\n"
1093 "%s quietPeriod=%d reAuthMax=%d\n"
1094 "%s authEntersConnecting=%d\n"
1095 "%s authEapLogoffsWhileConnecting=%d\n"
1096 "%s authEntersAuthenticating=%d\n"
1097 "%s authAuthSuccessesWhileAuthenticating=%d\n"
1098 "%s authAuthTimeoutsWhileAuthenticating=%d\n"
1099 "%s authAuthFailWhileAuthenticating=%d\n"
1100 "%s authAuthEapStartsWhileAuthenticating=%d\n"
1101 "%s authAuthEapLogoffWhileAuthenticating=%d\n"
1102 "%s authAuthReauthsWhileAuthenticated=%d\n"
1103 "%s authAuthEapStartsWhileAuthenticated=%d\n"
1104 "%s authAuthEapLogoffWhileAuthenticated=%d\n",
1105 prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
1106 _SB(sm->eapolLogoff), _SB(sm->eapolStart),
1107 _SB(sm->eap_if->eapRestart),
1108 prefix, port_type_txt(sm->portMode), sm->reAuthCount,
1109 prefix, sm->quietPeriod, sm->reAuthMax,
1110 prefix, sm->authEntersConnecting,
1111 prefix, sm->authEapLogoffsWhileConnecting,
1112 prefix, sm->authEntersAuthenticating,
1113 prefix, sm->authAuthSuccessesWhileAuthenticating,
1114 prefix, sm->authAuthTimeoutsWhileAuthenticating,
1115 prefix, sm->authAuthFailWhileAuthenticating,
1116 prefix, sm->authAuthEapStartsWhileAuthenticating,
1117 prefix, sm->authAuthEapLogoffWhileAuthenticating,
1118 prefix, sm->authAuthReauthsWhileAuthenticated,
1119 prefix, sm->authAuthEapStartsWhileAuthenticated,
1120 prefix, sm->authAuthEapLogoffWhileAuthenticated);
1122 fprintf(f, "%s Backend Authentication:\n"
1123 "%s state=%s\n"
1124 "%s eapNoReq=%s eapReq=%s eapResp=%s\n"
1125 "%s serverTimeout=%d\n"
1126 "%s backendResponses=%d\n"
1127 "%s backendAccessChallenges=%d\n"
1128 "%s backendOtherRequestsToSupplicant=%d\n"
1129 "%s backendAuthSuccesses=%d\n"
1130 "%s backendAuthFails=%d\n",
1131 prefix, prefix,
1132 be_auth_state_txt(sm->be_auth_state),
1133 prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq),
1134 _SB(sm->eap_if->eapResp),
1135 prefix, sm->serverTimeout,
1136 prefix, sm->backendResponses,
1137 prefix, sm->backendAccessChallenges,
1138 prefix, sm->backendOtherRequestsToSupplicant,
1139 prefix, sm->backendAuthSuccesses,
1140 prefix, sm->backendAuthFails);
1142 fprintf(f, "%s Reauthentication Timer:\n"
1143 "%s state=%s\n"
1144 "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
1145 reauth_timer_state_txt(sm->reauth_timer_state), prefix,
1146 sm->reAuthPeriod, _SB(sm->reAuthEnabled));
1148 fprintf(f, "%s Authenticator Key Transmit:\n"
1149 "%s state=%s\n", prefix, prefix,
1150 auth_key_tx_state_txt(sm->auth_key_tx_state));
1152 fprintf(f, "%s Key Receive:\n"
1153 "%s state=%s\n"
1154 "%s rxKey=%s\n", prefix, prefix,
1155 key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
1157 fprintf(f, "%s Controlled Directions:\n"
1158 "%s state=%s\n"
1159 "%s adminControlledDirections=%s "
1160 "operControlledDirections=%s\n"
1161 "%s operEdge=%s\n", prefix, prefix,
1162 ctrl_dir_state_txt(sm->ctrl_dir_state),
1163 prefix, ctrl_dir_txt(sm->adminControlledDirections),
1164 ctrl_dir_txt(sm->operControlledDirections),
1165 prefix, _SB(sm->operEdge));
1166 #undef _SB
1168 #endif /* HOSTAPD_DUMP_STATE */
1171 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
1172 size_t identity_len, int phase2,
1173 struct eap_user *user)
1175 struct eapol_state_machine *sm = ctx;
1176 return sm->eapol->cb.get_eap_user(sm->hapd, identity, identity_len,
1177 phase2, user);
1181 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
1183 struct eapol_state_machine *sm = ctx;
1184 *len = sm->eapol->conf.eap_req_id_text_len;
1185 return sm->eapol->conf.eap_req_id_text;
1189 static struct eapol_callbacks eapol_cb =
1191 .get_eap_user = eapol_sm_get_eap_user,
1192 .get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
1196 int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
1198 if (sm == NULL || ctx != sm->eap)
1199 return -1;
1201 eap_sm_pending_cb(sm->eap);
1202 eapol_auth_step(sm);
1204 return 0;
1208 static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
1209 struct eapol_auth_config *src)
1211 dst->hapd = src->hapd;
1212 dst->eap_reauth_period = src->eap_reauth_period;
1213 dst->wpa = src->wpa;
1214 dst->individual_wep_key_len = src->individual_wep_key_len;
1215 dst->eap_server = src->eap_server;
1216 dst->ssl_ctx = src->ssl_ctx;
1217 dst->eap_sim_db_priv = src->eap_sim_db_priv;
1218 os_free(dst->eap_req_id_text);
1219 if (src->eap_req_id_text) {
1220 dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
1221 if (dst->eap_req_id_text == NULL)
1222 return -1;
1223 os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
1224 src->eap_req_id_text_len);
1225 dst->eap_req_id_text_len = src->eap_req_id_text_len;
1226 } else {
1227 dst->eap_req_id_text = NULL;
1228 dst->eap_req_id_text_len = 0;
1230 if (src->pac_opaque_encr_key) {
1231 dst->pac_opaque_encr_key = os_malloc(16);
1232 os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
1233 16);
1234 } else
1235 dst->pac_opaque_encr_key = NULL;
1236 if (src->eap_fast_a_id)
1237 dst->eap_fast_a_id = os_strdup(src->eap_fast_a_id);
1238 else
1239 dst->eap_fast_a_id = NULL;
1240 dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
1241 dst->tnc = src->tnc;
1242 return 0;
1246 static void eapol_auth_conf_free(struct eapol_auth_config *conf)
1248 os_free(conf->eap_req_id_text);
1249 conf->eap_req_id_text = NULL;
1250 os_free(conf->pac_opaque_encr_key);
1251 conf->pac_opaque_encr_key = NULL;
1252 os_free(conf->eap_fast_a_id);
1253 conf->eap_fast_a_id = NULL;
1257 struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
1258 struct eapol_auth_cb *cb)
1260 struct eapol_authenticator *eapol;
1262 eapol = os_zalloc(sizeof(*eapol));
1263 if (eapol == NULL)
1264 return NULL;
1266 if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
1267 os_free(eapol);
1268 return NULL;
1271 eapol->cb.eapol_send = cb->eapol_send;
1272 eapol->cb.aaa_send = cb->aaa_send;
1273 eapol->cb.finished = cb->finished;
1274 eapol->cb.get_eap_user = cb->get_eap_user;
1275 eapol->cb.sta_entry_alive = cb->sta_entry_alive;
1276 eapol->cb.logger = cb->logger;
1277 eapol->cb.set_port_authorized = cb->set_port_authorized;
1278 eapol->cb.abort_auth = cb->abort_auth;
1279 eapol->cb.tx_key = cb->tx_key;
1281 return eapol;
1285 void eapol_auth_deinit(struct eapol_authenticator *eapol)
1287 if (eapol == NULL)
1288 return;
1290 eapol_auth_conf_free(&eapol->conf);
1291 os_free(eapol);