xref: /freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.c (revision 10b9d77bf1ccf2f3affafa6261692cb92cf7e992)
1 /*
2  * IEEE 802.1X-2004 Authenticator - EAPOL state machine
3  * Copyright (c) 2002-2009, Jouni Malinen <j@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, void *sta_ctx)
766 {
767 	struct eapol_state_machine *sm;
768 	struct eap_config eap_conf;
769 
770 	if (eapol == NULL)
771 		return NULL;
772 
773 	sm = os_zalloc(sizeof(*sm));
774 	if (sm == NULL) {
775 		wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation "
776 			   "failed");
777 		return NULL;
778 	}
779 	sm->radius_identifier = -1;
780 	os_memcpy(sm->addr, addr, ETH_ALEN);
781 	sm->flags = flags;
782 
783 	sm->eapol = eapol;
784 	sm->sta = sta_ctx;
785 
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;
790 
791 	sm->be_auth_state = BE_AUTH_INITIALIZE;
792 	sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
793 
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;
797 
798 	sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
799 
800 	sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
801 
802 	sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
803 
804 	sm->portControl = Auto;
805 
806 	if (!eapol->conf.wpa &&
807 	    (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
808 		sm->keyTxEnabled = TRUE;
809 	else
810 		sm->keyTxEnabled = FALSE;
811 	if (eapol->conf.wpa)
812 		sm->portValid = FALSE;
813 	else
814 		sm->portValid = TRUE;
815 
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.msg_ctx = eapol->conf.msg_ctx;
820 	eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
821 	eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
822 	eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
823 	eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
824 	eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
825 	eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
826 	eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
827 	eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
828 	eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
829 	eap_conf.tnc = eapol->conf.tnc;
830 	eap_conf.wps = eapol->conf.wps;
831 	eap_conf.assoc_wps_ie = assoc_wps_ie;
832 	eap_conf.peer_addr = addr;
833 	sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
834 	if (sm->eap == NULL) {
835 		eapol_auth_free(sm);
836 		return NULL;
837 	}
838 	sm->eap_if = eap_get_interface(sm->eap);
839 
840 	eapol_auth_initialize(sm);
841 
842 	return sm;
843 }
844 
845 
846 void eapol_auth_free(struct eapol_state_machine *sm)
847 {
848 	if (sm == NULL)
849 		return;
850 
851 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
852 	eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
853 	if (sm->eap)
854 		eap_server_sm_deinit(sm->eap);
855 	os_free(sm);
856 }
857 
858 
859 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
860 				    const u8 *addr)
861 {
862 	return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr);
863 }
864 
865 
866 static void eapol_sm_step_run(struct eapol_state_machine *sm)
867 {
868 	struct eapol_authenticator *eapol = sm->eapol;
869 	u8 addr[ETH_ALEN];
870 	unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
871 		prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
872 	int max_steps = 100;
873 
874 	os_memcpy(addr, sm->addr, ETH_ALEN);
875 
876 	/*
877 	 * Allow EAPOL state machines to run as long as there are state
878 	 * changes, but exit and return here through event loop if more than
879 	 * 100 steps is needed as a precaution against infinite loops inside
880 	 * eloop callback.
881 	 */
882 restart:
883 	prev_auth_pae = sm->auth_pae_state;
884 	prev_be_auth = sm->be_auth_state;
885 	prev_reauth_timer = sm->reauth_timer_state;
886 	prev_auth_key_tx = sm->auth_key_tx_state;
887 	prev_key_rx = sm->key_rx_state;
888 	prev_ctrl_dir = sm->ctrl_dir_state;
889 
890 	SM_STEP_RUN(AUTH_PAE);
891 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
892 		SM_STEP_RUN(BE_AUTH);
893 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
894 		SM_STEP_RUN(REAUTH_TIMER);
895 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
896 		SM_STEP_RUN(AUTH_KEY_TX);
897 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
898 		SM_STEP_RUN(KEY_RX);
899 	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
900 		SM_STEP_RUN(CTRL_DIR);
901 
902 	if (prev_auth_pae != sm->auth_pae_state ||
903 	    prev_be_auth != sm->be_auth_state ||
904 	    prev_reauth_timer != sm->reauth_timer_state ||
905 	    prev_auth_key_tx != sm->auth_key_tx_state ||
906 	    prev_key_rx != sm->key_rx_state ||
907 	    prev_ctrl_dir != sm->ctrl_dir_state) {
908 		if (--max_steps > 0)
909 			goto restart;
910 		/* Re-run from eloop timeout */
911 		eapol_auth_step(sm);
912 		return;
913 	}
914 
915 	if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
916 		if (eap_server_sm_step(sm->eap)) {
917 			if (--max_steps > 0)
918 				goto restart;
919 			/* Re-run from eloop timeout */
920 			eapol_auth_step(sm);
921 			return;
922 		}
923 
924 		/* TODO: find a better location for this */
925 		if (sm->eap_if->aaaEapResp) {
926 			sm->eap_if->aaaEapResp = FALSE;
927 			if (sm->eap_if->aaaEapRespData == NULL) {
928 				wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
929 					   "but no aaaEapRespData available");
930 				return;
931 			}
932 			sm->eapol->cb.aaa_send(
933 				sm->eapol->conf.ctx, sm->sta,
934 				wpabuf_head(sm->eap_if->aaaEapRespData),
935 				wpabuf_len(sm->eap_if->aaaEapRespData));
936 		}
937 	}
938 
939 	if (eapol_sm_sta_entry_alive(eapol, addr))
940 		sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
941 					  EAPOL_AUTH_SM_CHANGE);
942 }
943 
944 
945 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
946 {
947 	struct eapol_state_machine *sm = eloop_ctx;
948 	eapol_sm_step_run(sm);
949 }
950 
951 
952 /**
953  * eapol_auth_step - Advance EAPOL state machines
954  * @sm: EAPOL state machine
955  *
956  * This function is called to advance EAPOL state machines after any change
957  * that could affect their state.
958  */
959 void eapol_auth_step(struct eapol_state_machine *sm)
960 {
961 	/*
962 	 * Run eapol_sm_step_run from a registered timeout to make sure that
963 	 * other possible timeouts/events are processed and to avoid long
964 	 * function call chains.
965 	 */
966 
967 	eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
968 }
969 
970 
971 static void eapol_auth_initialize(struct eapol_state_machine *sm)
972 {
973 	sm->initializing = TRUE;
974 	/* Initialize the state machines by asserting initialize and then
975 	 * deasserting it after one step */
976 	sm->initialize = TRUE;
977 	eapol_sm_step_run(sm);
978 	sm->initialize = FALSE;
979 	eapol_sm_step_run(sm);
980 	sm->initializing = FALSE;
981 
982 	/* Start one second tick for port timers state machine */
983 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
984 	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
985 }
986 
987 
988 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
989 				 size_t identity_len, int phase2,
990 				 struct eap_user *user)
991 {
992 	struct eapol_state_machine *sm = ctx;
993 	return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity,
994 					  identity_len, phase2, user);
995 }
996 
997 
998 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
999 {
1000 	struct eapol_state_machine *sm = ctx;
1001 	*len = sm->eapol->conf.eap_req_id_text_len;
1002 	return sm->eapol->conf.eap_req_id_text;
1003 }
1004 
1005 
1006 static struct eapol_callbacks eapol_cb =
1007 {
1008 	eapol_sm_get_eap_user,
1009 	eapol_sm_get_eap_req_id_text
1010 };
1011 
1012 
1013 int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
1014 {
1015 	if (sm == NULL || ctx != sm->eap)
1016 		return -1;
1017 
1018 	eap_sm_pending_cb(sm->eap);
1019 	eapol_auth_step(sm);
1020 
1021 	return 0;
1022 }
1023 
1024 
1025 static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
1026 				 struct eapol_auth_config *src)
1027 {
1028 	dst->ctx = src->ctx;
1029 	dst->eap_reauth_period = src->eap_reauth_period;
1030 	dst->wpa = src->wpa;
1031 	dst->individual_wep_key_len = src->individual_wep_key_len;
1032 	dst->eap_server = src->eap_server;
1033 	dst->ssl_ctx = src->ssl_ctx;
1034 	dst->msg_ctx = src->msg_ctx;
1035 	dst->eap_sim_db_priv = src->eap_sim_db_priv;
1036 	os_free(dst->eap_req_id_text);
1037 	if (src->eap_req_id_text) {
1038 		dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
1039 		if (dst->eap_req_id_text == NULL)
1040 			return -1;
1041 		os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
1042 			  src->eap_req_id_text_len);
1043 		dst->eap_req_id_text_len = src->eap_req_id_text_len;
1044 	} else {
1045 		dst->eap_req_id_text = NULL;
1046 		dst->eap_req_id_text_len = 0;
1047 	}
1048 	if (src->pac_opaque_encr_key) {
1049 		dst->pac_opaque_encr_key = os_malloc(16);
1050 		os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
1051 			  16);
1052 	} else
1053 		dst->pac_opaque_encr_key = NULL;
1054 	if (src->eap_fast_a_id) {
1055 		dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
1056 		if (dst->eap_fast_a_id == NULL) {
1057 			os_free(dst->eap_req_id_text);
1058 			return -1;
1059 		}
1060 		os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
1061 			  src->eap_fast_a_id_len);
1062 		dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
1063 	} else
1064 		dst->eap_fast_a_id = NULL;
1065 	if (src->eap_fast_a_id_info) {
1066 		dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
1067 		if (dst->eap_fast_a_id_info == NULL) {
1068 			os_free(dst->eap_req_id_text);
1069 			os_free(dst->eap_fast_a_id);
1070 			return -1;
1071 		}
1072 	} else
1073 		dst->eap_fast_a_id_info = NULL;
1074 	dst->eap_fast_prov = src->eap_fast_prov;
1075 	dst->pac_key_lifetime = src->pac_key_lifetime;
1076 	dst->pac_key_refresh_time = src->pac_key_refresh_time;
1077 	dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
1078 	dst->tnc = src->tnc;
1079 	dst->wps = src->wps;
1080 	return 0;
1081 }
1082 
1083 
1084 static void eapol_auth_conf_free(struct eapol_auth_config *conf)
1085 {
1086 	os_free(conf->eap_req_id_text);
1087 	conf->eap_req_id_text = NULL;
1088 	os_free(conf->pac_opaque_encr_key);
1089 	conf->pac_opaque_encr_key = NULL;
1090 	os_free(conf->eap_fast_a_id);
1091 	conf->eap_fast_a_id = NULL;
1092 	os_free(conf->eap_fast_a_id_info);
1093 	conf->eap_fast_a_id_info = NULL;
1094 }
1095 
1096 
1097 struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
1098 					     struct eapol_auth_cb *cb)
1099 {
1100 	struct eapol_authenticator *eapol;
1101 
1102 	eapol = os_zalloc(sizeof(*eapol));
1103 	if (eapol == NULL)
1104 		return NULL;
1105 
1106 	if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
1107 		os_free(eapol);
1108 		return NULL;
1109 	}
1110 
1111 	if (conf->individual_wep_key_len > 0) {
1112 		/* use key0 in individual key and key1 in broadcast key */
1113 		eapol->default_wep_key_idx = 1;
1114 	}
1115 
1116 	eapol->cb.eapol_send = cb->eapol_send;
1117 	eapol->cb.aaa_send = cb->aaa_send;
1118 	eapol->cb.finished = cb->finished;
1119 	eapol->cb.get_eap_user = cb->get_eap_user;
1120 	eapol->cb.sta_entry_alive = cb->sta_entry_alive;
1121 	eapol->cb.logger = cb->logger;
1122 	eapol->cb.set_port_authorized = cb->set_port_authorized;
1123 	eapol->cb.abort_auth = cb->abort_auth;
1124 	eapol->cb.tx_key = cb->tx_key;
1125 	eapol->cb.eapol_event = cb->eapol_event;
1126 
1127 	return eapol;
1128 }
1129 
1130 
1131 void eapol_auth_deinit(struct eapol_authenticator *eapol)
1132 {
1133 	if (eapol == NULL)
1134 		return;
1135 
1136 	eapol_auth_conf_free(&eapol->conf);
1137 	os_free(eapol->default_wep_key);
1138 	os_free(eapol);
1139 }
1140