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