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