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