2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / IEEE 802.1X Authenticator - EAPOL state machine
4 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
19 #include <netinet/in.h>
21 #include <sys/socket.h>
24 #include "ieee802_1x.h"
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)
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 /* Definitions for clarifying state machine implementation */
51 #define SM_STATE(machine, state) \
52 static void sm_ ## machine ## _ ## state ## _Enter(struct eapol_state_machine \
55 #define SM_ENTRY(machine, _state, _data) \
56 sm->_data.state = machine ## _ ## _state; \
57 if (sm->hapd->conf->debug >= HOSTAPD_DEBUG_MINIMAL) \
58 printf("IEEE 802.1X: " MACSTR " " #machine " entering state " #_state \
59 "\n", MAC2STR(sm->addr));
61 #define SM_ENTER(machine, state) sm_ ## machine ## _ ## state ## _Enter(sm)
63 #define SM_STEP(machine) \
64 static void sm_ ## machine ## _Step(struct eapol_state_machine *sm)
66 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
69 static void eapol_sm_step_run(struct eapol_state_machine
*sm
);
70 static void eapol_sm_step_cb(void *eloop_ctx
, void *timeout_ctx
);
73 /* Port Timers state machine - implemented as a function that will be called
74 * once a second as a registered event loop timeout */
76 static void eapol_port_timers_tick(void *eloop_ctx
, void *timeout_ctx
)
78 struct eapol_state_machine
*state
= timeout_ctx
;
80 if (state
->aWhile
> 0) {
82 if (state
->aWhile
== 0) {
83 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
85 MAC2STR(state
->addr
));
89 if (state
->quietWhile
> 0) {
91 if (state
->quietWhile
== 0) {
92 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
93 " - quietWhile --> 0",
94 MAC2STR(state
->addr
));
98 if (state
->reAuthWhen
> 0) {
100 if (state
->reAuthWhen
== 0) {
101 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
102 " - reAuthWhen --> 0",
103 MAC2STR(state
->addr
));
107 eapol_sm_step_run(state
);
109 eloop_register_timeout(1, 0, eapol_port_timers_tick
, eloop_ctx
, state
);
114 /* Authenticator PAE state machine */
116 SM_STATE(AUTH_PAE
, INITIALIZE
)
118 SM_ENTRY(AUTH_PAE
, INITIALIZE
, auth_pae
);
119 sm
->auth_pae
.portMode
= Auto
;
125 SM_STATE(AUTH_PAE
, DISCONNECTED
)
127 int from_initialize
= sm
->auth_pae
.state
== AUTH_PAE_INITIALIZE
;
129 if (sm
->auth_pae
.eapolLogoff
) {
130 if (sm
->auth_pae
.state
== AUTH_PAE_CONNECTING
)
131 sm
->auth_pae
.authEapLogoffsWhileConnecting
++;
132 else if (sm
->auth_pae
.state
== AUTH_PAE_AUTHENTICATED
)
133 sm
->auth_pae
.authAuthEapLogoffWhileAuthenticated
++;
136 SM_ENTRY(AUTH_PAE
, DISCONNECTED
, auth_pae
);
138 sm
->authPortStatus
= Unauthorized
;
139 setPortUnauthorized();
140 sm
->auth_pae
.reAuthCount
= 0;
141 sm
->auth_pae
.eapolLogoff
= FALSE
;
142 if (!from_initialize
) {
143 if (sm
->flags
& EAPOL_SM_PREAUTH
)
144 rsn_preauth_finished(sm
->hapd
, sm
->sta
, 0);
146 ieee802_1x_finished(sm
->hapd
, sm
->sta
, 0);
151 SM_STATE(AUTH_PAE
, RESTART
)
153 if (sm
->auth_pae
.state
== AUTH_PAE_AUTHENTICATED
) {
154 if (sm
->reAuthenticate
)
155 sm
->auth_pae
.authAuthReauthsWhileAuthenticated
++;
156 if (sm
->auth_pae
.eapolStart
)
157 sm
->auth_pae
.authAuthEapStartsWhileAuthenticated
++;
158 if (sm
->auth_pae
.eapolLogoff
)
159 sm
->auth_pae
.authAuthEapLogoffWhileAuthenticated
++;
162 SM_ENTRY(AUTH_PAE
, RESTART
, auth_pae
);
164 sm
->auth_pae
.eapRestart
= TRUE
;
165 ieee802_1x_request_identity(sm
->hapd
, sm
->sta
);
169 SM_STATE(AUTH_PAE
, CONNECTING
)
171 if (sm
->auth_pae
.state
!= AUTH_PAE_CONNECTING
)
172 sm
->auth_pae
.authEntersConnecting
++;
174 SM_ENTRY(AUTH_PAE
, CONNECTING
, auth_pae
);
176 sm
->reAuthenticate
= FALSE
;
177 sm
->auth_pae
.reAuthCount
++;
181 SM_STATE(AUTH_PAE
, HELD
)
183 if (sm
->auth_pae
.state
== AUTH_PAE_AUTHENTICATING
&& sm
->authFail
)
184 sm
->auth_pae
.authAuthFailWhileAuthenticating
++;
186 SM_ENTRY(AUTH_PAE
, HELD
, auth_pae
);
188 sm
->authPortStatus
= Unauthorized
;
189 setPortUnauthorized();
190 sm
->quietWhile
= sm
->auth_pae
.quietPeriod
;
191 sm
->auth_pae
.eapolLogoff
= FALSE
;
193 hostapd_logger(sm
->hapd
, sm
->addr
, HOSTAPD_MODULE_IEEE8021X
,
194 HOSTAPD_LEVEL_WARNING
, "authentication failed");
195 if (sm
->flags
& EAPOL_SM_PREAUTH
)
196 rsn_preauth_finished(sm
->hapd
, sm
->sta
, 0);
198 ieee802_1x_finished(sm
->hapd
, sm
->sta
, 0);
202 SM_STATE(AUTH_PAE
, AUTHENTICATED
)
204 if (sm
->auth_pae
.state
== AUTH_PAE_AUTHENTICATING
&& sm
->authSuccess
)
205 sm
->auth_pae
.authAuthSuccessesWhileAuthenticating
++;
207 SM_ENTRY(AUTH_PAE
, AUTHENTICATED
, auth_pae
);
209 sm
->authPortStatus
= Authorized
;
211 sm
->auth_pae
.reAuthCount
= 0;
212 hostapd_logger(sm
->hapd
, sm
->addr
, HOSTAPD_MODULE_IEEE8021X
,
213 HOSTAPD_LEVEL_INFO
, "authenticated");
214 if (sm
->flags
& EAPOL_SM_PREAUTH
)
215 rsn_preauth_finished(sm
->hapd
, sm
->sta
, 1);
217 ieee802_1x_finished(sm
->hapd
, sm
->sta
, 1);
221 SM_STATE(AUTH_PAE
, AUTHENTICATING
)
223 if (sm
->auth_pae
.state
== AUTH_PAE_CONNECTING
&& sm
->rx_identity
) {
224 sm
->auth_pae
.authEntersAuthenticating
++;
225 sm
->rx_identity
= FALSE
;
228 SM_ENTRY(AUTH_PAE
, AUTHENTICATING
, auth_pae
);
230 sm
->auth_pae
.eapolStart
= FALSE
;
231 sm
->authSuccess
= FALSE
;
232 sm
->authFail
= FALSE
;
233 sm
->authTimeout
= FALSE
;
234 sm
->authStart
= TRUE
;
240 SM_STATE(AUTH_PAE
, ABORTING
)
242 if (sm
->auth_pae
.state
== AUTH_PAE_AUTHENTICATING
) {
244 sm
->auth_pae
.authAuthTimeoutsWhileAuthenticating
++;
245 if (sm
->auth_pae
.eapolStart
)
246 sm
->auth_pae
.authAuthEapStartsWhileAuthenticating
++;
247 if (sm
->auth_pae
.eapolLogoff
)
248 sm
->auth_pae
.authAuthEapLogoffWhileAuthenticating
++;
251 SM_ENTRY(AUTH_PAE
, ABORTING
, auth_pae
);
253 sm
->authAbort
= TRUE
;
259 SM_STATE(AUTH_PAE
, FORCE_AUTH
)
261 SM_ENTRY(AUTH_PAE
, FORCE_AUTH
, auth_pae
);
263 sm
->authPortStatus
= Authorized
;
265 sm
->auth_pae
.portMode
= ForceAuthorized
;
266 sm
->auth_pae
.eapolStart
= FALSE
;
271 SM_STATE(AUTH_PAE
, FORCE_UNAUTH
)
273 SM_ENTRY(AUTH_PAE
, FORCE_UNAUTH
, auth_pae
);
275 sm
->authPortStatus
= Unauthorized
;
276 setPortUnauthorized();
277 sm
->auth_pae
.portMode
= ForceUnauthorized
;
278 sm
->auth_pae
.eapolStart
= FALSE
;
285 if ((sm
->portControl
== Auto
&&
286 sm
->auth_pae
.portMode
!= sm
->portControl
) ||
287 sm
->initialize
|| !sm
->portEnabled
)
288 SM_ENTER(AUTH_PAE
, INITIALIZE
);
289 else if (sm
->portControl
== ForceAuthorized
&&
290 sm
->auth_pae
.portMode
!= sm
->portControl
&&
291 !(sm
->initialize
|| !sm
->portEnabled
))
292 SM_ENTER(AUTH_PAE
, FORCE_AUTH
);
293 else if (sm
->portControl
== ForceUnauthorized
&&
294 sm
->auth_pae
.portMode
!= sm
->portControl
&&
295 !(sm
->initialize
|| !sm
->portEnabled
))
296 SM_ENTER(AUTH_PAE
, FORCE_UNAUTH
);
298 switch (sm
->auth_pae
.state
) {
299 case AUTH_PAE_INITIALIZE
:
300 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
302 case AUTH_PAE_DISCONNECTED
:
303 SM_ENTER(AUTH_PAE
, RESTART
);
305 case AUTH_PAE_RESTART
:
306 if (!sm
->auth_pae
.eapRestart
)
307 SM_ENTER(AUTH_PAE
, CONNECTING
);
310 if (sm
->quietWhile
== 0)
311 SM_ENTER(AUTH_PAE
, RESTART
);
313 case AUTH_PAE_CONNECTING
:
314 if (sm
->auth_pae
.eapolLogoff
||
315 sm
->auth_pae
.reAuthCount
> sm
->auth_pae
.reAuthMax
)
316 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
317 else if ((sm
->be_auth
.eapReq
&&
318 sm
->auth_pae
.reAuthCount
<=
319 sm
->auth_pae
.reAuthMax
) ||
320 sm
->eapSuccess
|| sm
->eapFail
)
321 SM_ENTER(AUTH_PAE
, AUTHENTICATING
);
323 case AUTH_PAE_AUTHENTICATED
:
324 if (sm
->auth_pae
.eapolStart
|| sm
->reAuthenticate
)
325 SM_ENTER(AUTH_PAE
, RESTART
);
326 else if (sm
->auth_pae
.eapolLogoff
|| !sm
->portValid
)
327 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
329 case AUTH_PAE_AUTHENTICATING
:
330 if (sm
->authSuccess
&& sm
->portValid
)
331 SM_ENTER(AUTH_PAE
, AUTHENTICATED
);
332 else if (sm
->authFail
||
333 (sm
->keyDone
&& !sm
->portValid
))
334 SM_ENTER(AUTH_PAE
, HELD
);
335 else if (sm
->auth_pae
.eapolStart
||
336 sm
->auth_pae
.eapolLogoff
|| sm
->authTimeout
)
337 SM_ENTER(AUTH_PAE
, ABORTING
);
339 case AUTH_PAE_ABORTING
:
340 if (sm
->auth_pae
.eapolLogoff
&& !sm
->authAbort
)
341 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
342 else if (!sm
->auth_pae
.eapolLogoff
&& !sm
->authAbort
)
343 SM_ENTER(AUTH_PAE
, RESTART
);
345 case AUTH_PAE_FORCE_AUTH
:
346 if (sm
->auth_pae
.eapolStart
)
347 SM_ENTER(AUTH_PAE
, FORCE_AUTH
);
349 case AUTH_PAE_FORCE_UNAUTH
:
350 if (sm
->auth_pae
.eapolStart
)
351 SM_ENTER(AUTH_PAE
, FORCE_UNAUTH
);
359 /* Backend Authentication state machine */
361 SM_STATE(BE_AUTH
, INITIALIZE
)
363 SM_ENTRY(BE_AUTH
, INITIALIZE
, be_auth
);
366 sm
->be_auth
.eapNoReq
= FALSE
;
367 sm
->authAbort
= FALSE
;
371 SM_STATE(BE_AUTH
, REQUEST
)
373 SM_ENTRY(BE_AUTH
, REQUEST
, be_auth
);
376 sm
->be_auth
.eapReq
= FALSE
;
377 sm
->be_auth
.backendOtherRequestsToSupplicant
++;
380 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
381 * it looks like this would be logical thing to do there since the old
382 * EAP response would not be valid anymore after the new EAP request
385 * A race condition has been reported, in which hostapd ended up
386 * sending out EAP-Response/Identity as a response to the first
387 * EAP-Request from the main EAP method. This can be avoided by
388 * clearing eapolEap here.
390 sm
->eapolEap
= FALSE
;
394 SM_STATE(BE_AUTH
, RESPONSE
)
396 SM_ENTRY(BE_AUTH
, RESPONSE
, be_auth
);
398 sm
->authTimeout
= FALSE
;
399 sm
->eapolEap
= FALSE
;
400 sm
->be_auth
.eapNoReq
= FALSE
;
401 sm
->aWhile
= sm
->be_auth
.serverTimeout
;
402 sm
->be_auth
.eapResp
= TRUE
;
404 sm
->be_auth
.backendResponses
++;
408 SM_STATE(BE_AUTH
, SUCCESS
)
410 SM_ENTRY(BE_AUTH
, SUCCESS
, be_auth
);
413 sm
->authSuccess
= TRUE
;
418 SM_STATE(BE_AUTH
, FAIL
)
420 SM_ENTRY(BE_AUTH
, FAIL
, be_auth
);
422 /* Note: IEEE 802.1X-REV-d11 has unconditional txReq() here.
423 * txCannelFail() is used as a workaround for the case where
424 * authentication server does not include EAP-Message with
426 if (sm
->last_eap_radius
== NULL
)
434 SM_STATE(BE_AUTH
, TIMEOUT
)
436 SM_ENTRY(BE_AUTH
, TIMEOUT
, be_auth
);
438 sm
->authTimeout
= TRUE
;
442 SM_STATE(BE_AUTH
, IDLE
)
444 SM_ENTRY(BE_AUTH
, IDLE
, be_auth
);
446 sm
->authStart
= FALSE
;
450 SM_STATE(BE_AUTH
, IGNORE
)
452 SM_ENTRY(BE_AUTH
, IGNORE
, be_auth
);
454 sm
->be_auth
.eapNoReq
= FALSE
;
460 if (sm
->portControl
!= Auto
|| sm
->initialize
|| sm
->authAbort
) {
461 SM_ENTER(BE_AUTH
, INITIALIZE
);
465 switch (sm
->be_auth
.state
) {
466 case BE_AUTH_INITIALIZE
:
467 SM_ENTER(BE_AUTH
, IDLE
);
469 case BE_AUTH_REQUEST
:
471 SM_ENTER(BE_AUTH
, RESPONSE
);
472 else if (sm
->be_auth
.eapReq
)
473 SM_ENTER(BE_AUTH
, REQUEST
);
474 else if (sm
->eapTimeout
)
475 SM_ENTER(BE_AUTH
, TIMEOUT
);
477 case BE_AUTH_RESPONSE
:
478 if (sm
->be_auth
.eapNoReq
)
479 SM_ENTER(BE_AUTH
, IGNORE
);
480 if (sm
->be_auth
.eapReq
) {
481 sm
->be_auth
.backendAccessChallenges
++;
482 SM_ENTER(BE_AUTH
, REQUEST
);
483 } else if (sm
->aWhile
== 0)
484 SM_ENTER(BE_AUTH
, TIMEOUT
);
485 else if (sm
->eapFail
) {
486 sm
->be_auth
.backendAuthFails
++;
487 SM_ENTER(BE_AUTH
, FAIL
);
488 } else if (sm
->eapSuccess
) {
489 sm
->be_auth
.backendAuthSuccesses
++;
490 SM_ENTER(BE_AUTH
, SUCCESS
);
493 case BE_AUTH_SUCCESS
:
494 SM_ENTER(BE_AUTH
, IDLE
);
497 SM_ENTER(BE_AUTH
, IDLE
);
499 case BE_AUTH_TIMEOUT
:
500 SM_ENTER(BE_AUTH
, IDLE
);
503 if (sm
->eapFail
&& sm
->authStart
)
504 SM_ENTER(BE_AUTH
, FAIL
);
505 else if (sm
->be_auth
.eapReq
&& sm
->authStart
)
506 SM_ENTER(BE_AUTH
, REQUEST
);
507 else if (sm
->eapSuccess
&& sm
->authStart
)
508 SM_ENTER(BE_AUTH
, SUCCESS
);
512 SM_ENTER(BE_AUTH
, RESPONSE
);
513 else if (sm
->be_auth
.eapReq
)
514 SM_ENTER(BE_AUTH
, REQUEST
);
515 else if (sm
->eapTimeout
)
516 SM_ENTER(BE_AUTH
, TIMEOUT
);
523 /* Reauthentication Timer state machine */
525 SM_STATE(REAUTH_TIMER
, INITIALIZE
)
527 SM_ENTRY(REAUTH_TIMER
, INITIALIZE
, reauth_timer
);
529 sm
->reAuthWhen
= sm
->reauth_timer
.reAuthPeriod
;
533 SM_STATE(REAUTH_TIMER
, REAUTHENTICATE
)
535 SM_ENTRY(REAUTH_TIMER
, REAUTHENTICATE
, reauth_timer
);
537 sm
->reAuthenticate
= TRUE
;
538 wpa_sm_event(sm
->hapd
, sm
->sta
, WPA_REAUTH_EAPOL
);
542 SM_STEP(REAUTH_TIMER
)
544 if (sm
->portControl
!= Auto
|| sm
->initialize
||
545 sm
->authPortStatus
== Unauthorized
||
546 !sm
->reauth_timer
.reAuthEnabled
) {
547 SM_ENTER(REAUTH_TIMER
, INITIALIZE
);
551 switch (sm
->reauth_timer
.state
) {
552 case REAUTH_TIMER_INITIALIZE
:
553 if (sm
->reAuthWhen
== 0)
554 SM_ENTER(REAUTH_TIMER
, REAUTHENTICATE
);
556 case REAUTH_TIMER_REAUTHENTICATE
:
557 SM_ENTER(REAUTH_TIMER
, INITIALIZE
);
564 /* Authenticator Key Transmit state machine */
566 SM_STATE(AUTH_KEY_TX
, NO_KEY_TRANSMIT
)
568 SM_ENTRY(AUTH_KEY_TX
, NO_KEY_TRANSMIT
, auth_key_tx
);
572 SM_STATE(AUTH_KEY_TX
, KEY_TRANSMIT
)
574 SM_ENTRY(AUTH_KEY_TX
, KEY_TRANSMIT
, auth_key_tx
);
577 sm
->keyAvailable
= FALSE
;
584 if (sm
->initialize
|| sm
->portControl
!= Auto
) {
585 SM_ENTER(AUTH_KEY_TX
, NO_KEY_TRANSMIT
);
589 switch (sm
->auth_key_tx
.state
) {
590 case AUTH_KEY_TX_NO_KEY_TRANSMIT
:
591 if (sm
->keyTxEnabled
&& sm
->keyAvailable
&& sm
->keyRun
&&
593 SM_ENTER(AUTH_KEY_TX
, KEY_TRANSMIT
);
595 case AUTH_KEY_TX_KEY_TRANSMIT
:
596 if (!sm
->keyTxEnabled
|| !sm
->keyRun
)
597 SM_ENTER(AUTH_KEY_TX
, NO_KEY_TRANSMIT
);
598 else if (sm
->keyAvailable
)
599 SM_ENTER(AUTH_KEY_TX
, KEY_TRANSMIT
);
606 /* Key Receive state machine */
608 SM_STATE(KEY_RX
, NO_KEY_RECEIVE
)
610 SM_ENTRY(KEY_RX
, NO_KEY_RECEIVE
, key_rx
);
614 SM_STATE(KEY_RX
, KEY_RECEIVE
)
616 SM_ENTRY(KEY_RX
, KEY_RECEIVE
, key_rx
);
619 sm
->key_rx
.rxKey
= FALSE
;
625 if (sm
->initialize
|| !sm
->portEnabled
) {
626 SM_ENTER(KEY_RX
, NO_KEY_RECEIVE
);
630 switch (sm
->key_rx
.state
) {
631 case KEY_RX_NO_KEY_RECEIVE
:
632 if (sm
->key_rx
.rxKey
)
633 SM_ENTER(KEY_RX
, KEY_RECEIVE
);
635 case KEY_RX_KEY_RECEIVE
:
636 if (sm
->key_rx
.rxKey
)
637 SM_ENTER(KEY_RX
, KEY_RECEIVE
);
644 /* Controlled Directions state machine */
646 SM_STATE(CTRL_DIR
, FORCE_BOTH
)
648 SM_ENTRY(CTRL_DIR
, FORCE_BOTH
, ctrl_dir
);
649 sm
->ctrl_dir
.operControlledDirections
= Both
;
653 SM_STATE(CTRL_DIR
, IN_OR_BOTH
)
655 SM_ENTRY(CTRL_DIR
, IN_OR_BOTH
, ctrl_dir
);
656 sm
->ctrl_dir
.operControlledDirections
=
657 sm
->ctrl_dir
.adminControlledDirections
;
663 if (sm
->initialize
) {
664 SM_ENTER(CTRL_DIR
, IN_OR_BOTH
);
668 switch (sm
->ctrl_dir
.state
) {
669 case CTRL_DIR_FORCE_BOTH
:
670 if (sm
->portEnabled
&& sm
->ctrl_dir
.operEdge
)
671 SM_ENTER(CTRL_DIR
, IN_OR_BOTH
);
673 case CTRL_DIR_IN_OR_BOTH
:
674 if (sm
->ctrl_dir
.operControlledDirections
!=
675 sm
->ctrl_dir
.adminControlledDirections
)
676 SM_ENTER(CTRL_DIR
, IN_OR_BOTH
);
677 if (!sm
->portEnabled
|| !sm
->ctrl_dir
.operEdge
)
678 SM_ENTER(CTRL_DIR
, FORCE_BOTH
);
685 struct eapol_state_machine
*
686 eapol_sm_alloc(hostapd
*hapd
, struct sta_info
*sta
)
688 struct eapol_state_machine
*sm
;
690 sm
= (struct eapol_state_machine
*) malloc(sizeof(*sm
));
692 printf("IEEE 802.1X port state allocation failed\n");
695 memset(sm
, 0, sizeof(*sm
));
696 sm
->radius_identifier
= -1;
697 memcpy(sm
->addr
, sta
->addr
, ETH_ALEN
);
698 if (sta
->flags
& WLAN_STA_PREAUTH
)
699 sm
->flags
|= EAPOL_SM_PREAUTH
;
704 /* Set default values for state machine constants */
705 sm
->auth_pae
.state
= AUTH_PAE_INITIALIZE
;
706 sm
->auth_pae
.quietPeriod
= AUTH_PAE_DEFAULT_quietPeriod
;
707 sm
->auth_pae
.reAuthMax
= AUTH_PAE_DEFAULT_reAuthMax
;
709 sm
->be_auth
.state
= BE_AUTH_INITIALIZE
;
710 sm
->be_auth
.serverTimeout
= BE_AUTH_DEFAULT_serverTimeout
;
712 sm
->reauth_timer
.state
= REAUTH_TIMER_INITIALIZE
;
713 sm
->reauth_timer
.reAuthPeriod
= hapd
->conf
->eap_reauth_period
;
714 sm
->reauth_timer
.reAuthEnabled
= hapd
->conf
->eap_reauth_period
> 0 ?
717 sm
->auth_key_tx
.state
= AUTH_KEY_TX_NO_KEY_TRANSMIT
;
719 sm
->key_rx
.state
= KEY_RX_NO_KEY_RECEIVE
;
721 sm
->ctrl_dir
.state
= CTRL_DIR_IN_OR_BOTH
;
723 sm
->portEnabled
= FALSE
;
724 sm
->portControl
= Auto
;
726 sm
->keyAvailable
= FALSE
;
727 if (!hapd
->conf
->wpa
&&
728 (hapd
->default_wep_key
|| hapd
->conf
->individual_wep_key_len
> 0))
729 sm
->keyTxEnabled
= TRUE
;
731 sm
->keyTxEnabled
= FALSE
;
733 sm
->portValid
= FALSE
;
735 sm
->portValid
= TRUE
;
737 if (hapd
->conf
->eap_server
) {
738 struct eap_config eap_conf
;
739 memset(&eap_conf
, 0, sizeof(eap_conf
));
740 eap_conf
.ssl_ctx
= hapd
->ssl_ctx
;
741 eap_conf
.eap_sim_db_priv
= hapd
->eap_sim_db_priv
;
742 sm
->eap
= eap_sm_init(sm
, &eapol_cb
, &eap_conf
);
743 if (sm
->eap
== NULL
) {
749 eapol_sm_initialize(sm
);
755 void eapol_sm_free(struct eapol_state_machine
*sm
)
760 eloop_cancel_timeout(eapol_port_timers_tick
, sm
->hapd
, sm
);
761 eloop_cancel_timeout(eapol_sm_step_cb
, sm
, NULL
);
763 eap_sm_deinit(sm
->eap
);
768 static int eapol_sm_sta_entry_alive(struct hostapd_data
*hapd
, u8
*addr
)
770 struct sta_info
*sta
;
771 sta
= ap_get_sta(hapd
, addr
);
772 if (sta
== NULL
|| sta
->eapol_sm
== NULL
)
778 static void eapol_sm_step_run(struct eapol_state_machine
*sm
)
780 struct hostapd_data
*hapd
= sm
->hapd
;
782 int prev_auth_pae
, prev_be_auth
, prev_reauth_timer
, prev_auth_key_tx
,
783 prev_key_rx
, prev_ctrl_dir
;
786 memcpy(addr
, sm
->sta
->addr
, ETH_ALEN
);
789 * Allow EAPOL state machines to run as long as there are state
790 * changes, but exit and return here through event loop if more than
791 * 100 steps is needed as a precaution against infinite loops inside
795 prev_auth_pae
= sm
->auth_pae
.state
;
796 prev_be_auth
= sm
->be_auth
.state
;
797 prev_reauth_timer
= sm
->reauth_timer
.state
;
798 prev_auth_key_tx
= sm
->auth_key_tx
.state
;
799 prev_key_rx
= sm
->key_rx
.state
;
800 prev_ctrl_dir
= sm
->ctrl_dir
.state
;
802 SM_STEP_RUN(AUTH_PAE
);
803 if (sm
->initializing
|| eapol_sm_sta_entry_alive(hapd
, addr
))
804 SM_STEP_RUN(BE_AUTH
);
805 if (sm
->initializing
|| eapol_sm_sta_entry_alive(hapd
, addr
))
806 SM_STEP_RUN(REAUTH_TIMER
);
807 if (sm
->initializing
|| eapol_sm_sta_entry_alive(hapd
, addr
))
808 SM_STEP_RUN(AUTH_KEY_TX
);
809 if (sm
->initializing
|| eapol_sm_sta_entry_alive(hapd
, addr
))
811 if (sm
->initializing
|| eapol_sm_sta_entry_alive(hapd
, addr
))
812 SM_STEP_RUN(CTRL_DIR
);
814 if (prev_auth_pae
!= sm
->auth_pae
.state
||
815 prev_be_auth
!= sm
->be_auth
.state
||
816 prev_reauth_timer
!= sm
->reauth_timer
.state
||
817 prev_auth_key_tx
!= sm
->auth_key_tx
.state
||
818 prev_key_rx
!= sm
->key_rx
.state
||
819 prev_ctrl_dir
!= sm
->ctrl_dir
.state
) {
822 /* Re-run from eloop timeout */
827 if (eapol_sm_sta_entry_alive(hapd
, addr
) && sm
->eap
) {
828 if (eap_sm_step(sm
->eap
)) {
831 /* Re-run from eloop timeout */
837 if (eapol_sm_sta_entry_alive(hapd
, addr
))
838 wpa_sm_notify(sm
->hapd
, sm
->sta
);
842 static void eapol_sm_step_cb(void *eloop_ctx
, void *timeout_ctx
)
844 struct eapol_state_machine
*sm
= eloop_ctx
;
845 eapol_sm_step_run(sm
);
849 void eapol_sm_step(struct eapol_state_machine
*sm
)
852 * Run eapol_sm_step_run from a registered timeout to make sure that
853 * other possible timeouts/events are processed and to avoid long
854 * function call chains.
857 eloop_register_timeout(0, 0, eapol_sm_step_cb
, sm
, NULL
);
861 void eapol_sm_initialize(struct eapol_state_machine
*sm
)
863 sm
->initializing
= TRUE
;
864 /* Initialize the state machines by asserting initialize and then
865 * deasserting it after one step */
866 sm
->initialize
= TRUE
;
867 eapol_sm_step_run(sm
);
868 sm
->initialize
= FALSE
;
869 eapol_sm_step_run(sm
);
870 sm
->initializing
= FALSE
;
872 /* Start one second tick for port timers state machine */
873 eloop_cancel_timeout(eapol_port_timers_tick
, sm
->hapd
, sm
);
874 eloop_register_timeout(1, 0, eapol_port_timers_tick
, sm
->hapd
, sm
);
878 #ifdef HOSTAPD_DUMP_STATE
879 static inline const char * port_type_txt(PortTypes pt
)
882 case ForceUnauthorized
: return "ForceUnauthorized";
883 case ForceAuthorized
: return "ForceAuthorized";
884 case Auto
: return "Auto";
885 default: return "Unknown";
890 static inline const char * port_state_txt(PortState ps
)
893 case Unauthorized
: return "Unauthorized";
894 case Authorized
: return "Authorized";
895 default: return "Unknown";
900 static inline const char * ctrl_dir_txt(ControlledDirection dir
)
903 case Both
: return "Both";
904 case In
: return "In";
905 default: return "Unknown";
910 static inline const char * auth_pae_state_txt(int s
)
913 case AUTH_PAE_INITIALIZE
: return "INITIALIZE";
914 case AUTH_PAE_DISCONNECTED
: return "DISCONNECTED";
915 case AUTH_PAE_CONNECTING
: return "CONNECTING";
916 case AUTH_PAE_AUTHENTICATING
: return "AUTHENTICATING";
917 case AUTH_PAE_AUTHENTICATED
: return "AUTHENTICATED";
918 case AUTH_PAE_ABORTING
: return "ABORTING";
919 case AUTH_PAE_HELD
: return "HELD";
920 case AUTH_PAE_FORCE_AUTH
: return "FORCE_AUTH";
921 case AUTH_PAE_FORCE_UNAUTH
: return "FORCE_UNAUTH";
922 case AUTH_PAE_RESTART
: return "RESTART";
923 default: return "Unknown";
928 static inline const char * be_auth_state_txt(int s
)
931 case BE_AUTH_REQUEST
: return "REQUEST";
932 case BE_AUTH_RESPONSE
: return "RESPONSE";
933 case BE_AUTH_SUCCESS
: return "SUCCESS";
934 case BE_AUTH_FAIL
: return "FAIL";
935 case BE_AUTH_TIMEOUT
: return "TIMEOUT";
936 case BE_AUTH_IDLE
: return "IDLE";
937 case BE_AUTH_INITIALIZE
: return "INITIALIZE";
938 case BE_AUTH_IGNORE
: return "IGNORE";
939 default: return "Unknown";
944 static inline const char * reauth_timer_state_txt(int s
)
947 case REAUTH_TIMER_INITIALIZE
: return "INITIALIZE";
948 case REAUTH_TIMER_REAUTHENTICATE
: return "REAUTHENTICATE";
949 default: return "Unknown";
954 static inline const char * auth_key_tx_state_txt(int s
)
957 case AUTH_KEY_TX_NO_KEY_TRANSMIT
: return "NO_KEY_TRANSMIT";
958 case AUTH_KEY_TX_KEY_TRANSMIT
: return "KEY_TRANSMIT";
959 default: return "Unknown";
964 static inline const char * key_rx_state_txt(int s
)
967 case KEY_RX_NO_KEY_RECEIVE
: return "NO_KEY_RECEIVE";
968 case KEY_RX_KEY_RECEIVE
: return "KEY_RECEIVE";
969 default: return "Unknown";
974 static inline const char * ctrl_dir_state_txt(int s
)
977 case CTRL_DIR_FORCE_BOTH
: return "FORCE_BOTH";
978 case CTRL_DIR_IN_OR_BOTH
: return "IN_OR_BOTH";
979 default: return "Unknown";
984 void eapol_sm_dump_state(FILE *f
, const char *prefix
,
985 struct eapol_state_machine
*sm
)
987 fprintf(f
, "%sEAPOL state machine:\n", prefix
);
988 fprintf(f
, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix
,
989 sm
->aWhile
, sm
->quietWhile
, sm
->reAuthWhen
);
990 #define _SB(b) ((b) ? "TRUE" : "FALSE")
992 "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
993 "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
994 "%s eapSuccess=%s eapTimeout=%s initialize=%s "
996 "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
997 "%s portEnabled=%s portValid=%s reAuthenticate=%s\n",
998 prefix
, _SB(sm
->authAbort
), _SB(sm
->authFail
),
999 port_state_txt(sm
->authPortStatus
), _SB(sm
->authStart
),
1000 prefix
, _SB(sm
->authTimeout
), _SB(sm
->authSuccess
),
1001 _SB(sm
->eapFail
), _SB(sm
->eapolEap
),
1002 prefix
, _SB(sm
->eapSuccess
), _SB(sm
->eapTimeout
),
1003 _SB(sm
->initialize
), _SB(sm
->keyAvailable
),
1004 prefix
, _SB(sm
->keyDone
), _SB(sm
->keyRun
),
1005 _SB(sm
->keyTxEnabled
), port_type_txt(sm
->portControl
),
1006 prefix
, _SB(sm
->portEnabled
), _SB(sm
->portValid
),
1007 _SB(sm
->reAuthenticate
));
1009 fprintf(f
, "%s Authenticator PAE:\n"
1011 "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
1012 "%s portMode=%s reAuthCount=%d\n"
1013 "%s quietPeriod=%d reAuthMax=%d\n"
1014 "%s authEntersConnecting=%d\n"
1015 "%s authEapLogoffsWhileConnecting=%d\n"
1016 "%s authEntersAuthenticating=%d\n"
1017 "%s authAuthSuccessesWhileAuthenticating=%d\n"
1018 "%s authAuthTimeoutsWhileAuthenticating=%d\n"
1019 "%s authAuthFailWhileAuthenticating=%d\n"
1020 "%s authAuthEapStartsWhileAuthenticating=%d\n"
1021 "%s authAuthEapLogoffWhileAuthenticating=%d\n"
1022 "%s authAuthReauthsWhileAuthenticated=%d\n"
1023 "%s authAuthEapStartsWhileAuthenticated=%d\n"
1024 "%s authAuthEapLogoffWhileAuthenticated=%d\n",
1025 prefix
, prefix
, auth_pae_state_txt(sm
->auth_pae
.state
), prefix
,
1026 _SB(sm
->auth_pae
.eapolLogoff
), _SB(sm
->auth_pae
.eapolStart
),
1027 _SB(sm
->auth_pae
.eapRestart
), prefix
,
1028 port_type_txt(sm
->auth_pae
.portMode
), sm
->auth_pae
.reAuthCount
,
1029 prefix
, sm
->auth_pae
.quietPeriod
, sm
->auth_pae
.reAuthMax
,
1030 prefix
, sm
->auth_pae
.authEntersConnecting
,
1031 prefix
, sm
->auth_pae
.authEapLogoffsWhileConnecting
,
1032 prefix
, sm
->auth_pae
.authEntersAuthenticating
,
1033 prefix
, sm
->auth_pae
.authAuthSuccessesWhileAuthenticating
,
1034 prefix
, sm
->auth_pae
.authAuthTimeoutsWhileAuthenticating
,
1035 prefix
, sm
->auth_pae
.authAuthFailWhileAuthenticating
,
1036 prefix
, sm
->auth_pae
.authAuthEapStartsWhileAuthenticating
,
1037 prefix
, sm
->auth_pae
.authAuthEapLogoffWhileAuthenticating
,
1038 prefix
, sm
->auth_pae
.authAuthReauthsWhileAuthenticated
,
1039 prefix
, sm
->auth_pae
.authAuthEapStartsWhileAuthenticated
,
1040 prefix
, sm
->auth_pae
.authAuthEapLogoffWhileAuthenticated
);
1042 fprintf(f
, "%s Backend Authentication:\n"
1044 "%s eapNoReq=%s eapReq=%s eapResp=%s\n"
1045 "%s serverTimeout=%d\n"
1046 "%s backendResponses=%d\n"
1047 "%s backendAccessChallenges=%d\n"
1048 "%s backendOtherRequestsToSupplicant=%d\n"
1049 "%s backendAuthSuccesses=%d\n"
1050 "%s backendAuthFails=%d\n",
1052 be_auth_state_txt(sm
->be_auth
.state
),
1053 prefix
, _SB(sm
->be_auth
.eapNoReq
), _SB(sm
->be_auth
.eapReq
),
1054 _SB(sm
->be_auth
.eapResp
),
1055 prefix
, sm
->be_auth
.serverTimeout
,
1056 prefix
, sm
->be_auth
.backendResponses
,
1057 prefix
, sm
->be_auth
.backendAccessChallenges
,
1058 prefix
, sm
->be_auth
.backendOtherRequestsToSupplicant
,
1059 prefix
, sm
->be_auth
.backendAuthSuccesses
,
1060 prefix
, sm
->be_auth
.backendAuthFails
);
1062 fprintf(f
, "%s Reauthentication Timer:\n"
1064 "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix
, prefix
,
1065 reauth_timer_state_txt(sm
->reauth_timer
.state
), prefix
,
1066 sm
->reauth_timer
.reAuthPeriod
,
1067 _SB(sm
->reauth_timer
.reAuthEnabled
));
1069 fprintf(f
, "%s Authenticator Key Transmit:\n"
1070 "%s state=%s\n", prefix
, prefix
,
1071 auth_key_tx_state_txt(sm
->auth_key_tx
.state
));
1073 fprintf(f
, "%s Key Receive:\n"
1075 "%s rxKey=%s\n", prefix
, prefix
,
1076 key_rx_state_txt(sm
->key_rx
.state
),
1077 prefix
, _SB(sm
->key_rx
.rxKey
));
1079 fprintf(f
, "%s Controlled Directions:\n"
1081 "%s adminControlledDirections=%s "
1082 "operControlledDirections=%s\n"
1083 "%s operEdge=%s\n", prefix
, prefix
,
1084 ctrl_dir_state_txt(sm
->ctrl_dir
.state
),
1085 prefix
, ctrl_dir_txt(sm
->ctrl_dir
.adminControlledDirections
),
1086 ctrl_dir_txt(sm
->ctrl_dir
.operControlledDirections
),
1087 prefix
, _SB(sm
->ctrl_dir
.operEdge
));
1090 #endif /* HOSTAPD_DUMP_STATE */
1093 static Boolean
eapol_sm_get_bool(void *ctx
, enum eapol_bool_var variable
)
1095 struct eapol_state_machine
*sm
= ctx
;
1099 case EAPOL_eapSuccess
:
1100 return sm
->eapSuccess
;
1101 case EAPOL_eapRestart
:
1102 return sm
->auth_pae
.eapRestart
;
1106 return sm
->be_auth
.eapResp
;
1108 return sm
->be_auth
.eapReq
;
1109 case EAPOL_eapNoReq
:
1110 return sm
->be_auth
.eapNoReq
;
1111 case EAPOL_portEnabled
:
1112 return sm
->portEnabled
;
1113 case EAPOL_eapTimeout
:
1114 return sm
->eapTimeout
;
1120 static void eapol_sm_set_bool(void *ctx
, enum eapol_bool_var variable
,
1123 struct eapol_state_machine
*sm
= ctx
;
1127 case EAPOL_eapSuccess
:
1128 sm
->eapSuccess
= value
;
1130 case EAPOL_eapRestart
:
1131 sm
->auth_pae
.eapRestart
= value
;
1134 sm
->eapFail
= value
;
1137 sm
->be_auth
.eapResp
= value
;
1140 sm
->be_auth
.eapReq
= value
;
1142 case EAPOL_eapNoReq
:
1143 sm
->be_auth
.eapNoReq
= value
;
1145 case EAPOL_portEnabled
:
1146 sm
->portEnabled
= value
;
1148 case EAPOL_eapTimeout
:
1149 sm
->eapTimeout
= value
;
1155 static void eapol_sm_set_eapReqData(void *ctx
, const u8
*eapReqData
,
1156 size_t eapReqDataLen
)
1158 struct eapol_state_machine
*sm
= ctx
;
1162 free(sm
->last_eap_radius
);
1163 sm
->last_eap_radius
= malloc(eapReqDataLen
);
1164 if (sm
->last_eap_radius
== NULL
)
1166 memcpy(sm
->last_eap_radius
, eapReqData
, eapReqDataLen
);
1167 sm
->last_eap_radius_len
= eapReqDataLen
;
1171 static void eapol_sm_set_eapKeyData(void *ctx
, const u8
*eapKeyData
,
1172 size_t eapKeyDataLen
)
1174 struct eapol_state_machine
*sm
= ctx
;
1175 struct hostapd_data
*hapd
;
1182 if (eapKeyData
&& eapKeyDataLen
>= 64) {
1183 free(sm
->eapol_key_sign
);
1184 free(sm
->eapol_key_crypt
);
1185 sm
->eapol_key_crypt
= malloc(32);
1186 if (sm
->eapol_key_crypt
) {
1187 memcpy(sm
->eapol_key_crypt
, eapKeyData
, 32);
1188 sm
->eapol_key_crypt_len
= 32;
1190 sm
->eapol_key_sign
= malloc(32);
1191 if (sm
->eapol_key_sign
) {
1192 memcpy(sm
->eapol_key_sign
, eapKeyData
+ 32, 32);
1193 sm
->eapol_key_sign_len
= 32;
1195 if (hapd
->default_wep_key
||
1196 hapd
->conf
->individual_wep_key_len
> 0 ||
1198 sm
->keyAvailable
= TRUE
;
1200 free(sm
->eapol_key_sign
);
1201 free(sm
->eapol_key_crypt
);
1202 sm
->eapol_key_sign
= NULL
;
1203 sm
->eapol_key_crypt
= NULL
;
1204 sm
->eapol_key_sign_len
= 0;
1205 sm
->eapol_key_crypt_len
= 0;
1206 sm
->keyAvailable
= FALSE
;
1211 static int eapol_sm_get_eap_user(void *ctx
, const u8
*identity
,
1212 size_t identity_len
, int phase2
,
1213 struct eap_user
*user
)
1215 struct eapol_state_machine
*sm
= ctx
;
1216 const struct hostapd_eap_user
*eap_user
;
1218 eap_user
= hostapd_get_eap_user(sm
->hapd
->conf
, identity
,
1219 identity_len
, phase2
);
1220 if (eap_user
== NULL
)
1223 memset(user
, 0, sizeof(*user
));
1224 user
->phase2
= phase2
;
1225 memcpy(user
->methods
, eap_user
->methods
,
1226 EAP_USER_MAX_METHODS
> EAP_MAX_METHODS
?
1227 EAP_USER_MAX_METHODS
: EAP_MAX_METHODS
);
1229 if (eap_user
->password
) {
1230 user
->password
= malloc(eap_user
->password_len
);
1231 if (user
->password
== NULL
)
1233 memcpy(user
->password
, eap_user
->password
,
1234 eap_user
->password_len
);
1235 user
->password_len
= eap_user
->password_len
;
1237 user
->force_version
= eap_user
->force_version
;
1243 static const char * eapol_sm_get_eap_req_id_text(void *ctx
, size_t *len
)
1245 struct eapol_state_machine
*sm
= ctx
;
1246 *len
= sm
->hapd
->conf
->eap_req_id_text_len
;
1247 return sm
->hapd
->conf
->eap_req_id_text
;
1251 static struct eapol_callbacks eapol_cb
=
1253 .get_bool
= eapol_sm_get_bool
,
1254 .set_bool
= eapol_sm_set_bool
,
1255 .set_eapReqData
= eapol_sm_set_eapReqData
,
1256 .set_eapKeyData
= eapol_sm_set_eapKeyData
,
1257 .get_eap_user
= eapol_sm_get_eap_user
,
1258 .get_eap_req_id_text
= eapol_sm_get_eap_req_id_text
,