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