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
12 * See README and COPYING for more details.
18 #include "ieee802_1x.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)
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
,
58 if (eapol
->cb
.logger
== NULL
)
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
,
72 if (eapol
->cb
.logger
== NULL
)
75 maxlen
= os_strlen(fmt
) + 100;
76 format
= os_malloc(maxlen
);
81 vsnprintf(format
, maxlen
, fmt
, ap
);
84 eapol_auth_logger(eapol
, addr
, level
, format
);
90 static void eapol_auth_tx_canned_eap(struct eapol_state_machine
*sm
,
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
,
116 "TxReq called, but there is no EAP request "
117 "from authentication server");
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",
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)",
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
++;
139 sm
->dot1xAuthEapolReqFramesTx
++;
144 * eapol_port_timers_tick - Port Timers state machine
145 * @eloop_ctx: struct eapol_state_machine *
146 * @timeout_ctx: Not used
148 * This statemachine is implemented as a function that will be called
149 * once a second as a registered event loop timeout.
151 static void eapol_port_timers_tick(void *eloop_ctx
, void *timeout_ctx
)
153 struct eapol_state_machine
*state
= timeout_ctx
;
155 if (state
->aWhile
> 0) {
157 if (state
->aWhile
== 0) {
158 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
160 MAC2STR(state
->addr
));
164 if (state
->quietWhile
> 0) {
166 if (state
->quietWhile
== 0) {
167 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
168 " - quietWhile --> 0",
169 MAC2STR(state
->addr
));
173 if (state
->reAuthWhen
> 0) {
175 if (state
->reAuthWhen
== 0) {
176 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
177 " - reAuthWhen --> 0",
178 MAC2STR(state
->addr
));
182 if (state
->eap_if
->retransWhile
> 0) {
183 state
->eap_if
->retransWhile
--;
184 if (state
->eap_if
->retransWhile
== 0) {
185 wpa_printf(MSG_DEBUG
, "IEEE 802.1X: " MACSTR
186 " - (EAP) retransWhile --> 0",
187 MAC2STR(state
->addr
));
191 eapol_sm_step_run(state
);
193 eloop_register_timeout(1, 0, eapol_port_timers_tick
, eloop_ctx
, state
);
198 /* Authenticator PAE state machine */
200 SM_STATE(AUTH_PAE
, INITIALIZE
)
202 SM_ENTRY_MA(AUTH_PAE
, INITIALIZE
, auth_pae
);
207 SM_STATE(AUTH_PAE
, DISCONNECTED
)
209 int from_initialize
= sm
->auth_pae_state
== AUTH_PAE_INITIALIZE
;
211 if (sm
->eapolLogoff
) {
212 if (sm
->auth_pae_state
== AUTH_PAE_CONNECTING
)
213 sm
->authEapLogoffsWhileConnecting
++;
214 else if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATED
)
215 sm
->authAuthEapLogoffWhileAuthenticated
++;
218 SM_ENTRY_MA(AUTH_PAE
, DISCONNECTED
, auth_pae
);
220 sm
->authPortStatus
= Unauthorized
;
221 setPortUnauthorized();
223 sm
->eapolLogoff
= FALSE
;
224 if (!from_initialize
) {
225 sm
->eapol
->cb
.finished(sm
->hapd
, sm
->sta
, 0,
226 sm
->flags
& EAPOL_SM_PREAUTH
);
231 SM_STATE(AUTH_PAE
, RESTART
)
233 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATED
) {
234 if (sm
->reAuthenticate
)
235 sm
->authAuthReauthsWhileAuthenticated
++;
237 sm
->authAuthEapStartsWhileAuthenticated
++;
239 sm
->authAuthEapLogoffWhileAuthenticated
++;
242 SM_ENTRY_MA(AUTH_PAE
, RESTART
, auth_pae
);
244 sm
->eap_if
->eapRestart
= TRUE
;
248 SM_STATE(AUTH_PAE
, CONNECTING
)
250 if (sm
->auth_pae_state
!= AUTH_PAE_CONNECTING
)
251 sm
->authEntersConnecting
++;
253 SM_ENTRY_MA(AUTH_PAE
, CONNECTING
, auth_pae
);
255 sm
->reAuthenticate
= FALSE
;
260 SM_STATE(AUTH_PAE
, HELD
)
262 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATING
&& sm
->authFail
)
263 sm
->authAuthFailWhileAuthenticating
++;
265 SM_ENTRY_MA(AUTH_PAE
, HELD
, auth_pae
);
267 sm
->authPortStatus
= Unauthorized
;
268 setPortUnauthorized();
269 sm
->quietWhile
= sm
->quietPeriod
;
270 sm
->eapolLogoff
= FALSE
;
272 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_WARNING
,
273 "authentication failed - EAP type: %d (%s)",
274 sm
->eap_type_authsrv
,
275 eap_type_text(sm
->eap_type_authsrv
));
276 if (sm
->eap_type_authsrv
!= sm
->eap_type_supp
) {
277 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_INFO
,
278 "Supplicant used different EAP type: "
279 "%d (%s)", sm
->eap_type_supp
,
280 eap_type_text(sm
->eap_type_supp
));
282 sm
->eapol
->cb
.finished(sm
->hapd
, sm
->sta
, 0,
283 sm
->flags
& EAPOL_SM_PREAUTH
);
287 SM_STATE(AUTH_PAE
, AUTHENTICATED
)
291 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATING
&& sm
->authSuccess
)
292 sm
->authAuthSuccessesWhileAuthenticating
++;
294 SM_ENTRY_MA(AUTH_PAE
, AUTHENTICATED
, auth_pae
);
296 sm
->authPortStatus
= Authorized
;
299 if (sm
->flags
& EAPOL_SM_PREAUTH
)
300 extra
= " (pre-authentication)";
301 else if (wpa_auth_sta_get_pmksa(sm
->sta
->wpa_sm
))
302 extra
= " (PMKSA cache)";
303 eapol_auth_vlogger(sm
->eapol
, sm
->addr
, EAPOL_LOGGER_INFO
,
304 "authenticated - EAP type: %d (%s)%s",
305 sm
->eap_type_authsrv
,
306 eap_type_text(sm
->eap_type_authsrv
), extra
);
307 sm
->eapol
->cb
.finished(sm
->hapd
, sm
->sta
, 1,
308 sm
->flags
& EAPOL_SM_PREAUTH
);
312 SM_STATE(AUTH_PAE
, AUTHENTICATING
)
314 SM_ENTRY_MA(AUTH_PAE
, AUTHENTICATING
, auth_pae
);
316 sm
->eapolStart
= FALSE
;
317 sm
->authSuccess
= FALSE
;
318 sm
->authFail
= FALSE
;
319 sm
->authTimeout
= FALSE
;
320 sm
->authStart
= TRUE
;
326 SM_STATE(AUTH_PAE
, ABORTING
)
328 if (sm
->auth_pae_state
== AUTH_PAE_AUTHENTICATING
) {
330 sm
->authAuthTimeoutsWhileAuthenticating
++;
332 sm
->authAuthEapStartsWhileAuthenticating
++;
334 sm
->authAuthEapLogoffWhileAuthenticating
++;
337 SM_ENTRY_MA(AUTH_PAE
, ABORTING
, auth_pae
);
339 sm
->authAbort
= TRUE
;
345 SM_STATE(AUTH_PAE
, FORCE_AUTH
)
347 SM_ENTRY_MA(AUTH_PAE
, FORCE_AUTH
, auth_pae
);
349 sm
->authPortStatus
= Authorized
;
351 sm
->portMode
= ForceAuthorized
;
352 sm
->eapolStart
= FALSE
;
357 SM_STATE(AUTH_PAE
, FORCE_UNAUTH
)
359 SM_ENTRY_MA(AUTH_PAE
, FORCE_UNAUTH
, auth_pae
);
361 sm
->authPortStatus
= Unauthorized
;
362 setPortUnauthorized();
363 sm
->portMode
= ForceUnauthorized
;
364 sm
->eapolStart
= FALSE
;
371 if ((sm
->portControl
== Auto
&& sm
->portMode
!= sm
->portControl
) ||
372 sm
->initialize
|| !sm
->eap_if
->portEnabled
)
373 SM_ENTER_GLOBAL(AUTH_PAE
, INITIALIZE
);
374 else if (sm
->portControl
== ForceAuthorized
&&
375 sm
->portMode
!= sm
->portControl
&&
376 !(sm
->initialize
|| !sm
->eap_if
->portEnabled
))
377 SM_ENTER_GLOBAL(AUTH_PAE
, FORCE_AUTH
);
378 else if (sm
->portControl
== ForceUnauthorized
&&
379 sm
->portMode
!= sm
->portControl
&&
380 !(sm
->initialize
|| !sm
->eap_if
->portEnabled
))
381 SM_ENTER_GLOBAL(AUTH_PAE
, FORCE_UNAUTH
);
383 switch (sm
->auth_pae_state
) {
384 case AUTH_PAE_INITIALIZE
:
385 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
387 case AUTH_PAE_DISCONNECTED
:
388 SM_ENTER(AUTH_PAE
, RESTART
);
390 case AUTH_PAE_RESTART
:
391 if (!sm
->eap_if
->eapRestart
)
392 SM_ENTER(AUTH_PAE
, CONNECTING
);
395 if (sm
->quietWhile
== 0)
396 SM_ENTER(AUTH_PAE
, RESTART
);
398 case AUTH_PAE_CONNECTING
:
399 if (sm
->eapolLogoff
|| sm
->reAuthCount
> sm
->reAuthMax
)
400 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
401 else if ((sm
->eap_if
->eapReq
&&
402 sm
->reAuthCount
<= sm
->reAuthMax
) ||
403 sm
->eap_if
->eapSuccess
|| sm
->eap_if
->eapFail
)
404 SM_ENTER(AUTH_PAE
, AUTHENTICATING
);
406 case AUTH_PAE_AUTHENTICATED
:
407 if (sm
->eapolStart
|| sm
->reAuthenticate
)
408 SM_ENTER(AUTH_PAE
, RESTART
);
409 else if (sm
->eapolLogoff
|| !sm
->portValid
)
410 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
412 case AUTH_PAE_AUTHENTICATING
:
413 if (sm
->authSuccess
&& sm
->portValid
)
414 SM_ENTER(AUTH_PAE
, AUTHENTICATED
);
415 else if (sm
->authFail
||
416 (sm
->keyDone
&& !sm
->portValid
))
417 SM_ENTER(AUTH_PAE
, HELD
);
418 else if (sm
->eapolStart
|| sm
->eapolLogoff
||
420 SM_ENTER(AUTH_PAE
, ABORTING
);
422 case AUTH_PAE_ABORTING
:
423 if (sm
->eapolLogoff
&& !sm
->authAbort
)
424 SM_ENTER(AUTH_PAE
, DISCONNECTED
);
425 else if (!sm
->eapolLogoff
&& !sm
->authAbort
)
426 SM_ENTER(AUTH_PAE
, RESTART
);
428 case AUTH_PAE_FORCE_AUTH
:
430 SM_ENTER(AUTH_PAE
, FORCE_AUTH
);
432 case AUTH_PAE_FORCE_UNAUTH
:
434 SM_ENTER(AUTH_PAE
, FORCE_UNAUTH
);
442 /* Backend Authentication state machine */
444 SM_STATE(BE_AUTH
, INITIALIZE
)
446 SM_ENTRY_MA(BE_AUTH
, INITIALIZE
, be_auth
);
449 sm
->eap_if
->eapNoReq
= FALSE
;
450 sm
->authAbort
= FALSE
;
454 SM_STATE(BE_AUTH
, REQUEST
)
456 SM_ENTRY_MA(BE_AUTH
, REQUEST
, be_auth
);
459 sm
->eap_if
->eapReq
= FALSE
;
460 sm
->backendOtherRequestsToSupplicant
++;
463 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
464 * it looks like this would be logical thing to do there since the old
465 * EAP response would not be valid anymore after the new EAP request
468 * A race condition has been reported, in which hostapd ended up
469 * sending out EAP-Response/Identity as a response to the first
470 * EAP-Request from the main EAP method. This can be avoided by
471 * clearing eapolEap here.
473 sm
->eapolEap
= FALSE
;
477 SM_STATE(BE_AUTH
, RESPONSE
)
479 SM_ENTRY_MA(BE_AUTH
, RESPONSE
, be_auth
);
481 sm
->authTimeout
= FALSE
;
482 sm
->eapolEap
= FALSE
;
483 sm
->eap_if
->eapNoReq
= FALSE
;
484 sm
->aWhile
= sm
->serverTimeout
;
485 sm
->eap_if
->eapResp
= TRUE
;
486 /* sendRespToServer(); */
487 sm
->backendResponses
++;
491 SM_STATE(BE_AUTH
, SUCCESS
)
493 SM_ENTRY_MA(BE_AUTH
, SUCCESS
, be_auth
);
496 sm
->authSuccess
= TRUE
;
501 SM_STATE(BE_AUTH
, FAIL
)
503 SM_ENTRY_MA(BE_AUTH
, FAIL
, be_auth
);
510 SM_STATE(BE_AUTH
, TIMEOUT
)
512 SM_ENTRY_MA(BE_AUTH
, TIMEOUT
, be_auth
);
514 sm
->authTimeout
= TRUE
;
518 SM_STATE(BE_AUTH
, IDLE
)
520 SM_ENTRY_MA(BE_AUTH
, IDLE
, be_auth
);
522 sm
->authStart
= FALSE
;
526 SM_STATE(BE_AUTH
, IGNORE
)
528 SM_ENTRY_MA(BE_AUTH
, IGNORE
, be_auth
);
530 sm
->eap_if
->eapNoReq
= FALSE
;
536 if (sm
->portControl
!= Auto
|| sm
->initialize
|| sm
->authAbort
) {
537 SM_ENTER_GLOBAL(BE_AUTH
, INITIALIZE
);
541 switch (sm
->be_auth_state
) {
542 case BE_AUTH_INITIALIZE
:
543 SM_ENTER(BE_AUTH
, IDLE
);
545 case BE_AUTH_REQUEST
:
547 SM_ENTER(BE_AUTH
, RESPONSE
);
548 else if (sm
->eap_if
->eapReq
)
549 SM_ENTER(BE_AUTH
, REQUEST
);
550 else if (sm
->eap_if
->eapTimeout
)
551 SM_ENTER(BE_AUTH
, TIMEOUT
);
553 case BE_AUTH_RESPONSE
:
554 if (sm
->eap_if
->eapNoReq
)
555 SM_ENTER(BE_AUTH
, IGNORE
);
556 if (sm
->eap_if
->eapReq
) {
557 sm
->backendAccessChallenges
++;
558 SM_ENTER(BE_AUTH
, REQUEST
);
559 } else if (sm
->aWhile
== 0)
560 SM_ENTER(BE_AUTH
, TIMEOUT
);
561 else if (sm
->eap_if
->eapFail
) {
562 sm
->backendAuthFails
++;
563 SM_ENTER(BE_AUTH
, FAIL
);
564 } else if (sm
->eap_if
->eapSuccess
) {
565 sm
->backendAuthSuccesses
++;
566 SM_ENTER(BE_AUTH
, SUCCESS
);
569 case BE_AUTH_SUCCESS
:
570 SM_ENTER(BE_AUTH
, IDLE
);
573 SM_ENTER(BE_AUTH
, IDLE
);
575 case BE_AUTH_TIMEOUT
:
576 SM_ENTER(BE_AUTH
, IDLE
);
579 if (sm
->eap_if
->eapFail
&& sm
->authStart
)
580 SM_ENTER(BE_AUTH
, FAIL
);
581 else if (sm
->eap_if
->eapReq
&& sm
->authStart
)
582 SM_ENTER(BE_AUTH
, REQUEST
);
583 else if (sm
->eap_if
->eapSuccess
&& sm
->authStart
)
584 SM_ENTER(BE_AUTH
, SUCCESS
);
588 SM_ENTER(BE_AUTH
, RESPONSE
);
589 else if (sm
->eap_if
->eapReq
)
590 SM_ENTER(BE_AUTH
, REQUEST
);
591 else if (sm
->eap_if
->eapTimeout
)
592 SM_ENTER(BE_AUTH
, TIMEOUT
);
599 /* Reauthentication Timer state machine */
601 SM_STATE(REAUTH_TIMER
, INITIALIZE
)
603 SM_ENTRY_MA(REAUTH_TIMER
, INITIALIZE
, reauth_timer
);
605 sm
->reAuthWhen
= sm
->reAuthPeriod
;
609 SM_STATE(REAUTH_TIMER
, REAUTHENTICATE
)
611 SM_ENTRY_MA(REAUTH_TIMER
, REAUTHENTICATE
, reauth_timer
);
613 sm
->reAuthenticate
= TRUE
;
614 wpa_auth_sm_event(sm
->sta
->wpa_sm
, WPA_REAUTH_EAPOL
);
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
&& !wpa_auth_sta_wpa_version(sm
->sta
->wpa_sm
))
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 preauth
, struct sta_info
*sta
)
763 struct eapol_state_machine
*sm
;
764 struct hostapd_data
*hapd
; /* TODO: to be removed */
765 struct eap_config eap_conf
;
769 hapd
= eapol
->conf
.hapd
;
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
);
780 sm
->flags
|= EAPOL_SM_PREAUTH
;
786 /* Set default values for state machine constants */
787 sm
->auth_pae_state
= AUTH_PAE_INITIALIZE
;
788 sm
->quietPeriod
= AUTH_PAE_DEFAULT_quietPeriod
;
789 sm
->reAuthMax
= AUTH_PAE_DEFAULT_reAuthMax
;
791 sm
->be_auth_state
= BE_AUTH_INITIALIZE
;
792 sm
->serverTimeout
= BE_AUTH_DEFAULT_serverTimeout
;
794 sm
->reauth_timer_state
= REAUTH_TIMER_INITIALIZE
;
795 sm
->reAuthPeriod
= eapol
->conf
.eap_reauth_period
;
796 sm
->reAuthEnabled
= eapol
->conf
.eap_reauth_period
> 0 ? TRUE
: FALSE
;
798 sm
->auth_key_tx_state
= AUTH_KEY_TX_NO_KEY_TRANSMIT
;
800 sm
->key_rx_state
= KEY_RX_NO_KEY_RECEIVE
;
802 sm
->ctrl_dir_state
= CTRL_DIR_IN_OR_BOTH
;
804 sm
->portControl
= Auto
;
806 if (!eapol
->conf
.wpa
&&
807 (hapd
->default_wep_key
|| eapol
->conf
.individual_wep_key_len
> 0))
808 sm
->keyTxEnabled
= TRUE
;
810 sm
->keyTxEnabled
= FALSE
;
812 sm
->portValid
= FALSE
;
814 sm
->portValid
= TRUE
;
816 os_memset(&eap_conf
, 0, sizeof(eap_conf
));
817 eap_conf
.eap_server
= eapol
->conf
.eap_server
;
818 eap_conf
.ssl_ctx
= eapol
->conf
.ssl_ctx
;
819 eap_conf
.eap_sim_db_priv
= eapol
->conf
.eap_sim_db_priv
;
820 eap_conf
.pac_opaque_encr_key
= eapol
->conf
.pac_opaque_encr_key
;
821 eap_conf
.eap_fast_a_id
= eapol
->conf
.eap_fast_a_id
;
822 eap_conf
.eap_fast_a_id_len
= eapol
->conf
.eap_fast_a_id_len
;
823 eap_conf
.eap_fast_a_id_info
= eapol
->conf
.eap_fast_a_id_info
;
824 eap_conf
.eap_fast_prov
= eapol
->conf
.eap_fast_prov
;
825 eap_conf
.pac_key_lifetime
= eapol
->conf
.pac_key_lifetime
;
826 eap_conf
.pac_key_refresh_time
= eapol
->conf
.pac_key_refresh_time
;
827 eap_conf
.eap_sim_aka_result_ind
= eapol
->conf
.eap_sim_aka_result_ind
;
828 eap_conf
.tnc
= eapol
->conf
.tnc
;
829 eap_conf
.wps
= eapol
->conf
.wps
;
830 eap_conf
.assoc_wps_ie
= sta
->wps_ie
;
831 sm
->eap
= eap_server_sm_init(sm
, &eapol_cb
, &eap_conf
);
832 if (sm
->eap
== NULL
) {
836 sm
->eap_if
= eap_get_interface(sm
->eap
);
838 eapol_auth_initialize(sm
);
844 void eapol_auth_free(struct eapol_state_machine
*sm
)
849 eloop_cancel_timeout(eapol_port_timers_tick
, NULL
, sm
);
850 eloop_cancel_timeout(eapol_sm_step_cb
, sm
, NULL
);
852 eap_server_sm_deinit(sm
->eap
);
857 static int eapol_sm_sta_entry_alive(struct eapol_authenticator
*eapol
,
860 return eapol
->cb
.sta_entry_alive(eapol
->conf
.hapd
, addr
);
864 static void eapol_sm_step_run(struct eapol_state_machine
*sm
)
866 struct eapol_authenticator
*eapol
= sm
->eapol
;
868 unsigned int prev_auth_pae
, prev_be_auth
, prev_reauth_timer
,
869 prev_auth_key_tx
, prev_key_rx
, prev_ctrl_dir
;
872 os_memcpy(addr
, sm
->addr
, ETH_ALEN
);
875 * Allow EAPOL state machines to run as long as there are state
876 * changes, but exit and return here through event loop if more than
877 * 100 steps is needed as a precaution against infinite loops inside
881 prev_auth_pae
= sm
->auth_pae_state
;
882 prev_be_auth
= sm
->be_auth_state
;
883 prev_reauth_timer
= sm
->reauth_timer_state
;
884 prev_auth_key_tx
= sm
->auth_key_tx_state
;
885 prev_key_rx
= sm
->key_rx_state
;
886 prev_ctrl_dir
= sm
->ctrl_dir_state
;
888 SM_STEP_RUN(AUTH_PAE
);
889 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
890 SM_STEP_RUN(BE_AUTH
);
891 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
892 SM_STEP_RUN(REAUTH_TIMER
);
893 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
894 SM_STEP_RUN(AUTH_KEY_TX
);
895 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
897 if (sm
->initializing
|| eapol_sm_sta_entry_alive(eapol
, addr
))
898 SM_STEP_RUN(CTRL_DIR
);
900 if (prev_auth_pae
!= sm
->auth_pae_state
||
901 prev_be_auth
!= sm
->be_auth_state
||
902 prev_reauth_timer
!= sm
->reauth_timer_state
||
903 prev_auth_key_tx
!= sm
->auth_key_tx_state
||
904 prev_key_rx
!= sm
->key_rx_state
||
905 prev_ctrl_dir
!= sm
->ctrl_dir_state
) {
908 /* Re-run from eloop timeout */
913 if (eapol_sm_sta_entry_alive(eapol
, addr
) && sm
->eap
) {
914 if (eap_server_sm_step(sm
->eap
)) {
917 /* Re-run from eloop timeout */
922 /* TODO: find a better location for this */
923 if (sm
->eap_if
->aaaEapResp
) {
924 sm
->eap_if
->aaaEapResp
= FALSE
;
925 if (sm
->eap_if
->aaaEapRespData
== NULL
) {
926 wpa_printf(MSG_DEBUG
, "EAPOL: aaaEapResp set, "
927 "but no aaaEapRespData available");
930 sm
->eapol
->cb
.aaa_send(
932 wpabuf_head(sm
->eap_if
->aaaEapRespData
),
933 wpabuf_len(sm
->eap_if
->aaaEapRespData
));
937 if (eapol_sm_sta_entry_alive(eapol
, addr
))
938 wpa_auth_sm_notify(sm
->sta
->wpa_sm
);
942 static void eapol_sm_step_cb(void *eloop_ctx
, void *timeout_ctx
)
944 struct eapol_state_machine
*sm
= eloop_ctx
;
945 eapol_sm_step_run(sm
);
950 * eapol_auth_step - Advance EAPOL state machines
951 * @sm: EAPOL state machine
953 * This function is called to advance EAPOL state machines after any change
954 * that could affect their state.
956 void eapol_auth_step(struct eapol_state_machine
*sm
)
959 * Run eapol_sm_step_run from a registered timeout to make sure that
960 * other possible timeouts/events are processed and to avoid long
961 * function call chains.
964 eloop_register_timeout(0, 0, eapol_sm_step_cb
, sm
, NULL
);
968 void eapol_auth_initialize(struct eapol_state_machine
*sm
)
970 sm
->initializing
= TRUE
;
971 /* Initialize the state machines by asserting initialize and then
972 * deasserting it after one step */
973 sm
->initialize
= TRUE
;
974 eapol_sm_step_run(sm
);
975 sm
->initialize
= FALSE
;
976 eapol_sm_step_run(sm
);
977 sm
->initializing
= FALSE
;
979 /* Start one second tick for port timers state machine */
980 eloop_cancel_timeout(eapol_port_timers_tick
, NULL
, sm
);
981 eloop_register_timeout(1, 0, eapol_port_timers_tick
, NULL
, sm
);
985 #ifdef HOSTAPD_DUMP_STATE
986 static inline const char * port_type_txt(PortTypes pt
)
989 case ForceUnauthorized
: return "ForceUnauthorized";
990 case ForceAuthorized
: return "ForceAuthorized";
991 case Auto
: return "Auto";
992 default: return "Unknown";
997 static inline const char * port_state_txt(PortState ps
)
1000 case Unauthorized
: return "Unauthorized";
1001 case Authorized
: return "Authorized";
1002 default: return "Unknown";
1007 static inline const char * ctrl_dir_txt(ControlledDirection dir
)
1010 case Both
: return "Both";
1011 case In
: return "In";
1012 default: return "Unknown";
1017 static inline const char * auth_pae_state_txt(int s
)
1020 case AUTH_PAE_INITIALIZE
: return "INITIALIZE";
1021 case AUTH_PAE_DISCONNECTED
: return "DISCONNECTED";
1022 case AUTH_PAE_CONNECTING
: return "CONNECTING";
1023 case AUTH_PAE_AUTHENTICATING
: return "AUTHENTICATING";
1024 case AUTH_PAE_AUTHENTICATED
: return "AUTHENTICATED";
1025 case AUTH_PAE_ABORTING
: return "ABORTING";
1026 case AUTH_PAE_HELD
: return "HELD";
1027 case AUTH_PAE_FORCE_AUTH
: return "FORCE_AUTH";
1028 case AUTH_PAE_FORCE_UNAUTH
: return "FORCE_UNAUTH";
1029 case AUTH_PAE_RESTART
: return "RESTART";
1030 default: return "Unknown";
1035 static inline const char * be_auth_state_txt(int s
)
1038 case BE_AUTH_REQUEST
: return "REQUEST";
1039 case BE_AUTH_RESPONSE
: return "RESPONSE";
1040 case BE_AUTH_SUCCESS
: return "SUCCESS";
1041 case BE_AUTH_FAIL
: return "FAIL";
1042 case BE_AUTH_TIMEOUT
: return "TIMEOUT";
1043 case BE_AUTH_IDLE
: return "IDLE";
1044 case BE_AUTH_INITIALIZE
: return "INITIALIZE";
1045 case BE_AUTH_IGNORE
: return "IGNORE";
1046 default: return "Unknown";
1051 static inline const char * reauth_timer_state_txt(int s
)
1054 case REAUTH_TIMER_INITIALIZE
: return "INITIALIZE";
1055 case REAUTH_TIMER_REAUTHENTICATE
: return "REAUTHENTICATE";
1056 default: return "Unknown";
1061 static inline const char * auth_key_tx_state_txt(int s
)
1064 case AUTH_KEY_TX_NO_KEY_TRANSMIT
: return "NO_KEY_TRANSMIT";
1065 case AUTH_KEY_TX_KEY_TRANSMIT
: return "KEY_TRANSMIT";
1066 default: return "Unknown";
1071 static inline const char * key_rx_state_txt(int s
)
1074 case KEY_RX_NO_KEY_RECEIVE
: return "NO_KEY_RECEIVE";
1075 case KEY_RX_KEY_RECEIVE
: return "KEY_RECEIVE";
1076 default: return "Unknown";
1081 static inline const char * ctrl_dir_state_txt(int s
)
1084 case CTRL_DIR_FORCE_BOTH
: return "FORCE_BOTH";
1085 case CTRL_DIR_IN_OR_BOTH
: return "IN_OR_BOTH";
1086 default: return "Unknown";
1091 void eapol_auth_dump_state(FILE *f
, const char *prefix
,
1092 struct eapol_state_machine
*sm
)
1094 fprintf(f
, "%sEAPOL state machine:\n", prefix
);
1095 fprintf(f
, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix
,
1096 sm
->aWhile
, sm
->quietWhile
, sm
->reAuthWhen
);
1097 #define _SB(b) ((b) ? "TRUE" : "FALSE")
1099 "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
1100 "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
1101 "%s eapSuccess=%s eapTimeout=%s initialize=%s "
1103 "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
1104 "%s portEnabled=%s portValid=%s reAuthenticate=%s\n",
1105 prefix
, _SB(sm
->authAbort
), _SB(sm
->authFail
),
1106 port_state_txt(sm
->authPortStatus
), _SB(sm
->authStart
),
1107 prefix
, _SB(sm
->authTimeout
), _SB(sm
->authSuccess
),
1108 _SB(sm
->eap_if
->eapFail
), _SB(sm
->eapolEap
),
1109 prefix
, _SB(sm
->eap_if
->eapSuccess
),
1110 _SB(sm
->eap_if
->eapTimeout
),
1111 _SB(sm
->initialize
), _SB(sm
->eap_if
->eapKeyAvailable
),
1112 prefix
, _SB(sm
->keyDone
), _SB(sm
->keyRun
),
1113 _SB(sm
->keyTxEnabled
), port_type_txt(sm
->portControl
),
1114 prefix
, _SB(sm
->eap_if
->portEnabled
), _SB(sm
->portValid
),
1115 _SB(sm
->reAuthenticate
));
1117 fprintf(f
, "%s Authenticator PAE:\n"
1119 "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
1120 "%s portMode=%s reAuthCount=%d\n"
1121 "%s quietPeriod=%d reAuthMax=%d\n"
1122 "%s authEntersConnecting=%d\n"
1123 "%s authEapLogoffsWhileConnecting=%d\n"
1124 "%s authEntersAuthenticating=%d\n"
1125 "%s authAuthSuccessesWhileAuthenticating=%d\n"
1126 "%s authAuthTimeoutsWhileAuthenticating=%d\n"
1127 "%s authAuthFailWhileAuthenticating=%d\n"
1128 "%s authAuthEapStartsWhileAuthenticating=%d\n"
1129 "%s authAuthEapLogoffWhileAuthenticating=%d\n"
1130 "%s authAuthReauthsWhileAuthenticated=%d\n"
1131 "%s authAuthEapStartsWhileAuthenticated=%d\n"
1132 "%s authAuthEapLogoffWhileAuthenticated=%d\n",
1133 prefix
, prefix
, auth_pae_state_txt(sm
->auth_pae_state
), prefix
,
1134 _SB(sm
->eapolLogoff
), _SB(sm
->eapolStart
),
1135 _SB(sm
->eap_if
->eapRestart
),
1136 prefix
, port_type_txt(sm
->portMode
), sm
->reAuthCount
,
1137 prefix
, sm
->quietPeriod
, sm
->reAuthMax
,
1138 prefix
, sm
->authEntersConnecting
,
1139 prefix
, sm
->authEapLogoffsWhileConnecting
,
1140 prefix
, sm
->authEntersAuthenticating
,
1141 prefix
, sm
->authAuthSuccessesWhileAuthenticating
,
1142 prefix
, sm
->authAuthTimeoutsWhileAuthenticating
,
1143 prefix
, sm
->authAuthFailWhileAuthenticating
,
1144 prefix
, sm
->authAuthEapStartsWhileAuthenticating
,
1145 prefix
, sm
->authAuthEapLogoffWhileAuthenticating
,
1146 prefix
, sm
->authAuthReauthsWhileAuthenticated
,
1147 prefix
, sm
->authAuthEapStartsWhileAuthenticated
,
1148 prefix
, sm
->authAuthEapLogoffWhileAuthenticated
);
1150 fprintf(f
, "%s Backend Authentication:\n"
1152 "%s eapNoReq=%s eapReq=%s eapResp=%s\n"
1153 "%s serverTimeout=%d\n"
1154 "%s backendResponses=%d\n"
1155 "%s backendAccessChallenges=%d\n"
1156 "%s backendOtherRequestsToSupplicant=%d\n"
1157 "%s backendAuthSuccesses=%d\n"
1158 "%s backendAuthFails=%d\n",
1160 be_auth_state_txt(sm
->be_auth_state
),
1161 prefix
, _SB(sm
->eap_if
->eapNoReq
), _SB(sm
->eap_if
->eapReq
),
1162 _SB(sm
->eap_if
->eapResp
),
1163 prefix
, sm
->serverTimeout
,
1164 prefix
, sm
->backendResponses
,
1165 prefix
, sm
->backendAccessChallenges
,
1166 prefix
, sm
->backendOtherRequestsToSupplicant
,
1167 prefix
, sm
->backendAuthSuccesses
,
1168 prefix
, sm
->backendAuthFails
);
1170 fprintf(f
, "%s Reauthentication Timer:\n"
1172 "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix
, prefix
,
1173 reauth_timer_state_txt(sm
->reauth_timer_state
), prefix
,
1174 sm
->reAuthPeriod
, _SB(sm
->reAuthEnabled
));
1176 fprintf(f
, "%s Authenticator Key Transmit:\n"
1177 "%s state=%s\n", prefix
, prefix
,
1178 auth_key_tx_state_txt(sm
->auth_key_tx_state
));
1180 fprintf(f
, "%s Key Receive:\n"
1182 "%s rxKey=%s\n", prefix
, prefix
,
1183 key_rx_state_txt(sm
->key_rx_state
), prefix
, _SB(sm
->rxKey
));
1185 fprintf(f
, "%s Controlled Directions:\n"
1187 "%s adminControlledDirections=%s "
1188 "operControlledDirections=%s\n"
1189 "%s operEdge=%s\n", prefix
, prefix
,
1190 ctrl_dir_state_txt(sm
->ctrl_dir_state
),
1191 prefix
, ctrl_dir_txt(sm
->adminControlledDirections
),
1192 ctrl_dir_txt(sm
->operControlledDirections
),
1193 prefix
, _SB(sm
->operEdge
));
1196 #endif /* HOSTAPD_DUMP_STATE */
1199 static int eapol_sm_get_eap_user(void *ctx
, const u8
*identity
,
1200 size_t identity_len
, int phase2
,
1201 struct eap_user
*user
)
1203 struct eapol_state_machine
*sm
= ctx
;
1204 return sm
->eapol
->cb
.get_eap_user(sm
->hapd
, identity
, identity_len
,
1209 static const char * eapol_sm_get_eap_req_id_text(void *ctx
, size_t *len
)
1211 struct eapol_state_machine
*sm
= ctx
;
1212 *len
= sm
->eapol
->conf
.eap_req_id_text_len
;
1213 return sm
->eapol
->conf
.eap_req_id_text
;
1217 static struct eapol_callbacks eapol_cb
=
1219 .get_eap_user
= eapol_sm_get_eap_user
,
1220 .get_eap_req_id_text
= eapol_sm_get_eap_req_id_text
,
1224 int eapol_auth_eap_pending_cb(struct eapol_state_machine
*sm
, void *ctx
)
1226 if (sm
== NULL
|| ctx
!= sm
->eap
)
1229 eap_sm_pending_cb(sm
->eap
);
1230 eapol_auth_step(sm
);
1236 static int eapol_auth_conf_clone(struct eapol_auth_config
*dst
,
1237 struct eapol_auth_config
*src
)
1239 dst
->hapd
= src
->hapd
;
1240 dst
->eap_reauth_period
= src
->eap_reauth_period
;
1241 dst
->wpa
= src
->wpa
;
1242 dst
->individual_wep_key_len
= src
->individual_wep_key_len
;
1243 dst
->eap_server
= src
->eap_server
;
1244 dst
->ssl_ctx
= src
->ssl_ctx
;
1245 dst
->eap_sim_db_priv
= src
->eap_sim_db_priv
;
1246 os_free(dst
->eap_req_id_text
);
1247 if (src
->eap_req_id_text
) {
1248 dst
->eap_req_id_text
= os_malloc(src
->eap_req_id_text_len
);
1249 if (dst
->eap_req_id_text
== NULL
)
1251 os_memcpy(dst
->eap_req_id_text
, src
->eap_req_id_text
,
1252 src
->eap_req_id_text_len
);
1253 dst
->eap_req_id_text_len
= src
->eap_req_id_text_len
;
1255 dst
->eap_req_id_text
= NULL
;
1256 dst
->eap_req_id_text_len
= 0;
1258 if (src
->pac_opaque_encr_key
) {
1259 dst
->pac_opaque_encr_key
= os_malloc(16);
1260 os_memcpy(dst
->pac_opaque_encr_key
, src
->pac_opaque_encr_key
,
1263 dst
->pac_opaque_encr_key
= NULL
;
1264 if (src
->eap_fast_a_id
) {
1265 dst
->eap_fast_a_id
= os_malloc(src
->eap_fast_a_id_len
);
1266 if (dst
->eap_fast_a_id
== NULL
) {
1267 os_free(dst
->eap_req_id_text
);
1270 os_memcpy(dst
->eap_fast_a_id
, src
->eap_fast_a_id
,
1271 src
->eap_fast_a_id_len
);
1272 dst
->eap_fast_a_id_len
= src
->eap_fast_a_id_len
;
1274 dst
->eap_fast_a_id
= NULL
;
1275 if (src
->eap_fast_a_id_info
) {
1276 dst
->eap_fast_a_id_info
= os_strdup(src
->eap_fast_a_id_info
);
1277 if (dst
->eap_fast_a_id_info
== NULL
) {
1278 os_free(dst
->eap_req_id_text
);
1279 os_free(dst
->eap_fast_a_id
);
1283 dst
->eap_fast_a_id_info
= NULL
;
1284 dst
->eap_fast_prov
= src
->eap_fast_prov
;
1285 dst
->pac_key_lifetime
= src
->pac_key_lifetime
;
1286 dst
->pac_key_refresh_time
= src
->pac_key_refresh_time
;
1287 dst
->eap_sim_aka_result_ind
= src
->eap_sim_aka_result_ind
;
1288 dst
->tnc
= src
->tnc
;
1289 dst
->wps
= src
->wps
;
1294 static void eapol_auth_conf_free(struct eapol_auth_config
*conf
)
1296 os_free(conf
->eap_req_id_text
);
1297 conf
->eap_req_id_text
= NULL
;
1298 os_free(conf
->pac_opaque_encr_key
);
1299 conf
->pac_opaque_encr_key
= NULL
;
1300 os_free(conf
->eap_fast_a_id
);
1301 conf
->eap_fast_a_id
= NULL
;
1302 os_free(conf
->eap_fast_a_id_info
);
1303 conf
->eap_fast_a_id_info
= NULL
;
1307 struct eapol_authenticator
* eapol_auth_init(struct eapol_auth_config
*conf
,
1308 struct eapol_auth_cb
*cb
)
1310 struct eapol_authenticator
*eapol
;
1312 eapol
= os_zalloc(sizeof(*eapol
));
1316 if (eapol_auth_conf_clone(&eapol
->conf
, conf
) < 0) {
1321 eapol
->cb
.eapol_send
= cb
->eapol_send
;
1322 eapol
->cb
.aaa_send
= cb
->aaa_send
;
1323 eapol
->cb
.finished
= cb
->finished
;
1324 eapol
->cb
.get_eap_user
= cb
->get_eap_user
;
1325 eapol
->cb
.sta_entry_alive
= cb
->sta_entry_alive
;
1326 eapol
->cb
.logger
= cb
->logger
;
1327 eapol
->cb
.set_port_authorized
= cb
->set_port_authorized
;
1328 eapol
->cb
.abort_auth
= cb
->abort_auth
;
1329 eapol
->cb
.tx_key
= cb
->tx_key
;
1335 void eapol_auth_deinit(struct eapol_authenticator
*eapol
)
1340 eapol_auth_conf_free(&eapol
->conf
);