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