Home | History | Annotate | Download | only in eapol_auth
      1 /*
      2  * IEEE 802.1X-2004 Authenticator - EAPOL state machine
      3  * Copyright (c) 2002-2009, Jouni Malinen <j (at) w1.fi>
      4  *
      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.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "eloop.h"
     19 #include "state_machine.h"
     20 #include "common/eapol_common.h"
     21 #include "eap_common/eap_defs.h"
     22 #include "eap_common/eap_common.h"
     23 #include "eap_server/eap.h"
     24 #include "eapol_auth_sm.h"
     25 #include "eapol_auth_sm_i.h"
     26 
     27 #define STATE_MACHINE_DATA struct eapol_state_machine
     28 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
     29 #define STATE_MACHINE_ADDR sm->addr
     30 
     31 static struct eapol_callbacks eapol_cb;
     32 
     33 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
     34 
     35 #define setPortAuthorized() \
     36 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1)
     37 #define setPortUnauthorized() \
     38 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0)
     39 
     40 /* procedures */
     41 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
     42 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
     43 #define txReq() eapol_auth_tx_req(sm)
     44 #define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta)
     45 #define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta)
     46 #define processKey() do { } while (0)
     47 
     48 
     49 static void eapol_sm_step_run(struct eapol_state_machine *sm);
     50 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
     51 static void eapol_auth_initialize(struct eapol_state_machine *sm);
     52 
     53 
     54 static void eapol_auth_logger(struct eapol_authenticator *eapol,
     55 			      const u8 *addr, eapol_logger_level level,
     56 			      const char *txt)
     57 {
     58 	if (eapol->cb.logger == NULL)
     59 		return;
     60 	eapol->cb.logger(eapol->conf.ctx, addr, level, txt);
     61 }
     62 
     63 
     64 static void eapol_auth_vlogger(struct eapol_authenticator *eapol,
     65 			       const u8 *addr, eapol_logger_level level,
     66 			       const char *fmt, ...)
     67 {
     68 	char *format;
     69 	int maxlen;
     70 	va_list ap;
     71 
     72 	if (eapol->cb.logger == NULL)
     73 		return;
     74 
     75 	maxlen = os_strlen(fmt) + 100;
     76 	format = os_malloc(maxlen);
     77 	if (!format)
     78 		return;
     79 
     80 	va_start(ap, fmt);
     81 	vsnprintf(format, maxlen, fmt, ap);
     82 	va_end(ap);
     83 
     84 	eapol_auth_logger(eapol, addr, level, format);
     85 
     86 	os_free(format);
     87 }
     88 
     89 
     90 static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
     91 				     int success)
     92 {
     93 	struct eap_hdr eap;
     94 
     95 	os_memset(&eap, 0, sizeof(eap));
     96 
     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));
    100 
    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->eapol->conf.ctx, sm->sta,
    105 				 IEEE802_1X_TYPE_EAP_PACKET,
    106 				 (u8 *) &eap, sizeof(eap));
    107 	sm->dot1xAuthEapolFramesTx++;
    108 }
    109 
    110 
    111 static void eapol_auth_tx_req(struct eapol_state_machine *sm)
    112 {
    113 	if (sm->eap_if->eapReqData == NULL ||
    114 	    wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) {
    115 		eapol_auth_logger(sm->eapol, sm->addr,
    116 				  EAPOL_LOGGER_DEBUG,
    117 				  "TxReq called, but there is no EAP request "
    118 				  "from authentication server");
    119 		return;
    120 	}
    121 
    122 	if (sm->flags & EAPOL_SM_WAIT_START) {
    123 		wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR
    124 			   " while waiting for EAPOL-Start",
    125 			   MAC2STR(sm->addr));
    126 		return;
    127 	}
    128 
    129 	sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData);
    130 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
    131 			   "Sending EAP Packet (identifier %d)",
    132 			   sm->last_eap_id);
    133 	sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
    134 				 IEEE802_1X_TYPE_EAP_PACKET,
    135 				 wpabuf_head(sm->eap_if->eapReqData),
    136 				 wpabuf_len(sm->eap_if->eapReqData));
    137 	sm->dot1xAuthEapolFramesTx++;
    138 	if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY)
    139 		sm->dot1xAuthEapolReqIdFramesTx++;
    140 	else
    141 		sm->dot1xAuthEapolReqFramesTx++;
    142 }
    143 
    144 
    145 /**
    146  * eapol_port_timers_tick - Port Timers state machine
    147  * @eloop_ctx: struct eapol_state_machine *
    148  * @timeout_ctx: Not used
    149  *
    150  * This statemachine is implemented as a function that will be called
    151  * once a second as a registered event loop timeout.
    152  */
    153 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
    154 {
    155 	struct eapol_state_machine *state = timeout_ctx;
    156 
    157 	if (state->aWhile > 0) {
    158 		state->aWhile--;
    159 		if (state->aWhile == 0) {
    160 			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
    161 				   " - aWhile --> 0",
    162 				   MAC2STR(state->addr));
    163 		}
    164 	}
    165 
    166 	if (state->quietWhile > 0) {
    167 		state->quietWhile--;
    168 		if (state->quietWhile == 0) {
    169 			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
    170 				   " - quietWhile --> 0",
    171 				   MAC2STR(state->addr));
    172 		}
    173 	}
    174 
    175 	if (state->reAuthWhen > 0) {
    176 		state->reAuthWhen--;
    177 		if (state->reAuthWhen == 0) {
    178 			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
    179 				   " - reAuthWhen --> 0",
    180 				   MAC2STR(state->addr));
    181 		}
    182 	}
    183 
    184 	if (state->eap_if->retransWhile > 0) {
    185 		state->eap_if->retransWhile--;
    186 		if (state->eap_if->retransWhile == 0) {
    187 			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
    188 				   " - (EAP) retransWhile --> 0",
    189 				   MAC2STR(state->addr));
    190 		}
    191 	}
    192 
    193 	eapol_sm_step_run(state);
    194 
    195 	eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
    196 }
    197 
    198 
    199 
    200 /* Authenticator PAE state machine */
    201 
    202 SM_STATE(AUTH_PAE, INITIALIZE)
    203 {
    204 	SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
    205 	sm->portMode = Auto;
    206 }
    207 
    208 
    209 SM_STATE(AUTH_PAE, DISCONNECTED)
    210 {
    211 	int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
    212 
    213 	if (sm->eapolLogoff) {
    214 		if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
    215 			sm->authEapLogoffsWhileConnecting++;
    216 		else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)
    217 			sm->authAuthEapLogoffWhileAuthenticated++;
    218 	}
    219 
    220 	SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
    221 
    222 	sm->authPortStatus = Unauthorized;
    223 	setPortUnauthorized();
    224 	sm->reAuthCount = 0;
    225 	sm->eapolLogoff = FALSE;
    226 	if (!from_initialize) {
    227 		sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
    228 				       sm->flags & EAPOL_SM_PREAUTH);
    229 	}
    230 }
    231 
    232 
    233 SM_STATE(AUTH_PAE, RESTART)
    234 {
    235 	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
    236 		if (sm->reAuthenticate)
    237 			sm->authAuthReauthsWhileAuthenticated++;
    238 		if (sm->eapolStart)
    239 			sm->authAuthEapStartsWhileAuthenticated++;
    240 		if (sm->eapolLogoff)
    241 			sm->authAuthEapLogoffWhileAuthenticated++;
    242 	}
    243 
    244 	SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
    245 
    246 	sm->eap_if->eapRestart = TRUE;
    247 }
    248 
    249 
    250 SM_STATE(AUTH_PAE, CONNECTING)
    251 {
    252 	if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
    253 		sm->authEntersConnecting++;
    254 
    255 	SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
    256 
    257 	sm->reAuthenticate = FALSE;
    258 	sm->reAuthCount++;
    259 }
    260 
    261 
    262 SM_STATE(AUTH_PAE, HELD)
    263 {
    264 	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
    265 		sm->authAuthFailWhileAuthenticating++;
    266 
    267 	SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
    268 
    269 	sm->authPortStatus = Unauthorized;
    270 	setPortUnauthorized();
    271 	sm->quietWhile = sm->quietPeriod;
    272 	sm->eapolLogoff = FALSE;
    273 
    274 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING,
    275 			   "authentication failed - EAP type: %d (%s)",
    276 			   sm->eap_type_authsrv,
    277 			   eap_server_get_name(0, sm->eap_type_authsrv));
    278 	if (sm->eap_type_authsrv != sm->eap_type_supp) {
    279 		eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
    280 				   "Supplicant used different EAP type: "
    281 				   "%d (%s)", sm->eap_type_supp,
    282 				   eap_server_get_name(0, sm->eap_type_supp));
    283 	}
    284 	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
    285 			       sm->flags & EAPOL_SM_PREAUTH);
    286 }
    287 
    288 
    289 SM_STATE(AUTH_PAE, AUTHENTICATED)
    290 {
    291 	char *extra = "";
    292 
    293 	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
    294 		sm->authAuthSuccessesWhileAuthenticating++;
    295 
    296 	SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
    297 
    298 	sm->authPortStatus = Authorized;
    299 	setPortAuthorized();
    300 	sm->reAuthCount = 0;
    301 	if (sm->flags & EAPOL_SM_PREAUTH)
    302 		extra = " (pre-authentication)";
    303 	else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE)
    304 		extra = " (PMKSA cache)";
    305 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
    306 			   "authenticated - EAP type: %d (%s)%s",
    307 			   sm->eap_type_authsrv,
    308 			   eap_server_get_name(0, sm->eap_type_authsrv),
    309 			   extra);
    310 	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
    311 			       sm->flags & EAPOL_SM_PREAUTH);
    312 }
    313 
    314 
    315 SM_STATE(AUTH_PAE, AUTHENTICATING)
    316 {
    317 	SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
    318 
    319 	sm->eapolStart = FALSE;
    320 	sm->authSuccess = FALSE;
    321 	sm->authFail = FALSE;
    322 	sm->authTimeout = FALSE;
    323 	sm->authStart = TRUE;
    324 	sm->keyRun = FALSE;
    325 	sm->keyDone = FALSE;
    326 }
    327 
    328 
    329 SM_STATE(AUTH_PAE, ABORTING)
    330 {
    331 	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
    332 		if (sm->authTimeout)
    333 			sm->authAuthTimeoutsWhileAuthenticating++;
    334 		if (sm->eapolStart)
    335 			sm->authAuthEapStartsWhileAuthenticating++;
    336 		if (sm->eapolLogoff)
    337 			sm->authAuthEapLogoffWhileAuthenticating++;
    338 	}
    339 
    340 	SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
    341 
    342 	sm->authAbort = TRUE;
    343 	sm->keyRun = FALSE;
    344 	sm->keyDone = FALSE;
    345 }
    346 
    347 
    348 SM_STATE(AUTH_PAE, FORCE_AUTH)
    349 {
    350 	SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
    351 
    352 	sm->authPortStatus = Authorized;
    353 	setPortAuthorized();
    354 	sm->portMode = ForceAuthorized;
    355 	sm->eapolStart = FALSE;
    356 	txCannedSuccess();
    357 }
    358 
    359 
    360 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
    361 {
    362 	SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
    363 
    364 	sm->authPortStatus = Unauthorized;
    365 	setPortUnauthorized();
    366 	sm->portMode = ForceUnauthorized;
    367 	sm->eapolStart = FALSE;
    368 	txCannedFail();
    369 }
    370 
    371 
    372 SM_STEP(AUTH_PAE)
    373 {
    374 	if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
    375 	    sm->initialize || !sm->eap_if->portEnabled)
    376 		SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE);
    377 	else if (sm->portControl == ForceAuthorized &&
    378 		 sm->portMode != sm->portControl &&
    379 		 !(sm->initialize || !sm->eap_if->portEnabled))
    380 		SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH);
    381 	else if (sm->portControl == ForceUnauthorized &&
    382 		 sm->portMode != sm->portControl &&
    383 		 !(sm->initialize || !sm->eap_if->portEnabled))
    384 		SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH);
    385 	else {
    386 		switch (sm->auth_pae_state) {
    387 		case AUTH_PAE_INITIALIZE:
    388 			SM_ENTER(AUTH_PAE, DISCONNECTED);
    389 			break;
    390 		case AUTH_PAE_DISCONNECTED:
    391 			SM_ENTER(AUTH_PAE, RESTART);
    392 			break;
    393 		case AUTH_PAE_RESTART:
    394 			if (!sm->eap_if->eapRestart)
    395 				SM_ENTER(AUTH_PAE, CONNECTING);
    396 			break;
    397 		case AUTH_PAE_HELD:
    398 			if (sm->quietWhile == 0)
    399 				SM_ENTER(AUTH_PAE, RESTART);
    400 			break;
    401 		case AUTH_PAE_CONNECTING:
    402 			if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
    403 				SM_ENTER(AUTH_PAE, DISCONNECTED);
    404 			else if ((sm->eap_if->eapReq &&
    405 				  sm->reAuthCount <= sm->reAuthMax) ||
    406 				 sm->eap_if->eapSuccess || sm->eap_if->eapFail)
    407 				SM_ENTER(AUTH_PAE, AUTHENTICATING);
    408 			break;
    409 		case AUTH_PAE_AUTHENTICATED:
    410 			if (sm->eapolStart || sm->reAuthenticate)
    411 				SM_ENTER(AUTH_PAE, RESTART);
    412 			else if (sm->eapolLogoff || !sm->portValid)
    413 				SM_ENTER(AUTH_PAE, DISCONNECTED);
    414 			break;
    415 		case AUTH_PAE_AUTHENTICATING:
    416 			if (sm->authSuccess && sm->portValid)
    417 				SM_ENTER(AUTH_PAE, AUTHENTICATED);
    418 			else if (sm->authFail ||
    419 				 (sm->keyDone && !sm->portValid))
    420 				SM_ENTER(AUTH_PAE, HELD);
    421 			else if (sm->eapolStart || sm->eapolLogoff ||
    422 				 sm->authTimeout)
    423 				SM_ENTER(AUTH_PAE, ABORTING);
    424 			break;
    425 		case AUTH_PAE_ABORTING:
    426 			if (sm->eapolLogoff && !sm->authAbort)
    427 				SM_ENTER(AUTH_PAE, DISCONNECTED);
    428 			else if (!sm->eapolLogoff && !sm->authAbort)
    429 				SM_ENTER(AUTH_PAE, RESTART);
    430 			break;
    431 		case AUTH_PAE_FORCE_AUTH:
    432 			if (sm->eapolStart)
    433 				SM_ENTER(AUTH_PAE, FORCE_AUTH);
    434 			break;
    435 		case AUTH_PAE_FORCE_UNAUTH:
    436 			if (sm->eapolStart)
    437 				SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
    438 			break;
    439 		}
    440 	}
    441 }
    442 
    443 
    444 
    445 /* Backend Authentication state machine */
    446 
    447 SM_STATE(BE_AUTH, INITIALIZE)
    448 {
    449 	SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
    450 
    451 	abortAuth();
    452 	sm->eap_if->eapNoReq = FALSE;
    453 	sm->authAbort = FALSE;
    454 }
    455 
    456 
    457 SM_STATE(BE_AUTH, REQUEST)
    458 {
    459 	SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
    460 
    461 	txReq();
    462 	sm->eap_if->eapReq = FALSE;
    463 	sm->backendOtherRequestsToSupplicant++;
    464 
    465 	/*
    466 	 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
    467 	 * it looks like this would be logical thing to do there since the old
    468 	 * EAP response would not be valid anymore after the new EAP request
    469 	 * was sent out.
    470 	 *
    471 	 * A race condition has been reported, in which hostapd ended up
    472 	 * sending out EAP-Response/Identity as a response to the first
    473 	 * EAP-Request from the main EAP method. This can be avoided by
    474 	 * clearing eapolEap here.
    475 	 */
    476 	sm->eapolEap = FALSE;
    477 }
    478 
    479 
    480 SM_STATE(BE_AUTH, RESPONSE)
    481 {
    482 	SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
    483 
    484 	sm->authTimeout = FALSE;
    485 	sm->eapolEap = FALSE;
    486 	sm->eap_if->eapNoReq = FALSE;
    487 	sm->aWhile = sm->serverTimeout;
    488 	sm->eap_if->eapResp = TRUE;
    489 	/* sendRespToServer(); */
    490 	sm->backendResponses++;
    491 }
    492 
    493 
    494 SM_STATE(BE_AUTH, SUCCESS)
    495 {
    496 	SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
    497 
    498 	txReq();
    499 	sm->authSuccess = TRUE;
    500 	sm->keyRun = TRUE;
    501 }
    502 
    503 
    504 SM_STATE(BE_AUTH, FAIL)
    505 {
    506 	SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
    507 
    508 	txReq();
    509 	sm->authFail = TRUE;
    510 }
    511 
    512 
    513 SM_STATE(BE_AUTH, TIMEOUT)
    514 {
    515 	SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
    516 
    517 	sm->authTimeout = TRUE;
    518 }
    519 
    520 
    521 SM_STATE(BE_AUTH, IDLE)
    522 {
    523 	SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
    524 
    525 	sm->authStart = FALSE;
    526 }
    527 
    528 
    529 SM_STATE(BE_AUTH, IGNORE)
    530 {
    531 	SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
    532 
    533 	sm->eap_if->eapNoReq = FALSE;
    534 }
    535 
    536 
    537 SM_STEP(BE_AUTH)
    538 {
    539 	if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
    540 		SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE);
    541 		return;
    542 	}
    543 
    544 	switch (sm->be_auth_state) {
    545 	case BE_AUTH_INITIALIZE:
    546 		SM_ENTER(BE_AUTH, IDLE);
    547 		break;
    548 	case BE_AUTH_REQUEST:
    549 		if (sm->eapolEap)
    550 			SM_ENTER(BE_AUTH, RESPONSE);
    551 		else if (sm->eap_if->eapReq)
    552 			SM_ENTER(BE_AUTH, REQUEST);
    553 		else if (sm->eap_if->eapTimeout)
    554 			SM_ENTER(BE_AUTH, TIMEOUT);
    555 		break;
    556 	case BE_AUTH_RESPONSE:
    557 		if (sm->eap_if->eapNoReq)
    558 			SM_ENTER(BE_AUTH, IGNORE);
    559 		if (sm->eap_if->eapReq) {
    560 			sm->backendAccessChallenges++;
    561 			SM_ENTER(BE_AUTH, REQUEST);
    562 		} else if (sm->aWhile == 0)
    563 			SM_ENTER(BE_AUTH, TIMEOUT);
    564 		else if (sm->eap_if->eapFail) {
    565 			sm->backendAuthFails++;
    566 			SM_ENTER(BE_AUTH, FAIL);
    567 		} else if (sm->eap_if->eapSuccess) {
    568 			sm->backendAuthSuccesses++;
    569 			SM_ENTER(BE_AUTH, SUCCESS);
    570 		}
    571 		break;
    572 	case BE_AUTH_SUCCESS:
    573 		SM_ENTER(BE_AUTH, IDLE);
    574 		break;
    575 	case BE_AUTH_FAIL:
    576 		SM_ENTER(BE_AUTH, IDLE);
    577 		break;
    578 	case BE_AUTH_TIMEOUT:
    579 		SM_ENTER(BE_AUTH, IDLE);
    580 		break;
    581 	case BE_AUTH_IDLE:
    582 		if (sm->eap_if->eapFail && sm->authStart)
    583 			SM_ENTER(BE_AUTH, FAIL);
    584 		else if (sm->eap_if->eapReq && sm->authStart)
    585 			SM_ENTER(BE_AUTH, REQUEST);
    586 		else if (sm->eap_if->eapSuccess && sm->authStart)
    587 			SM_ENTER(BE_AUTH, SUCCESS);
    588 		break;
    589 	case BE_AUTH_IGNORE:
    590 		if (sm->eapolEap)
    591 			SM_ENTER(BE_AUTH, RESPONSE);
    592 		else if (sm->eap_if->eapReq)
    593 			SM_ENTER(BE_AUTH, REQUEST);
    594 		else if (sm->eap_if->eapTimeout)
    595 			SM_ENTER(BE_AUTH, TIMEOUT);
    596 		break;
    597 	}
    598 }
    599 
    600 
    601 
    602 /* Reauthentication Timer state machine */
    603 
    604 SM_STATE(REAUTH_TIMER, INITIALIZE)
    605 {
    606 	SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
    607 
    608 	sm->reAuthWhen = sm->reAuthPeriod;
    609 }
    610 
    611 
    612 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
    613 {
    614 	SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
    615 
    616 	sm->reAuthenticate = TRUE;
    617 	sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
    618 				  EAPOL_AUTH_REAUTHENTICATE);
    619 }
    620 
    621 
    622 SM_STEP(REAUTH_TIMER)
    623 {
    624 	if (sm->portControl != Auto || sm->initialize ||
    625 	    sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
    626 		SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE);
    627 		return;
    628 	}
    629 
    630 	switch (sm->reauth_timer_state) {
    631 	case REAUTH_TIMER_INITIALIZE:
    632 		if (sm->reAuthWhen == 0)
    633 			SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
    634 		break;
    635 	case REAUTH_TIMER_REAUTHENTICATE:
    636 		SM_ENTER(REAUTH_TIMER, INITIALIZE);
    637 		break;
    638 	}
    639 }
    640 
    641 
    642 
    643 /* Authenticator Key Transmit state machine */
    644 
    645 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
    646 {
    647 	SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
    648 }
    649 
    650 
    651 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
    652 {
    653 	SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
    654 
    655 	txKey();
    656 	sm->eap_if->eapKeyAvailable = FALSE;
    657 	sm->keyDone = TRUE;
    658 }
    659 
    660 
    661 SM_STEP(AUTH_KEY_TX)
    662 {
    663 	if (sm->initialize || sm->portControl != Auto) {
    664 		SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT);
    665 		return;
    666 	}
    667 
    668 	switch (sm->auth_key_tx_state) {
    669 	case AUTH_KEY_TX_NO_KEY_TRANSMIT:
    670 		if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
    671 		    sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA))
    672 			SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
    673 		break;
    674 	case AUTH_KEY_TX_KEY_TRANSMIT:
    675 		if (!sm->keyTxEnabled || !sm->keyRun)
    676 			SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
    677 		else if (sm->eap_if->eapKeyAvailable)
    678 			SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
    679 		break;
    680 	}
    681 }
    682 
    683 
    684 
    685 /* Key Receive state machine */
    686 
    687 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
    688 {
    689 	SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
    690 }
    691 
    692 
    693 SM_STATE(KEY_RX, KEY_RECEIVE)
    694 {
    695 	SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
    696 
    697 	processKey();
    698 	sm->rxKey = FALSE;
    699 }
    700 
    701 
    702 SM_STEP(KEY_RX)
    703 {
    704 	if (sm->initialize || !sm->eap_if->portEnabled) {
    705 		SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
    706 		return;
    707 	}
    708 
    709 	switch (sm->key_rx_state) {
    710 	case KEY_RX_NO_KEY_RECEIVE:
    711 		if (sm->rxKey)
    712 			SM_ENTER(KEY_RX, KEY_RECEIVE);
    713 		break;
    714 	case KEY_RX_KEY_RECEIVE:
    715 		if (sm->rxKey)
    716 			SM_ENTER(KEY_RX, KEY_RECEIVE);
    717 		break;
    718 	}
    719 }
    720 
    721 
    722 
    723 /* Controlled Directions state machine */
    724 
    725 SM_STATE(CTRL_DIR, FORCE_BOTH)
    726 {
    727 	SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
    728 	sm->operControlledDirections = Both;
    729 }
    730 
    731 
    732 SM_STATE(CTRL_DIR, IN_OR_BOTH)
    733 {
    734 	SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
    735 	sm->operControlledDirections = sm->adminControlledDirections;
    736 }
    737 
    738 
    739 SM_STEP(CTRL_DIR)
    740 {
    741 	if (sm->initialize) {
    742 		SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH);
    743 		return;
    744 	}
    745 
    746 	switch (sm->ctrl_dir_state) {
    747 	case CTRL_DIR_FORCE_BOTH:
    748 		if (sm->eap_if->portEnabled && sm->operEdge)
    749 			SM_ENTER(CTRL_DIR, IN_OR_BOTH);
    750 		break;
    751 	case CTRL_DIR_IN_OR_BOTH:
    752 		if (sm->operControlledDirections !=
    753 		    sm->adminControlledDirections)
    754 			SM_ENTER(CTRL_DIR, IN_OR_BOTH);
    755 		if (!sm->eap_if->portEnabled || !sm->operEdge)
    756 			SM_ENTER(CTRL_DIR, FORCE_BOTH);
    757 		break;
    758 	}
    759 }
    760 
    761 
    762 
    763 struct eapol_state_machine *
    764 eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
    765 		 int flags, const struct wpabuf *assoc_wps_ie,
    766 		 const struct wpabuf *assoc_p2p_ie, void *sta_ctx)
    767 {
    768 	struct eapol_state_machine *sm;
    769 	struct eap_config eap_conf;
    770 
    771 	if (eapol == NULL)
    772 		return NULL;
    773 
    774 	sm = os_zalloc(sizeof(*sm));
    775 	if (sm == NULL) {
    776 		wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation "
    777 			   "failed");
    778 		return NULL;
    779 	}
    780 	sm->radius_identifier = -1;
    781 	os_memcpy(sm->addr, addr, ETH_ALEN);
    782 	sm->flags = flags;
    783 
    784 	sm->eapol = eapol;
    785 	sm->sta = sta_ctx;
    786 
    787 	/* Set default values for state machine constants */
    788 	sm->auth_pae_state = AUTH_PAE_INITIALIZE;
    789 	sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
    790 	sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
    791 
    792 	sm->be_auth_state = BE_AUTH_INITIALIZE;
    793 	sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
    794 
    795 	sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
    796 	sm->reAuthPeriod = eapol->conf.eap_reauth_period;
    797 	sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE;
    798 
    799 	sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
    800 
    801 	sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
    802 
    803 	sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
    804 
    805 	sm->portControl = Auto;
    806 
    807 	if (!eapol->conf.wpa &&
    808 	    (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
    809 		sm->keyTxEnabled = TRUE;
    810 	else
    811 		sm->keyTxEnabled = FALSE;
    812 	if (eapol->conf.wpa)
    813 		sm->portValid = FALSE;
    814 	else
    815 		sm->portValid = TRUE;
    816 
    817 	os_memset(&eap_conf, 0, sizeof(eap_conf));
    818 	eap_conf.eap_server = eapol->conf.eap_server;
    819 	eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
    820 	eap_conf.msg_ctx = eapol->conf.msg_ctx;
    821 	eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
    822 	eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
    823 	eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
    824 	eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
    825 	eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
    826 	eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
    827 	eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
    828 	eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
    829 	eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
    830 	eap_conf.tnc = eapol->conf.tnc;
    831 	eap_conf.wps = eapol->conf.wps;
    832 	eap_conf.assoc_wps_ie = assoc_wps_ie;
    833 	eap_conf.assoc_p2p_ie = assoc_p2p_ie;
    834 	eap_conf.peer_addr = addr;
    835 	eap_conf.fragment_size = eapol->conf.fragment_size;
    836 	eap_conf.pwd_group = eapol->conf.pwd_group;
    837 	eap_conf.pbc_in_m1 = eapol->conf.pbc_in_m1;
    838 	sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
    839 	if (sm->eap == NULL) {
    840 		eapol_auth_free(sm);
    841 		return NULL;
    842 	}
    843 	sm->eap_if = eap_get_interface(sm->eap);
    844 
    845 	eapol_auth_initialize(sm);
    846 
    847 	return sm;
    848 }
    849 
    850 
    851 void eapol_auth_free(struct eapol_state_machine *sm)
    852 {
    853 	if (sm == NULL)
    854 		return;
    855 
    856 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
    857 	eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
    858 	if (sm->eap)
    859 		eap_server_sm_deinit(sm->eap);
    860 	os_free(sm);
    861 }
    862 
    863 
    864 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
    865 				    const u8 *addr)
    866 {
    867 	return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr);
    868 }
    869 
    870 
    871 static void eapol_sm_step_run(struct eapol_state_machine *sm)
    872 {
    873 	struct eapol_authenticator *eapol = sm->eapol;
    874 	u8 addr[ETH_ALEN];
    875 	unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
    876 		prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
    877 	int max_steps = 100;
    878 
    879 	os_memcpy(addr, sm->addr, ETH_ALEN);
    880 
    881 	/*
    882 	 * Allow EAPOL state machines to run as long as there are state
    883 	 * changes, but exit and return here through event loop if more than
    884 	 * 100 steps is needed as a precaution against infinite loops inside
    885 	 * eloop callback.
    886 	 */
    887 restart:
    888 	prev_auth_pae = sm->auth_pae_state;
    889 	prev_be_auth = sm->be_auth_state;
    890 	prev_reauth_timer = sm->reauth_timer_state;
    891 	prev_auth_key_tx = sm->auth_key_tx_state;
    892 	prev_key_rx = sm->key_rx_state;
    893 	prev_ctrl_dir = sm->ctrl_dir_state;
    894 
    895 	SM_STEP_RUN(AUTH_PAE);
    896 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
    897 		SM_STEP_RUN(BE_AUTH);
    898 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
    899 		SM_STEP_RUN(REAUTH_TIMER);
    900 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
    901 		SM_STEP_RUN(AUTH_KEY_TX);
    902 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
    903 		SM_STEP_RUN(KEY_RX);
    904 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
    905 		SM_STEP_RUN(CTRL_DIR);
    906 
    907 	if (prev_auth_pae != sm->auth_pae_state ||
    908 	    prev_be_auth != sm->be_auth_state ||
    909 	    prev_reauth_timer != sm->reauth_timer_state ||
    910 	    prev_auth_key_tx != sm->auth_key_tx_state ||
    911 	    prev_key_rx != sm->key_rx_state ||
    912 	    prev_ctrl_dir != sm->ctrl_dir_state) {
    913 		if (--max_steps > 0)
    914 			goto restart;
    915 		/* Re-run from eloop timeout */
    916 		eapol_auth_step(sm);
    917 		return;
    918 	}
    919 
    920 	if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
    921 		if (eap_server_sm_step(sm->eap)) {
    922 			if (--max_steps > 0)
    923 				goto restart;
    924 			/* Re-run from eloop timeout */
    925 			eapol_auth_step(sm);
    926 			return;
    927 		}
    928 
    929 		/* TODO: find a better location for this */
    930 		if (sm->eap_if->aaaEapResp) {
    931 			sm->eap_if->aaaEapResp = FALSE;
    932 			if (sm->eap_if->aaaEapRespData == NULL) {
    933 				wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
    934 					   "but no aaaEapRespData available");
    935 				return;
    936 			}
    937 			sm->eapol->cb.aaa_send(
    938 				sm->eapol->conf.ctx, sm->sta,
    939 				wpabuf_head(sm->eap_if->aaaEapRespData),
    940 				wpabuf_len(sm->eap_if->aaaEapRespData));
    941 		}
    942 	}
    943 
    944 	if (eapol_sm_sta_entry_alive(eapol, addr))
    945 		sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
    946 					  EAPOL_AUTH_SM_CHANGE);
    947 }
    948 
    949 
    950 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
    951 {
    952 	struct eapol_state_machine *sm = eloop_ctx;
    953 	eapol_sm_step_run(sm);
    954 }
    955 
    956 
    957 /**
    958  * eapol_auth_step - Advance EAPOL state machines
    959  * @sm: EAPOL state machine
    960  *
    961  * This function is called to advance EAPOL state machines after any change
    962  * that could affect their state.
    963  */
    964 void eapol_auth_step(struct eapol_state_machine *sm)
    965 {
    966 	/*
    967 	 * Run eapol_sm_step_run from a registered timeout to make sure that
    968 	 * other possible timeouts/events are processed and to avoid long
    969 	 * function call chains.
    970 	 */
    971 
    972 	eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
    973 }
    974 
    975 
    976 static void eapol_auth_initialize(struct eapol_state_machine *sm)
    977 {
    978 	sm->initializing = TRUE;
    979 	/* Initialize the state machines by asserting initialize and then
    980 	 * deasserting it after one step */
    981 	sm->initialize = TRUE;
    982 	eapol_sm_step_run(sm);
    983 	sm->initialize = FALSE;
    984 	eapol_sm_step_run(sm);
    985 	sm->initializing = FALSE;
    986 
    987 	/* Start one second tick for port timers state machine */
    988 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
    989 	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
    990 }
    991 
    992 
    993 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
    994 				 size_t identity_len, int phase2,
    995 				 struct eap_user *user)
    996 {
    997 	struct eapol_state_machine *sm = ctx;
    998 	return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity,
    999 					  identity_len, phase2, user);
   1000 }
   1001 
   1002 
   1003 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
   1004 {
   1005 	struct eapol_state_machine *sm = ctx;
   1006 	*len = sm->eapol->conf.eap_req_id_text_len;
   1007 	return sm->eapol->conf.eap_req_id_text;
   1008 }
   1009 
   1010 
   1011 static struct eapol_callbacks eapol_cb =
   1012 {
   1013 	eapol_sm_get_eap_user,
   1014 	eapol_sm_get_eap_req_id_text
   1015 };
   1016 
   1017 
   1018 int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
   1019 {
   1020 	if (sm == NULL || ctx != sm->eap)
   1021 		return -1;
   1022 
   1023 	eap_sm_pending_cb(sm->eap);
   1024 	eapol_auth_step(sm);
   1025 
   1026 	return 0;
   1027 }
   1028 
   1029 
   1030 static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
   1031 				 struct eapol_auth_config *src)
   1032 {
   1033 	dst->ctx = src->ctx;
   1034 	dst->eap_reauth_period = src->eap_reauth_period;
   1035 	dst->wpa = src->wpa;
   1036 	dst->individual_wep_key_len = src->individual_wep_key_len;
   1037 	dst->eap_server = src->eap_server;
   1038 	dst->ssl_ctx = src->ssl_ctx;
   1039 	dst->msg_ctx = src->msg_ctx;
   1040 	dst->eap_sim_db_priv = src->eap_sim_db_priv;
   1041 	os_free(dst->eap_req_id_text);
   1042 	dst->pwd_group = src->pwd_group;
   1043 	dst->pbc_in_m1 = src->pbc_in_m1;
   1044 	if (src->eap_req_id_text) {
   1045 		dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
   1046 		if (dst->eap_req_id_text == NULL)
   1047 			return -1;
   1048 		os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
   1049 			  src->eap_req_id_text_len);
   1050 		dst->eap_req_id_text_len = src->eap_req_id_text_len;
   1051 	} else {
   1052 		dst->eap_req_id_text = NULL;
   1053 		dst->eap_req_id_text_len = 0;
   1054 	}
   1055 	if (src->pac_opaque_encr_key) {
   1056 		dst->pac_opaque_encr_key = os_malloc(16);
   1057 		os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
   1058 			  16);
   1059 	} else
   1060 		dst->pac_opaque_encr_key = NULL;
   1061 	if (src->eap_fast_a_id) {
   1062 		dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
   1063 		if (dst->eap_fast_a_id == NULL) {
   1064 			os_free(dst->eap_req_id_text);
   1065 			return -1;
   1066 		}
   1067 		os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
   1068 			  src->eap_fast_a_id_len);
   1069 		dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
   1070 	} else
   1071 		dst->eap_fast_a_id = NULL;
   1072 	if (src->eap_fast_a_id_info) {
   1073 		dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
   1074 		if (dst->eap_fast_a_id_info == NULL) {
   1075 			os_free(dst->eap_req_id_text);
   1076 			os_free(dst->eap_fast_a_id);
   1077 			return -1;
   1078 		}
   1079 	} else
   1080 		dst->eap_fast_a_id_info = NULL;
   1081 	dst->eap_fast_prov = src->eap_fast_prov;
   1082 	dst->pac_key_lifetime = src->pac_key_lifetime;
   1083 	dst->pac_key_refresh_time = src->pac_key_refresh_time;
   1084 	dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
   1085 	dst->tnc = src->tnc;
   1086 	dst->wps = src->wps;
   1087 	dst->fragment_size = src->fragment_size;
   1088 	return 0;
   1089 }
   1090 
   1091 
   1092 static void eapol_auth_conf_free(struct eapol_auth_config *conf)
   1093 {
   1094 	os_free(conf->eap_req_id_text);
   1095 	conf->eap_req_id_text = NULL;
   1096 	os_free(conf->pac_opaque_encr_key);
   1097 	conf->pac_opaque_encr_key = NULL;
   1098 	os_free(conf->eap_fast_a_id);
   1099 	conf->eap_fast_a_id = NULL;
   1100 	os_free(conf->eap_fast_a_id_info);
   1101 	conf->eap_fast_a_id_info = NULL;
   1102 }
   1103 
   1104 
   1105 struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
   1106 					     struct eapol_auth_cb *cb)
   1107 {
   1108 	struct eapol_authenticator *eapol;
   1109 
   1110 	eapol = os_zalloc(sizeof(*eapol));
   1111 	if (eapol == NULL)
   1112 		return NULL;
   1113 
   1114 	if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
   1115 		os_free(eapol);
   1116 		return NULL;
   1117 	}
   1118 
   1119 	if (conf->individual_wep_key_len > 0) {
   1120 		/* use key0 in individual key and key1 in broadcast key */
   1121 		eapol->default_wep_key_idx = 1;
   1122 	}
   1123 
   1124 	eapol->cb.eapol_send = cb->eapol_send;
   1125 	eapol->cb.aaa_send = cb->aaa_send;
   1126 	eapol->cb.finished = cb->finished;
   1127 	eapol->cb.get_eap_user = cb->get_eap_user;
   1128 	eapol->cb.sta_entry_alive = cb->sta_entry_alive;
   1129 	eapol->cb.logger = cb->logger;
   1130 	eapol->cb.set_port_authorized = cb->set_port_authorized;
   1131 	eapol->cb.abort_auth = cb->abort_auth;
   1132 	eapol->cb.tx_key = cb->tx_key;
   1133 	eapol->cb.eapol_event = cb->eapol_event;
   1134 
   1135 	return eapol;
   1136 }
   1137 
   1138 
   1139 void eapol_auth_deinit(struct eapol_authenticator *eapol)
   1140 {
   1141 	if (eapol == NULL)
   1142 		return;
   1143 
   1144 	eapol_auth_conf_free(&eapol->conf);
   1145 	os_free(eapol->default_wep_key);
   1146 	os_free(eapol);
   1147 }
   1148