]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/hostapd/eapol_sm.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / hostapd / eapol_sm.c
1 /*
2  * hostapd / IEEE 802.1X Authenticator - EAPOL state machine
3  * Copyright (c) 2002-2005, 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  * $FreeBSD$
15  */
16
17 #include "includes.h"
18
19 #include "hostapd.h"
20 #include "ieee802_1x.h"
21 #include "eapol_sm.h"
22 #include "eloop.h"
23 #include "wpa.h"
24 #include "preauth.h"
25 #include "sta_info.h"
26 #include "eap.h"
27 #include "state_machine.h"
28
29 #define STATE_MACHINE_DATA struct eapol_state_machine
30 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
31 #define STATE_MACHINE_ADDR sm->addr
32
33 static struct eapol_callbacks eapol_cb;
34
35 /* EAPOL state machines are described in IEEE Std 802.1X-REV-d11, Chap. 8.2 */
36
37 #define setPortAuthorized() \
38 ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 1)
39 #define setPortUnauthorized() \
40 ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 0)
41
42 /* procedures */
43 #define txCannedFail() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 0)
44 #define txCannedSuccess() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 1)
45 #define txReq() ieee802_1x_tx_req(sm->hapd, sm->sta)
46 #define sendRespToServer() ieee802_1x_send_resp_to_server(sm->hapd, sm->sta)
47 #define abortAuth() ieee802_1x_abort_auth(sm->hapd, sm->sta)
48 #define txKey() ieee802_1x_tx_key(sm->hapd, sm->sta)
49 #define processKey() do { } while (0)
50
51
52 static void eapol_sm_step_run(struct eapol_state_machine *sm);
53 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
54
55
56 /* Port Timers state machine - implemented as a function that will be called
57  * once a second as a registered event loop timeout */
58
59 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
60 {
61         struct eapol_state_machine *state = timeout_ctx;
62
63         if (state->aWhile > 0) {
64                 state->aWhile--;
65                 if (state->aWhile == 0) {
66                         wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
67                                    " - aWhile --> 0",
68                                    MAC2STR(state->addr));
69                 }
70         }
71
72         if (state->quietWhile > 0) {
73                 state->quietWhile--;
74                 if (state->quietWhile == 0) {
75                         wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
76                                    " - quietWhile --> 0",
77                                    MAC2STR(state->addr));
78                 }
79         }
80
81         if (state->reAuthWhen > 0) {
82                 state->reAuthWhen--;
83                 if (state->reAuthWhen == 0) {
84                         wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
85                                    " - reAuthWhen --> 0",
86                                    MAC2STR(state->addr));
87                 }
88         }
89
90         eapol_sm_step_run(state);
91
92         eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
93 }
94
95
96
97 /* Authenticator PAE state machine */
98
99 SM_STATE(AUTH_PAE, INITIALIZE)
100 {
101         SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
102         sm->portMode = Auto;
103
104         sm->currentId = 255;
105 }
106
107
108 SM_STATE(AUTH_PAE, DISCONNECTED)
109 {
110         int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
111
112         if (sm->eapolLogoff) {
113                 if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
114                         sm->authEapLogoffsWhileConnecting++;
115                 else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)
116                         sm->authAuthEapLogoffWhileAuthenticated++;
117         }
118
119         SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
120
121         sm->authPortStatus = Unauthorized;
122         setPortUnauthorized();
123         sm->reAuthCount = 0;
124         sm->eapolLogoff = FALSE;
125         if (!from_initialize) {
126                 if (sm->flags & EAPOL_SM_PREAUTH)
127                         rsn_preauth_finished(sm->hapd, sm->sta, 0);
128                 else
129                         ieee802_1x_finished(sm->hapd, sm->sta, 0);
130         }
131 }
132
133
134 SM_STATE(AUTH_PAE, RESTART)
135 {
136         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
137                 if (sm->reAuthenticate)
138                         sm->authAuthReauthsWhileAuthenticated++;
139                 if (sm->eapolStart)
140                         sm->authAuthEapStartsWhileAuthenticated++;
141                 if (sm->eapolLogoff)
142                         sm->authAuthEapLogoffWhileAuthenticated++;
143         }
144
145         SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
146
147         sm->eapRestart = TRUE;
148         ieee802_1x_request_identity(sm->hapd, sm->sta);
149 }
150
151
152 SM_STATE(AUTH_PAE, CONNECTING)
153 {
154         if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
155                 sm->authEntersConnecting++;
156
157         SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
158
159         sm->reAuthenticate = FALSE;
160         sm->reAuthCount++;
161 }
162
163
164 SM_STATE(AUTH_PAE, HELD)
165 {
166         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
167                 sm->authAuthFailWhileAuthenticating++;
168
169         SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
170
171         sm->authPortStatus = Unauthorized;
172         setPortUnauthorized();
173         sm->quietWhile = sm->quietPeriod;
174         sm->eapolLogoff = FALSE;
175
176         hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
177                        HOSTAPD_LEVEL_WARNING, "authentication failed - "
178                        "EAP type: %d (%s)",
179                        sm->eap_type_authsrv,
180                        eap_type_text(sm->eap_type_authsrv));
181         if (sm->eap_type_authsrv != sm->eap_type_supp) {
182                 hostapd_logger(sm->hapd, sm->addr,
183                                HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_INFO,
184                                "Supplicant used different EAP type: %d (%s)",
185                                sm->eap_type_supp,
186                                eap_type_text(sm->eap_type_supp));
187         }
188         if (sm->flags & EAPOL_SM_PREAUTH)
189                 rsn_preauth_finished(sm->hapd, sm->sta, 0);
190         else
191                 ieee802_1x_finished(sm->hapd, sm->sta, 0);
192 }
193
194
195 SM_STATE(AUTH_PAE, AUTHENTICATED)
196 {
197         char *extra = "";
198
199         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
200                 sm->authAuthSuccessesWhileAuthenticating++;
201                                                         
202         SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
203
204         sm->authPortStatus = Authorized;
205         setPortAuthorized();
206         sm->reAuthCount = 0;
207         if (sm->flags & EAPOL_SM_PREAUTH)
208                 extra = " (pre-authentication)";
209         else if (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm))
210                 extra = " (PMKSA cache)";
211         hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
212                        HOSTAPD_LEVEL_INFO, "authenticated - EAP type: %d (%s)"
213                        "%s", sm->eap_type_authsrv,
214                        eap_type_text(sm->eap_type_authsrv), extra);
215         if (sm->flags & EAPOL_SM_PREAUTH)
216                 rsn_preauth_finished(sm->hapd, sm->sta, 1);
217         else
218                 ieee802_1x_finished(sm->hapd, sm->sta, 1);
219 }
220
221
222 SM_STATE(AUTH_PAE, AUTHENTICATING)
223 {
224         if (sm->auth_pae_state == AUTH_PAE_CONNECTING && sm->rx_identity) {
225                 sm->authEntersAuthenticating++;
226                 sm->rx_identity = FALSE;
227         }
228
229         SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
230
231         sm->eapolStart = FALSE;
232         sm->authSuccess = FALSE;
233         sm->authFail = FALSE;
234         sm->authTimeout = FALSE;
235         sm->authStart = TRUE;
236         sm->keyRun = FALSE;
237         sm->keyDone = FALSE;
238 }
239
240
241 SM_STATE(AUTH_PAE, ABORTING)
242 {
243         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
244                 if (sm->authTimeout)
245                         sm->authAuthTimeoutsWhileAuthenticating++;
246                 if (sm->eapolStart)
247                         sm->authAuthEapStartsWhileAuthenticating++;
248                 if (sm->eapolLogoff)
249                         sm->authAuthEapLogoffWhileAuthenticating++;
250         }
251
252         SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
253
254         sm->authAbort = TRUE;
255         sm->keyRun = FALSE;
256         sm->keyDone = FALSE;
257 }
258
259
260 SM_STATE(AUTH_PAE, FORCE_AUTH)
261 {
262         SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
263
264         sm->authPortStatus = Authorized;
265         setPortAuthorized();
266         sm->portMode = ForceAuthorized;
267         sm->eapolStart = FALSE;
268         txCannedSuccess();
269 }
270
271
272 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
273 {
274         SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
275
276         sm->authPortStatus = Unauthorized;
277         setPortUnauthorized();
278         sm->portMode = ForceUnauthorized;
279         sm->eapolStart = FALSE;
280         txCannedFail();
281 }
282
283
284 SM_STEP(AUTH_PAE)
285 {
286         if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
287             sm->initialize || !sm->portEnabled)
288                 SM_ENTER(AUTH_PAE, INITIALIZE);
289         else if (sm->portControl == ForceAuthorized &&
290                  sm->portMode != sm->portControl &&
291                  !(sm->initialize || !sm->portEnabled))
292                 SM_ENTER(AUTH_PAE, FORCE_AUTH);
293         else if (sm->portControl == ForceUnauthorized &&
294                  sm->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->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->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
315                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
316                         else if ((sm->eapReq &&
317                                   sm->reAuthCount <= sm->reAuthMax) ||
318                                  sm->eapSuccess || sm->eapFail)
319                                 SM_ENTER(AUTH_PAE, AUTHENTICATING);
320                         break;
321                 case AUTH_PAE_AUTHENTICATED:
322                         if (sm->eapolStart || sm->reAuthenticate)
323                                 SM_ENTER(AUTH_PAE, RESTART);
324                         else if (sm->eapolLogoff || !sm->portValid)
325                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
326                         break;
327                 case AUTH_PAE_AUTHENTICATING:
328                         if (sm->authSuccess && sm->portValid)
329                                 SM_ENTER(AUTH_PAE, AUTHENTICATED);
330                         else if (sm->authFail ||
331                                  (sm->keyDone && !sm->portValid))
332                                 SM_ENTER(AUTH_PAE, HELD);
333                         else if (sm->eapolStart || sm->eapolLogoff ||
334                                  sm->authTimeout)
335                                 SM_ENTER(AUTH_PAE, ABORTING);
336                         break;
337                 case AUTH_PAE_ABORTING:
338                         if (sm->eapolLogoff && !sm->authAbort)
339                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
340                         else if (!sm->eapolLogoff && !sm->authAbort)
341                                 SM_ENTER(AUTH_PAE, RESTART);
342                         break;
343                 case AUTH_PAE_FORCE_AUTH:
344                         if (sm->eapolStart)
345                                 SM_ENTER(AUTH_PAE, FORCE_AUTH);
346                         break;
347                 case AUTH_PAE_FORCE_UNAUTH:
348                         if (sm->eapolStart)
349                                 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
350                         break;
351                 }
352         }
353 }
354
355
356
357 /* Backend Authentication state machine */
358
359 SM_STATE(BE_AUTH, INITIALIZE)
360 {
361         SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
362
363         abortAuth();
364         sm->eapNoReq = FALSE;
365         sm->authAbort = FALSE;
366 }
367
368
369 SM_STATE(BE_AUTH, REQUEST)
370 {
371         SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
372
373         txReq();
374         sm->eapReq = FALSE;
375         sm->backendOtherRequestsToSupplicant++;
376
377         /*
378          * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
379          * it looks like this would be logical thing to do there since the old
380          * EAP response would not be valid anymore after the new EAP request
381          * was sent out.
382          *
383          * A race condition has been reported, in which hostapd ended up
384          * sending out EAP-Response/Identity as a response to the first
385          * EAP-Request from the main EAP method. This can be avoided by
386          * clearing eapolEap here.
387          */
388         sm->eapolEap = FALSE;
389 }
390
391
392 SM_STATE(BE_AUTH, RESPONSE)
393 {
394         SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
395
396         sm->authTimeout = FALSE;
397         sm->eapolEap = FALSE;
398         sm->eapNoReq = FALSE;
399         sm->aWhile = sm->serverTimeout;
400         sm->eapResp = TRUE;
401         sendRespToServer();
402         sm->backendResponses++;
403 }
404
405
406 SM_STATE(BE_AUTH, SUCCESS)
407 {
408         SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
409
410         txReq();
411         sm->authSuccess = TRUE;
412         sm->keyRun = TRUE;
413 }
414
415
416 SM_STATE(BE_AUTH, FAIL)
417 {
418         SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
419
420         /* Note: IEEE 802.1X-REV-d11 has unconditional txReq() here.
421          * txCannelFail() is used as a workaround for the case where
422          * authentication server does not include EAP-Message with
423          * Access-Reject. */
424         if (sm->last_eap_radius == NULL)
425                 txCannedFail();
426         else
427                 txReq();
428         sm->authFail = TRUE;
429 }
430
431
432 SM_STATE(BE_AUTH, TIMEOUT)
433 {
434         SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
435
436         sm->authTimeout = TRUE;
437 }
438
439
440 SM_STATE(BE_AUTH, IDLE)
441 {
442         SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
443
444         sm->authStart = FALSE;
445 }
446
447
448 SM_STATE(BE_AUTH, IGNORE)
449 {
450         SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
451
452         sm->eapNoReq = FALSE;
453 }
454
455
456 SM_STEP(BE_AUTH)
457 {
458         if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
459                 SM_ENTER(BE_AUTH, INITIALIZE);
460                 return;
461         }
462
463         switch (sm->be_auth_state) {
464         case BE_AUTH_INITIALIZE:
465                 SM_ENTER(BE_AUTH, IDLE);
466                 break;
467         case BE_AUTH_REQUEST:
468                 if (sm->eapolEap)
469                         SM_ENTER(BE_AUTH, RESPONSE);
470                 else if (sm->eapReq)
471                         SM_ENTER(BE_AUTH, REQUEST);
472                 else if (sm->eapTimeout)
473                         SM_ENTER(BE_AUTH, TIMEOUT);
474                 break;
475         case BE_AUTH_RESPONSE:
476                 if (sm->eapNoReq)
477                         SM_ENTER(BE_AUTH, IGNORE);
478                 if (sm->eapReq) {
479                         sm->backendAccessChallenges++;
480                         SM_ENTER(BE_AUTH, REQUEST);
481                 } else if (sm->aWhile == 0)
482                         SM_ENTER(BE_AUTH, TIMEOUT);
483                 else if (sm->eapFail) {
484                         sm->backendAuthFails++;
485                         SM_ENTER(BE_AUTH, FAIL);
486                 } else if (sm->eapSuccess) {
487                         sm->backendAuthSuccesses++;
488                         SM_ENTER(BE_AUTH, SUCCESS);
489                 }
490                 break;
491         case BE_AUTH_SUCCESS:
492                 SM_ENTER(BE_AUTH, IDLE);
493                 break;
494         case BE_AUTH_FAIL:
495                 SM_ENTER(BE_AUTH, IDLE);
496                 break;
497         case BE_AUTH_TIMEOUT:
498                 SM_ENTER(BE_AUTH, IDLE);
499                 break;
500         case BE_AUTH_IDLE:
501                 if (sm->eapFail && sm->authStart)
502                         SM_ENTER(BE_AUTH, FAIL);
503                 else if (sm->eapReq && sm->authStart)
504                         SM_ENTER(BE_AUTH, REQUEST);
505                 else if (sm->eapSuccess && sm->authStart)
506                         SM_ENTER(BE_AUTH, SUCCESS);
507                 break;
508         case BE_AUTH_IGNORE:
509                 if (sm->eapolEap)
510                         SM_ENTER(BE_AUTH, RESPONSE);
511                 else if (sm->eapReq)
512                         SM_ENTER(BE_AUTH, REQUEST);
513                 else if (sm->eapTimeout)
514                         SM_ENTER(BE_AUTH, TIMEOUT);
515                 break;
516         }
517 }
518
519
520
521 /* Reauthentication Timer state machine */
522
523 SM_STATE(REAUTH_TIMER, INITIALIZE)
524 {
525         SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
526
527         sm->reAuthWhen = sm->reAuthPeriod;
528 }
529
530
531 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
532 {
533         SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
534
535         sm->reAuthenticate = TRUE;
536         wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL);
537 }
538
539
540 SM_STEP(REAUTH_TIMER)
541 {
542         if (sm->portControl != Auto || sm->initialize ||
543             sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
544                 SM_ENTER(REAUTH_TIMER, INITIALIZE);
545                 return;
546         }
547
548         switch (sm->reauth_timer_state) {
549         case REAUTH_TIMER_INITIALIZE:
550                 if (sm->reAuthWhen == 0)
551                         SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
552                 break;
553         case REAUTH_TIMER_REAUTHENTICATE:
554                 SM_ENTER(REAUTH_TIMER, INITIALIZE);
555                 break;
556         }
557 }
558
559
560
561 /* Authenticator Key Transmit state machine */
562
563 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
564 {
565         SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
566 }
567
568
569 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
570 {
571         SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
572
573         txKey();
574         sm->keyAvailable = FALSE;
575         sm->keyDone = TRUE;
576 }
577
578
579 SM_STEP(AUTH_KEY_TX)
580 {
581         if (sm->initialize || sm->portControl != Auto) {
582                 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
583                 return;
584         }
585
586         switch (sm->auth_key_tx_state) {
587         case AUTH_KEY_TX_NO_KEY_TRANSMIT:
588                 if (sm->keyTxEnabled && sm->keyAvailable && sm->keyRun &&
589                     !wpa_auth_sta_wpa_version(sm->sta->wpa_sm))
590                         SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
591                 break;
592         case AUTH_KEY_TX_KEY_TRANSMIT:
593                 if (!sm->keyTxEnabled || !sm->keyRun)
594                         SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
595                 else if (sm->keyAvailable)
596                         SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
597                 break;
598         }
599 }
600
601
602
603 /* Key Receive state machine */
604
605 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
606 {
607         SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
608 }
609
610
611 SM_STATE(KEY_RX, KEY_RECEIVE)
612 {
613         SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
614
615         processKey();
616         sm->rxKey = FALSE;
617 }
618
619
620 SM_STEP(KEY_RX)
621 {
622         if (sm->initialize || !sm->portEnabled) {
623                 SM_ENTER(KEY_RX, NO_KEY_RECEIVE);
624                 return;
625         }
626
627         switch (sm->key_rx_state) {
628         case KEY_RX_NO_KEY_RECEIVE:
629                 if (sm->rxKey)
630                         SM_ENTER(KEY_RX, KEY_RECEIVE);
631                 break;
632         case KEY_RX_KEY_RECEIVE:
633                 if (sm->rxKey)
634                         SM_ENTER(KEY_RX, KEY_RECEIVE);
635                 break;
636         }
637 }
638
639
640
641 /* Controlled Directions state machine */
642
643 SM_STATE(CTRL_DIR, FORCE_BOTH)
644 {
645         SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
646         sm->operControlledDirections = Both;
647 }
648
649
650 SM_STATE(CTRL_DIR, IN_OR_BOTH)
651 {
652         SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
653         sm->operControlledDirections = sm->adminControlledDirections;
654 }
655
656
657 SM_STEP(CTRL_DIR)
658 {
659         if (sm->initialize) {
660                 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
661                 return;
662         }
663
664         switch (sm->ctrl_dir_state) {
665         case CTRL_DIR_FORCE_BOTH:
666                 if (sm->portEnabled && sm->operEdge)
667                         SM_ENTER(CTRL_DIR, IN_OR_BOTH);
668                 break;
669         case CTRL_DIR_IN_OR_BOTH:
670                 if (sm->operControlledDirections !=
671                     sm->adminControlledDirections)
672                         SM_ENTER(CTRL_DIR, IN_OR_BOTH);
673                 if (!sm->portEnabled || !sm->operEdge)
674                         SM_ENTER(CTRL_DIR, FORCE_BOTH);
675                 break;
676         }
677 }
678
679
680
681 struct eapol_state_machine *
682 eapol_sm_alloc(struct hostapd_data *hapd, struct sta_info *sta)
683 {
684         struct eapol_state_machine *sm;
685
686         sm = wpa_zalloc(sizeof(*sm));
687         if (sm == NULL) {
688                 printf("IEEE 802.1X port state allocation failed\n");
689                 return NULL;
690         }
691         sm->radius_identifier = -1;
692         memcpy(sm->addr, sta->addr, ETH_ALEN);
693         if (sta->flags & WLAN_STA_PREAUTH)
694                 sm->flags |= EAPOL_SM_PREAUTH;
695
696         sm->hapd = hapd;
697         sm->sta = sta;
698
699         /* Set default values for state machine constants */
700         sm->auth_pae_state = AUTH_PAE_INITIALIZE;
701         sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
702         sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
703
704         sm->be_auth_state = BE_AUTH_INITIALIZE;
705         sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
706
707         sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
708         sm->reAuthPeriod = hapd->conf->eap_reauth_period;
709         sm->reAuthEnabled = hapd->conf->eap_reauth_period > 0 ? TRUE : FALSE;
710
711         sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
712
713         sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
714
715         sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
716
717         sm->portEnabled = FALSE;
718         sm->portControl = Auto;
719
720         sm->keyAvailable = FALSE;
721         if (!hapd->conf->wpa &&
722             (hapd->default_wep_key || hapd->conf->individual_wep_key_len > 0))
723                 sm->keyTxEnabled = TRUE;
724         else
725                 sm->keyTxEnabled = FALSE;
726         if (hapd->conf->wpa)
727                 sm->portValid = FALSE;
728         else
729                 sm->portValid = TRUE;
730
731         if (hapd->conf->eap_server) {
732                 struct eap_config eap_conf;
733                 memset(&eap_conf, 0, sizeof(eap_conf));
734                 eap_conf.ssl_ctx = hapd->ssl_ctx;
735                 eap_conf.eap_sim_db_priv = hapd->eap_sim_db_priv;
736                 sm->eap = eap_sm_init(sm, &eapol_cb, &eap_conf);
737                 if (sm->eap == NULL) {
738                         eapol_sm_free(sm);
739                         return NULL;
740                 }
741         }
742
743         eapol_sm_initialize(sm);
744
745         return sm;
746 }
747
748
749 void eapol_sm_free(struct eapol_state_machine *sm)
750 {
751         if (sm == NULL)
752                 return;
753
754         eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
755         eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
756         if (sm->eap)
757                 eap_sm_deinit(sm->eap);
758         free(sm);
759 }
760
761
762 static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr)
763 {
764         struct sta_info *sta;
765         sta = ap_get_sta(hapd, addr);
766         if (sta == NULL || sta->eapol_sm == NULL)
767                 return 0;
768         return 1;
769 }
770
771
772 static void eapol_sm_step_run(struct eapol_state_machine *sm)
773 {
774         struct hostapd_data *hapd = sm->hapd;
775         u8 addr[ETH_ALEN];
776         unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
777                 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
778         int max_steps = 100;
779
780         memcpy(addr, sm->sta->addr, ETH_ALEN);
781
782         /*
783          * Allow EAPOL state machines to run as long as there are state
784          * changes, but exit and return here through event loop if more than
785          * 100 steps is needed as a precaution against infinite loops inside
786          * eloop callback.
787          */
788 restart:
789         prev_auth_pae = sm->auth_pae_state;
790         prev_be_auth = sm->be_auth_state;
791         prev_reauth_timer = sm->reauth_timer_state;
792         prev_auth_key_tx = sm->auth_key_tx_state;
793         prev_key_rx = sm->key_rx_state;
794         prev_ctrl_dir = sm->ctrl_dir_state;
795
796         SM_STEP_RUN(AUTH_PAE);
797         if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
798                 SM_STEP_RUN(BE_AUTH);
799         if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
800                 SM_STEP_RUN(REAUTH_TIMER);
801         if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
802                 SM_STEP_RUN(AUTH_KEY_TX);
803         if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
804                 SM_STEP_RUN(KEY_RX);
805         if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
806                 SM_STEP_RUN(CTRL_DIR);
807
808         if (prev_auth_pae != sm->auth_pae_state ||
809             prev_be_auth != sm->be_auth_state ||
810             prev_reauth_timer != sm->reauth_timer_state ||
811             prev_auth_key_tx != sm->auth_key_tx_state ||
812             prev_key_rx != sm->key_rx_state ||
813             prev_ctrl_dir != sm->ctrl_dir_state) {
814                 if (--max_steps > 0)
815                         goto restart;
816                 /* Re-run from eloop timeout */
817                 eapol_sm_step(sm);
818                 return;
819         }
820
821         if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) {
822                 if (eap_sm_step(sm->eap)) {
823                         if (--max_steps > 0)
824                                 goto restart;
825                         /* Re-run from eloop timeout */
826                         eapol_sm_step(sm);
827                         return;
828                 }
829         }
830
831         if (eapol_sm_sta_entry_alive(hapd, addr))
832                 wpa_auth_sm_notify(sm->sta->wpa_sm);
833 }
834
835
836 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
837 {
838         struct eapol_state_machine *sm = eloop_ctx;
839         eapol_sm_step_run(sm);
840 }
841
842
843 void eapol_sm_step(struct eapol_state_machine *sm)
844 {
845         /*
846          * Run eapol_sm_step_run from a registered timeout to make sure that
847          * other possible timeouts/events are processed and to avoid long
848          * function call chains.
849          */
850
851         eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
852 }
853
854
855 void eapol_sm_initialize(struct eapol_state_machine *sm)
856 {
857         sm->initializing = TRUE;
858         /* Initialize the state machines by asserting initialize and then
859          * deasserting it after one step */
860         sm->initialize = TRUE;
861         eapol_sm_step_run(sm);
862         sm->initialize = FALSE;
863         eapol_sm_step_run(sm);
864         sm->initializing = FALSE;
865
866         /* Start one second tick for port timers state machine */
867         eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
868         eloop_register_timeout(1, 0, eapol_port_timers_tick, sm->hapd, sm);
869 }
870
871
872 #ifdef HOSTAPD_DUMP_STATE
873 static inline const char * port_type_txt(PortTypes pt)
874 {
875         switch (pt) {
876         case ForceUnauthorized: return "ForceUnauthorized";
877         case ForceAuthorized: return "ForceAuthorized";
878         case Auto: return "Auto";
879         default: return "Unknown";
880         }
881 }
882
883
884 static inline const char * port_state_txt(PortState ps)
885 {
886         switch (ps) {
887         case Unauthorized: return "Unauthorized";
888         case Authorized: return "Authorized";
889         default: return "Unknown";
890         }
891 }
892
893
894 static inline const char * ctrl_dir_txt(ControlledDirection dir)
895 {
896         switch (dir) {
897         case Both: return "Both";
898         case In: return "In";
899         default: return "Unknown";
900         }
901 }
902
903
904 static inline const char * auth_pae_state_txt(int s)
905 {
906         switch (s) {
907         case AUTH_PAE_INITIALIZE: return "INITIALIZE";
908         case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
909         case AUTH_PAE_CONNECTING: return "CONNECTING";
910         case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
911         case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
912         case AUTH_PAE_ABORTING: return "ABORTING";
913         case AUTH_PAE_HELD: return "HELD";
914         case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
915         case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
916         case AUTH_PAE_RESTART: return "RESTART";
917         default: return "Unknown";
918         }
919 }
920
921
922 static inline const char * be_auth_state_txt(int s)
923 {
924         switch (s) {
925         case BE_AUTH_REQUEST: return "REQUEST";
926         case BE_AUTH_RESPONSE: return "RESPONSE";
927         case BE_AUTH_SUCCESS: return "SUCCESS";
928         case BE_AUTH_FAIL: return "FAIL";
929         case BE_AUTH_TIMEOUT: return "TIMEOUT";
930         case BE_AUTH_IDLE: return "IDLE";
931         case BE_AUTH_INITIALIZE: return "INITIALIZE";
932         case BE_AUTH_IGNORE: return "IGNORE";
933         default: return "Unknown";
934         }
935 }
936
937
938 static inline const char * reauth_timer_state_txt(int s)
939 {
940         switch (s) {
941         case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
942         case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
943         default: return "Unknown";
944         }
945 }
946
947
948 static inline const char * auth_key_tx_state_txt(int s)
949 {
950         switch (s) {
951         case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
952         case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
953         default: return "Unknown";
954         }
955 }
956
957
958 static inline const char * key_rx_state_txt(int s)
959 {
960         switch (s) {
961         case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
962         case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
963         default: return "Unknown";
964         }
965 }
966
967
968 static inline const char * ctrl_dir_state_txt(int s)
969 {
970         switch (s) {
971         case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
972         case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
973         default: return "Unknown";
974         }
975 }
976
977
978 void eapol_sm_dump_state(FILE *f, const char *prefix,
979                          struct eapol_state_machine *sm)
980 {
981         fprintf(f, "%sEAPOL state machine:\n", prefix);
982         fprintf(f, "%s  aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
983                 sm->aWhile, sm->quietWhile, sm->reAuthWhen);
984 #define _SB(b) ((b) ? "TRUE" : "FALSE")
985         fprintf(f,
986                 "%s  authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
987                 "%s  authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
988                 "%s  eapSuccess=%s eapTimeout=%s initialize=%s "
989                 "keyAvailable=%s\n"
990                 "%s  keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
991                 "%s  portEnabled=%s portValid=%s reAuthenticate=%s\n",
992                 prefix, _SB(sm->authAbort), _SB(sm->authFail),
993                 port_state_txt(sm->authPortStatus), _SB(sm->authStart),
994                 prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
995                 _SB(sm->eapFail), _SB(sm->eapolEap),
996                 prefix, _SB(sm->eapSuccess), _SB(sm->eapTimeout),
997                 _SB(sm->initialize), _SB(sm->keyAvailable),
998                 prefix, _SB(sm->keyDone), _SB(sm->keyRun),
999                 _SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
1000                 prefix, _SB(sm->portEnabled), _SB(sm->portValid),
1001                 _SB(sm->reAuthenticate));
1002
1003         fprintf(f, "%s  Authenticator PAE:\n"
1004                 "%s    state=%s\n"
1005                 "%s    eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
1006                 "%s    portMode=%s reAuthCount=%d\n"
1007                 "%s    quietPeriod=%d reAuthMax=%d\n"
1008                 "%s    authEntersConnecting=%d\n"
1009                 "%s    authEapLogoffsWhileConnecting=%d\n"
1010                 "%s    authEntersAuthenticating=%d\n"
1011                 "%s    authAuthSuccessesWhileAuthenticating=%d\n"
1012                 "%s    authAuthTimeoutsWhileAuthenticating=%d\n"
1013                 "%s    authAuthFailWhileAuthenticating=%d\n"
1014                 "%s    authAuthEapStartsWhileAuthenticating=%d\n"
1015                 "%s    authAuthEapLogoffWhileAuthenticating=%d\n"
1016                 "%s    authAuthReauthsWhileAuthenticated=%d\n"
1017                 "%s    authAuthEapStartsWhileAuthenticated=%d\n"
1018                 "%s    authAuthEapLogoffWhileAuthenticated=%d\n",
1019                 prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
1020                 _SB(sm->eapolLogoff), _SB(sm->eapolStart), _SB(sm->eapRestart),
1021                 prefix, port_type_txt(sm->portMode), sm->reAuthCount,
1022                 prefix, sm->quietPeriod, sm->reAuthMax,
1023                 prefix, sm->authEntersConnecting,
1024                 prefix, sm->authEapLogoffsWhileConnecting,
1025                 prefix, sm->authEntersAuthenticating,
1026                 prefix, sm->authAuthSuccessesWhileAuthenticating,
1027                 prefix, sm->authAuthTimeoutsWhileAuthenticating,
1028                 prefix, sm->authAuthFailWhileAuthenticating,
1029                 prefix, sm->authAuthEapStartsWhileAuthenticating,
1030                 prefix, sm->authAuthEapLogoffWhileAuthenticating,
1031                 prefix, sm->authAuthReauthsWhileAuthenticated,
1032                 prefix, sm->authAuthEapStartsWhileAuthenticated,
1033                 prefix, sm->authAuthEapLogoffWhileAuthenticated);
1034
1035         fprintf(f, "%s  Backend Authentication:\n"
1036                 "%s    state=%s\n"
1037                 "%s    eapNoReq=%s eapReq=%s eapResp=%s\n"
1038                 "%s    serverTimeout=%d\n"
1039                 "%s    backendResponses=%d\n"
1040                 "%s    backendAccessChallenges=%d\n"
1041                 "%s    backendOtherRequestsToSupplicant=%d\n"
1042                 "%s    backendAuthSuccesses=%d\n"
1043                 "%s    backendAuthFails=%d\n",
1044                 prefix, prefix,
1045                 be_auth_state_txt(sm->be_auth_state),
1046                 prefix, _SB(sm->eapNoReq), _SB(sm->eapReq), _SB(sm->eapResp),
1047                 prefix, sm->serverTimeout,
1048                 prefix, sm->backendResponses,
1049                 prefix, sm->backendAccessChallenges,
1050                 prefix, sm->backendOtherRequestsToSupplicant,
1051                 prefix, sm->backendAuthSuccesses,
1052                 prefix, sm->backendAuthFails);
1053
1054         fprintf(f, "%s  Reauthentication Timer:\n"
1055                 "%s    state=%s\n"
1056                 "%s    reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
1057                 reauth_timer_state_txt(sm->reauth_timer_state), prefix,
1058                 sm->reAuthPeriod, _SB(sm->reAuthEnabled));
1059
1060         fprintf(f, "%s  Authenticator Key Transmit:\n"
1061                 "%s    state=%s\n", prefix, prefix,
1062                 auth_key_tx_state_txt(sm->auth_key_tx_state));
1063
1064         fprintf(f, "%s  Key Receive:\n"
1065                 "%s    state=%s\n"
1066                 "%s    rxKey=%s\n", prefix, prefix,
1067                 key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
1068
1069         fprintf(f, "%s  Controlled Directions:\n"
1070                 "%s    state=%s\n"
1071                 "%s    adminControlledDirections=%s "
1072                 "operControlledDirections=%s\n"
1073                 "%s    operEdge=%s\n", prefix, prefix,
1074                 ctrl_dir_state_txt(sm->ctrl_dir_state),
1075                 prefix, ctrl_dir_txt(sm->adminControlledDirections),
1076                 ctrl_dir_txt(sm->operControlledDirections),
1077                 prefix, _SB(sm->operEdge));
1078 #undef _SB
1079 }
1080 #endif /* HOSTAPD_DUMP_STATE */
1081
1082
1083 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1084 {
1085         struct eapol_state_machine *sm = ctx;
1086         if (sm == NULL)
1087                 return FALSE;
1088         switch (variable) {
1089         case EAPOL_eapSuccess:
1090                 return sm->eapSuccess;
1091         case EAPOL_eapRestart:
1092                 return sm->eapRestart;
1093         case EAPOL_eapFail:
1094                 return sm->eapFail;
1095         case EAPOL_eapResp:
1096                 return sm->eapResp;
1097         case EAPOL_eapReq:
1098                 return sm->eapReq;
1099         case EAPOL_eapNoReq:
1100                 return sm->eapNoReq;
1101         case EAPOL_portEnabled:
1102                 return sm->portEnabled;
1103         case EAPOL_eapTimeout:
1104                 return sm->eapTimeout;
1105         }
1106         return FALSE;
1107 }
1108
1109
1110 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1111                               Boolean value)
1112 {
1113         struct eapol_state_machine *sm = ctx;
1114         if (sm == NULL)
1115                 return;
1116         switch (variable) {
1117         case EAPOL_eapSuccess:
1118                 sm->eapSuccess = value;
1119                 break;
1120         case EAPOL_eapRestart:
1121                 sm->eapRestart = value;
1122                 break;
1123         case EAPOL_eapFail:
1124                 sm->eapFail = value;
1125                 break;
1126         case EAPOL_eapResp:
1127                 sm->eapResp = value;
1128                 break;
1129         case EAPOL_eapReq:
1130                 sm->eapReq = value;
1131                 break;
1132         case EAPOL_eapNoReq:
1133                 sm->eapNoReq = value;
1134                 break;
1135         case EAPOL_portEnabled:
1136                 sm->portEnabled = value;
1137                 break;
1138         case EAPOL_eapTimeout:
1139                 sm->eapTimeout = value;
1140                 break;
1141         }
1142 }
1143
1144
1145 static void eapol_sm_set_eapReqData(void *ctx, const u8 *eapReqData,
1146                                     size_t eapReqDataLen)
1147 {
1148         struct eapol_state_machine *sm = ctx;
1149         if (sm == NULL)
1150                 return;
1151
1152         free(sm->last_eap_radius);
1153         sm->last_eap_radius = malloc(eapReqDataLen);
1154         if (sm->last_eap_radius == NULL)
1155                 return;
1156         memcpy(sm->last_eap_radius, eapReqData, eapReqDataLen);
1157         sm->last_eap_radius_len = eapReqDataLen;
1158 }
1159
1160
1161 static void eapol_sm_set_eapKeyData(void *ctx, const u8 *eapKeyData,
1162                                     size_t eapKeyDataLen)
1163 {
1164         struct eapol_state_machine *sm = ctx;
1165         struct hostapd_data *hapd;
1166
1167         if (sm == NULL)
1168                 return;
1169
1170         hapd = sm->hapd;
1171
1172         if (eapKeyData && eapKeyDataLen >= 64) {
1173                 free(sm->eapol_key_sign);
1174                 free(sm->eapol_key_crypt);
1175                 sm->eapol_key_crypt = malloc(32);
1176                 if (sm->eapol_key_crypt) {
1177                         memcpy(sm->eapol_key_crypt, eapKeyData, 32);
1178                         sm->eapol_key_crypt_len = 32;
1179                 }
1180                 sm->eapol_key_sign = malloc(32);
1181                 if (sm->eapol_key_sign) {
1182                         memcpy(sm->eapol_key_sign, eapKeyData + 32, 32);
1183                         sm->eapol_key_sign_len = 32;
1184                 }
1185                 if (hapd->default_wep_key ||
1186                     hapd->conf->individual_wep_key_len > 0 ||
1187                     hapd->conf->wpa)
1188                         sm->keyAvailable = TRUE;
1189         } else {
1190                 free(sm->eapol_key_sign);
1191                 free(sm->eapol_key_crypt);
1192                 sm->eapol_key_sign = NULL;
1193                 sm->eapol_key_crypt = NULL;
1194                 sm->eapol_key_sign_len = 0;
1195                 sm->eapol_key_crypt_len = 0;
1196                 sm->keyAvailable = FALSE;
1197         }
1198 }
1199
1200
1201 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
1202                                  size_t identity_len, int phase2,
1203                                  struct eap_user *user)
1204 {
1205         struct eapol_state_machine *sm = ctx;
1206         const struct hostapd_eap_user *eap_user;
1207         int i, count;
1208
1209         eap_user = hostapd_get_eap_user(sm->hapd->conf, identity,
1210                                         identity_len, phase2);
1211         if (eap_user == NULL)
1212                 return -1;
1213
1214         memset(user, 0, sizeof(*user));
1215         user->phase2 = phase2;
1216         count = EAP_USER_MAX_METHODS;
1217         if (count > EAP_MAX_METHODS)
1218                 count = EAP_MAX_METHODS;
1219         for (i = 0; i < count; i++) {
1220                 user->methods[i].vendor = eap_user->methods[i].vendor;
1221                 user->methods[i].method = eap_user->methods[i].method;
1222         }
1223
1224         if (eap_user->password) {
1225                 user->password = malloc(eap_user->password_len);
1226                 if (user->password == NULL)
1227                         return -1;
1228                 memcpy(user->password, eap_user->password,
1229                        eap_user->password_len);
1230                 user->password_len = eap_user->password_len;
1231         }
1232         user->force_version = eap_user->force_version;
1233
1234         return 0;
1235 }
1236
1237
1238 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
1239 {
1240         struct eapol_state_machine *sm = ctx;
1241         *len = sm->hapd->conf->eap_req_id_text_len;
1242         return sm->hapd->conf->eap_req_id_text;
1243 }
1244
1245
1246 static struct eapol_callbacks eapol_cb =
1247 {
1248         .get_bool = eapol_sm_get_bool,
1249         .set_bool = eapol_sm_set_bool,
1250         .set_eapReqData = eapol_sm_set_eapReqData,
1251         .set_eapKeyData = eapol_sm_set_eapKeyData,
1252         .get_eap_user = eapol_sm_get_eap_user,
1253         .get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
1254 };
1255
1256
1257 int eapol_sm_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
1258 {
1259         if (sm == NULL || ctx != sm->eap)
1260                 return -1;
1261
1262         eap_sm_pending_cb(sm->eap);
1263         eapol_sm_step(sm);
1264
1265         return 0;
1266 }