Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / contrib / hostapd-0.4.9 / eapol_sm.c
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>
5  *
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.
9  *
10  * Alternatively, this software may be distributed under the terms of BSD
11  * license.
12  *
13  * See README and COPYING for more details.
14  */
15
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>
22
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"
30
31 static struct eapol_callbacks eapol_cb;
32
33 /* EAPOL state machines are described in IEEE Std 802.1X-REV-d11, Chap. 8.2 */
34
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)
39
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)
48
49
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)
54
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));
60
61 #define SM_ENTER(machine, state) sm_ ## machine ## _ ## state ## _Enter(sm)
62
63 #define SM_STEP(machine) \
64 static void sm_ ## machine ## _Step(struct eapol_state_machine *sm)
65
66 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
67
68
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);
71
72
73 /* Port Timers state machine - implemented as a function that will be called
74  * once a second as a registered event loop timeout */
75
76 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
77 {
78         struct eapol_state_machine *state = timeout_ctx;
79
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));
86                 }
87         }
88
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));
95                 }
96         }
97
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));
104                 }
105         }
106
107         eapol_sm_step_run(state);
108
109         eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
110 }
111
112
113
114 /* Authenticator PAE state machine */
115
116 SM_STATE(AUTH_PAE, INITIALIZE)
117 {
118         SM_ENTRY(AUTH_PAE, INITIALIZE, auth_pae);
119         sm->auth_pae.portMode = Auto;
120
121         sm->currentId = 255;
122 }
123
124
125 SM_STATE(AUTH_PAE, DISCONNECTED)
126 {
127         int from_initialize = sm->auth_pae.state == AUTH_PAE_INITIALIZE;
128
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++;
134         }
135
136         SM_ENTRY(AUTH_PAE, DISCONNECTED, auth_pae);
137
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);
147         }
148 }
149
150
151 SM_STATE(AUTH_PAE, RESTART)
152 {
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++;
160         }
161
162         SM_ENTRY(AUTH_PAE, RESTART, auth_pae);
163
164         sm->auth_pae.eapRestart = TRUE;
165         ieee802_1x_request_identity(sm->hapd, sm->sta);
166 }
167
168
169 SM_STATE(AUTH_PAE, CONNECTING)
170 {
171         if (sm->auth_pae.state != AUTH_PAE_CONNECTING)
172                 sm->auth_pae.authEntersConnecting++;
173
174         SM_ENTRY(AUTH_PAE, CONNECTING, auth_pae);
175
176         sm->reAuthenticate = FALSE;
177         sm->auth_pae.reAuthCount++;
178 }
179
180
181 SM_STATE(AUTH_PAE, HELD)
182 {
183         if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authFail)
184                 sm->auth_pae.authAuthFailWhileAuthenticating++;
185
186         SM_ENTRY(AUTH_PAE, HELD, auth_pae);
187
188         sm->authPortStatus = Unauthorized;
189         setPortUnauthorized();
190         sm->quietWhile = sm->auth_pae.quietPeriod;
191         sm->auth_pae.eapolLogoff = FALSE;
192
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);
199 }
200
201
202 SM_STATE(AUTH_PAE, AUTHENTICATED)
203 {
204         if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
205                 sm->auth_pae.authAuthSuccessesWhileAuthenticating++;
206                                                         
207         SM_ENTRY(AUTH_PAE, AUTHENTICATED, auth_pae);
208
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);
218 }
219
220
221 SM_STATE(AUTH_PAE, AUTHENTICATING)
222 {
223         if (sm->auth_pae.state == AUTH_PAE_CONNECTING && sm->rx_identity) {
224                 sm->auth_pae.authEntersAuthenticating++;
225                 sm->rx_identity = FALSE;
226         }
227
228         SM_ENTRY(AUTH_PAE, AUTHENTICATING, auth_pae);
229
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;
237 }
238
239
240 SM_STATE(AUTH_PAE, ABORTING)
241 {
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++;
249         }
250
251         SM_ENTRY(AUTH_PAE, ABORTING, auth_pae);
252
253         sm->authAbort = TRUE;
254         sm->keyRun = FALSE;
255         sm->keyDone = FALSE;
256 }
257
258
259 SM_STATE(AUTH_PAE, FORCE_AUTH)
260 {
261         SM_ENTRY(AUTH_PAE, FORCE_AUTH, auth_pae);
262
263         sm->authPortStatus = Authorized;
264         setPortAuthorized();
265         sm->auth_pae.portMode = ForceAuthorized;
266         sm->auth_pae.eapolStart = FALSE;
267         txCannedSuccess();
268 }
269
270
271 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
272 {
273         SM_ENTRY(AUTH_PAE, FORCE_UNAUTH, auth_pae);
274
275         sm->authPortStatus = Unauthorized;
276         setPortUnauthorized();
277         sm->auth_pae.portMode = ForceUnauthorized;
278         sm->auth_pae.eapolStart = FALSE;
279         txCannedFail();
280 }
281
282
283 SM_STEP(AUTH_PAE)
284 {
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;
353                 }
354         }
355 }
356
357
358
359 /* Backend Authentication state machine */
360
361 SM_STATE(BE_AUTH, INITIALIZE)
362 {
363         SM_ENTRY(BE_AUTH, INITIALIZE, be_auth);
364
365         abortAuth();
366         sm->be_auth.eapNoReq = FALSE;
367         sm->authAbort = FALSE;
368 }
369
370
371 SM_STATE(BE_AUTH, REQUEST)
372 {
373         SM_ENTRY(BE_AUTH, REQUEST, be_auth);
374
375         txReq();
376         sm->be_auth.eapReq = FALSE;
377         sm->be_auth.backendOtherRequestsToSupplicant++;
378
379         /*
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.
384          *
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.
389          */
390         sm->eapolEap = FALSE;
391 }
392
393
394 SM_STATE(BE_AUTH, RESPONSE)
395 {
396         SM_ENTRY(BE_AUTH, RESPONSE, be_auth);
397
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++;
405 }
406
407
408 SM_STATE(BE_AUTH, SUCCESS)
409 {
410         SM_ENTRY(BE_AUTH, SUCCESS, be_auth);
411
412         txReq();
413         sm->authSuccess = TRUE;
414         sm->keyRun = TRUE;
415 }
416
417
418 SM_STATE(BE_AUTH, FAIL)
419 {
420         SM_ENTRY(BE_AUTH, FAIL, be_auth);
421
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;
431 }
432
433
434 SM_STATE(BE_AUTH, TIMEOUT)
435 {
436         SM_ENTRY(BE_AUTH, TIMEOUT, be_auth);
437
438         sm->authTimeout = TRUE;
439 }
440
441
442 SM_STATE(BE_AUTH, IDLE)
443 {
444         SM_ENTRY(BE_AUTH, IDLE, be_auth);
445
446         sm->authStart = FALSE;
447 }
448
449
450 SM_STATE(BE_AUTH, IGNORE)
451 {
452         SM_ENTRY(BE_AUTH, IGNORE, be_auth);
453
454         sm->be_auth.eapNoReq = FALSE;
455 }
456
457
458 SM_STEP(BE_AUTH)
459 {
460         if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
461                 SM_ENTER(BE_AUTH, INITIALIZE);
462                 return;
463         }
464
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);
491                 }
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;
518         }
519 }
520
521
522
523 /* Reauthentication Timer state machine */
524
525 SM_STATE(REAUTH_TIMER, INITIALIZE)
526 {
527         SM_ENTRY(REAUTH_TIMER, INITIALIZE, reauth_timer);
528
529         sm->reAuthWhen = sm->reauth_timer.reAuthPeriod;
530 }
531
532
533 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
534 {
535         SM_ENTRY(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
536
537         sm->reAuthenticate = TRUE;
538         wpa_sm_event(sm->hapd, sm->sta, WPA_REAUTH_EAPOL);
539 }
540
541
542 SM_STEP(REAUTH_TIMER)
543 {
544         if (sm->portControl != Auto || sm->initialize ||
545             sm->authPortStatus == Unauthorized ||
546             !sm->reauth_timer.reAuthEnabled) {
547                 SM_ENTER(REAUTH_TIMER, INITIALIZE);
548                 return;
549         }
550
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;
559         }
560 }
561
562
563
564 /* Authenticator Key Transmit state machine */
565
566 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
567 {
568         SM_ENTRY(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
569 }
570
571
572 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
573 {
574         SM_ENTRY(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
575
576         txKey();
577         sm->keyAvailable = FALSE;
578         sm->keyDone = TRUE;
579 }
580
581
582 SM_STEP(AUTH_KEY_TX)
583 {
584         if (sm->initialize || sm->portControl != Auto) {
585                 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
586                 return;
587         }
588
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;
601         }
602 }
603
604
605
606 /* Key Receive state machine */
607
608 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
609 {
610         SM_ENTRY(KEY_RX, NO_KEY_RECEIVE, key_rx);
611 }
612
613
614 SM_STATE(KEY_RX, KEY_RECEIVE)
615 {
616         SM_ENTRY(KEY_RX, KEY_RECEIVE, key_rx);
617
618         processKey();
619         sm->key_rx.rxKey = FALSE;
620 }
621
622
623 SM_STEP(KEY_RX)
624 {
625         if (sm->initialize || !sm->portEnabled) {
626                 SM_ENTER(KEY_RX, NO_KEY_RECEIVE);
627                 return;
628         }
629
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;
639         }
640 }
641
642
643
644 /* Controlled Directions state machine */
645
646 SM_STATE(CTRL_DIR, FORCE_BOTH)
647 {
648         SM_ENTRY(CTRL_DIR, FORCE_BOTH, ctrl_dir);
649         sm->ctrl_dir.operControlledDirections = Both;
650 }
651
652
653 SM_STATE(CTRL_DIR, IN_OR_BOTH)
654 {
655         SM_ENTRY(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
656         sm->ctrl_dir.operControlledDirections =
657                 sm->ctrl_dir.adminControlledDirections;
658 }
659
660
661 SM_STEP(CTRL_DIR)
662 {
663         if (sm->initialize) {
664                 SM_ENTER(CTRL_DIR, IN_OR_BOTH);
665                 return;
666         }
667
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;
680         }
681 }
682
683
684
685 struct eapol_state_machine *
686 eapol_sm_alloc(hostapd *hapd, struct sta_info *sta)
687 {
688         struct eapol_state_machine *sm;
689
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;
694         }
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;
700
701         sm->hapd = hapd;
702         sm->sta = sta;
703
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;
708
709         sm->be_auth.state = BE_AUTH_INITIALIZE;
710         sm->be_auth.serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
711
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;
716
717         sm->auth_key_tx.state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
718
719         sm->key_rx.state = KEY_RX_NO_KEY_RECEIVE;
720
721         sm->ctrl_dir.state = CTRL_DIR_IN_OR_BOTH;
722
723         sm->portEnabled = FALSE;
724         sm->portControl = Auto;
725
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;
736
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;
746                 }
747         }
748
749         eapol_sm_initialize(sm);
750
751         return sm;
752 }
753
754
755 void eapol_sm_free(struct eapol_state_machine *sm)
756 {
757         if (sm == NULL)
758                 return;
759
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);
765 }
766
767
768 static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr)
769 {
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;
775 }
776
777
778 static void eapol_sm_step_run(struct eapol_state_machine *sm)
779 {
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;
785
786         memcpy(addr, sm->sta->addr, ETH_ALEN);
787
788         /*
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.
793          */
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;
801
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);
813
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;
825         }
826
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;
834                 }
835         }
836
837         if (eapol_sm_sta_entry_alive(hapd, addr))
838                 wpa_sm_notify(sm->hapd, sm->sta);
839 }
840
841
842 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
843 {
844         struct eapol_state_machine *sm = eloop_ctx;
845         eapol_sm_step_run(sm);
846 }
847
848
849 void eapol_sm_step(struct eapol_state_machine *sm)
850 {
851         /*
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.
855          */
856
857         eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
858 }
859
860
861 void eapol_sm_initialize(struct eapol_state_machine *sm)
862 {
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;
871
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);
875 }
876
877
878 #ifdef HOSTAPD_DUMP_STATE
879 static inline const char * port_type_txt(PortTypes pt)
880 {
881         switch (pt) {
882         case ForceUnauthorized: return "ForceUnauthorized";
883         case ForceAuthorized: return "ForceAuthorized";
884         case Auto: return "Auto";
885         default: return "Unknown";
886         }
887 }
888
889
890 static inline const char * port_state_txt(PortState ps)
891 {
892         switch (ps) {
893         case Unauthorized: return "Unauthorized";
894         case Authorized: return "Authorized";
895         default: return "Unknown";
896         }
897 }
898
899
900 static inline const char * ctrl_dir_txt(ControlledDirection dir)
901 {
902         switch (dir) {
903         case Both: return "Both";
904         case In: return "In";
905         default: return "Unknown";
906         }
907 }
908
909
910 static inline const char * auth_pae_state_txt(int s)
911 {
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";
924         }
925 }
926
927
928 static inline const char * be_auth_state_txt(int s)
929 {
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";
940         }
941 }
942
943
944 static inline const char * reauth_timer_state_txt(int s)
945 {
946         switch (s) {
947         case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
948         case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
949         default: return "Unknown";
950         }
951 }
952
953
954 static inline const char * auth_key_tx_state_txt(int s)
955 {
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";
960         }
961 }
962
963
964 static inline const char * key_rx_state_txt(int s)
965 {
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";
970         }
971 }
972
973
974 static inline const char * ctrl_dir_state_txt(int s)
975 {
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";
980         }
981 }
982
983
984 void eapol_sm_dump_state(FILE *f, const char *prefix,
985                          struct eapol_state_machine *sm)
986 {
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));
1008
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);
1041
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);
1061
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));
1068
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));
1072
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));
1078
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
1089 }
1090 #endif /* HOSTAPD_DUMP_STATE */
1091
1092
1093 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1094 {
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;
1115         }
1116         return FALSE;
1117 }
1118
1119
1120 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1121                               Boolean value)
1122 {
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;
1151         }
1152 }
1153
1154
1155 static void eapol_sm_set_eapReqData(void *ctx, const u8 *eapReqData,
1156                                     size_t eapReqDataLen)
1157 {
1158         struct eapol_state_machine *sm = ctx;
1159         if (sm == NULL)
1160                 return;
1161
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;
1168 }
1169
1170
1171 static void eapol_sm_set_eapKeyData(void *ctx, const u8 *eapKeyData,
1172                                     size_t eapKeyDataLen)
1173 {
1174         struct eapol_state_machine *sm = ctx;
1175         struct hostapd_data *hapd;
1176
1177         if (sm == NULL)
1178                 return;
1179
1180         hapd = sm->hapd;
1181
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;
1189                 }
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;
1194                 }
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;
1207         }
1208 }
1209
1210
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)
1214 {
1215         struct eapol_state_machine *sm = ctx;
1216         const struct hostapd_eap_user *eap_user;
1217
1218         eap_user = hostapd_get_eap_user(sm->hapd->conf, identity,
1219                                         identity_len, phase2);
1220         if (eap_user == NULL)
1221                 return -1;
1222
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);
1228
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;
1236         }
1237         user->force_version = eap_user->force_version;
1238
1239         return 0;
1240 }
1241
1242
1243 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
1244 {
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;
1248 }
1249
1250
1251 static struct eapol_callbacks eapol_cb =
1252 {
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,
1259 };