2 * IEEE 802.1X-2004 Authenticator - EAPOL state machine
3 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "state_machine.h"
14 #include "common/eapol_common.h"
15 #include "eap_common/eap_defs.h"
16 #include "eap_common/eap_common.h"
17 #include "eap_server/eap.h"
18 #include "eapol_auth_sm.h"
19 #include "eapol_auth_sm_i.h"
21 #define STATE_MACHINE_DATA struct eapol_state_machine
22 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
23 #define STATE_MACHINE_ADDR sm->addr
25 static const struct eapol_callbacks eapol_cb
;
27 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
29 #define setPortAuthorized() \
30 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1)
31 #define setPortUnauthorized() \
32 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0)
35 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
36 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
37 #define txReq() eapol_auth_tx_req(sm)
38 #define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta)
39 #define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta)
40 #define processKey() do { } while (0)
43 static void eapol_sm_step_run(struct eapol_state_machine
*sm
);
44 static void eapol_sm_step_cb(void *eloop_ctx
, void *timeout_ctx
);
45 static void eapol_auth_initialize(struct eapol_state_machine
*sm
);
46 static void eapol_auth_conf_free(struct eapol_auth_config
*conf
);
49 static void eapol_auth_logger(struct eapol_authenticator
*eapol
,
50 const u8
*addr
, eapol_logger_level level
,
53 if (eapol
->cb
.logger
== NULL
)
55 eapol
->cb
.logger(eapol
->conf
.ctx
, addr
, level
, txt
);
59 static void eapol_auth_vlogger(struct eapol_authenticator
*eapol
,
60 const u8
*addr
, eapol_logger_level level
,
67 if (eapol
->cb
.logger
== NULL
)
70 maxlen
= os_strlen(fmt
) + 100;
71 format
= os_malloc(maxlen
);
76 vsnprintf(format
, maxlen
, fmt
, ap
);
79 eapol_auth_logger(eapol
, addr
, level
, format
);
85 static void eapol_auth_tx_canned_eap(struct eapol_state_machine
*sm
,
90 os_memset(&eap
, 0, sizeof(eap
));
92 eap
.code
= success
? EAP_CODE_SUCCESS
: EAP_CODE_FAILURE
;
93 eap
.identifier
= ++sm
->last_eap_id
;
94 eap
.length
= host_to_be16(sizeof(eap
));
96 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_DEBUG
,
97 "Sending canned EAP packet %s (identifier %d)",
98 success
? "SUCCESS" : "FAILURE", eap
.identifier
);
99 sm
->eapol
->cb
.eapol_send(sm
->eapol
->conf
.ctx
, sm
->sta
,
100 IEEE802_1X_TYPE_EAP_PACKET
,
101 (u8
*) &eap
, sizeof(eap
));
102 sm
->dot1xAuthEapolFramesTx
++;
106 static void eapol_auth_tx_req(struct eapol_state_machine
*sm
)
108 if (sm
->eap_if
->eapReqData
== NULL
||
109 wpabuf_len(sm
->eap_if
->eapReqData
) < sizeof(struct eap_hdr
)) {
110 eapol_auth_logger(sm
->eapol
, sm
->addr
,
112 "TxReq called, but there is no EAP request "
113 "from authentication server");
117 if (sm
->flags
& EAPOL_SM_WAIT_START
) {
118 wpa_printf(MSG_DEBUG
, "EAPOL: Drop EAPOL TX to " MACSTR
119 " while waiting for EAPOL-Start",
124 sm
->last_eap_id
= eap_get_id(sm
->eap_if
->eapReqData
);
125 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_DEBUG
,
126 "Sending EAP Packet (identifier %d)",
128 sm
->eapol
->cb
.eapol_send(sm
->eapol
->conf
.ctx
, sm
->sta
,
129 IEEE802_1X_TYPE_EAP_PACKET
,
130 wpabuf_head(sm
->eap_if
->eapReqData
),
131 wpabuf_len(sm
->eap_if
->eapReqData
));
132 sm
->dot1xAuthEapolFramesTx
++;
133 if (eap_get_type(sm
->eap_if
->eapReqData
) == EAP_TYPE_IDENTITY
)
134 sm
->dot1xAuthEapolReqIdFramesTx
++;
136 sm
->dot1xAuthEapolReqFramesTx
++;
141 * eapol_port_timers_tick - Port Timers state machine
142 * @eloop_ctx: struct eapol_state_machine *
143 * @timeout_ctx: Not used
145 * This statemachine is implemented as a function that will be called
146 * once a second as a registered event loop timeout.
148 static void eapol_port_timers_tick(void *eloop_ctx
, void *timeout_ctx
)
150 struct eapol_state_machine
*state
= timeout_ctx
;
152 if (state
->aWhile
> 0) {
154 if (state
->aWhile
== 0) {
155 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
157 MAC2STR(state
->addr
));
161 if (state
->quietWhile
> 0) {
163 if (state
->quietWhile
== 0) {
164 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
165 " - quietWhile --> 0",
166 MAC2STR(state
->addr
));
170 if (state
->reAuthWhen
> 0) {
172 if (state
->reAuthWhen
== 0) {
173 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
174 " - reAuthWhen --> 0",
175 MAC2STR(state
->addr
));
179 if (state
->eap_if
->retransWhile
> 0) {
180 state
->eap_if
->retransWhile
--;
181 if (state
->eap_if
->retransWhile
== 0) {
182 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
183 " - (EAP) retransWhile --> 0",
184 MAC2STR(state
->addr
));
188 eapol_sm_step_run(state
);
190 eloop_register_timeout(1, 0, eapol_port_timers_tick
, eloop_ctx
, state
);
195 /* Authenticator PAE state machine */
197 SM_STATE(AUTH_PAE
, INITIALIZE
)
199 SM_ENTRY_MA(AUTH_PAE
, INITIALIZE
, auth_pae
);
204 SM_STATE(AUTH_PAE
, DISCONNECTED
)
206 int from_initialize
= sm
->auth_pae_state
== AUTH_PAE_INITIALIZE
;
208 if (sm
->eapolLogoff
) {
209 if (sm
->auth_pae_state
== AUTH_PAE_CONNECTING
)
210 sm
->authEapLogoffsWhileConnecting
++;
211 else if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATED
)
212 sm
->authAuthEapLogoffWhileAuthenticated
++;
215 SM_ENTRY_MA(AUTH_PAE
, DISCONNECTED
, auth_pae
);
217 sm
->authPortStatus
= Unauthorized
;
218 setPortUnauthorized();
220 sm
->eapolLogoff
= FALSE
;
221 if (!from_initialize
) {
222 sm
->eapol
->cb
.finished(sm
->eapol
->conf
.ctx
, sm
->sta
, 0,
223 sm
->flags
& EAPOL_SM_PREAUTH
,
229 SM_STATE(AUTH_PAE
, RESTART
)
231 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATED
) {
232 if (sm
->reAuthenticate
)
233 sm
->authAuthReauthsWhileAuthenticated
++;
235 sm
->authAuthEapStartsWhileAuthenticated
++;
237 sm
->authAuthEapLogoffWhileAuthenticated
++;
240 SM_ENTRY_MA(AUTH_PAE
, RESTART
, auth_pae
);
242 sm
->eap_if
->eapRestart
= TRUE
;
246 SM_STATE(AUTH_PAE
, CONNECTING
)
248 if (sm
->auth_pae_state
!= AUTH_PAE_CONNECTING
)
249 sm
->authEntersConnecting
++;
251 SM_ENTRY_MA(AUTH_PAE
, CONNECTING
, auth_pae
);
253 sm
->reAuthenticate
= FALSE
;
258 SM_STATE(AUTH_PAE
, HELD
)
260 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATING
&& sm
->authFail
)
261 sm
->authAuthFailWhileAuthenticating
++;
263 SM_ENTRY_MA(AUTH_PAE
, HELD
, auth_pae
);
265 sm
->authPortStatus
= Unauthorized
;
266 setPortUnauthorized();
267 sm
->quietWhile
= sm
->quietPeriod
;
268 sm
->eapolLogoff
= FALSE
;
270 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_WARNING
,
271 "authentication failed - EAP type: %d (%s)",
272 sm
->eap_type_authsrv
,
273 eap_server_get_name(0, sm
->eap_type_authsrv
));
274 if (sm
->eap_type_authsrv
!= sm
->eap_type_supp
) {
275 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_INFO
,
276 "Supplicant used different EAP type: "
277 "%d (%s)", sm
->eap_type_supp
,
278 eap_server_get_name(0, sm
->eap_type_supp
));
280 sm
->eapol
->cb
.finished(sm
->eapol
->conf
.ctx
, sm
->sta
, 0,
281 sm
->flags
& EAPOL_SM_PREAUTH
, sm
->remediation
);
285 SM_STATE(AUTH_PAE
, AUTHENTICATED
)
289 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATING
&& sm
->authSuccess
)
290 sm
->authAuthSuccessesWhileAuthenticating
++;
292 SM_ENTRY_MA(AUTH_PAE
, AUTHENTICATED
, auth_pae
);
294 sm
->authPortStatus
= Authorized
;
297 if (sm
->flags
& EAPOL_SM_PREAUTH
)
298 extra
= " (pre-authentication)";
299 else if (sm
->flags
& EAPOL_SM_FROM_PMKSA_CACHE
)
300 extra
= " (PMKSA cache)";
301 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_INFO
,
302 "authenticated - EAP type: %d (%s)%s",
303 sm
->eap_type_authsrv
,
304 eap_server_get_name(0, sm
->eap_type_authsrv
),
306 sm
->eapol
->cb
.finished(sm
->eapol
->conf
.ctx
, sm
->sta
, 1,
307 sm
->flags
& EAPOL_SM_PREAUTH
, sm
->remediation
);
311 SM_STATE(AUTH_PAE
, AUTHENTICATING
)
313 SM_ENTRY_MA(AUTH_PAE
, AUTHENTICATING
, auth_pae
);
315 sm
->eapolStart
= FALSE
;
316 sm
->authSuccess
= FALSE
;
317 sm
->authFail
= FALSE
;
318 sm
->authTimeout
= FALSE
;
319 sm
->authStart
= TRUE
;
325 SM_STATE(AUTH_PAE
, ABORTING
)
327 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATING
) {
329 sm
->authAuthTimeoutsWhileAuthenticating
++;
331 sm
->authAuthEapStartsWhileAuthenticating
++;
333 sm
->authAuthEapLogoffWhileAuthenticating
++;
336 SM_ENTRY_MA(AUTH_PAE
, ABORTING
, auth_pae
);
338 sm
->authAbort
= TRUE
;
344 SM_STATE(AUTH_PAE
, FORCE_AUTH
)
346 SM_ENTRY_MA(AUTH_PAE
, FORCE_AUTH
, auth_pae
);
348 sm
->authPortStatus
= Authorized
;
350 sm
->portMode
= ForceAuthorized
;
351 sm
->eapolStart
= FALSE
;
356 SM_STATE(AUTH_PAE
, FORCE_UNAUTH
)
358 SM_ENTRY_MA(AUTH_PAE
, FORCE_UNAUTH
, auth_pae
);
360 sm
->authPortStatus
= Unauthorized
;
361 setPortUnauthorized();
362 sm
->portMode
= ForceUnauthorized
;
363 sm
->eapolStart
= FALSE
;
370 if ((sm
->portControl
== Auto
&& sm
->portMode
!= sm
->portControl
) ||
371 sm
->initialize
|| !sm
->eap_if
->portEnabled
)
372 SM_ENTER_GLOBAL(AUTH_PAE
, INITIALIZE
);
373 else if (sm
->portControl
== ForceAuthorized
&&
374 sm
->portMode
!= sm
->portControl
&&
375 !(sm
->initialize
|| !sm
->eap_if
->portEnabled
))
376 SM_ENTER_GLOBAL(AUTH_PAE
, FORCE_AUTH
);
377 else if (sm
->portControl
== ForceUnauthorized
&&
378 sm
->portMode
!= sm
->portControl
&&
379 !(sm
->initialize
|| !sm
->eap_if
->portEnabled
))
380 SM_ENTER_GLOBAL(AUTH_PAE
, FORCE_UNAUTH
);
382 switch (sm
->auth_pae_state
) {
383 case AUTH_PAE_INITIALIZE
:
384 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
386 case AUTH_PAE_DISCONNECTED
:
387 SM_ENTER(AUTH_PAE
, RESTART
);
389 case AUTH_PAE_RESTART
:
390 if (!sm
->eap_if
->eapRestart
)
391 SM_ENTER(AUTH_PAE
, CONNECTING
);
394 if (sm
->quietWhile
== 0)
395 SM_ENTER(AUTH_PAE
, RESTART
);
397 case AUTH_PAE_CONNECTING
:
398 if (sm
->eapolLogoff
|| sm
->reAuthCount
> sm
->reAuthMax
)
399 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
400 else if ((sm
->eap_if
->eapReq
&&
401 sm
->reAuthCount
<= sm
->reAuthMax
) ||
402 sm
->eap_if
->eapSuccess
|| sm
->eap_if
->eapFail
)
403 SM_ENTER(AUTH_PAE
, AUTHENTICATING
);
405 case AUTH_PAE_AUTHENTICATED
:
406 if (sm
->eapolStart
|| sm
->reAuthenticate
)
407 SM_ENTER(AUTH_PAE
, RESTART
);
408 else if (sm
->eapolLogoff
|| !sm
->portValid
)
409 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
411 case AUTH_PAE_AUTHENTICATING
:
412 if (sm
->authSuccess
&& sm
->portValid
)
413 SM_ENTER(AUTH_PAE
, AUTHENTICATED
);
414 else if (sm
->authFail
||
415 (sm
->keyDone
&& !sm
->portValid
))
416 SM_ENTER(AUTH_PAE
, HELD
);
417 else if (sm
->eapolStart
|| sm
->eapolLogoff
||
419 SM_ENTER(AUTH_PAE
, ABORTING
);
421 case AUTH_PAE_ABORTING
:
422 if (sm
->eapolLogoff
&& !sm
->authAbort
)
423 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
424 else if (!sm
->eapolLogoff
&& !sm
->authAbort
)
425 SM_ENTER(AUTH_PAE
, RESTART
);
427 case AUTH_PAE_FORCE_AUTH
:
429 SM_ENTER(AUTH_PAE
, FORCE_AUTH
);
431 case AUTH_PAE_FORCE_UNAUTH
:
433 SM_ENTER(AUTH_PAE
, FORCE_UNAUTH
);
441 /* Backend Authentication state machine */
443 SM_STATE(BE_AUTH
, INITIALIZE
)
445 SM_ENTRY_MA(BE_AUTH
, INITIALIZE
, be_auth
);
448 sm
->eap_if
->eapNoReq
= FALSE
;
449 sm
->authAbort
= FALSE
;
453 SM_STATE(BE_AUTH
, REQUEST
)
455 SM_ENTRY_MA(BE_AUTH
, REQUEST
, be_auth
);
458 sm
->eap_if
->eapReq
= FALSE
;
459 sm
->backendOtherRequestsToSupplicant
++;
462 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
463 * it looks like this would be logical thing to do there since the old
464 * EAP response would not be valid anymore after the new EAP request
467 * A race condition has been reported, in which hostapd ended up
468 * sending out EAP-Response/Identity as a response to the first
469 * EAP-Request from the main EAP method. This can be avoided by
470 * clearing eapolEap here.
472 sm
->eapolEap
= FALSE
;
476 SM_STATE(BE_AUTH
, RESPONSE
)
478 SM_ENTRY_MA(BE_AUTH
, RESPONSE
, be_auth
);
480 sm
->authTimeout
= FALSE
;
481 sm
->eapolEap
= FALSE
;
482 sm
->eap_if
->eapNoReq
= FALSE
;
483 sm
->aWhile
= sm
->serverTimeout
;
484 sm
->eap_if
->eapResp
= TRUE
;
485 /* sendRespToServer(); */
486 sm
->backendResponses
++;
490 SM_STATE(BE_AUTH
, SUCCESS
)
492 SM_ENTRY_MA(BE_AUTH
, SUCCESS
, be_auth
);
495 sm
->authSuccess
= TRUE
;
500 SM_STATE(BE_AUTH
, FAIL
)
502 SM_ENTRY_MA(BE_AUTH
, FAIL
, be_auth
);
509 SM_STATE(BE_AUTH
, TIMEOUT
)
511 SM_ENTRY_MA(BE_AUTH
, TIMEOUT
, be_auth
);
513 sm
->authTimeout
= TRUE
;
517 SM_STATE(BE_AUTH
, IDLE
)
519 SM_ENTRY_MA(BE_AUTH
, IDLE
, be_auth
);
521 sm
->authStart
= FALSE
;
525 SM_STATE(BE_AUTH
, IGNORE
)
527 SM_ENTRY_MA(BE_AUTH
, IGNORE
, be_auth
);
529 sm
->eap_if
->eapNoReq
= FALSE
;
535 if (sm
->portControl
!= Auto
|| sm
->initialize
|| sm
->authAbort
) {
536 SM_ENTER_GLOBAL(BE_AUTH
, INITIALIZE
);
540 switch (sm
->be_auth_state
) {
541 case BE_AUTH_INITIALIZE
:
542 SM_ENTER(BE_AUTH
, IDLE
);
544 case BE_AUTH_REQUEST
:
546 SM_ENTER(BE_AUTH
, RESPONSE
);
547 else if (sm
->eap_if
->eapReq
)
548 SM_ENTER(BE_AUTH
, REQUEST
);
549 else if (sm
->eap_if
->eapTimeout
)
550 SM_ENTER(BE_AUTH
, TIMEOUT
);
552 case BE_AUTH_RESPONSE
:
553 if (sm
->eap_if
->eapNoReq
)
554 SM_ENTER(BE_AUTH
, IGNORE
);
555 if (sm
->eap_if
->eapReq
) {
556 sm
->backendAccessChallenges
++;
557 SM_ENTER(BE_AUTH
, REQUEST
);
558 } else if (sm
->aWhile
== 0)
559 SM_ENTER(BE_AUTH
, TIMEOUT
);
560 else if (sm
->eap_if
->eapFail
) {
561 sm
->backendAuthFails
++;
562 SM_ENTER(BE_AUTH
, FAIL
);
563 } else if (sm
->eap_if
->eapSuccess
) {
564 sm
->backendAuthSuccesses
++;
565 SM_ENTER(BE_AUTH
, SUCCESS
);
568 case BE_AUTH_SUCCESS
:
569 SM_ENTER(BE_AUTH
, IDLE
);
572 SM_ENTER(BE_AUTH
, IDLE
);
574 case BE_AUTH_TIMEOUT
:
575 SM_ENTER(BE_AUTH
, IDLE
);
578 if (sm
->eap_if
->eapFail
&& sm
->authStart
)
579 SM_ENTER(BE_AUTH
, FAIL
);
580 else if (sm
->eap_if
->eapReq
&& sm
->authStart
)
581 SM_ENTER(BE_AUTH
, REQUEST
);
582 else if (sm
->eap_if
->eapSuccess
&& sm
->authStart
)
583 SM_ENTER(BE_AUTH
, SUCCESS
);
587 SM_ENTER(BE_AUTH
, RESPONSE
);
588 else if (sm
->eap_if
->eapReq
)
589 SM_ENTER(BE_AUTH
, REQUEST
);
590 else if (sm
->eap_if
->eapTimeout
)
591 SM_ENTER(BE_AUTH
, TIMEOUT
);
598 /* Reauthentication Timer state machine */
600 SM_STATE(REAUTH_TIMER
, INITIALIZE
)
602 SM_ENTRY_MA(REAUTH_TIMER
, INITIALIZE
, reauth_timer
);
604 sm
->reAuthWhen
= sm
->reAuthPeriod
;
608 SM_STATE(REAUTH_TIMER
, REAUTHENTICATE
)
610 SM_ENTRY_MA(REAUTH_TIMER
, REAUTHENTICATE
, reauth_timer
);
612 sm
->reAuthenticate
= TRUE
;
613 sm
->eapol
->cb
.eapol_event(sm
->eapol
->conf
.ctx
, sm
->sta
,
614 EAPOL_AUTH_REAUTHENTICATE
);
618 SM_STEP(REAUTH_TIMER
)
620 if (sm
->portControl
!= Auto
|| sm
->initialize
||
621 sm
->authPortStatus
== Unauthorized
|| !sm
->reAuthEnabled
) {
622 SM_ENTER_GLOBAL(REAUTH_TIMER
, INITIALIZE
);
626 switch (sm
->reauth_timer_state
) {
627 case REAUTH_TIMER_INITIALIZE
:
628 if (sm
->reAuthWhen
== 0)
629 SM_ENTER(REAUTH_TIMER
, REAUTHENTICATE
);
631 case REAUTH_TIMER_REAUTHENTICATE
:
632 SM_ENTER(REAUTH_TIMER
, INITIALIZE
);
639 /* Authenticator Key Transmit state machine */
641 SM_STATE(AUTH_KEY_TX
, NO_KEY_TRANSMIT
)
643 SM_ENTRY_MA(AUTH_KEY_TX
, NO_KEY_TRANSMIT
, auth_key_tx
);
647 SM_STATE(AUTH_KEY_TX
, KEY_TRANSMIT
)
649 SM_ENTRY_MA(AUTH_KEY_TX
, KEY_TRANSMIT
, auth_key_tx
);
652 sm
->eap_if
->eapKeyAvailable
= FALSE
;
659 if (sm
->initialize
|| sm
->portControl
!= Auto
) {
660 SM_ENTER_GLOBAL(AUTH_KEY_TX
, NO_KEY_TRANSMIT
);
664 switch (sm
->auth_key_tx_state
) {
665 case AUTH_KEY_TX_NO_KEY_TRANSMIT
:
666 if (sm
->keyTxEnabled
&& sm
->eap_if
->eapKeyAvailable
&&
667 sm
->keyRun
&& !(sm
->flags
& EAPOL_SM_USES_WPA
))
668 SM_ENTER(AUTH_KEY_TX
, KEY_TRANSMIT
);
670 case AUTH_KEY_TX_KEY_TRANSMIT
:
671 if (!sm
->keyTxEnabled
|| !sm
->keyRun
)
672 SM_ENTER(AUTH_KEY_TX
, NO_KEY_TRANSMIT
);
673 else if (sm
->eap_if
->eapKeyAvailable
)
674 SM_ENTER(AUTH_KEY_TX
, KEY_TRANSMIT
);
681 /* Key Receive state machine */
683 SM_STATE(KEY_RX
, NO_KEY_RECEIVE
)
685 SM_ENTRY_MA(KEY_RX
, NO_KEY_RECEIVE
, key_rx
);
689 SM_STATE(KEY_RX
, KEY_RECEIVE
)
691 SM_ENTRY_MA(KEY_RX
, KEY_RECEIVE
, key_rx
);
700 if (sm
->initialize
|| !sm
->eap_if
->portEnabled
) {
701 SM_ENTER_GLOBAL(KEY_RX
, NO_KEY_RECEIVE
);
705 switch (sm
->key_rx_state
) {
706 case KEY_RX_NO_KEY_RECEIVE
:
708 SM_ENTER(KEY_RX
, KEY_RECEIVE
);
710 case KEY_RX_KEY_RECEIVE
:
712 SM_ENTER(KEY_RX
, KEY_RECEIVE
);
719 /* Controlled Directions state machine */
721 SM_STATE(CTRL_DIR
, FORCE_BOTH
)
723 SM_ENTRY_MA(CTRL_DIR
, FORCE_BOTH
, ctrl_dir
);
724 sm
->operControlledDirections
= Both
;
728 SM_STATE(CTRL_DIR
, IN_OR_BOTH
)
730 SM_ENTRY_MA(CTRL_DIR
, IN_OR_BOTH
, ctrl_dir
);
731 sm
->operControlledDirections
= sm
->adminControlledDirections
;
737 if (sm
->initialize
) {
738 SM_ENTER_GLOBAL(CTRL_DIR
, IN_OR_BOTH
);
742 switch (sm
->ctrl_dir_state
) {
743 case CTRL_DIR_FORCE_BOTH
:
744 if (sm
->eap_if
->portEnabled
&& sm
->operEdge
)
745 SM_ENTER(CTRL_DIR
, IN_OR_BOTH
);
747 case CTRL_DIR_IN_OR_BOTH
:
748 if (sm
->operControlledDirections
!=
749 sm
->adminControlledDirections
)
750 SM_ENTER(CTRL_DIR
, IN_OR_BOTH
);
751 if (!sm
->eap_if
->portEnabled
|| !sm
->operEdge
)
752 SM_ENTER(CTRL_DIR
, FORCE_BOTH
);
759 struct eapol_state_machine
*
760 eapol_auth_alloc(struct eapol_authenticator
*eapol
, const u8
*addr
,
761 int flags
, const struct wpabuf
*assoc_wps_ie
,
762 const struct wpabuf
*assoc_p2p_ie
, void *sta_ctx
,
763 const char *identity
, const char *radius_cui
)
765 struct eapol_state_machine
*sm
;
766 struct eap_config eap_conf
;
771 sm
= os_zalloc(sizeof(*sm
));
773 wpa_printf(MSG_DEBUG
, "IEEE 802.1X state machine allocation "
777 sm
->radius_identifier
= -1;
778 os_memcpy(sm
->addr
, addr
, ETH_ALEN
);
784 /* Set default values for state machine constants */
785 sm
->auth_pae_state
= AUTH_PAE_INITIALIZE
;
786 sm
->quietPeriod
= AUTH_PAE_DEFAULT_quietPeriod
;
787 sm
->reAuthMax
= AUTH_PAE_DEFAULT_reAuthMax
;
789 sm
->be_auth_state
= BE_AUTH_INITIALIZE
;
790 sm
->serverTimeout
= BE_AUTH_DEFAULT_serverTimeout
;
792 sm
->reauth_timer_state
= REAUTH_TIMER_INITIALIZE
;
793 sm
->reAuthPeriod
= eapol
->conf
.eap_reauth_period
;
794 sm
->reAuthEnabled
= eapol
->conf
.eap_reauth_period
> 0 ? TRUE
: FALSE
;
796 sm
->auth_key_tx_state
= AUTH_KEY_TX_NO_KEY_TRANSMIT
;
798 sm
->key_rx_state
= KEY_RX_NO_KEY_RECEIVE
;
800 sm
->ctrl_dir_state
= CTRL_DIR_IN_OR_BOTH
;
802 sm
->portControl
= Auto
;
804 if (!eapol
->conf
.wpa
&&
805 (eapol
->default_wep_key
|| eapol
->conf
.individual_wep_key_len
> 0))
806 sm
->keyTxEnabled
= TRUE
;
808 sm
->keyTxEnabled
= FALSE
;
810 sm
->portValid
= FALSE
;
812 sm
->portValid
= TRUE
;
814 os_memset(&eap_conf
, 0, sizeof(eap_conf
));
815 eap_conf
.eap_server
= eapol
->conf
.eap_server
;
816 eap_conf
.ssl_ctx
= eapol
->conf
.ssl_ctx
;
817 eap_conf
.msg_ctx
= eapol
->conf
.msg_ctx
;
818 eap_conf
.eap_sim_db_priv
= eapol
->conf
.eap_sim_db_priv
;
819 eap_conf
.pac_opaque_encr_key
= eapol
->conf
.pac_opaque_encr_key
;
820 eap_conf
.eap_fast_a_id
= eapol
->conf
.eap_fast_a_id
;
821 eap_conf
.eap_fast_a_id_len
= eapol
->conf
.eap_fast_a_id_len
;
822 eap_conf
.eap_fast_a_id_info
= eapol
->conf
.eap_fast_a_id_info
;
823 eap_conf
.eap_fast_prov
= eapol
->conf
.eap_fast_prov
;
824 eap_conf
.pac_key_lifetime
= eapol
->conf
.pac_key_lifetime
;
825 eap_conf
.pac_key_refresh_time
= eapol
->conf
.pac_key_refresh_time
;
826 eap_conf
.eap_sim_aka_result_ind
= eapol
->conf
.eap_sim_aka_result_ind
;
827 eap_conf
.tnc
= eapol
->conf
.tnc
;
828 eap_conf
.wps
= eapol
->conf
.wps
;
829 eap_conf
.assoc_wps_ie
= assoc_wps_ie
;
830 eap_conf
.assoc_p2p_ie
= assoc_p2p_ie
;
831 eap_conf
.peer_addr
= addr
;
832 eap_conf
.fragment_size
= eapol
->conf
.fragment_size
;
833 eap_conf
.pwd_group
= eapol
->conf
.pwd_group
;
834 eap_conf
.pbc_in_m1
= eapol
->conf
.pbc_in_m1
;
835 eap_conf
.server_id
= eapol
->conf
.server_id
;
836 eap_conf
.server_id_len
= eapol
->conf
.server_id_len
;
837 eap_conf
.erp
= eapol
->conf
.erp
;
838 eap_conf
.tls_session_lifetime
= eapol
->conf
.tls_session_lifetime
;
839 sm
->eap
= eap_server_sm_init(sm
, &eapol_cb
, &eap_conf
);
840 if (sm
->eap
== NULL
) {
844 sm
->eap_if
= eap_get_interface(sm
->eap
);
846 eapol_auth_initialize(sm
);
849 sm
->identity
= (u8
*) os_strdup(identity
);
851 sm
->identity_len
= os_strlen(identity
);
854 sm
->radius_cui
= wpabuf_alloc_copy(radius_cui
,
855 os_strlen(radius_cui
));
857 sm
->acct_multi_session_id_lo
= eapol
->acct_multi_session_id_lo
++;
858 if (eapol
->acct_multi_session_id_lo
== 0)
859 eapol
->acct_multi_session_id_hi
++;
860 sm
->acct_multi_session_id_hi
= eapol
->acct_multi_session_id_hi
;
866 void eapol_auth_free(struct eapol_state_machine
*sm
)
871 eloop_cancel_timeout(eapol_port_timers_tick
, NULL
, sm
);
872 eloop_cancel_timeout(eapol_sm_step_cb
, sm
, NULL
);
874 eap_server_sm_deinit(sm
->eap
);
879 static int eapol_sm_sta_entry_alive(struct eapol_authenticator
*eapol
,
882 return eapol
->cb
.sta_entry_alive(eapol
->conf
.ctx
, addr
);
886 static void eapol_sm_step_run(struct eapol_state_machine
*sm
)
888 struct eapol_authenticator
*eapol
= sm
->eapol
;
890 unsigned int prev_auth_pae
, prev_be_auth
, prev_reauth_timer
,
891 prev_auth_key_tx
, prev_key_rx
, prev_ctrl_dir
;
894 os_memcpy(addr
, sm
->addr
, ETH_ALEN
);
897 * Allow EAPOL state machines to run as long as there are state
898 * changes, but exit and return here through event loop if more than
899 * 100 steps is needed as a precaution against infinite loops inside
903 prev_auth_pae
= sm
->auth_pae_state
;
904 prev_be_auth
= sm
->be_auth_state
;
905 prev_reauth_timer
= sm
->reauth_timer_state
;
906 prev_auth_key_tx
= sm
->auth_key_tx_state
;
907 prev_key_rx
= sm
->key_rx_state
;
908 prev_ctrl_dir
= sm
->ctrl_dir_state
;
910 SM_STEP_RUN(AUTH_PAE
);
911 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
912 SM_STEP_RUN(BE_AUTH
);
913 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
914 SM_STEP_RUN(REAUTH_TIMER
);
915 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
916 SM_STEP_RUN(AUTH_KEY_TX
);
917 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
919 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
920 SM_STEP_RUN(CTRL_DIR
);
922 if (prev_auth_pae
!= sm
->auth_pae_state
||
923 prev_be_auth
!= sm
->be_auth_state
||
924 prev_reauth_timer
!= sm
->reauth_timer_state
||
925 prev_auth_key_tx
!= sm
->auth_key_tx_state
||
926 prev_key_rx
!= sm
->key_rx_state
||
927 prev_ctrl_dir
!= sm
->ctrl_dir_state
) {
930 /* Re-run from eloop timeout */
935 if (eapol_sm_sta_entry_alive(eapol
, addr
) && sm
->eap
) {
936 if (eap_server_sm_step(sm
->eap
)) {
939 /* Re-run from eloop timeout */
944 /* TODO: find a better location for this */
945 if (sm
->eap_if
->aaaEapResp
) {
946 sm
->eap_if
->aaaEapResp
= FALSE
;
947 if (sm
->eap_if
->aaaEapRespData
== NULL
) {
948 wpa_printf(MSG_DEBUG
, "EAPOL: aaaEapResp set, "
949 "but no aaaEapRespData available");
952 sm
->eapol
->cb
.aaa_send(
953 sm
->eapol
->conf
.ctx
, sm
->sta
,
954 wpabuf_head(sm
->eap_if
->aaaEapRespData
),
955 wpabuf_len(sm
->eap_if
->aaaEapRespData
));
959 if (eapol_sm_sta_entry_alive(eapol
, addr
))
960 sm
->eapol
->cb
.eapol_event(sm
->eapol
->conf
.ctx
, sm
->sta
,
961 EAPOL_AUTH_SM_CHANGE
);
965 static void eapol_sm_step_cb(void *eloop_ctx
, void *timeout_ctx
)
967 struct eapol_state_machine
*sm
= eloop_ctx
;
968 eapol_sm_step_run(sm
);
973 * eapol_auth_step - Advance EAPOL state machines
974 * @sm: EAPOL state machine
976 * This function is called to advance EAPOL state machines after any change
977 * that could affect their state.
979 void eapol_auth_step(struct eapol_state_machine
*sm
)
982 * Run eapol_sm_step_run from a registered timeout to make sure that
983 * other possible timeouts/events are processed and to avoid long
984 * function call chains.
987 eloop_register_timeout(0, 0, eapol_sm_step_cb
, sm
, NULL
);
991 static void eapol_auth_initialize(struct eapol_state_machine
*sm
)
993 sm
->initializing
= TRUE
;
994 /* Initialize the state machines by asserting initialize and then
995 * deasserting it after one step */
996 sm
->initialize
= TRUE
;
997 eapol_sm_step_run(sm
);
998 sm
->initialize
= FALSE
;
999 eapol_sm_step_run(sm
);
1000 sm
->initializing
= FALSE
;
1002 /* Start one second tick for port timers state machine */
1003 eloop_cancel_timeout(eapol_port_timers_tick
, NULL
, sm
);
1004 eloop_register_timeout(1, 0, eapol_port_timers_tick
, NULL
, sm
);
1008 static int eapol_sm_get_eap_user(void *ctx
, const u8
*identity
,
1009 size_t identity_len
, int phase2
,
1010 struct eap_user
*user
)
1012 struct eapol_state_machine
*sm
= ctx
;
1015 ret
= sm
->eapol
->cb
.get_eap_user(sm
->eapol
->conf
.ctx
, identity
,
1016 identity_len
, phase2
, user
);
1017 if (user
->remediation
)
1018 sm
->remediation
= 1;
1023 static const char * eapol_sm_get_eap_req_id_text(void *ctx
, size_t *len
)
1025 struct eapol_state_machine
*sm
= ctx
;
1026 *len
= sm
->eapol
->conf
.eap_req_id_text_len
;
1027 return sm
->eapol
->conf
.eap_req_id_text
;
1031 static int eapol_sm_get_erp_send_reauth_start(void *ctx
)
1033 struct eapol_state_machine
*sm
= ctx
;
1034 return sm
->eapol
->conf
.erp_send_reauth_start
;
1038 static const char * eapol_sm_get_erp_domain(void *ctx
)
1040 struct eapol_state_machine
*sm
= ctx
;
1041 return sm
->eapol
->conf
.erp_domain
;
1045 static struct eap_server_erp_key
* eapol_sm_erp_get_key(void *ctx
,
1046 const char *keyname
)
1048 struct eapol_state_machine
*sm
= ctx
;
1049 return sm
->eapol
->cb
.erp_get_key(sm
->eapol
->conf
.ctx
, keyname
);
1053 static int eapol_sm_erp_add_key(void *ctx
, struct eap_server_erp_key
*erp
)
1055 struct eapol_state_machine
*sm
= ctx
;
1056 return sm
->eapol
->cb
.erp_add_key(sm
->eapol
->conf
.ctx
, erp
);
1060 static const struct eapol_callbacks eapol_cb
=
1062 eapol_sm_get_eap_user
,
1063 eapol_sm_get_eap_req_id_text
,
1065 eapol_sm_get_erp_send_reauth_start
,
1066 eapol_sm_get_erp_domain
,
1067 eapol_sm_erp_get_key
,
1068 eapol_sm_erp_add_key
,
1072 int eapol_auth_eap_pending_cb(struct eapol_state_machine
*sm
, void *ctx
)
1074 if (sm
== NULL
|| ctx
== NULL
|| ctx
!= sm
->eap
)
1077 eap_sm_pending_cb(sm
->eap
);
1078 eapol_auth_step(sm
);
1084 void eapol_auth_reauthenticate(struct eapol_state_machine
*sm
)
1086 wpa_printf(MSG_DEBUG
, "EAPOL: External reauthentication trigger for "
1087 MACSTR
, MAC2STR(sm
->addr
));
1088 sm
->reAuthenticate
= TRUE
;
1089 eapol_auth_step(sm
);
1093 int eapol_auth_set_conf(struct eapol_state_machine
*sm
, const char *param
,
1096 wpa_printf(MSG_DEBUG
, "EAPOL: External configuration operation for "
1097 MACSTR
" - param=%s value=%s",
1098 MAC2STR(sm
->addr
), param
, value
);
1100 if (os_strcasecmp(param
, "AdminControlledDirections") == 0) {
1101 if (os_strcmp(value
, "Both") == 0)
1102 sm
->adminControlledDirections
= Both
;
1103 else if (os_strcmp(value
, "In") == 0)
1104 sm
->adminControlledDirections
= In
;
1107 eapol_auth_step(sm
);
1111 if (os_strcasecmp(param
, "AdminControlledPortControl") == 0) {
1112 if (os_strcmp(value
, "ForceAuthorized") == 0)
1113 sm
->portControl
= ForceAuthorized
;
1114 else if (os_strcmp(value
, "ForceUnauthorized") == 0)
1115 sm
->portControl
= ForceUnauthorized
;
1116 else if (os_strcmp(value
, "Auto") == 0)
1117 sm
->portControl
= Auto
;
1120 eapol_auth_step(sm
);
1124 if (os_strcasecmp(param
, "quietPeriod") == 0) {
1125 sm
->quietPeriod
= atoi(value
);
1129 if (os_strcasecmp(param
, "serverTimeout") == 0) {
1130 sm
->serverTimeout
= atoi(value
);
1134 if (os_strcasecmp(param
, "reAuthPeriod") == 0) {
1135 sm
->reAuthPeriod
= atoi(value
);
1139 if (os_strcasecmp(param
, "reAuthEnabled") == 0) {
1140 if (os_strcmp(value
, "TRUE") == 0)
1141 sm
->reAuthEnabled
= TRUE
;
1142 else if (os_strcmp(value
, "FALSE") == 0)
1143 sm
->reAuthEnabled
= FALSE
;
1146 eapol_auth_step(sm
);
1150 if (os_strcasecmp(param
, "KeyTransmissionEnabled") == 0) {
1151 if (os_strcmp(value
, "TRUE") == 0)
1152 sm
->keyTxEnabled
= TRUE
;
1153 else if (os_strcmp(value
, "FALSE") == 0)
1154 sm
->keyTxEnabled
= FALSE
;
1157 eapol_auth_step(sm
);
1165 static int eapol_auth_conf_clone(struct eapol_auth_config
*dst
,
1166 struct eapol_auth_config
*src
)
1168 dst
->ctx
= src
->ctx
;
1169 dst
->eap_reauth_period
= src
->eap_reauth_period
;
1170 dst
->wpa
= src
->wpa
;
1171 dst
->individual_wep_key_len
= src
->individual_wep_key_len
;
1172 dst
->eap_server
= src
->eap_server
;
1173 dst
->ssl_ctx
= src
->ssl_ctx
;
1174 dst
->msg_ctx
= src
->msg_ctx
;
1175 dst
->eap_sim_db_priv
= src
->eap_sim_db_priv
;
1176 os_free(dst
->eap_req_id_text
);
1177 dst
->pwd_group
= src
->pwd_group
;
1178 dst
->pbc_in_m1
= src
->pbc_in_m1
;
1179 dst
->server_id
= src
->server_id
;
1180 dst
->server_id_len
= src
->server_id_len
;
1181 if (src
->eap_req_id_text
) {
1182 dst
->eap_req_id_text
= os_malloc(src
->eap_req_id_text_len
);
1183 if (dst
->eap_req_id_text
== NULL
)
1185 os_memcpy(dst
->eap_req_id_text
, src
->eap_req_id_text
,
1186 src
->eap_req_id_text_len
);
1187 dst
->eap_req_id_text_len
= src
->eap_req_id_text_len
;
1189 dst
->eap_req_id_text
= NULL
;
1190 dst
->eap_req_id_text_len
= 0;
1192 if (src
->pac_opaque_encr_key
) {
1193 dst
->pac_opaque_encr_key
= os_malloc(16);
1194 if (dst
->pac_opaque_encr_key
== NULL
)
1196 os_memcpy(dst
->pac_opaque_encr_key
, src
->pac_opaque_encr_key
,
1199 dst
->pac_opaque_encr_key
= NULL
;
1200 if (src
->eap_fast_a_id
) {
1201 dst
->eap_fast_a_id
= os_malloc(src
->eap_fast_a_id_len
);
1202 if (dst
->eap_fast_a_id
== NULL
)
1204 os_memcpy(dst
->eap_fast_a_id
, src
->eap_fast_a_id
,
1205 src
->eap_fast_a_id_len
);
1206 dst
->eap_fast_a_id_len
= src
->eap_fast_a_id_len
;
1208 dst
->eap_fast_a_id
= NULL
;
1209 if (src
->eap_fast_a_id_info
) {
1210 dst
->eap_fast_a_id_info
= os_strdup(src
->eap_fast_a_id_info
);
1211 if (dst
->eap_fast_a_id_info
== NULL
)
1214 dst
->eap_fast_a_id_info
= NULL
;
1215 dst
->eap_fast_prov
= src
->eap_fast_prov
;
1216 dst
->pac_key_lifetime
= src
->pac_key_lifetime
;
1217 dst
->pac_key_refresh_time
= src
->pac_key_refresh_time
;
1218 dst
->eap_sim_aka_result_ind
= src
->eap_sim_aka_result_ind
;
1219 dst
->tnc
= src
->tnc
;
1220 dst
->wps
= src
->wps
;
1221 dst
->fragment_size
= src
->fragment_size
;
1223 os_free(dst
->erp_domain
);
1224 if (src
->erp_domain
) {
1225 dst
->erp_domain
= os_strdup(src
->erp_domain
);
1226 if (dst
->erp_domain
== NULL
)
1229 dst
->erp_domain
= NULL
;
1231 dst
->erp_send_reauth_start
= src
->erp_send_reauth_start
;
1232 dst
->erp
= src
->erp
;
1233 dst
->tls_session_lifetime
= src
->tls_session_lifetime
;
1238 eapol_auth_conf_free(dst
);
1243 static void eapol_auth_conf_free(struct eapol_auth_config
*conf
)
1245 os_free(conf
->eap_req_id_text
);
1246 conf
->eap_req_id_text
= NULL
;
1247 os_free(conf
->pac_opaque_encr_key
);
1248 conf
->pac_opaque_encr_key
= NULL
;
1249 os_free(conf
->eap_fast_a_id
);
1250 conf
->eap_fast_a_id
= NULL
;
1251 os_free(conf
->eap_fast_a_id_info
);
1252 conf
->eap_fast_a_id_info
= NULL
;
1253 os_free(conf
->erp_domain
);
1254 conf
->erp_domain
= NULL
;
1258 struct eapol_authenticator
* eapol_auth_init(struct eapol_auth_config
*conf
,
1259 struct eapol_auth_cb
*cb
)
1261 struct eapol_authenticator
*eapol
;
1264 eapol
= os_zalloc(sizeof(*eapol
));
1268 if (eapol_auth_conf_clone(&eapol
->conf
, conf
) < 0) {
1273 if (conf
->individual_wep_key_len
> 0) {
1274 /* use key0 in individual key and key1 in broadcast key */
1275 eapol
->default_wep_key_idx
= 1;
1278 eapol
->cb
.eapol_send
= cb
->eapol_send
;
1279 eapol
->cb
.aaa_send
= cb
->aaa_send
;
1280 eapol
->cb
.finished
= cb
->finished
;
1281 eapol
->cb
.get_eap_user
= cb
->get_eap_user
;
1282 eapol
->cb
.sta_entry_alive
= cb
->sta_entry_alive
;
1283 eapol
->cb
.logger
= cb
->logger
;
1284 eapol
->cb
.set_port_authorized
= cb
->set_port_authorized
;
1285 eapol
->cb
.abort_auth
= cb
->abort_auth
;
1286 eapol
->cb
.tx_key
= cb
->tx_key
;
1287 eapol
->cb
.eapol_event
= cb
->eapol_event
;
1288 eapol
->cb
.erp_get_key
= cb
->erp_get_key
;
1289 eapol
->cb
.erp_add_key
= cb
->erp_add_key
;
1291 /* Acct-Multi-Session-Id should be unique over reboots. If reliable
1292 * clock is not available, this could be replaced with reboot counter,
1295 eapol
->acct_multi_session_id_hi
= now
.sec
;
1301 void eapol_auth_deinit(struct eapol_authenticator
*eapol
)
1306 eapol_auth_conf_free(&eapol
->conf
);
1307 os_free(eapol
->default_wep_key
);