Rename the new cvsup bootstrap kit so make nrelease knows a new one
[dfdiff.git] / contrib / hostapd-0.4.9 / eapol_sm.c
blobf2d5ec7c5298a7fac90dcc35876c588d9bd8c7a5
1 /*
2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / IEEE 802.1X Authenticator - EAPOL state machine
4 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
11 * license.
13 * See README and COPYING for more details.
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <netinet/in.h>
20 #include <string.h>
21 #include <sys/socket.h>
23 #include "hostapd.h"
24 #include "ieee802_1x.h"
25 #include "eapol_sm.h"
26 #include "eloop.h"
27 #include "wpa.h"
28 #include "sta_info.h"
29 #include "eap.h"
31 static struct eapol_callbacks eapol_cb;
33 /* EAPOL state machines are described in IEEE Std 802.1X-REV-d11, Chap. 8.2 */
35 #define setPortAuthorized() \
36 ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 1)
37 #define setPortUnauthorized() \
38 ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 0)
40 /* procedures */
41 #define txCannedFail() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 0)
42 #define txCannedSuccess() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 1)
43 #define txReq() ieee802_1x_tx_req(sm->hapd, sm->sta)
44 #define sendRespToServer() ieee802_1x_send_resp_to_server(sm->hapd, sm->sta)
45 #define abortAuth() ieee802_1x_abort_auth(sm->hapd, sm->sta)
46 #define txKey() ieee802_1x_tx_key(sm->hapd, sm->sta)
47 #define processKey() do { } while (0)
50 /* Definitions for clarifying state machine implementation */
51 #define SM_STATE(machine, state) \
52 static void sm_ ## machine ## _ ## state ## _Enter(struct eapol_state_machine \
53 *sm)
55 #define SM_ENTRY(machine, _state, _data) \
56 sm->_data.state = machine ## _ ## _state; \
57 if (sm->hapd->conf->debug >= HOSTAPD_DEBUG_MINIMAL) \
58 printf("IEEE 802.1X: " MACSTR " " #machine " entering state " #_state \
59 "\n", MAC2STR(sm->addr));
61 #define SM_ENTER(machine, state) sm_ ## machine ## _ ## state ## _Enter(sm)
63 #define SM_STEP(machine) \
64 static void sm_ ## machine ## _Step(struct eapol_state_machine *sm)
66 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
69 static void eapol_sm_step_run(struct eapol_state_machine *sm);
70 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
73 /* Port Timers state machine - implemented as a function that will be called
74 * once a second as a registered event loop timeout */
76 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
78 struct eapol_state_machine *state = timeout_ctx;
80 if (state->aWhile > 0) {
81 state->aWhile--;
82 if (state->aWhile == 0) {
83 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
84 " - aWhile --> 0",
85 MAC2STR(state->addr));
89 if (state->quietWhile > 0) {
90 state->quietWhile--;
91 if (state->quietWhile == 0) {
92 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
93 " - quietWhile --> 0",
94 MAC2STR(state->addr));
98 if (state->reAuthWhen > 0) {
99 state->reAuthWhen--;
100 if (state->reAuthWhen == 0) {
101 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
102 " - reAuthWhen --> 0",
103 MAC2STR(state->addr));
107 eapol_sm_step_run(state);
109 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
114 /* Authenticator PAE state machine */
116 SM_STATE(AUTH_PAE, INITIALIZE)
118 SM_ENTRY(AUTH_PAE, INITIALIZE, auth_pae);
119 sm->auth_pae.portMode = Auto;
121 sm->currentId = 255;
125 SM_STATE(AUTH_PAE, DISCONNECTED)
127 int from_initialize = sm->auth_pae.state == AUTH_PAE_INITIALIZE;
129 if (sm->auth_pae.eapolLogoff) {
130 if (sm->auth_pae.state == AUTH_PAE_CONNECTING)
131 sm->auth_pae.authEapLogoffsWhileConnecting++;
132 else if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATED)
133 sm->auth_pae.authAuthEapLogoffWhileAuthenticated++;
136 SM_ENTRY(AUTH_PAE, DISCONNECTED, auth_pae);
138 sm->authPortStatus = Unauthorized;
139 setPortUnauthorized();
140 sm->auth_pae.reAuthCount = 0;
141 sm->auth_pae.eapolLogoff = FALSE;
142 if (!from_initialize) {
143 if (sm->flags & EAPOL_SM_PREAUTH)
144 rsn_preauth_finished(sm->hapd, sm->sta, 0);
145 else
146 ieee802_1x_finished(sm->hapd, sm->sta, 0);
151 SM_STATE(AUTH_PAE, RESTART)
153 if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATED) {
154 if (sm->reAuthenticate)
155 sm->auth_pae.authAuthReauthsWhileAuthenticated++;
156 if (sm->auth_pae.eapolStart)
157 sm->auth_pae.authAuthEapStartsWhileAuthenticated++;
158 if (sm->auth_pae.eapolLogoff)
159 sm->auth_pae.authAuthEapLogoffWhileAuthenticated++;
162 SM_ENTRY(AUTH_PAE, RESTART, auth_pae);
164 sm->auth_pae.eapRestart = TRUE;
165 ieee802_1x_request_identity(sm->hapd, sm->sta);
169 SM_STATE(AUTH_PAE, CONNECTING)
171 if (sm->auth_pae.state != AUTH_PAE_CONNECTING)
172 sm->auth_pae.authEntersConnecting++;
174 SM_ENTRY(AUTH_PAE, CONNECTING, auth_pae);
176 sm->reAuthenticate = FALSE;
177 sm->auth_pae.reAuthCount++;
181 SM_STATE(AUTH_PAE, HELD)
183 if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authFail)
184 sm->auth_pae.authAuthFailWhileAuthenticating++;
186 SM_ENTRY(AUTH_PAE, HELD, auth_pae);
188 sm->authPortStatus = Unauthorized;
189 setPortUnauthorized();
190 sm->quietWhile = sm->auth_pae.quietPeriod;
191 sm->auth_pae.eapolLogoff = FALSE;
193 hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
194 HOSTAPD_LEVEL_WARNING, "authentication failed");
195 if (sm->flags & EAPOL_SM_PREAUTH)
196 rsn_preauth_finished(sm->hapd, sm->sta, 0);
197 else
198 ieee802_1x_finished(sm->hapd, sm->sta, 0);
202 SM_STATE(AUTH_PAE, AUTHENTICATED)
204 if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
205 sm->auth_pae.authAuthSuccessesWhileAuthenticating++;
207 SM_ENTRY(AUTH_PAE, AUTHENTICATED, auth_pae);
209 sm->authPortStatus = Authorized;
210 setPortAuthorized();
211 sm->auth_pae.reAuthCount = 0;
212 hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
213 HOSTAPD_LEVEL_INFO, "authenticated");
214 if (sm->flags & EAPOL_SM_PREAUTH)
215 rsn_preauth_finished(sm->hapd, sm->sta, 1);
216 else
217 ieee802_1x_finished(sm->hapd, sm->sta, 1);
221 SM_STATE(AUTH_PAE, AUTHENTICATING)
223 if (sm->auth_pae.state == AUTH_PAE_CONNECTING && sm->rx_identity) {
224 sm->auth_pae.authEntersAuthenticating++;
225 sm->rx_identity = FALSE;
228 SM_ENTRY(AUTH_PAE, AUTHENTICATING, auth_pae);
230 sm->auth_pae.eapolStart = FALSE;
231 sm->authSuccess = FALSE;
232 sm->authFail = FALSE;
233 sm->authTimeout = FALSE;
234 sm->authStart = TRUE;
235 sm->keyRun = FALSE;
236 sm->keyDone = FALSE;
240 SM_STATE(AUTH_PAE, ABORTING)
242 if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING) {
243 if (sm->authTimeout)
244 sm->auth_pae.authAuthTimeoutsWhileAuthenticating++;
245 if (sm->auth_pae.eapolStart)
246 sm->auth_pae.authAuthEapStartsWhileAuthenticating++;
247 if (sm->auth_pae.eapolLogoff)
248 sm->auth_pae.authAuthEapLogoffWhileAuthenticating++;
251 SM_ENTRY(AUTH_PAE, ABORTING, auth_pae);
253 sm->authAbort = TRUE;
254 sm->keyRun = FALSE;
255 sm->keyDone = FALSE;
259 SM_STATE(AUTH_PAE, FORCE_AUTH)
261 SM_ENTRY(AUTH_PAE, FORCE_AUTH, auth_pae);
263 sm->authPortStatus = Authorized;
264 setPortAuthorized();
265 sm->auth_pae.portMode = ForceAuthorized;
266 sm->auth_pae.eapolStart = FALSE;
267 txCannedSuccess();
271 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
273 SM_ENTRY(AUTH_PAE, FORCE_UNAUTH, auth_pae);
275 sm->authPortStatus = Unauthorized;
276 setPortUnauthorized();
277 sm->auth_pae.portMode = ForceUnauthorized;
278 sm->auth_pae.eapolStart = FALSE;
279 txCannedFail();
283 SM_STEP(AUTH_PAE)
285 if ((sm->portControl == Auto &&
286 sm->auth_pae.portMode != sm->portControl) ||
287 sm->initialize || !sm->portEnabled)
288 SM_ENTER(AUTH_PAE, INITIALIZE);
289 else if (sm->portControl == ForceAuthorized &&
290 sm->auth_pae.portMode != sm->portControl &&
291 !(sm->initialize || !sm->portEnabled))
292 SM_ENTER(AUTH_PAE, FORCE_AUTH);
293 else if (sm->portControl == ForceUnauthorized &&
294 sm->auth_pae.portMode != sm->portControl &&
295 !(sm->initialize || !sm->portEnabled))
296 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
297 else {
298 switch (sm->auth_pae.state) {
299 case AUTH_PAE_INITIALIZE:
300 SM_ENTER(AUTH_PAE, DISCONNECTED);
301 break;
302 case AUTH_PAE_DISCONNECTED:
303 SM_ENTER(AUTH_PAE, RESTART);
304 break;
305 case AUTH_PAE_RESTART:
306 if (!sm->auth_pae.eapRestart)
307 SM_ENTER(AUTH_PAE, CONNECTING);
308 break;
309 case AUTH_PAE_HELD:
310 if (sm->quietWhile == 0)
311 SM_ENTER(AUTH_PAE, RESTART);
312 break;
313 case AUTH_PAE_CONNECTING:
314 if (sm->auth_pae.eapolLogoff ||
315 sm->auth_pae.reAuthCount > sm->auth_pae.reAuthMax)
316 SM_ENTER(AUTH_PAE, DISCONNECTED);
317 else if ((sm->be_auth.eapReq &&
318 sm->auth_pae.reAuthCount <=
319 sm->auth_pae.reAuthMax) ||
320 sm->eapSuccess || sm->eapFail)
321 SM_ENTER(AUTH_PAE, AUTHENTICATING);
322 break;
323 case AUTH_PAE_AUTHENTICATED:
324 if (sm->auth_pae.eapolStart || sm->reAuthenticate)
325 SM_ENTER(AUTH_PAE, RESTART);
326 else if (sm->auth_pae.eapolLogoff || !sm->portValid)
327 SM_ENTER(AUTH_PAE, DISCONNECTED);
328 break;
329 case AUTH_PAE_AUTHENTICATING:
330 if (sm->authSuccess && sm->portValid)
331 SM_ENTER(AUTH_PAE, AUTHENTICATED);
332 else if (sm->authFail ||
333 (sm->keyDone && !sm->portValid))
334 SM_ENTER(AUTH_PAE, HELD);
335 else if (sm->auth_pae.eapolStart ||
336 sm->auth_pae.eapolLogoff || sm->authTimeout)
337 SM_ENTER(AUTH_PAE, ABORTING);
338 break;
339 case AUTH_PAE_ABORTING:
340 if (sm->auth_pae.eapolLogoff && !sm->authAbort)
341 SM_ENTER(AUTH_PAE, DISCONNECTED);
342 else if (!sm->auth_pae.eapolLogoff && !sm->authAbort)
343 SM_ENTER(AUTH_PAE, RESTART);
344 break;
345 case AUTH_PAE_FORCE_AUTH:
346 if (sm->auth_pae.eapolStart)
347 SM_ENTER(AUTH_PAE, FORCE_AUTH);
348 break;
349 case AUTH_PAE_FORCE_UNAUTH:
350 if (sm->auth_pae.eapolStart)
351 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
352 break;
359 /* Backend Authentication state machine */
361 SM_STATE(BE_AUTH, INITIALIZE)
363 SM_ENTRY(BE_AUTH, INITIALIZE, be_auth);
365 abortAuth();
366 sm->be_auth.eapNoReq = FALSE;
367 sm->authAbort = FALSE;
371 SM_STATE(BE_AUTH, REQUEST)
373 SM_ENTRY(BE_AUTH, REQUEST, be_auth);
375 txReq();
376 sm->be_auth.eapReq = FALSE;
377 sm->be_auth.backendOtherRequestsToSupplicant++;
380 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
381 * it looks like this would be logical thing to do there since the old
382 * EAP response would not be valid anymore after the new EAP request
383 * was sent out.
385 * A race condition has been reported, in which hostapd ended up
386 * sending out EAP-Response/Identity as a response to the first
387 * EAP-Request from the main EAP method. This can be avoided by
388 * clearing eapolEap here.
390 sm->eapolEap = FALSE;
394 SM_STATE(BE_AUTH, RESPONSE)
396 SM_ENTRY(BE_AUTH, RESPONSE, be_auth);
398 sm->authTimeout = FALSE;
399 sm->eapolEap = FALSE;
400 sm->be_auth.eapNoReq = FALSE;
401 sm->aWhile = sm->be_auth.serverTimeout;
402 sm->be_auth.eapResp = TRUE;
403 sendRespToServer();
404 sm->be_auth.backendResponses++;
408 SM_STATE(BE_AUTH, SUCCESS)
410 SM_ENTRY(BE_AUTH, SUCCESS, be_auth);
412 txReq();
413 sm->authSuccess = TRUE;
414 sm->keyRun = TRUE;
418 SM_STATE(BE_AUTH, FAIL)
420 SM_ENTRY(BE_AUTH, FAIL, be_auth);
422 /* Note: IEEE 802.1X-REV-d11 has unconditional txReq() here.
423 * txCannelFail() is used as a workaround for the case where
424 * authentication server does not include EAP-Message with
425 * Access-Reject. */
426 if (sm->last_eap_radius == NULL)
427 txCannedFail();
428 else
429 txReq();
430 sm->authFail = TRUE;
434 SM_STATE(BE_AUTH, TIMEOUT)
436 SM_ENTRY(BE_AUTH, TIMEOUT, be_auth);
438 sm->authTimeout = TRUE;
442 SM_STATE(BE_AUTH, IDLE)
444 SM_ENTRY(BE_AUTH, IDLE, be_auth);
446 sm->authStart = FALSE;
450 SM_STATE(BE_AUTH, IGNORE)
452 SM_ENTRY(BE_AUTH, IGNORE, be_auth);
454 sm->be_auth.eapNoReq = FALSE;
458 SM_STEP(BE_AUTH)
460 if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
461 SM_ENTER(BE_AUTH, INITIALIZE);
462 return;
465 switch (sm->be_auth.state) {
466 case BE_AUTH_INITIALIZE:
467 SM_ENTER(BE_AUTH, IDLE);
468 break;
469 case BE_AUTH_REQUEST:
470 if (sm->eapolEap)
471 SM_ENTER(BE_AUTH, RESPONSE);
472 else if (sm->be_auth.eapReq)
473 SM_ENTER(BE_AUTH, REQUEST);
474 else if (sm->eapTimeout)
475 SM_ENTER(BE_AUTH, TIMEOUT);
476 break;
477 case BE_AUTH_RESPONSE:
478 if (sm->be_auth.eapNoReq)
479 SM_ENTER(BE_AUTH, IGNORE);
480 if (sm->be_auth.eapReq) {
481 sm->be_auth.backendAccessChallenges++;
482 SM_ENTER(BE_AUTH, REQUEST);
483 } else if (sm->aWhile == 0)
484 SM_ENTER(BE_AUTH, TIMEOUT);
485 else if (sm->eapFail) {
486 sm->be_auth.backendAuthFails++;
487 SM_ENTER(BE_AUTH, FAIL);
488 } else if (sm->eapSuccess) {
489 sm->be_auth.backendAuthSuccesses++;
490 SM_ENTER(BE_AUTH, SUCCESS);
492 break;
493 case BE_AUTH_SUCCESS:
494 SM_ENTER(BE_AUTH, IDLE);
495 break;
496 case BE_AUTH_FAIL:
497 SM_ENTER(BE_AUTH, IDLE);
498 break;
499 case BE_AUTH_TIMEOUT:
500 SM_ENTER(BE_AUTH, IDLE);
501 break;
502 case BE_AUTH_IDLE:
503 if (sm->eapFail && sm->authStart)
504 SM_ENTER(BE_AUTH, FAIL);
505 else if (sm->be_auth.eapReq && sm->authStart)
506 SM_ENTER(BE_AUTH, REQUEST);
507 else if (sm->eapSuccess && sm->authStart)
508 SM_ENTER(BE_AUTH, SUCCESS);
509 break;
510 case BE_AUTH_IGNORE:
511 if (sm->eapolEap)
512 SM_ENTER(BE_AUTH, RESPONSE);
513 else if (sm->be_auth.eapReq)
514 SM_ENTER(BE_AUTH, REQUEST);
515 else if (sm->eapTimeout)
516 SM_ENTER(BE_AUTH, TIMEOUT);
517 break;
523 /* Reauthentication Timer state machine */
525 SM_STATE(REAUTH_TIMER, INITIALIZE)
527 SM_ENTRY(REAUTH_TIMER, INITIALIZE, reauth_timer);
529 sm->reAuthWhen = sm->reauth_timer.reAuthPeriod;
533 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
535 SM_ENTRY(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
537 sm->reAuthenticate = TRUE;
538 wpa_sm_event(sm->hapd, sm->sta, WPA_REAUTH_EAPOL);
542 SM_STEP(REAUTH_TIMER)
544 if (sm->portControl != Auto || sm->initialize ||
545 sm->authPortStatus == Unauthorized ||
546 !sm->reauth_timer.reAuthEnabled) {
547 SM_ENTER(REAUTH_TIMER, INITIALIZE);
548 return;
551 switch (sm->reauth_timer.state) {
552 case REAUTH_TIMER_INITIALIZE:
553 if (sm->reAuthWhen == 0)
554 SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
555 break;
556 case REAUTH_TIMER_REAUTHENTICATE:
557 SM_ENTER(REAUTH_TIMER, INITIALIZE);
558 break;
564 /* Authenticator Key Transmit state machine */
566 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
568 SM_ENTRY(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
572 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
574 SM_ENTRY(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
576 txKey();
577 sm->keyAvailable = FALSE;
578 sm->keyDone = TRUE;
582 SM_STEP(AUTH_KEY_TX)
584 if (sm->initialize || sm->portControl != Auto) {
585 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
586 return;
589 switch (sm->auth_key_tx.state) {
590 case AUTH_KEY_TX_NO_KEY_TRANSMIT:
591 if (sm->keyTxEnabled && sm->keyAvailable && sm->keyRun &&
592 !sm->sta->wpa)
593 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
594 break;
595 case AUTH_KEY_TX_KEY_TRANSMIT:
596 if (!sm->keyTxEnabled || !sm->keyRun)
597 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
598 else if (sm->keyAvailable)
599 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
600 break;
606 /* Key Receive state machine */
608 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
610 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE, key_rx);
614 SM_STATE(KEY_RX, KEY_RECEIVE)
616 SM_ENTRY(KEY_RX, KEY_RECEIVE, key_rx);
618 processKey();
619 sm->key_rx.rxKey = FALSE;
623 SM_STEP(KEY_RX)
625 if (sm->initialize || !sm->portEnabled) {
626 SM_ENTER(KEY_RX, NO_KEY_RECEIVE);
627 return;
630 switch (sm->key_rx.state) {
631 case KEY_RX_NO_KEY_RECEIVE:
632 if (sm->key_rx.rxKey)
633 SM_ENTER(KEY_RX, KEY_RECEIVE);
634 break;
635 case KEY_RX_KEY_RECEIVE:
636 if (sm->key_rx.rxKey)
637 SM_ENTER(KEY_RX, KEY_RECEIVE);
638 break;
644 /* Controlled Directions state machine */
646 SM_STATE(CTRL_DIR, FORCE_BOTH)
648 SM_ENTRY(CTRL_DIR, FORCE_BOTH, ctrl_dir);
649 sm->ctrl_dir.operControlledDirections = Both;
653 SM_STATE(CTRL_DIR, IN_OR_BOTH)
655 SM_ENTRY(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
656 sm->ctrl_dir.operControlledDirections =
657 sm->ctrl_dir.adminControlledDirections;
661 SM_STEP(CTRL_DIR)
663 if (sm->initialize) {
664 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
665 return;
668 switch (sm->ctrl_dir.state) {
669 case CTRL_DIR_FORCE_BOTH:
670 if (sm->portEnabled && sm->ctrl_dir.operEdge)
671 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
672 break;
673 case CTRL_DIR_IN_OR_BOTH:
674 if (sm->ctrl_dir.operControlledDirections !=
675 sm->ctrl_dir.adminControlledDirections)
676 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
677 if (!sm->portEnabled || !sm->ctrl_dir.operEdge)
678 SM_ENTER(CTRL_DIR, FORCE_BOTH);
679 break;
685 struct eapol_state_machine *
686 eapol_sm_alloc(hostapd *hapd, struct sta_info *sta)
688 struct eapol_state_machine *sm;
690 sm = (struct eapol_state_machine *) malloc(sizeof(*sm));
691 if (sm == NULL) {
692 printf("IEEE 802.1X port state allocation failed\n");
693 return NULL;
695 memset(sm, 0, sizeof(*sm));
696 sm->radius_identifier = -1;
697 memcpy(sm->addr, sta->addr, ETH_ALEN);
698 if (sta->flags & WLAN_STA_PREAUTH)
699 sm->flags |= EAPOL_SM_PREAUTH;
701 sm->hapd = hapd;
702 sm->sta = sta;
704 /* Set default values for state machine constants */
705 sm->auth_pae.state = AUTH_PAE_INITIALIZE;
706 sm->auth_pae.quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
707 sm->auth_pae.reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
709 sm->be_auth.state = BE_AUTH_INITIALIZE;
710 sm->be_auth.serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
712 sm->reauth_timer.state = REAUTH_TIMER_INITIALIZE;
713 sm->reauth_timer.reAuthPeriod = hapd->conf->eap_reauth_period;
714 sm->reauth_timer.reAuthEnabled = hapd->conf->eap_reauth_period > 0 ?
715 TRUE : FALSE;
717 sm->auth_key_tx.state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
719 sm->key_rx.state = KEY_RX_NO_KEY_RECEIVE;
721 sm->ctrl_dir.state = CTRL_DIR_IN_OR_BOTH;
723 sm->portEnabled = FALSE;
724 sm->portControl = Auto;
726 sm->keyAvailable = FALSE;
727 if (!hapd->conf->wpa &&
728 (hapd->default_wep_key || hapd->conf->individual_wep_key_len > 0))
729 sm->keyTxEnabled = TRUE;
730 else
731 sm->keyTxEnabled = FALSE;
732 if (hapd->conf->wpa)
733 sm->portValid = FALSE;
734 else
735 sm->portValid = TRUE;
737 if (hapd->conf->eap_server) {
738 struct eap_config eap_conf;
739 memset(&eap_conf, 0, sizeof(eap_conf));
740 eap_conf.ssl_ctx = hapd->ssl_ctx;
741 eap_conf.eap_sim_db_priv = hapd->eap_sim_db_priv;
742 sm->eap = eap_sm_init(sm, &eapol_cb, &eap_conf);
743 if (sm->eap == NULL) {
744 eapol_sm_free(sm);
745 return NULL;
749 eapol_sm_initialize(sm);
751 return sm;
755 void eapol_sm_free(struct eapol_state_machine *sm)
757 if (sm == NULL)
758 return;
760 eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
761 eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
762 if (sm->eap)
763 eap_sm_deinit(sm->eap);
764 free(sm);
768 static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr)
770 struct sta_info *sta;
771 sta = ap_get_sta(hapd, addr);
772 if (sta == NULL || sta->eapol_sm == NULL)
773 return 0;
774 return 1;
778 static void eapol_sm_step_run(struct eapol_state_machine *sm)
780 struct hostapd_data *hapd = sm->hapd;
781 u8 addr[ETH_ALEN];
782 int prev_auth_pae, prev_be_auth, prev_reauth_timer, prev_auth_key_tx,
783 prev_key_rx, prev_ctrl_dir;
784 int max_steps = 100;
786 memcpy(addr, sm->sta->addr, ETH_ALEN);
789 * Allow EAPOL state machines to run as long as there are state
790 * changes, but exit and return here through event loop if more than
791 * 100 steps is needed as a precaution against infinite loops inside
792 * eloop callback.
794 restart:
795 prev_auth_pae = sm->auth_pae.state;
796 prev_be_auth = sm->be_auth.state;
797 prev_reauth_timer = sm->reauth_timer.state;
798 prev_auth_key_tx = sm->auth_key_tx.state;
799 prev_key_rx = sm->key_rx.state;
800 prev_ctrl_dir = sm->ctrl_dir.state;
802 SM_STEP_RUN(AUTH_PAE);
803 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
804 SM_STEP_RUN(BE_AUTH);
805 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
806 SM_STEP_RUN(REAUTH_TIMER);
807 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
808 SM_STEP_RUN(AUTH_KEY_TX);
809 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
810 SM_STEP_RUN(KEY_RX);
811 if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
812 SM_STEP_RUN(CTRL_DIR);
814 if (prev_auth_pae != sm->auth_pae.state ||
815 prev_be_auth != sm->be_auth.state ||
816 prev_reauth_timer != sm->reauth_timer.state ||
817 prev_auth_key_tx != sm->auth_key_tx.state ||
818 prev_key_rx != sm->key_rx.state ||
819 prev_ctrl_dir != sm->ctrl_dir.state) {
820 if (--max_steps > 0)
821 goto restart;
822 /* Re-run from eloop timeout */
823 eapol_sm_step(sm);
824 return;
827 if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) {
828 if (eap_sm_step(sm->eap)) {
829 if (--max_steps > 0)
830 goto restart;
831 /* Re-run from eloop timeout */
832 eapol_sm_step(sm);
833 return;
837 if (eapol_sm_sta_entry_alive(hapd, addr))
838 wpa_sm_notify(sm->hapd, sm->sta);
842 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
844 struct eapol_state_machine *sm = eloop_ctx;
845 eapol_sm_step_run(sm);
849 void eapol_sm_step(struct eapol_state_machine *sm)
852 * Run eapol_sm_step_run from a registered timeout to make sure that
853 * other possible timeouts/events are processed and to avoid long
854 * function call chains.
857 eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
861 void eapol_sm_initialize(struct eapol_state_machine *sm)
863 sm->initializing = TRUE;
864 /* Initialize the state machines by asserting initialize and then
865 * deasserting it after one step */
866 sm->initialize = TRUE;
867 eapol_sm_step_run(sm);
868 sm->initialize = FALSE;
869 eapol_sm_step_run(sm);
870 sm->initializing = FALSE;
872 /* Start one second tick for port timers state machine */
873 eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
874 eloop_register_timeout(1, 0, eapol_port_timers_tick, sm->hapd, sm);
878 #ifdef HOSTAPD_DUMP_STATE
879 static inline const char * port_type_txt(PortTypes pt)
881 switch (pt) {
882 case ForceUnauthorized: return "ForceUnauthorized";
883 case ForceAuthorized: return "ForceAuthorized";
884 case Auto: return "Auto";
885 default: return "Unknown";
890 static inline const char * port_state_txt(PortState ps)
892 switch (ps) {
893 case Unauthorized: return "Unauthorized";
894 case Authorized: return "Authorized";
895 default: return "Unknown";
900 static inline const char * ctrl_dir_txt(ControlledDirection dir)
902 switch (dir) {
903 case Both: return "Both";
904 case In: return "In";
905 default: return "Unknown";
910 static inline const char * auth_pae_state_txt(int s)
912 switch (s) {
913 case AUTH_PAE_INITIALIZE: return "INITIALIZE";
914 case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
915 case AUTH_PAE_CONNECTING: return "CONNECTING";
916 case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
917 case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
918 case AUTH_PAE_ABORTING: return "ABORTING";
919 case AUTH_PAE_HELD: return "HELD";
920 case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
921 case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
922 case AUTH_PAE_RESTART: return "RESTART";
923 default: return "Unknown";
928 static inline const char * be_auth_state_txt(int s)
930 switch (s) {
931 case BE_AUTH_REQUEST: return "REQUEST";
932 case BE_AUTH_RESPONSE: return "RESPONSE";
933 case BE_AUTH_SUCCESS: return "SUCCESS";
934 case BE_AUTH_FAIL: return "FAIL";
935 case BE_AUTH_TIMEOUT: return "TIMEOUT";
936 case BE_AUTH_IDLE: return "IDLE";
937 case BE_AUTH_INITIALIZE: return "INITIALIZE";
938 case BE_AUTH_IGNORE: return "IGNORE";
939 default: return "Unknown";
944 static inline const char * reauth_timer_state_txt(int s)
946 switch (s) {
947 case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
948 case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
949 default: return "Unknown";
954 static inline const char * auth_key_tx_state_txt(int s)
956 switch (s) {
957 case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
958 case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
959 default: return "Unknown";
964 static inline const char * key_rx_state_txt(int s)
966 switch (s) {
967 case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
968 case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
969 default: return "Unknown";
974 static inline const char * ctrl_dir_state_txt(int s)
976 switch (s) {
977 case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
978 case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
979 default: return "Unknown";
984 void eapol_sm_dump_state(FILE *f, const char *prefix,
985 struct eapol_state_machine *sm)
987 fprintf(f, "%sEAPOL state machine:\n", prefix);
988 fprintf(f, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
989 sm->aWhile, sm->quietWhile, sm->reAuthWhen);
990 #define _SB(b) ((b) ? "TRUE" : "FALSE")
991 fprintf(f,
992 "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
993 "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
994 "%s eapSuccess=%s eapTimeout=%s initialize=%s "
995 "keyAvailable=%s\n"
996 "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
997 "%s portEnabled=%s portValid=%s reAuthenticate=%s\n",
998 prefix, _SB(sm->authAbort), _SB(sm->authFail),
999 port_state_txt(sm->authPortStatus), _SB(sm->authStart),
1000 prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
1001 _SB(sm->eapFail), _SB(sm->eapolEap),
1002 prefix, _SB(sm->eapSuccess), _SB(sm->eapTimeout),
1003 _SB(sm->initialize), _SB(sm->keyAvailable),
1004 prefix, _SB(sm->keyDone), _SB(sm->keyRun),
1005 _SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
1006 prefix, _SB(sm->portEnabled), _SB(sm->portValid),
1007 _SB(sm->reAuthenticate));
1009 fprintf(f, "%s Authenticator PAE:\n"
1010 "%s state=%s\n"
1011 "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
1012 "%s portMode=%s reAuthCount=%d\n"
1013 "%s quietPeriod=%d reAuthMax=%d\n"
1014 "%s authEntersConnecting=%d\n"
1015 "%s authEapLogoffsWhileConnecting=%d\n"
1016 "%s authEntersAuthenticating=%d\n"
1017 "%s authAuthSuccessesWhileAuthenticating=%d\n"
1018 "%s authAuthTimeoutsWhileAuthenticating=%d\n"
1019 "%s authAuthFailWhileAuthenticating=%d\n"
1020 "%s authAuthEapStartsWhileAuthenticating=%d\n"
1021 "%s authAuthEapLogoffWhileAuthenticating=%d\n"
1022 "%s authAuthReauthsWhileAuthenticated=%d\n"
1023 "%s authAuthEapStartsWhileAuthenticated=%d\n"
1024 "%s authAuthEapLogoffWhileAuthenticated=%d\n",
1025 prefix, prefix, auth_pae_state_txt(sm->auth_pae.state), prefix,
1026 _SB(sm->auth_pae.eapolLogoff), _SB(sm->auth_pae.eapolStart),
1027 _SB(sm->auth_pae.eapRestart), prefix,
1028 port_type_txt(sm->auth_pae.portMode), sm->auth_pae.reAuthCount,
1029 prefix, sm->auth_pae.quietPeriod, sm->auth_pae.reAuthMax,
1030 prefix, sm->auth_pae.authEntersConnecting,
1031 prefix, sm->auth_pae.authEapLogoffsWhileConnecting,
1032 prefix, sm->auth_pae.authEntersAuthenticating,
1033 prefix, sm->auth_pae.authAuthSuccessesWhileAuthenticating,
1034 prefix, sm->auth_pae.authAuthTimeoutsWhileAuthenticating,
1035 prefix, sm->auth_pae.authAuthFailWhileAuthenticating,
1036 prefix, sm->auth_pae.authAuthEapStartsWhileAuthenticating,
1037 prefix, sm->auth_pae.authAuthEapLogoffWhileAuthenticating,
1038 prefix, sm->auth_pae.authAuthReauthsWhileAuthenticated,
1039 prefix, sm->auth_pae.authAuthEapStartsWhileAuthenticated,
1040 prefix, sm->auth_pae.authAuthEapLogoffWhileAuthenticated);
1042 fprintf(f, "%s Backend Authentication:\n"
1043 "%s state=%s\n"
1044 "%s eapNoReq=%s eapReq=%s eapResp=%s\n"
1045 "%s serverTimeout=%d\n"
1046 "%s backendResponses=%d\n"
1047 "%s backendAccessChallenges=%d\n"
1048 "%s backendOtherRequestsToSupplicant=%d\n"
1049 "%s backendAuthSuccesses=%d\n"
1050 "%s backendAuthFails=%d\n",
1051 prefix, prefix,
1052 be_auth_state_txt(sm->be_auth.state),
1053 prefix, _SB(sm->be_auth.eapNoReq), _SB(sm->be_auth.eapReq),
1054 _SB(sm->be_auth.eapResp),
1055 prefix, sm->be_auth.serverTimeout,
1056 prefix, sm->be_auth.backendResponses,
1057 prefix, sm->be_auth.backendAccessChallenges,
1058 prefix, sm->be_auth.backendOtherRequestsToSupplicant,
1059 prefix, sm->be_auth.backendAuthSuccesses,
1060 prefix, sm->be_auth.backendAuthFails);
1062 fprintf(f, "%s Reauthentication Timer:\n"
1063 "%s state=%s\n"
1064 "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
1065 reauth_timer_state_txt(sm->reauth_timer.state), prefix,
1066 sm->reauth_timer.reAuthPeriod,
1067 _SB(sm->reauth_timer.reAuthEnabled));
1069 fprintf(f, "%s Authenticator Key Transmit:\n"
1070 "%s state=%s\n", prefix, prefix,
1071 auth_key_tx_state_txt(sm->auth_key_tx.state));
1073 fprintf(f, "%s Key Receive:\n"
1074 "%s state=%s\n"
1075 "%s rxKey=%s\n", prefix, prefix,
1076 key_rx_state_txt(sm->key_rx.state),
1077 prefix, _SB(sm->key_rx.rxKey));
1079 fprintf(f, "%s Controlled Directions:\n"
1080 "%s state=%s\n"
1081 "%s adminControlledDirections=%s "
1082 "operControlledDirections=%s\n"
1083 "%s operEdge=%s\n", prefix, prefix,
1084 ctrl_dir_state_txt(sm->ctrl_dir.state),
1085 prefix, ctrl_dir_txt(sm->ctrl_dir.adminControlledDirections),
1086 ctrl_dir_txt(sm->ctrl_dir.operControlledDirections),
1087 prefix, _SB(sm->ctrl_dir.operEdge));
1088 #undef _SB
1090 #endif /* HOSTAPD_DUMP_STATE */
1093 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1095 struct eapol_state_machine *sm = ctx;
1096 if (sm == NULL)
1097 return FALSE;
1098 switch (variable) {
1099 case EAPOL_eapSuccess:
1100 return sm->eapSuccess;
1101 case EAPOL_eapRestart:
1102 return sm->auth_pae.eapRestart;
1103 case EAPOL_eapFail:
1104 return sm->eapFail;
1105 case EAPOL_eapResp:
1106 return sm->be_auth.eapResp;
1107 case EAPOL_eapReq:
1108 return sm->be_auth.eapReq;
1109 case EAPOL_eapNoReq:
1110 return sm->be_auth.eapNoReq;
1111 case EAPOL_portEnabled:
1112 return sm->portEnabled;
1113 case EAPOL_eapTimeout:
1114 return sm->eapTimeout;
1116 return FALSE;
1120 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1121 Boolean value)
1123 struct eapol_state_machine *sm = ctx;
1124 if (sm == NULL)
1125 return;
1126 switch (variable) {
1127 case EAPOL_eapSuccess:
1128 sm->eapSuccess = value;
1129 break;
1130 case EAPOL_eapRestart:
1131 sm->auth_pae.eapRestart = value;
1132 break;
1133 case EAPOL_eapFail:
1134 sm->eapFail = value;
1135 break;
1136 case EAPOL_eapResp:
1137 sm->be_auth.eapResp = value;
1138 break;
1139 case EAPOL_eapReq:
1140 sm->be_auth.eapReq = value;
1141 break;
1142 case EAPOL_eapNoReq:
1143 sm->be_auth.eapNoReq = value;
1144 break;
1145 case EAPOL_portEnabled:
1146 sm->portEnabled = value;
1147 break;
1148 case EAPOL_eapTimeout:
1149 sm->eapTimeout = value;
1150 break;
1155 static void eapol_sm_set_eapReqData(void *ctx, const u8 *eapReqData,
1156 size_t eapReqDataLen)
1158 struct eapol_state_machine *sm = ctx;
1159 if (sm == NULL)
1160 return;
1162 free(sm->last_eap_radius);
1163 sm->last_eap_radius = malloc(eapReqDataLen);
1164 if (sm->last_eap_radius == NULL)
1165 return;
1166 memcpy(sm->last_eap_radius, eapReqData, eapReqDataLen);
1167 sm->last_eap_radius_len = eapReqDataLen;
1171 static void eapol_sm_set_eapKeyData(void *ctx, const u8 *eapKeyData,
1172 size_t eapKeyDataLen)
1174 struct eapol_state_machine *sm = ctx;
1175 struct hostapd_data *hapd;
1177 if (sm == NULL)
1178 return;
1180 hapd = sm->hapd;
1182 if (eapKeyData && eapKeyDataLen >= 64) {
1183 free(sm->eapol_key_sign);
1184 free(sm->eapol_key_crypt);
1185 sm->eapol_key_crypt = malloc(32);
1186 if (sm->eapol_key_crypt) {
1187 memcpy(sm->eapol_key_crypt, eapKeyData, 32);
1188 sm->eapol_key_crypt_len = 32;
1190 sm->eapol_key_sign = malloc(32);
1191 if (sm->eapol_key_sign) {
1192 memcpy(sm->eapol_key_sign, eapKeyData + 32, 32);
1193 sm->eapol_key_sign_len = 32;
1195 if (hapd->default_wep_key ||
1196 hapd->conf->individual_wep_key_len > 0 ||
1197 hapd->conf->wpa)
1198 sm->keyAvailable = TRUE;
1199 } else {
1200 free(sm->eapol_key_sign);
1201 free(sm->eapol_key_crypt);
1202 sm->eapol_key_sign = NULL;
1203 sm->eapol_key_crypt = NULL;
1204 sm->eapol_key_sign_len = 0;
1205 sm->eapol_key_crypt_len = 0;
1206 sm->keyAvailable = FALSE;
1211 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
1212 size_t identity_len, int phase2,
1213 struct eap_user *user)
1215 struct eapol_state_machine *sm = ctx;
1216 const struct hostapd_eap_user *eap_user;
1218 eap_user = hostapd_get_eap_user(sm->hapd->conf, identity,
1219 identity_len, phase2);
1220 if (eap_user == NULL)
1221 return -1;
1223 memset(user, 0, sizeof(*user));
1224 user->phase2 = phase2;
1225 memcpy(user->methods, eap_user->methods,
1226 EAP_USER_MAX_METHODS > EAP_MAX_METHODS ?
1227 EAP_USER_MAX_METHODS : EAP_MAX_METHODS);
1229 if (eap_user->password) {
1230 user->password = malloc(eap_user->password_len);
1231 if (user->password == NULL)
1232 return -1;
1233 memcpy(user->password, eap_user->password,
1234 eap_user->password_len);
1235 user->password_len = eap_user->password_len;
1237 user->force_version = eap_user->force_version;
1239 return 0;
1243 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
1245 struct eapol_state_machine *sm = ctx;
1246 *len = sm->hapd->conf->eap_req_id_text_len;
1247 return sm->hapd->conf->eap_req_id_text;
1251 static struct eapol_callbacks eapol_cb =
1253 .get_bool = eapol_sm_get_bool,
1254 .set_bool = eapol_sm_set_bool,
1255 .set_eapReqData = eapol_sm_set_eapReqData,
1256 .set_eapKeyData = eapol_sm_set_eapKeyData,
1257 .get_eap_user = eapol_sm_get_eap_user,
1258 .get_eap_req_id_text = eapol_sm_get_eap_req_id_text,