remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / eap_server / eap_server.c
1 /*
2  * hostapd / EAP Full Authenticator state machine (RFC 4137)
3  * Copyright (c) 2004-2007, 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  * This state machine is based on the full authenticator state machine defined
15  * in RFC 4137. However, to support backend authentication in RADIUS
16  * authentication server functionality, parts of backend authenticator (also
17  * from RFC 4137) are mixed in. This functionality is enabled by setting
18  * backend_auth configuration variable to TRUE.
19  */
20
21 #include "includes.h"
22
23 #include "common.h"
24 #include "eap_i.h"
25 #include "state_machine.h"
26 #include "common/wpa_ctrl.h"
27
28 #define STATE_MACHINE_DATA struct eap_sm
29 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
30
31 #define EAP_MAX_AUTH_ROUNDS 50
32
33 static void eap_user_free(struct eap_user *user);
34
35
36 /* EAP state machines are described in RFC 4137 */
37
38 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
39                                    int eapSRTT, int eapRTTVAR,
40                                    int methodTimeout);
41 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp);
42 static int eap_sm_getId(const struct wpabuf *data);
43 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id);
44 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id);
45 static int eap_sm_nextId(struct eap_sm *sm, int id);
46 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
47                                  size_t len);
48 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor);
49 static int eap_sm_Policy_getDecision(struct eap_sm *sm);
50 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
51
52
53 static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
54 {
55         if (src == NULL)
56                 return -1;
57
58         wpabuf_free(*dst);
59         *dst = wpabuf_dup(src);
60         return *dst ? 0 : -1;
61 }
62
63
64 static int eap_copy_data(u8 **dst, size_t *dst_len,
65                          const u8 *src, size_t src_len)
66 {
67         if (src == NULL)
68                 return -1;
69
70         os_free(*dst);
71         *dst = os_malloc(src_len);
72         if (*dst) {
73                 os_memcpy(*dst, src, src_len);
74                 *dst_len = src_len;
75                 return 0;
76         } else {
77                 *dst_len = 0;
78                 return -1;
79         }
80 }
81
82 #define EAP_COPY(dst, src) \
83         eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
84
85
86 /**
87  * eap_user_get - Fetch user information from the database
88  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
89  * @identity: Identity (User-Name) of the user
90  * @identity_len: Length of identity in bytes
91  * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user
92  * Returns: 0 on success, or -1 on failure
93  *
94  * This function is used to fetch user information for EAP. The user will be
95  * selected based on the specified identity. sm->user and
96  * sm->user_eap_method_index are updated for the new user when a matching user
97  * is found. sm->user can be used to get user information (e.g., password).
98  */
99 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
100                  int phase2)
101 {
102         struct eap_user *user;
103
104         if (sm == NULL || sm->eapol_cb == NULL ||
105             sm->eapol_cb->get_eap_user == NULL)
106                 return -1;
107
108         eap_user_free(sm->user);
109         sm->user = NULL;
110
111         user = os_zalloc(sizeof(*user));
112         if (user == NULL)
113             return -1;
114
115         if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
116                                        identity_len, phase2, user) != 0) {
117                 eap_user_free(user);
118                 return -1;
119         }
120
121         sm->user = user;
122         sm->user_eap_method_index = 0;
123
124         return 0;
125 }
126
127
128 SM_STATE(EAP, DISABLED)
129 {
130         SM_ENTRY(EAP, DISABLED);
131         sm->num_rounds = 0;
132 }
133
134
135 SM_STATE(EAP, INITIALIZE)
136 {
137         SM_ENTRY(EAP, INITIALIZE);
138
139         sm->currentId = -1;
140         sm->eap_if.eapSuccess = FALSE;
141         sm->eap_if.eapFail = FALSE;
142         sm->eap_if.eapTimeout = FALSE;
143         os_free(sm->eap_if.eapKeyData);
144         sm->eap_if.eapKeyData = NULL;
145         sm->eap_if.eapKeyDataLen = 0;
146         sm->eap_if.eapKeyAvailable = FALSE;
147         sm->eap_if.eapRestart = FALSE;
148
149         /*
150          * Start reauthentication with identity request even if we know the
151          * previously used identity. This is needed to get reauthentication
152          * started properly.
153          */
154         sm->start_reauth = TRUE;
155
156         /*
157          * This is not defined in RFC 4137, but method state needs to be
158          * reseted here so that it does not remain in success state when
159          * re-authentication starts.
160          */
161         if (sm->m && sm->eap_method_priv) {
162                 sm->m->reset(sm, sm->eap_method_priv);
163                 sm->eap_method_priv = NULL;
164         }
165         sm->m = NULL;
166         sm->user_eap_method_index = 0;
167
168         if (sm->backend_auth) {
169                 sm->currentMethod = EAP_TYPE_NONE;
170                 /* parse rxResp, respId, respMethod */
171                 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
172                 if (sm->rxResp) {
173                         sm->currentId = sm->respId;
174                 }
175         }
176         sm->num_rounds = 0;
177         sm->method_pending = METHOD_PENDING_NONE;
178
179         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
180                 MACSTR, MAC2STR(sm->peer_addr));
181 }
182
183
184 SM_STATE(EAP, PICK_UP_METHOD)
185 {
186         SM_ENTRY(EAP, PICK_UP_METHOD);
187
188         if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
189                 sm->currentMethod = sm->respMethod;
190                 if (sm->m && sm->eap_method_priv) {
191                         sm->m->reset(sm, sm->eap_method_priv);
192                         sm->eap_method_priv = NULL;
193                 }
194                 sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF,
195                                                   sm->currentMethod);
196                 if (sm->m && sm->m->initPickUp) {
197                         sm->eap_method_priv = sm->m->initPickUp(sm);
198                         if (sm->eap_method_priv == NULL) {
199                                 wpa_printf(MSG_DEBUG, "EAP: Failed to "
200                                            "initialize EAP method %d",
201                                            sm->currentMethod);
202                                 sm->m = NULL;
203                                 sm->currentMethod = EAP_TYPE_NONE;
204                         }
205                 } else {
206                         sm->m = NULL;
207                         sm->currentMethod = EAP_TYPE_NONE;
208                 }
209         }
210
211         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
212                 "method=%u", sm->currentMethod);
213 }
214
215
216 SM_STATE(EAP, IDLE)
217 {
218         SM_ENTRY(EAP, IDLE);
219
220         sm->eap_if.retransWhile = eap_sm_calculateTimeout(
221                 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
222                 sm->methodTimeout);
223 }
224
225
226 SM_STATE(EAP, RETRANSMIT)
227 {
228         SM_ENTRY(EAP, RETRANSMIT);
229
230         sm->retransCount++;
231         if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
232                 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
233                         sm->eap_if.eapReq = TRUE;
234         }
235 }
236
237
238 SM_STATE(EAP, RECEIVED)
239 {
240         SM_ENTRY(EAP, RECEIVED);
241
242         /* parse rxResp, respId, respMethod */
243         eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
244         sm->num_rounds++;
245 }
246
247
248 SM_STATE(EAP, DISCARD)
249 {
250         SM_ENTRY(EAP, DISCARD);
251         sm->eap_if.eapResp = FALSE;
252         sm->eap_if.eapNoReq = TRUE;
253 }
254
255
256 SM_STATE(EAP, SEND_REQUEST)
257 {
258         SM_ENTRY(EAP, SEND_REQUEST);
259
260         sm->retransCount = 0;
261         if (sm->eap_if.eapReqData) {
262                 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
263                 {
264                         sm->eap_if.eapResp = FALSE;
265                         sm->eap_if.eapReq = TRUE;
266                 } else {
267                         sm->eap_if.eapResp = FALSE;
268                         sm->eap_if.eapReq = FALSE;
269                 }
270         } else {
271                 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
272                 sm->eap_if.eapResp = FALSE;
273                 sm->eap_if.eapReq = FALSE;
274                 sm->eap_if.eapNoReq = TRUE;
275         }
276 }
277
278
279 SM_STATE(EAP, INTEGRITY_CHECK)
280 {
281         SM_ENTRY(EAP, INTEGRITY_CHECK);
282
283         if (sm->m->check) {
284                 sm->ignore = sm->m->check(sm, sm->eap_method_priv,
285                                           sm->eap_if.eapRespData);
286         }
287 }
288
289
290 SM_STATE(EAP, METHOD_REQUEST)
291 {
292         SM_ENTRY(EAP, METHOD_REQUEST);
293
294         if (sm->m == NULL) {
295                 wpa_printf(MSG_DEBUG, "EAP: method not initialized");
296                 return;
297         }
298
299         sm->currentId = eap_sm_nextId(sm, sm->currentId);
300         wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
301                    sm->currentId);
302         sm->lastId = sm->currentId;
303         wpabuf_free(sm->eap_if.eapReqData);
304         sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
305                                                 sm->currentId);
306         if (sm->m->getTimeout)
307                 sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
308         else
309                 sm->methodTimeout = 0;
310 }
311
312
313 SM_STATE(EAP, METHOD_RESPONSE)
314 {
315         SM_ENTRY(EAP, METHOD_RESPONSE);
316
317         sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
318         if (sm->m->isDone(sm, sm->eap_method_priv)) {
319                 eap_sm_Policy_update(sm, NULL, 0);
320                 os_free(sm->eap_if.eapKeyData);
321                 if (sm->m->getKey) {
322                         sm->eap_if.eapKeyData = sm->m->getKey(
323                                 sm, sm->eap_method_priv,
324                                 &sm->eap_if.eapKeyDataLen);
325                 } else {
326                         sm->eap_if.eapKeyData = NULL;
327                         sm->eap_if.eapKeyDataLen = 0;
328                 }
329                 sm->methodState = METHOD_END;
330         } else {
331                 sm->methodState = METHOD_CONTINUE;
332         }
333 }
334
335
336 SM_STATE(EAP, PROPOSE_METHOD)
337 {
338         int vendor;
339         EapType type;
340
341         SM_ENTRY(EAP, PROPOSE_METHOD);
342
343         type = eap_sm_Policy_getNextMethod(sm, &vendor);
344         if (vendor == EAP_VENDOR_IETF)
345                 sm->currentMethod = type;
346         else
347                 sm->currentMethod = EAP_TYPE_EXPANDED;
348         if (sm->m && sm->eap_method_priv) {
349                 sm->m->reset(sm, sm->eap_method_priv);
350                 sm->eap_method_priv = NULL;
351         }
352         sm->m = eap_server_get_eap_method(vendor, type);
353         if (sm->m) {
354                 sm->eap_method_priv = sm->m->init(sm);
355                 if (sm->eap_method_priv == NULL) {
356                         wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
357                                    "method %d", sm->currentMethod);
358                         sm->m = NULL;
359                         sm->currentMethod = EAP_TYPE_NONE;
360                 }
361         }
362         if (sm->currentMethod == EAP_TYPE_IDENTITY ||
363             sm->currentMethod == EAP_TYPE_NOTIFICATION)
364                 sm->methodState = METHOD_CONTINUE;
365         else
366                 sm->methodState = METHOD_PROPOSED;
367
368         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
369                 "vendor=%u method=%u", vendor, sm->currentMethod);
370 }
371
372
373 SM_STATE(EAP, NAK)
374 {
375         const struct eap_hdr *nak;
376         size_t len = 0;
377         const u8 *pos;
378         const u8 *nak_list = NULL;
379
380         SM_ENTRY(EAP, NAK);
381
382         if (sm->eap_method_priv) {
383                 sm->m->reset(sm, sm->eap_method_priv);
384                 sm->eap_method_priv = NULL;
385         }
386         sm->m = NULL;
387
388         nak = wpabuf_head(sm->eap_if.eapRespData);
389         if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
390                 len = be_to_host16(nak->length);
391                 if (len > wpabuf_len(sm->eap_if.eapRespData))
392                         len = wpabuf_len(sm->eap_if.eapRespData);
393                 pos = (const u8 *) (nak + 1);
394                 len -= sizeof(*nak);
395                 if (*pos == EAP_TYPE_NAK) {
396                         pos++;
397                         len--;
398                         nak_list = pos;
399                 }
400         }
401         eap_sm_Policy_update(sm, nak_list, len);
402 }
403
404
405 SM_STATE(EAP, SELECT_ACTION)
406 {
407         SM_ENTRY(EAP, SELECT_ACTION);
408
409         sm->decision = eap_sm_Policy_getDecision(sm);
410 }
411
412
413 SM_STATE(EAP, TIMEOUT_FAILURE)
414 {
415         SM_ENTRY(EAP, TIMEOUT_FAILURE);
416
417         sm->eap_if.eapTimeout = TRUE;
418 }
419
420
421 SM_STATE(EAP, FAILURE)
422 {
423         SM_ENTRY(EAP, FAILURE);
424
425         wpabuf_free(sm->eap_if.eapReqData);
426         sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId);
427         wpabuf_free(sm->lastReqData);
428         sm->lastReqData = NULL;
429         sm->eap_if.eapFail = TRUE;
430
431         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
432                 MACSTR, MAC2STR(sm->peer_addr));
433 }
434
435
436 SM_STATE(EAP, SUCCESS)
437 {
438         SM_ENTRY(EAP, SUCCESS);
439
440         wpabuf_free(sm->eap_if.eapReqData);
441         sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId);
442         wpabuf_free(sm->lastReqData);
443         sm->lastReqData = NULL;
444         if (sm->eap_if.eapKeyData)
445                 sm->eap_if.eapKeyAvailable = TRUE;
446         sm->eap_if.eapSuccess = TRUE;
447
448         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
449                 MACSTR, MAC2STR(sm->peer_addr));
450 }
451
452
453 SM_STATE(EAP, INITIALIZE_PASSTHROUGH)
454 {
455         SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
456
457         wpabuf_free(sm->eap_if.aaaEapRespData);
458         sm->eap_if.aaaEapRespData = NULL;
459 }
460
461
462 SM_STATE(EAP, IDLE2)
463 {
464         SM_ENTRY(EAP, IDLE2);
465
466         sm->eap_if.retransWhile = eap_sm_calculateTimeout(
467                 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
468                 sm->methodTimeout);
469 }
470
471
472 SM_STATE(EAP, RETRANSMIT2)
473 {
474         SM_ENTRY(EAP, RETRANSMIT2);
475
476         sm->retransCount++;
477         if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
478                 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
479                         sm->eap_if.eapReq = TRUE;
480         }
481 }
482
483
484 SM_STATE(EAP, RECEIVED2)
485 {
486         SM_ENTRY(EAP, RECEIVED2);
487
488         /* parse rxResp, respId, respMethod */
489         eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
490 }
491
492
493 SM_STATE(EAP, DISCARD2)
494 {
495         SM_ENTRY(EAP, DISCARD2);
496         sm->eap_if.eapResp = FALSE;
497         sm->eap_if.eapNoReq = TRUE;
498 }
499
500
501 SM_STATE(EAP, SEND_REQUEST2)
502 {
503         SM_ENTRY(EAP, SEND_REQUEST2);
504
505         sm->retransCount = 0;
506         if (sm->eap_if.eapReqData) {
507                 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
508                 {
509                         sm->eap_if.eapResp = FALSE;
510                         sm->eap_if.eapReq = TRUE;
511                 } else {
512                         sm->eap_if.eapResp = FALSE;
513                         sm->eap_if.eapReq = FALSE;
514                 }
515         } else {
516                 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData");
517                 sm->eap_if.eapResp = FALSE;
518                 sm->eap_if.eapReq = FALSE;
519                 sm->eap_if.eapNoReq = TRUE;
520         }
521 }
522
523
524 SM_STATE(EAP, AAA_REQUEST)
525 {
526         SM_ENTRY(EAP, AAA_REQUEST);
527
528         if (sm->eap_if.eapRespData == NULL) {
529                 wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData");
530                 return;
531         }
532
533         /*
534          * if (respMethod == IDENTITY)
535          *      aaaIdentity = eapRespData
536          * This is already taken care of by the EAP-Identity method which
537          * stores the identity into sm->identity.
538          */
539
540         eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData);
541 }
542
543
544 SM_STATE(EAP, AAA_RESPONSE)
545 {
546         SM_ENTRY(EAP, AAA_RESPONSE);
547
548         eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
549         sm->currentId = eap_sm_getId(sm->eap_if.eapReqData);
550         sm->methodTimeout = sm->eap_if.aaaMethodTimeout;
551 }
552
553
554 SM_STATE(EAP, AAA_IDLE)
555 {
556         SM_ENTRY(EAP, AAA_IDLE);
557
558         sm->eap_if.aaaFail = FALSE;
559         sm->eap_if.aaaSuccess = FALSE;
560         sm->eap_if.aaaEapReq = FALSE;
561         sm->eap_if.aaaEapNoReq = FALSE;
562         sm->eap_if.aaaEapResp = TRUE;
563 }
564
565
566 SM_STATE(EAP, TIMEOUT_FAILURE2)
567 {
568         SM_ENTRY(EAP, TIMEOUT_FAILURE2);
569
570         sm->eap_if.eapTimeout = TRUE;
571 }
572
573
574 SM_STATE(EAP, FAILURE2)
575 {
576         SM_ENTRY(EAP, FAILURE2);
577
578         eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
579         sm->eap_if.eapFail = TRUE;
580 }
581
582
583 SM_STATE(EAP, SUCCESS2)
584 {
585         SM_ENTRY(EAP, SUCCESS2);
586
587         eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
588
589         sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable;
590         if (sm->eap_if.aaaEapKeyAvailable) {
591                 EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
592         } else {
593                 os_free(sm->eap_if.eapKeyData);
594                 sm->eap_if.eapKeyData = NULL;
595                 sm->eap_if.eapKeyDataLen = 0;
596         }
597
598         sm->eap_if.eapSuccess = TRUE;
599
600         /*
601          * Start reauthentication with identity request even though we know the
602          * previously used identity. This is needed to get reauthentication
603          * started properly.
604          */
605         sm->start_reauth = TRUE;
606 }
607
608
609 SM_STEP(EAP)
610 {
611         if (sm->eap_if.eapRestart && sm->eap_if.portEnabled)
612                 SM_ENTER_GLOBAL(EAP, INITIALIZE);
613         else if (!sm->eap_if.portEnabled)
614                 SM_ENTER_GLOBAL(EAP, DISABLED);
615         else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
616                 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
617                         wpa_printf(MSG_DEBUG, "EAP: more than %d "
618                                    "authentication rounds - abort",
619                                    EAP_MAX_AUTH_ROUNDS);
620                         sm->num_rounds++;
621                         SM_ENTER_GLOBAL(EAP, FAILURE);
622                 }
623         } else switch (sm->EAP_state) {
624         case EAP_INITIALIZE:
625                 if (sm->backend_auth) {
626                         if (!sm->rxResp)
627                                 SM_ENTER(EAP, SELECT_ACTION);
628                         else if (sm->rxResp &&
629                                  (sm->respMethod == EAP_TYPE_NAK ||
630                                   (sm->respMethod == EAP_TYPE_EXPANDED &&
631                                    sm->respVendor == EAP_VENDOR_IETF &&
632                                    sm->respVendorMethod == EAP_TYPE_NAK)))
633                                 SM_ENTER(EAP, NAK);
634                         else
635                                 SM_ENTER(EAP, PICK_UP_METHOD);
636                 } else {
637                         SM_ENTER(EAP, SELECT_ACTION);
638                 }
639                 break;
640         case EAP_PICK_UP_METHOD:
641                 if (sm->currentMethod == EAP_TYPE_NONE) {
642                         SM_ENTER(EAP, SELECT_ACTION);
643                 } else {
644                         SM_ENTER(EAP, METHOD_RESPONSE);
645                 }
646                 break;
647         case EAP_DISABLED:
648                 if (sm->eap_if.portEnabled)
649                         SM_ENTER(EAP, INITIALIZE);
650                 break;
651         case EAP_IDLE:
652                 if (sm->eap_if.retransWhile == 0)
653                         SM_ENTER(EAP, RETRANSMIT);
654                 else if (sm->eap_if.eapResp)
655                         SM_ENTER(EAP, RECEIVED);
656                 break;
657         case EAP_RETRANSMIT:
658                 if (sm->retransCount > sm->MaxRetrans)
659                         SM_ENTER(EAP, TIMEOUT_FAILURE);
660                 else
661                         SM_ENTER(EAP, IDLE);
662                 break;
663         case EAP_RECEIVED:
664                 if (sm->rxResp && (sm->respId == sm->currentId) &&
665                     (sm->respMethod == EAP_TYPE_NAK ||
666                      (sm->respMethod == EAP_TYPE_EXPANDED &&
667                       sm->respVendor == EAP_VENDOR_IETF &&
668                       sm->respVendorMethod == EAP_TYPE_NAK))
669                     && (sm->methodState == METHOD_PROPOSED))
670                         SM_ENTER(EAP, NAK);
671                 else if (sm->rxResp && (sm->respId == sm->currentId) &&
672                          ((sm->respMethod == sm->currentMethod) ||
673                           (sm->respMethod == EAP_TYPE_EXPANDED &&
674                            sm->respVendor == EAP_VENDOR_IETF &&
675                            sm->respVendorMethod == sm->currentMethod)))
676                         SM_ENTER(EAP, INTEGRITY_CHECK);
677                 else {
678                         wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
679                                    "rxResp=%d respId=%d currentId=%d "
680                                    "respMethod=%d currentMethod=%d",
681                                    sm->rxResp, sm->respId, sm->currentId,
682                                    sm->respMethod, sm->currentMethod);
683                         SM_ENTER(EAP, DISCARD);
684                 }
685                 break;
686         case EAP_DISCARD:
687                 SM_ENTER(EAP, IDLE);
688                 break;
689         case EAP_SEND_REQUEST:
690                 SM_ENTER(EAP, IDLE);
691                 break;
692         case EAP_INTEGRITY_CHECK:
693                 if (sm->ignore)
694                         SM_ENTER(EAP, DISCARD);
695                 else
696                         SM_ENTER(EAP, METHOD_RESPONSE);
697                 break;
698         case EAP_METHOD_REQUEST:
699                 SM_ENTER(EAP, SEND_REQUEST);
700                 break;
701         case EAP_METHOD_RESPONSE:
702                 /*
703                  * Note: Mechanism to allow EAP methods to wait while going
704                  * through pending processing is an extension to RFC 4137
705                  * which only defines the transits to SELECT_ACTION and
706                  * METHOD_REQUEST from this METHOD_RESPONSE state.
707                  */
708                 if (sm->methodState == METHOD_END)
709                         SM_ENTER(EAP, SELECT_ACTION);
710                 else if (sm->method_pending == METHOD_PENDING_WAIT) {
711                         wpa_printf(MSG_DEBUG, "EAP: Method has pending "
712                                    "processing - wait before proceeding to "
713                                    "METHOD_REQUEST state");
714                 } else if (sm->method_pending == METHOD_PENDING_CONT) {
715                         wpa_printf(MSG_DEBUG, "EAP: Method has completed "
716                                    "pending processing - reprocess pending "
717                                    "EAP message");
718                         sm->method_pending = METHOD_PENDING_NONE;
719                         SM_ENTER(EAP, METHOD_RESPONSE);
720                 } else
721                         SM_ENTER(EAP, METHOD_REQUEST);
722                 break;
723         case EAP_PROPOSE_METHOD:
724                 /*
725                  * Note: Mechanism to allow EAP methods to wait while going
726                  * through pending processing is an extension to RFC 4137
727                  * which only defines the transit to METHOD_REQUEST from this
728                  * PROPOSE_METHOD state.
729                  */
730                 if (sm->method_pending == METHOD_PENDING_WAIT) {
731                         wpa_printf(MSG_DEBUG, "EAP: Method has pending "
732                                    "processing - wait before proceeding to "
733                                    "METHOD_REQUEST state");
734                         if (sm->user_eap_method_index > 0)
735                                 sm->user_eap_method_index--;
736                 } else if (sm->method_pending == METHOD_PENDING_CONT) {
737                         wpa_printf(MSG_DEBUG, "EAP: Method has completed "
738                                    "pending processing - reprocess pending "
739                                    "EAP message");
740                         sm->method_pending = METHOD_PENDING_NONE;
741                         SM_ENTER(EAP, PROPOSE_METHOD);
742                 } else
743                         SM_ENTER(EAP, METHOD_REQUEST);
744                 break;
745         case EAP_NAK:
746                 SM_ENTER(EAP, SELECT_ACTION);
747                 break;
748         case EAP_SELECT_ACTION:
749                 if (sm->decision == DECISION_FAILURE)
750                         SM_ENTER(EAP, FAILURE);
751                 else if (sm->decision == DECISION_SUCCESS)
752                         SM_ENTER(EAP, SUCCESS);
753                 else if (sm->decision == DECISION_PASSTHROUGH)
754                         SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
755                 else
756                         SM_ENTER(EAP, PROPOSE_METHOD);
757                 break;
758         case EAP_TIMEOUT_FAILURE:
759                 break;
760         case EAP_FAILURE:
761                 break;
762         case EAP_SUCCESS:
763                 break;
764
765         case EAP_INITIALIZE_PASSTHROUGH:
766                 if (sm->currentId == -1)
767                         SM_ENTER(EAP, AAA_IDLE);
768                 else
769                         SM_ENTER(EAP, AAA_REQUEST);
770                 break;
771         case EAP_IDLE2:
772                 if (sm->eap_if.eapResp)
773                         SM_ENTER(EAP, RECEIVED2);
774                 else if (sm->eap_if.retransWhile == 0)
775                         SM_ENTER(EAP, RETRANSMIT2);
776                 break;
777         case EAP_RETRANSMIT2:
778                 if (sm->retransCount > sm->MaxRetrans)
779                         SM_ENTER(EAP, TIMEOUT_FAILURE2);
780                 else
781                         SM_ENTER(EAP, IDLE2);
782                 break;
783         case EAP_RECEIVED2:
784                 if (sm->rxResp && (sm->respId == sm->currentId))
785                         SM_ENTER(EAP, AAA_REQUEST);
786                 else
787                         SM_ENTER(EAP, DISCARD2);
788                 break;
789         case EAP_DISCARD2:
790                 SM_ENTER(EAP, IDLE2);
791                 break;
792         case EAP_SEND_REQUEST2:
793                 SM_ENTER(EAP, IDLE2);
794                 break;
795         case EAP_AAA_REQUEST:
796                 SM_ENTER(EAP, AAA_IDLE);
797                 break;
798         case EAP_AAA_RESPONSE:
799                 SM_ENTER(EAP, SEND_REQUEST2);
800                 break;
801         case EAP_AAA_IDLE:
802                 if (sm->eap_if.aaaFail)
803                         SM_ENTER(EAP, FAILURE2);
804                 else if (sm->eap_if.aaaSuccess)
805                         SM_ENTER(EAP, SUCCESS2);
806                 else if (sm->eap_if.aaaEapReq)
807                         SM_ENTER(EAP, AAA_RESPONSE);
808                 else if (sm->eap_if.aaaTimeout)
809                         SM_ENTER(EAP, TIMEOUT_FAILURE2);
810                 break;
811         case EAP_TIMEOUT_FAILURE2:
812                 break;
813         case EAP_FAILURE2:
814                 break;
815         case EAP_SUCCESS2:
816                 break;
817         }
818 }
819
820
821 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
822                                    int eapSRTT, int eapRTTVAR,
823                                    int methodTimeout)
824 {
825         int rto, i;
826
827         if (methodTimeout) {
828                 /*
829                  * EAP method (either internal or through AAA server, provided
830                  * timeout hint. Use that as-is as a timeout for retransmitting
831                  * the EAP request if no response is received.
832                  */
833                 wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
834                            "(from EAP method hint)", methodTimeout);
835                 return methodTimeout;
836         }
837
838         /*
839          * RFC 3748 recommends algorithms described in RFC 2988 for estimation
840          * of the retransmission timeout. This should be implemented once
841          * round-trip time measurements are available. For nowm a simple
842          * backoff mechanism is used instead if there are no EAP method
843          * specific hints.
844          *
845          * SRTT = smoothed round-trip time
846          * RTTVAR = round-trip time variation
847          * RTO = retransmission timeout
848          */
849
850         /*
851          * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
852          * initial retransmission and then double the RTO to provide back off
853          * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
854          * modified RTOmax.
855          */
856         rto = 3;
857         for (i = 0; i < retransCount; i++) {
858                 rto *= 2;
859                 if (rto >= 20) {
860                         rto = 20;
861                         break;
862                 }
863         }
864
865         wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
866                    "(from dynamic back off; retransCount=%d)",
867                    rto, retransCount);
868
869         return rto;
870 }
871
872
873 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp)
874 {
875         const struct eap_hdr *hdr;
876         size_t plen;
877
878         /* parse rxResp, respId, respMethod */
879         sm->rxResp = FALSE;
880         sm->respId = -1;
881         sm->respMethod = EAP_TYPE_NONE;
882         sm->respVendor = EAP_VENDOR_IETF;
883         sm->respVendorMethod = EAP_TYPE_NONE;
884
885         if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) {
886                 wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p "
887                            "len=%lu", resp,
888                            resp ? (unsigned long) wpabuf_len(resp) : 0);
889                 return;
890         }
891
892         hdr = wpabuf_head(resp);
893         plen = be_to_host16(hdr->length);
894         if (plen > wpabuf_len(resp)) {
895                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
896                            "(len=%lu plen=%lu)",
897                            (unsigned long) wpabuf_len(resp),
898                            (unsigned long) plen);
899                 return;
900         }
901
902         sm->respId = hdr->identifier;
903
904         if (hdr->code == EAP_CODE_RESPONSE)
905                 sm->rxResp = TRUE;
906
907         if (plen > sizeof(*hdr)) {
908                 u8 *pos = (u8 *) (hdr + 1);
909                 sm->respMethod = *pos++;
910                 if (sm->respMethod == EAP_TYPE_EXPANDED) {
911                         if (plen < sizeof(*hdr) + 8) {
912                                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
913                                            "expanded EAP-Packet (plen=%lu)",
914                                            (unsigned long) plen);
915                                 return;
916                         }
917                         sm->respVendor = WPA_GET_BE24(pos);
918                         pos += 3;
919                         sm->respVendorMethod = WPA_GET_BE32(pos);
920                 }
921         }
922
923         wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "
924                    "respMethod=%u respVendor=%u respVendorMethod=%u",
925                    sm->rxResp, sm->respId, sm->respMethod, sm->respVendor,
926                    sm->respVendorMethod);
927 }
928
929
930 static int eap_sm_getId(const struct wpabuf *data)
931 {
932         const struct eap_hdr *hdr;
933
934         if (data == NULL || wpabuf_len(data) < sizeof(*hdr))
935                 return -1;
936
937         hdr = wpabuf_head(data);
938         wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
939         return hdr->identifier;
940 }
941
942
943 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
944 {
945         struct wpabuf *msg;
946         struct eap_hdr *resp;
947         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
948
949         msg = wpabuf_alloc(sizeof(*resp));
950         if (msg == NULL)
951                 return NULL;
952         resp = wpabuf_put(msg, sizeof(*resp));
953         resp->code = EAP_CODE_SUCCESS;
954         resp->identifier = id;
955         resp->length = host_to_be16(sizeof(*resp));
956
957         return msg;
958 }
959
960
961 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id)
962 {
963         struct wpabuf *msg;
964         struct eap_hdr *resp;
965         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
966
967         msg = wpabuf_alloc(sizeof(*resp));
968         if (msg == NULL)
969                 return NULL;
970         resp = wpabuf_put(msg, sizeof(*resp));
971         resp->code = EAP_CODE_FAILURE;
972         resp->identifier = id;
973         resp->length = host_to_be16(sizeof(*resp));
974
975         return msg;
976 }
977
978
979 static int eap_sm_nextId(struct eap_sm *sm, int id)
980 {
981         if (id < 0) {
982                 /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
983                  * random number */
984                 id = rand() & 0xff;
985                 if (id != sm->lastId)
986                         return id;
987         }
988         return (id + 1) & 0xff;
989 }
990
991
992 /**
993  * eap_sm_process_nak - Process EAP-Response/Nak
994  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
995  * @nak_list: Nak list (allowed methods) from the supplicant
996  * @len: Length of nak_list in bytes
997  *
998  * This function is called when EAP-Response/Nak is received from the
999  * supplicant. This can happen for both phase 1 and phase 2 authentications.
1000  */
1001 void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len)
1002 {
1003         int i;
1004         size_t j;
1005
1006         if (sm->user == NULL)
1007                 return;
1008
1009         wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
1010                    "index %d)", sm->user_eap_method_index);
1011
1012         wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
1013                     (u8 *) sm->user->methods,
1014                     EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
1015         wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
1016                     nak_list, len);
1017
1018         i = sm->user_eap_method_index;
1019         while (i < EAP_MAX_METHODS &&
1020                (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
1021                 sm->user->methods[i].method != EAP_TYPE_NONE)) {
1022                 if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
1023                         goto not_found;
1024                 for (j = 0; j < len; j++) {
1025                         if (nak_list[j] == sm->user->methods[i].method) {
1026                                 break;
1027                         }
1028                 }
1029
1030                 if (j < len) {
1031                         /* found */
1032                         i++;
1033                         continue;
1034                 }
1035
1036         not_found:
1037                 /* not found - remove from the list */
1038                 os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1],
1039                            (EAP_MAX_METHODS - i - 1) *
1040                            sizeof(sm->user->methods[0]));
1041                 sm->user->methods[EAP_MAX_METHODS - 1].vendor =
1042                         EAP_VENDOR_IETF;
1043                 sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
1044         }
1045
1046         wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
1047                     (u8 *) sm->user->methods, EAP_MAX_METHODS *
1048                     sizeof(sm->user->methods[0]));
1049 }
1050
1051
1052 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
1053                                  size_t len)
1054 {
1055         if (nak_list == NULL || sm == NULL || sm->user == NULL)
1056                 return;
1057
1058         if (sm->user->phase2) {
1059                 wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
1060                            " info was selected - reject");
1061                 sm->decision = DECISION_FAILURE;
1062                 return;
1063         }
1064
1065         eap_sm_process_nak(sm, nak_list, len);
1066 }
1067
1068
1069 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
1070 {
1071         EapType next;
1072         int idx = sm->user_eap_method_index;
1073
1074         /* In theory, there should be no problems with starting
1075          * re-authentication with something else than EAP-Request/Identity and
1076          * this does indeed work with wpa_supplicant. However, at least Funk
1077          * Supplicant seemed to ignore re-auth if it skipped
1078          * EAP-Request/Identity.
1079          * Re-auth sets currentId == -1, so that can be used here to select
1080          * whether Identity needs to be requested again. */
1081         if (sm->identity == NULL || sm->currentId == -1) {
1082                 *vendor = EAP_VENDOR_IETF;
1083                 next = EAP_TYPE_IDENTITY;
1084                 sm->update_user = TRUE;
1085         } else if (sm->user && idx < EAP_MAX_METHODS &&
1086                    (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
1087                     sm->user->methods[idx].method != EAP_TYPE_NONE)) {
1088                 *vendor = sm->user->methods[idx].vendor;
1089                 next = sm->user->methods[idx].method;
1090                 sm->user_eap_method_index++;
1091         } else {
1092                 *vendor = EAP_VENDOR_IETF;
1093                 next = EAP_TYPE_NONE;
1094         }
1095         wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
1096                    *vendor, next);
1097         return next;
1098 }
1099
1100
1101 static int eap_sm_Policy_getDecision(struct eap_sm *sm)
1102 {
1103         if (!sm->eap_server && sm->identity && !sm->start_reauth) {
1104                 wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
1105                 return DECISION_PASSTHROUGH;
1106         }
1107
1108         if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
1109             sm->m->isSuccess(sm, sm->eap_method_priv)) {
1110                 wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
1111                            "SUCCESS");
1112                 sm->update_user = TRUE;
1113                 return DECISION_SUCCESS;
1114         }
1115
1116         if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
1117             !sm->m->isSuccess(sm, sm->eap_method_priv)) {
1118                 wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
1119                            "FAILURE");
1120                 sm->update_user = TRUE;
1121                 return DECISION_FAILURE;
1122         }
1123
1124         if ((sm->user == NULL || sm->update_user) && sm->identity &&
1125             !sm->start_reauth) {
1126                 /*
1127                  * Allow Identity method to be started once to allow identity
1128                  * selection hint to be sent from the authentication server,
1129                  * but prevent a loop of Identity requests by only allowing
1130                  * this to happen once.
1131                  */
1132                 int id_req = 0;
1133                 if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
1134                     sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1135                     sm->user->methods[0].method == EAP_TYPE_IDENTITY)
1136                         id_req = 1;
1137                 if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
1138                         wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
1139                                    "found from database -> FAILURE");
1140                         return DECISION_FAILURE;
1141                 }
1142                 if (id_req && sm->user &&
1143                     sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1144                     sm->user->methods[0].method == EAP_TYPE_IDENTITY) {
1145                         wpa_printf(MSG_DEBUG, "EAP: getDecision: stop "
1146                                    "identity request loop -> FAILURE");
1147                         sm->update_user = TRUE;
1148                         return DECISION_FAILURE;
1149                 }
1150                 sm->update_user = FALSE;
1151         }
1152         sm->start_reauth = FALSE;
1153
1154         if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
1155             (sm->user->methods[sm->user_eap_method_index].vendor !=
1156              EAP_VENDOR_IETF ||
1157              sm->user->methods[sm->user_eap_method_index].method !=
1158              EAP_TYPE_NONE)) {
1159                 wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
1160                            "available -> CONTINUE");
1161                 return DECISION_CONTINUE;
1162         }
1163
1164         if (sm->identity == NULL || sm->currentId == -1) {
1165                 wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
1166                            "yet -> CONTINUE");
1167                 return DECISION_CONTINUE;
1168         }
1169
1170         wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
1171                    "FAILURE");
1172         return DECISION_FAILURE;
1173 }
1174
1175
1176 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
1177 {
1178         return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
1179 }
1180
1181
1182 /**
1183  * eap_server_sm_step - Step EAP server state machine
1184  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1185  * Returns: 1 if EAP state was changed or 0 if not
1186  *
1187  * This function advances EAP state machine to a new state to match with the
1188  * current variables. This should be called whenever variables used by the EAP
1189  * state machine have changed.
1190  */
1191 int eap_server_sm_step(struct eap_sm *sm)
1192 {
1193         int res = 0;
1194         do {
1195                 sm->changed = FALSE;
1196                 SM_STEP_RUN(EAP);
1197                 if (sm->changed)
1198                         res = 1;
1199         } while (sm->changed);
1200         return res;
1201 }
1202
1203
1204 static void eap_user_free(struct eap_user *user)
1205 {
1206         if (user == NULL)
1207                 return;
1208         os_free(user->password);
1209         user->password = NULL;
1210         os_free(user);
1211 }
1212
1213
1214 /**
1215  * eap_server_sm_init - Allocate and initialize EAP server state machine
1216  * @eapol_ctx: Context data to be used with eapol_cb calls
1217  * @eapol_cb: Pointer to EAPOL callback functions
1218  * @conf: EAP configuration
1219  * Returns: Pointer to the allocated EAP state machine or %NULL on failure
1220  *
1221  * This function allocates and initializes an EAP state machine.
1222  */
1223 struct eap_sm * eap_server_sm_init(void *eapol_ctx,
1224                                    struct eapol_callbacks *eapol_cb,
1225                                    struct eap_config *conf)
1226 {
1227         struct eap_sm *sm;
1228
1229         sm = os_zalloc(sizeof(*sm));
1230         if (sm == NULL)
1231                 return NULL;
1232         sm->eapol_ctx = eapol_ctx;
1233         sm->eapol_cb = eapol_cb;
1234         sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
1235         sm->ssl_ctx = conf->ssl_ctx;
1236         sm->msg_ctx = conf->msg_ctx;
1237         sm->eap_sim_db_priv = conf->eap_sim_db_priv;
1238         sm->backend_auth = conf->backend_auth;
1239         sm->eap_server = conf->eap_server;
1240         if (conf->pac_opaque_encr_key) {
1241                 sm->pac_opaque_encr_key = os_malloc(16);
1242                 if (sm->pac_opaque_encr_key) {
1243                         os_memcpy(sm->pac_opaque_encr_key,
1244                                   conf->pac_opaque_encr_key, 16);
1245                 }
1246         }
1247         if (conf->eap_fast_a_id) {
1248                 sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1249                 if (sm->eap_fast_a_id) {
1250                         os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
1251                                   conf->eap_fast_a_id_len);
1252                         sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1253                 }
1254         }
1255         if (conf->eap_fast_a_id_info)
1256                 sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1257         sm->eap_fast_prov = conf->eap_fast_prov;
1258         sm->pac_key_lifetime = conf->pac_key_lifetime;
1259         sm->pac_key_refresh_time = conf->pac_key_refresh_time;
1260         sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1261         sm->tnc = conf->tnc;
1262         sm->wps = conf->wps;
1263         if (conf->assoc_wps_ie)
1264                 sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
1265         if (conf->assoc_p2p_ie)
1266                 sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie);
1267         if (conf->peer_addr)
1268                 os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
1269         sm->fragment_size = conf->fragment_size;
1270         sm->pwd_group = conf->pwd_group;
1271
1272         wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
1273
1274         return sm;
1275 }
1276
1277
1278 /**
1279  * eap_server_sm_deinit - Deinitialize and free an EAP server state machine
1280  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1281  *
1282  * This function deinitializes EAP state machine and frees all allocated
1283  * resources.
1284  */
1285 void eap_server_sm_deinit(struct eap_sm *sm)
1286 {
1287         if (sm == NULL)
1288                 return;
1289         wpa_printf(MSG_DEBUG, "EAP: Server state machine removed");
1290         if (sm->m && sm->eap_method_priv)
1291                 sm->m->reset(sm, sm->eap_method_priv);
1292         wpabuf_free(sm->eap_if.eapReqData);
1293         os_free(sm->eap_if.eapKeyData);
1294         wpabuf_free(sm->lastReqData);
1295         wpabuf_free(sm->eap_if.eapRespData);
1296         os_free(sm->identity);
1297         os_free(sm->pac_opaque_encr_key);
1298         os_free(sm->eap_fast_a_id);
1299         os_free(sm->eap_fast_a_id_info);
1300         wpabuf_free(sm->eap_if.aaaEapReqData);
1301         wpabuf_free(sm->eap_if.aaaEapRespData);
1302         os_free(sm->eap_if.aaaEapKeyData);
1303         eap_user_free(sm->user);
1304         wpabuf_free(sm->assoc_wps_ie);
1305         wpabuf_free(sm->assoc_p2p_ie);
1306         os_free(sm);
1307 }
1308
1309
1310 /**
1311  * eap_sm_notify_cached - Notify EAP state machine of cached PMK
1312  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1313  *
1314  * This function is called when PMKSA caching is used to skip EAP
1315  * authentication.
1316  */
1317 void eap_sm_notify_cached(struct eap_sm *sm)
1318 {
1319         if (sm == NULL)
1320                 return;
1321
1322         sm->EAP_state = EAP_SUCCESS;
1323 }
1324
1325
1326 /**
1327  * eap_sm_pending_cb - EAP state machine callback for a pending EAP request
1328  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1329  *
1330  * This function is called when data for a pending EAP-Request is received.
1331  */
1332 void eap_sm_pending_cb(struct eap_sm *sm)
1333 {
1334         if (sm == NULL)
1335                 return;
1336         wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
1337         if (sm->method_pending == METHOD_PENDING_WAIT)
1338                 sm->method_pending = METHOD_PENDING_CONT;
1339 }
1340
1341
1342 /**
1343  * eap_sm_method_pending - Query whether EAP method is waiting for pending data
1344  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1345  * Returns: 1 if method is waiting for pending data or 0 if not
1346  */
1347 int eap_sm_method_pending(struct eap_sm *sm)
1348 {
1349         if (sm == NULL)
1350                 return 0;
1351         return sm->method_pending == METHOD_PENDING_WAIT;
1352 }
1353
1354
1355 /**
1356  * eap_get_identity - Get the user identity (from EAP-Response/Identity)
1357  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1358  * @len: Buffer for returning identity length
1359  * Returns: Pointer to the user identity or %NULL if not available
1360  */
1361 const u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
1362 {
1363         *len = sm->identity_len;
1364         return sm->identity;
1365 }
1366
1367
1368 /**
1369  * eap_get_interface - Get pointer to EAP-EAPOL interface data
1370  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1371  * Returns: Pointer to the EAP-EAPOL interface data
1372  */
1373 struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
1374 {
1375         return &sm->eap_if;
1376 }