wpa_supplicant: update vendor branch to 0.6.10
[dragonfly.git] / contrib / hostapd / eap.c
1 /*
2  * hostapd / EAP Standalone Authenticator state machine (RFC 4137)
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "hostapd.h"
18 #include "sta_info.h"
19 #include "eap_i.h"
20 #include "state_machine.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, u8 *resp, size_t len);
36 static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len);
37 static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len);
38 static int eap_sm_nextId(struct eap_sm *sm, int id);
39 static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len);
40 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor);
41 static int eap_sm_Policy_getDecision(struct eap_sm *sm);
42 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
43
44
45 static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
46 {
47         return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
48 }
49
50
51 static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
52                            Boolean value)
53 {
54         sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
55 }
56
57
58 static void eapol_set_eapReqData(struct eap_sm *sm,
59                                  const u8 *eapReqData, size_t eapReqDataLen)
60 {
61         wpa_hexdump(MSG_MSGDUMP, "EAP: eapReqData -> EAPOL",
62                     sm->eapReqData, sm->eapReqDataLen);
63         sm->eapol_cb->set_eapReqData(sm->eapol_ctx, eapReqData, eapReqDataLen);
64 }
65
66
67 static void eapol_set_eapKeyData(struct eap_sm *sm,
68                                  const u8 *eapKeyData, size_t eapKeyDataLen)
69 {
70         wpa_hexdump(MSG_MSGDUMP, "EAP: eapKeyData -> EAPOL",
71                     sm->eapKeyData, sm->eapKeyDataLen);
72         sm->eapol_cb->set_eapKeyData(sm->eapol_ctx, eapKeyData, eapKeyDataLen);
73 }
74
75
76 /**
77  * eap_user_get - Fetch user information from the database
78  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
79  * @identity: Identity (User-Name) of the user
80  * @identity_len: Length of identity in bytes
81  * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user
82  * Returns: 0 on success, or -1 on failure
83  *
84  * This function is used to fetch user information for EAP. The user will be
85  * selected based on the specified identity. sm->user and
86  * sm->user_eap_method_index are updated for the new user when a matching user
87  * is found. sm->user can be used to get user information (e.g., password).
88  */
89 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
90                  int phase2)
91 {
92         struct eap_user *user;
93
94         if (sm == NULL || sm->eapol_cb == NULL ||
95             sm->eapol_cb->get_eap_user == NULL)
96                 return -1;
97
98         eap_user_free(sm->user);
99         sm->user = NULL;
100
101         user = wpa_zalloc(sizeof(*user));
102         if (user == NULL)
103             return -1;
104
105         if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
106                                        identity_len, phase2, user) != 0) {
107                 eap_user_free(user);
108                 return -1;
109         }
110
111         sm->user = user;
112         sm->user_eap_method_index = 0;
113
114         return 0;
115 }
116
117
118 SM_STATE(EAP, DISABLED)
119 {
120         SM_ENTRY(EAP, DISABLED);
121         sm->num_rounds = 0;
122 }
123
124
125 SM_STATE(EAP, INITIALIZE)
126 {
127         SM_ENTRY(EAP, INITIALIZE);
128
129         sm->currentId = -1;
130         eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
131         eapol_set_bool(sm, EAPOL_eapFail, FALSE);
132         eapol_set_bool(sm, EAPOL_eapTimeout, FALSE);
133         free(sm->eapKeyData);
134         sm->eapKeyData = NULL;
135         sm->eapKeyDataLen = 0;
136         /* eapKeyAvailable = FALSE */
137         eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
138
139         /*
140          * This is not defined in RFC 4137, but method state needs to be
141          * reseted here so that it does not remain in success state when
142          * re-authentication starts.
143          */
144         if (sm->m && sm->eap_method_priv) {
145                 sm->m->reset(sm, sm->eap_method_priv);
146                 sm->eap_method_priv = NULL;
147         }
148         sm->m = NULL;
149         sm->user_eap_method_index = 0;
150
151         if (sm->backend_auth) {
152                 sm->currentMethod = EAP_TYPE_NONE;
153                 /* parse rxResp, respId, respMethod */
154                 eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);
155                 if (sm->rxResp) {
156                         sm->currentId = sm->respId;
157                 }
158         }
159         sm->num_rounds = 0;
160         sm->method_pending = METHOD_PENDING_NONE;
161 }
162
163
164 SM_STATE(EAP, PICK_UP_METHOD)
165 {
166         SM_ENTRY(EAP, PICK_UP_METHOD);
167
168         if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
169                 sm->currentMethod = sm->respMethod;
170                 if (sm->m && sm->eap_method_priv) {
171                         sm->m->reset(sm, sm->eap_method_priv);
172                         sm->eap_method_priv = NULL;
173                 }
174                 sm->m = eap_sm_get_eap_methods(EAP_VENDOR_IETF,
175                                                sm->currentMethod);
176                 if (sm->m && sm->m->initPickUp) {
177                         sm->eap_method_priv = sm->m->initPickUp(sm);
178                         if (sm->eap_method_priv == NULL) {
179                                 wpa_printf(MSG_DEBUG, "EAP: Failed to "
180                                            "initialize EAP method %d",
181                                            sm->currentMethod);
182                                 sm->m = NULL;
183                                 sm->currentMethod = EAP_TYPE_NONE;
184                         }
185                 } else {
186                         sm->m = NULL;
187                         sm->currentMethod = EAP_TYPE_NONE;
188                 }
189         }
190 }
191
192
193 SM_STATE(EAP, IDLE)
194 {
195         SM_ENTRY(EAP, IDLE);
196
197         sm->retransWhile = eap_sm_calculateTimeout(sm, sm->retransCount,
198                                                    sm->eapSRTT, sm->eapRTTVAR,
199                                                    sm->methodTimeout);
200 }
201
202
203 SM_STATE(EAP, RETRANSMIT)
204 {
205         SM_ENTRY(EAP, RETRANSMIT);
206
207         /* TODO: Is this needed since EAPOL state machines take care of
208          * retransmit? */
209 }
210
211
212 SM_STATE(EAP, RECEIVED)
213 {
214         SM_ENTRY(EAP, RECEIVED);
215
216         /* parse rxResp, respId, respMethod */
217         eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);
218         sm->num_rounds++;
219 }
220
221
222 SM_STATE(EAP, DISCARD)
223 {
224         SM_ENTRY(EAP, DISCARD);
225         eapol_set_bool(sm, EAPOL_eapResp, FALSE);
226         eapol_set_bool(sm, EAPOL_eapNoReq, TRUE);
227 }
228
229
230 SM_STATE(EAP, SEND_REQUEST)
231 {
232         SM_ENTRY(EAP, SEND_REQUEST);
233
234         sm->retransCount = 0;
235         if (sm->eapReqData) {
236                 eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);
237                 free(sm->lastReqData);
238                 sm->lastReqData = sm->eapReqData;
239                 sm->lastReqDataLen = sm->eapReqDataLen;
240                 sm->eapReqData = NULL;
241                 sm->eapReqDataLen = 0;
242                 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
243                 eapol_set_bool(sm, EAPOL_eapReq, TRUE);
244         } else {
245                 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
246                 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
247                 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
248                 eapol_set_bool(sm, EAPOL_eapNoReq, TRUE);
249         }
250 }
251
252
253 SM_STATE(EAP, INTEGRITY_CHECK)
254 {
255         SM_ENTRY(EAP, INTEGRITY_CHECK);
256
257         if (sm->m->check) {
258                 sm->ignore = sm->m->check(sm, sm->eap_method_priv,
259                                           sm->eapRespData, sm->eapRespDataLen);
260         }
261 }
262
263
264 SM_STATE(EAP, METHOD_REQUEST)
265 {
266         SM_ENTRY(EAP, METHOD_REQUEST);
267
268         if (sm->m == NULL) {
269                 wpa_printf(MSG_DEBUG, "EAP: method not initialized");
270                 return;
271         }
272
273         sm->currentId = eap_sm_nextId(sm, sm->currentId);
274         wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
275                    sm->currentId);
276         sm->lastId = sm->currentId;
277         free(sm->eapReqData);
278         sm->eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
279                                          sm->currentId, &sm->eapReqDataLen);
280         if (sm->m->getTimeout)
281                 sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
282         else
283                 sm->methodTimeout = 0;
284 }
285
286
287 SM_STATE(EAP, METHOD_RESPONSE)
288 {
289         SM_ENTRY(EAP, METHOD_RESPONSE);
290
291         sm->m->process(sm, sm->eap_method_priv, sm->eapRespData,
292                        sm->eapRespDataLen);
293         if (sm->m->isDone(sm, sm->eap_method_priv)) {
294                 eap_sm_Policy_update(sm, NULL, 0);
295                 free(sm->eapKeyData);
296                 if (sm->m->getKey) {
297                         sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
298                                                        &sm->eapKeyDataLen);
299                 } else {
300                         sm->eapKeyData = NULL;
301                         sm->eapKeyDataLen = 0;
302                 }
303                 sm->methodState = METHOD_END;
304         } else {
305                 sm->methodState = METHOD_CONTINUE;
306         }
307 }
308
309
310 SM_STATE(EAP, PROPOSE_METHOD)
311 {
312         int vendor;
313         EapType type;
314
315         SM_ENTRY(EAP, PROPOSE_METHOD);
316
317         type = eap_sm_Policy_getNextMethod(sm, &vendor);
318         if (vendor == EAP_VENDOR_IETF)
319                 sm->currentMethod = type;
320         else
321                 sm->currentMethod = EAP_TYPE_EXPANDED;
322         if (sm->m && sm->eap_method_priv) {
323                 sm->m->reset(sm, sm->eap_method_priv);
324                 sm->eap_method_priv = NULL;
325         }
326         sm->m = eap_sm_get_eap_methods(vendor, type);
327         if (sm->m) {
328                 sm->eap_method_priv = sm->m->init(sm);
329                 if (sm->eap_method_priv == NULL) {
330                         wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
331                                    "method %d", sm->currentMethod);
332                         sm->m = NULL;
333                         sm->currentMethod = EAP_TYPE_NONE;
334                 }
335         }
336         if (sm->currentMethod == EAP_TYPE_IDENTITY ||
337             sm->currentMethod == EAP_TYPE_NOTIFICATION)
338                 sm->methodState = METHOD_CONTINUE;
339         else
340                 sm->methodState = METHOD_PROPOSED;
341 }
342
343
344 SM_STATE(EAP, NAK)
345 {
346         struct eap_hdr *nak;
347         size_t len = 0;
348         u8 *pos, *nak_list = NULL;
349
350         SM_ENTRY(EAP, NAK);
351
352         if (sm->eap_method_priv) {
353                 sm->m->reset(sm, sm->eap_method_priv);
354                 sm->eap_method_priv = NULL;
355         }
356         sm->m = NULL;
357
358         nak = (struct eap_hdr *) sm->eapRespData;
359         if (nak && sm->eapRespDataLen > sizeof(*nak)) {
360                 len = ntohs(nak->length);
361                 if (len > sm->eapRespDataLen)
362                         len = sm->eapRespDataLen;
363                 pos = (u8 *) (nak + 1);
364                 len -= sizeof(*nak);
365                 if (*pos == EAP_TYPE_NAK) {
366                         pos++;
367                         len--;
368                         nak_list = pos;
369                 }
370         }
371         eap_sm_Policy_update(sm, nak_list, len);
372 }
373
374
375 SM_STATE(EAP, SELECT_ACTION)
376 {
377         SM_ENTRY(EAP, SELECT_ACTION);
378
379         sm->decision = eap_sm_Policy_getDecision(sm);
380 }
381
382
383 SM_STATE(EAP, TIMEOUT_FAILURE)
384 {
385         SM_ENTRY(EAP, TIMEOUT_FAILURE);
386
387         eapol_set_bool(sm, EAPOL_eapTimeout, TRUE);
388 }
389
390
391 SM_STATE(EAP, FAILURE)
392 {
393         SM_ENTRY(EAP, FAILURE);
394
395         free(sm->eapReqData);
396         sm->eapReqData = eap_sm_buildFailure(sm, sm->currentId,
397                                              &sm->eapReqDataLen);
398         if (sm->eapReqData) {
399                 eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);
400                 free(sm->eapReqData);
401                 sm->eapReqData = NULL;
402                 sm->eapReqDataLen = 0;
403         }
404         free(sm->lastReqData);
405         sm->lastReqData = NULL;
406         sm->lastReqDataLen = 0;
407         eapol_set_bool(sm, EAPOL_eapFail, TRUE);
408 }
409
410
411 SM_STATE(EAP, SUCCESS)
412 {
413         SM_ENTRY(EAP, SUCCESS);
414
415         free(sm->eapReqData);
416         sm->eapReqData = eap_sm_buildSuccess(sm, sm->currentId,
417                                              &sm->eapReqDataLen);
418         if (sm->eapReqData) {
419                 eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);
420                 free(sm->eapReqData);
421                 sm->eapReqData = NULL;
422                 sm->eapReqDataLen = 0;
423         }
424         free(sm->lastReqData);
425         sm->lastReqData = NULL;
426         sm->lastReqDataLen = 0;
427         if (sm->eapKeyData) {
428                 eapol_set_eapKeyData(sm, sm->eapKeyData, sm->eapKeyDataLen);
429         }
430         eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
431 }
432
433
434 SM_STEP(EAP)
435 {
436         if (eapol_get_bool(sm, EAPOL_eapRestart) &&
437             eapol_get_bool(sm, EAPOL_portEnabled))
438                 SM_ENTER_GLOBAL(EAP, INITIALIZE);
439         else if (!eapol_get_bool(sm, EAPOL_portEnabled))
440                 SM_ENTER_GLOBAL(EAP, DISABLED);
441         else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
442                 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
443                         wpa_printf(MSG_DEBUG, "EAP: more than %d "
444                                    "authentication rounds - abort",
445                                    EAP_MAX_AUTH_ROUNDS);
446                         sm->num_rounds++;
447                         SM_ENTER_GLOBAL(EAP, FAILURE);
448                 }
449         } else switch (sm->EAP_state) {
450         case EAP_INITIALIZE:
451                 if (sm->backend_auth) {
452                         if (!sm->rxResp)
453                                 SM_ENTER(EAP, SELECT_ACTION);
454                         else if (sm->rxResp &&
455                                  (sm->respMethod == EAP_TYPE_NAK ||
456                                   (sm->respMethod == EAP_TYPE_EXPANDED &&
457                                    sm->respVendor == EAP_VENDOR_IETF &&
458                                    sm->respVendorMethod == EAP_TYPE_NAK)))
459                                 SM_ENTER(EAP, NAK);
460                         else
461                                 SM_ENTER(EAP, PICK_UP_METHOD);
462                 } else {
463                         SM_ENTER(EAP, SELECT_ACTION);
464                 }
465                 break;
466         case EAP_PICK_UP_METHOD:
467                 if (sm->currentMethod == EAP_TYPE_NONE) {
468                         SM_ENTER(EAP, SELECT_ACTION);
469                 } else {
470                         SM_ENTER(EAP, METHOD_RESPONSE);
471                 }
472                 break;
473         case EAP_DISABLED:
474                 if (eapol_get_bool(sm, EAPOL_portEnabled))
475                         SM_ENTER(EAP, INITIALIZE);
476                 break;
477         case EAP_IDLE:
478                 if (sm->retransWhile == 0)
479                         SM_ENTER(EAP, RETRANSMIT);
480                 else if (eapol_get_bool(sm, EAPOL_eapResp))
481                         SM_ENTER(EAP, RECEIVED);
482                 break;
483         case EAP_RETRANSMIT:
484                 if (sm->retransCount > sm->MaxRetrans)
485                         SM_ENTER(EAP, TIMEOUT_FAILURE);
486                 else
487                         SM_ENTER(EAP, IDLE);
488                 break;
489         case EAP_RECEIVED:
490                 if (sm->rxResp && (sm->respId == sm->currentId) &&
491                     (sm->respMethod == EAP_TYPE_NAK ||
492                      (sm->respMethod == EAP_TYPE_EXPANDED &&
493                       sm->respVendor == EAP_VENDOR_IETF &&
494                       sm->respVendorMethod == EAP_TYPE_NAK))
495                     && (sm->methodState == METHOD_PROPOSED))
496                         SM_ENTER(EAP, NAK);
497                 else if (sm->rxResp && (sm->respId == sm->currentId) &&
498                          ((sm->respMethod == sm->currentMethod) ||
499                           (sm->respMethod == EAP_TYPE_EXPANDED &&
500                            sm->respVendor == EAP_VENDOR_IETF &&
501                            sm->respVendorMethod == sm->currentMethod)))
502                         SM_ENTER(EAP, INTEGRITY_CHECK);
503                 else {
504                         wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
505                                    "rxResp=%d respId=%d currentId=%d "
506                                    "respMethod=%d currentMethod=%d",
507                                    sm->rxResp, sm->respId, sm->currentId,
508                                    sm->respMethod, sm->currentMethod);
509                         SM_ENTER(EAP, DISCARD);
510                 }
511                 break;
512         case EAP_DISCARD:
513                 SM_ENTER(EAP, IDLE);
514                 break;
515         case EAP_SEND_REQUEST:
516                 SM_ENTER(EAP, IDLE);
517                 break;
518         case EAP_INTEGRITY_CHECK:
519                 if (sm->ignore)
520                         SM_ENTER(EAP, DISCARD);
521                 else
522                         SM_ENTER(EAP, METHOD_RESPONSE);
523                 break;
524         case EAP_METHOD_REQUEST:
525                 SM_ENTER(EAP, SEND_REQUEST);
526                 break;
527         case EAP_METHOD_RESPONSE:
528                 /*
529                  * Note: Mechanism to allow EAP methods to wait while going
530                  * through pending processing is an extension to RFC 4137
531                  * which only defines the transits to SELECT_ACTION and
532                  * METHOD_REQUEST from this METHOD_RESPONSE state.
533                  */
534                 if (sm->methodState == METHOD_END)
535                         SM_ENTER(EAP, SELECT_ACTION);
536                 else if (sm->method_pending == METHOD_PENDING_WAIT) {
537                         wpa_printf(MSG_DEBUG, "EAP: Method has pending "
538                                    "processing - wait before proceeding to "
539                                    "METHOD_REQUEST state");
540                 } else if (sm->method_pending == METHOD_PENDING_CONT) {
541                         wpa_printf(MSG_DEBUG, "EAP: Method has completed "
542                                    "pending processing - reprocess pending "
543                                    "EAP message");
544                         sm->method_pending = METHOD_PENDING_NONE;
545                         SM_ENTER(EAP, METHOD_RESPONSE);
546                 } else
547                         SM_ENTER(EAP, METHOD_REQUEST);
548                 break;
549         case EAP_PROPOSE_METHOD:
550                 /*
551                  * Note: Mechanism to allow EAP methods to wait while going
552                  * through pending processing is an extension to RFC 4137
553                  * which only defines the transit to METHOD_REQUEST from this
554                  * PROPOSE_METHOD state.
555                  */
556                 if (sm->method_pending == METHOD_PENDING_WAIT) {
557                         wpa_printf(MSG_DEBUG, "EAP: Method has pending "
558                                    "processing - wait before proceeding to "
559                                    "METHOD_REQUEST state");
560                         if (sm->user_eap_method_index > 0)
561                                 sm->user_eap_method_index--;
562                 } else if (sm->method_pending == METHOD_PENDING_CONT) {
563                         wpa_printf(MSG_DEBUG, "EAP: Method has completed "
564                                    "pending processing - reprocess pending "
565                                    "EAP message");
566                         sm->method_pending = METHOD_PENDING_NONE;
567                         SM_ENTER(EAP, PROPOSE_METHOD);
568                 } else
569                         SM_ENTER(EAP, METHOD_REQUEST);
570                 break;
571         case EAP_NAK:
572                 SM_ENTER(EAP, SELECT_ACTION);
573                 break;
574         case EAP_SELECT_ACTION:
575                 if (sm->decision == DECISION_FAILURE)
576                         SM_ENTER(EAP, FAILURE);
577                 else if (sm->decision == DECISION_SUCCESS)
578                         SM_ENTER(EAP, SUCCESS);
579                 else
580                         SM_ENTER(EAP, PROPOSE_METHOD);
581                 break;
582         case EAP_TIMEOUT_FAILURE:
583                 break;
584         case EAP_FAILURE:
585                 break;
586         case EAP_SUCCESS:
587                 break;
588         }
589 }
590
591
592 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
593                                    int eapSRTT, int eapRTTVAR,
594                                    int methodTimeout)
595 {
596         /* For now, retransmission is done in EAPOL state machines, so make
597          * sure EAP state machine does not end up trying to retransmit packets.
598          */
599         return 1;
600 }
601
602
603 static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len)
604 {
605         struct eap_hdr *hdr;
606         size_t plen;
607
608         /* parse rxResp, respId, respMethod */
609         sm->rxResp = FALSE;
610         sm->respId = -1;
611         sm->respMethod = EAP_TYPE_NONE;
612         sm->respVendor = EAP_VENDOR_IETF;
613         sm->respVendorMethod = EAP_TYPE_NONE;
614
615         if (resp == NULL || len < sizeof(*hdr))
616                 return;
617
618         hdr = (struct eap_hdr *) resp;
619         plen = ntohs(hdr->length);
620         if (plen > len) {
621                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
622                            "(len=%lu plen=%lu)", (unsigned long) len,
623                            (unsigned long) plen);
624                 return;
625         }
626
627         sm->respId = hdr->identifier;
628
629         if (hdr->code == EAP_CODE_RESPONSE)
630                 sm->rxResp = TRUE;
631
632         if (plen > sizeof(*hdr)) {
633                 u8 *pos = (u8 *) (hdr + 1);
634                 sm->respMethod = *pos++;
635                 if (sm->respMethod == EAP_TYPE_EXPANDED) {
636                         if (plen < sizeof(*hdr) + 8) {
637                                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
638                                            "expanded EAP-Packet (plen=%lu)",
639                                            (unsigned long) plen);
640                                 return;
641                         }
642                         sm->respVendor = WPA_GET_BE24(pos);
643                         pos += 3;
644                         sm->respVendorMethod = WPA_GET_BE32(pos);
645                 }
646         }
647
648         wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "
649                    "respMethod=%u respVendor=%u respVendorMethod=%u",
650                    sm->rxResp, sm->respId, sm->respMethod, sm->respVendor,
651                    sm->respVendorMethod);
652 }
653
654
655 static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len)
656 {
657         struct eap_hdr *resp;
658         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
659
660         *len = sizeof(*resp);
661         resp = malloc(*len);
662         if (resp == NULL)
663                 return NULL;
664         resp->code = EAP_CODE_SUCCESS;
665         resp->identifier = id;
666         resp->length = htons(*len);
667
668         return (u8 *) resp;
669 }
670
671
672 static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len)
673 {
674         struct eap_hdr *resp;
675         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
676
677         *len = sizeof(*resp);
678         resp = malloc(*len);
679         if (resp == NULL)
680                 return NULL;
681         resp->code = EAP_CODE_FAILURE;
682         resp->identifier = id;
683         resp->length = htons(*len);
684
685         return (u8 *) resp;
686 }
687
688
689 static int eap_sm_nextId(struct eap_sm *sm, int id)
690 {
691         if (id < 0) {
692                 /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
693                  * random number */
694                 id = rand() & 0xff;
695                 if (id != sm->lastId)
696                         return id;
697         }
698         return (id + 1) & 0xff;
699 }
700
701
702 /**
703  * eap_sm_process_nak - Process EAP-Response/Nak
704  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
705  * @nak_list: Nak list (allowed methods) from the supplicant
706  * @len: Length of nak_list in bytes
707  *
708  * This function is called when EAP-Response/Nak is received from the
709  * supplicant. This can happen for both phase 1 and phase 2 authentications.
710  */
711 void eap_sm_process_nak(struct eap_sm *sm, u8 *nak_list, size_t len)
712 {
713         int i;
714         size_t j;
715
716         if (sm->user == NULL)
717                 return;
718
719         wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
720                    "index %d)", sm->user_eap_method_index);
721
722         wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
723                     (u8 *) sm->user->methods,
724                     EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
725         wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
726                     nak_list, len);
727
728         i = sm->user_eap_method_index;
729         while (i < EAP_MAX_METHODS &&
730                (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
731                 sm->user->methods[i].method != EAP_TYPE_NONE)) {
732                 if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
733                         goto not_found;
734                 for (j = 0; j < len; j++) {
735                         if (nak_list[j] == sm->user->methods[i].method) {
736                                 break;
737                         }
738                 }
739
740                 if (j < len) {
741                         /* found */
742                         i++;
743                         continue;
744                 }
745
746         not_found:
747                 /* not found - remove from the list */
748                 memmove(&sm->user->methods[i], &sm->user->methods[i + 1],
749                         (EAP_MAX_METHODS - i - 1) *
750                         sizeof(sm->user->methods[0]));
751                 sm->user->methods[EAP_MAX_METHODS - 1].vendor =
752                         EAP_VENDOR_IETF;
753                 sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
754         }
755
756         wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
757                     (u8 *) sm->user->methods, EAP_MAX_METHODS *
758                     sizeof(sm->user->methods[0]));
759 }
760
761
762 static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len)
763 {
764         if (nak_list == NULL || sm == NULL || sm->user == NULL)
765                 return;
766
767         if (sm->user->phase2) {
768                 wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
769                            " info was selected - reject");
770                 sm->decision = DECISION_FAILURE;
771                 return;
772         }
773
774         eap_sm_process_nak(sm, nak_list, len);
775 }
776
777
778 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
779 {
780         EapType next;
781         int idx = sm->user_eap_method_index;
782
783         /* In theory, there should be no problems with starting
784          * re-authentication with something else than EAP-Request/Identity and
785          * this does indeed work with wpa_supplicant. However, at least Funk
786          * Supplicant seemed to ignore re-auth if it skipped
787          * EAP-Request/Identity.
788          * Re-auth sets currentId == -1, so that can be used here to select
789          * whether Identity needs to be requested again. */
790         if (sm->identity == NULL || sm->currentId == -1) {
791                 *vendor = EAP_VENDOR_IETF;
792                 next = EAP_TYPE_IDENTITY;
793                 sm->update_user = TRUE;
794         } else if (sm->user && idx < EAP_MAX_METHODS &&
795                    (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
796                     sm->user->methods[idx].method != EAP_TYPE_NONE)) {
797                 *vendor = sm->user->methods[idx].vendor;
798                 next = sm->user->methods[idx].method;
799                 sm->user_eap_method_index++;
800         } else {
801                 *vendor = EAP_VENDOR_IETF;
802                 next = EAP_TYPE_NONE;
803         }
804         wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
805                    *vendor, next);
806         return next;
807 }
808
809
810 static int eap_sm_Policy_getDecision(struct eap_sm *sm)
811 {
812         if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
813             sm->m->isSuccess(sm, sm->eap_method_priv)) {
814                 wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
815                            "SUCCESS");
816                 sm->update_user = TRUE;
817                 return DECISION_SUCCESS;
818         }
819
820         if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
821             !sm->m->isSuccess(sm, sm->eap_method_priv)) {
822                 wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
823                            "FAILURE");
824                 sm->update_user = TRUE;
825                 return DECISION_FAILURE;
826         }
827
828         if ((sm->user == NULL || sm->update_user) && sm->identity) {
829                 if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
830                         wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
831                                    "found from database -> FAILURE");
832                         return DECISION_FAILURE;
833                 }
834                 sm->update_user = FALSE;
835         }
836
837         if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
838             (sm->user->methods[sm->user_eap_method_index].vendor !=
839              EAP_VENDOR_IETF ||
840              sm->user->methods[sm->user_eap_method_index].method !=
841              EAP_TYPE_NONE)) {
842                 wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
843                            "available -> CONTINUE");
844                 return DECISION_CONTINUE;
845         }
846
847         if (sm->identity == NULL || sm->currentId == -1) {
848                 wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
849                            "yet -> CONTINUE");
850                 return DECISION_CONTINUE;
851         }
852
853         wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
854                    "FAILURE");
855         return DECISION_FAILURE;
856 }
857
858
859 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
860 {
861         return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
862 }
863
864
865 /**
866  * eap_sm_step - Step EAP state machine
867  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
868  * Returns: 1 if EAP state was changed or 0 if not
869  *
870  * This function advances EAP state machine to a new state to match with the
871  * current variables. This should be called whenever variables used by the EAP
872  * state machine have changed.
873  */
874 int eap_sm_step(struct eap_sm *sm)
875 {
876         int res = 0;
877         do {
878                 sm->changed = FALSE;
879                 SM_STEP_RUN(EAP);
880                 if (sm->changed)
881                         res = 1;
882         } while (sm->changed);
883         return res;
884 }
885
886
887 /**
888  * eap_set_eapRespData - Set EAP response (eapRespData)
889  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
890  * @eapRespData: EAP-Response payload from the supplicant
891  * @eapRespDataLen: Length of eapRespData in bytes
892  *
893  * This function is called when an EAP-Response is received from a supplicant.
894  */
895 void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData,
896                          size_t eapRespDataLen)
897 {
898         if (sm == NULL)
899                 return;
900         free(sm->eapRespData);
901         sm->eapRespData = malloc(eapRespDataLen);
902         if (sm->eapRespData == NULL)
903                 return;
904         memcpy(sm->eapRespData, eapRespData, eapRespDataLen);
905         sm->eapRespDataLen = eapRespDataLen;
906         wpa_hexdump(MSG_MSGDUMP, "EAP: EAP-Response received",
907                     eapRespData, eapRespDataLen);
908 }
909
910
911 static void eap_user_free(struct eap_user *user)
912 {
913         if (user == NULL)
914                 return;
915         free(user->password);
916         user->password = NULL;
917         free(user);
918 }
919
920
921 /**
922  * eap_sm_init - Allocate and initialize EAP state machine
923  * @eapol_ctx: Context data to be used with eapol_cb calls
924  * @eapol_cb: Pointer to EAPOL callback functions
925  * @conf: EAP configuration
926  * Returns: Pointer to the allocated EAP state machine or %NULL on failure
927  *
928  * This function allocates and initializes an EAP state machine.
929  */
930 struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
931                             struct eap_config *conf)
932 {
933         struct eap_sm *sm;
934
935         sm = wpa_zalloc(sizeof(*sm));
936         if (sm == NULL)
937                 return NULL;
938         sm->eapol_ctx = eapol_ctx;
939         sm->eapol_cb = eapol_cb;
940         sm->MaxRetrans = 10;
941         sm->ssl_ctx = conf->ssl_ctx;
942         sm->eap_sim_db_priv = conf->eap_sim_db_priv;
943         sm->backend_auth = conf->backend_auth;
944
945         wpa_printf(MSG_DEBUG, "EAP: State machine created");
946
947         return sm;
948 }
949
950
951 /**
952  * eap_sm_deinit - Deinitialize and free an EAP state machine
953  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
954  *
955  * This function deinitializes EAP state machine and frees all allocated
956  * resources.
957  */
958 void eap_sm_deinit(struct eap_sm *sm)
959 {
960         if (sm == NULL)
961                 return;
962         wpa_printf(MSG_DEBUG, "EAP: State machine removed");
963         if (sm->m && sm->eap_method_priv)
964                 sm->m->reset(sm, sm->eap_method_priv);
965         free(sm->eapReqData);
966         free(sm->eapKeyData);
967         free(sm->lastReqData);
968         free(sm->eapRespData);
969         free(sm->identity);
970         eap_user_free(sm->user);
971         free(sm);
972 }
973
974
975 /**
976  * eap_sm_notify_cached - Notify EAP state machine of cached PMK
977  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
978  *
979  * This function is called when PMKSA caching is used to skip EAP
980  * authentication.
981  */
982 void eap_sm_notify_cached(struct eap_sm *sm)
983 {
984         if (sm == NULL)
985                 return;
986
987         sm->EAP_state = EAP_SUCCESS;
988 }
989
990
991 /**
992  * eap_sm_pending_cb - EAP state machine callback for a pending EAP request
993  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
994  *
995  * This function is called when data for a pending EAP-Request is received.
996  */
997 void eap_sm_pending_cb(struct eap_sm *sm)
998 {
999         if (sm == NULL)
1000                 return;
1001         wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
1002         if (sm->method_pending == METHOD_PENDING_WAIT)
1003                 sm->method_pending = METHOD_PENDING_CONT;
1004 }
1005
1006
1007 /**
1008  * eap_sm_method_pending - Query whether EAP method is waiting for pending data
1009  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1010  * Returns: 1 if method is waiting for pending data or 0 if not
1011  */
1012 int eap_sm_method_pending(struct eap_sm *sm)
1013 {
1014         if (sm == NULL)
1015                 return 0;
1016         return sm->method_pending == METHOD_PENDING_WAIT;
1017 }
1018
1019
1020 /**
1021  * eap_hdr_validate - Validate EAP header
1022  * @vendor: Expected EAP Vendor-Id (0 = IETF)
1023  * @eap_type: Expected EAP type number
1024  * @msg: EAP frame (starting with EAP header)
1025  * @msglen: Length of msg
1026  * @plen: Pointer to variable to contain the returned payload length
1027  * Returns: Pointer to EAP payload (after type field), or %NULL on failure
1028  *
1029  * This is a helper function for EAP method implementations. This is usually
1030  * called in the beginning of struct eap_method::process() function to verify
1031  * that the received EAP request packet has a valid header. This function is
1032  * able to process both legacy and expanded EAP headers and in most cases, the
1033  * caller can just use the returned payload pointer (into *plen) for processing
1034  * the payload regardless of whether the packet used the expanded EAP header or
1035  * not.
1036  */
1037 const u8 * eap_hdr_validate(int vendor, EapType eap_type,
1038                             const u8 *msg, size_t msglen, size_t *plen)
1039 {
1040         const struct eap_hdr *hdr;
1041         const u8 *pos;
1042         size_t len;
1043
1044         hdr = (const struct eap_hdr *) msg;
1045
1046         if (msglen < sizeof(*hdr)) {
1047                 wpa_printf(MSG_INFO, "EAP: Too short EAP frame");
1048                 return NULL;
1049         }
1050
1051         len = be_to_host16(hdr->length);
1052         if (len < sizeof(*hdr) + 1 || len > msglen) {
1053                 wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
1054                 return NULL;
1055         }
1056
1057         pos = (const u8 *) (hdr + 1);
1058
1059         if (*pos == EAP_TYPE_EXPANDED) {
1060                 int exp_vendor;
1061                 u32 exp_type;
1062                 if (len < sizeof(*hdr) + 8) {
1063                         wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP "
1064                                    "length");
1065                         return NULL;
1066                 }
1067                 pos++;
1068                 exp_vendor = WPA_GET_BE24(pos);
1069                 pos += 3;
1070                 exp_type = WPA_GET_BE32(pos);
1071                 pos += 4;
1072                 if (exp_vendor != vendor || exp_type != (u32) eap_type) {
1073                         wpa_printf(MSG_INFO, "EAP: Invalid expanded frame "
1074                                    "type");
1075                         return NULL;
1076                 }
1077
1078                 *plen = len - sizeof(*hdr) - 8;
1079                 return pos;
1080         } else {
1081                 if (vendor != EAP_VENDOR_IETF || *pos != eap_type) {
1082                         wpa_printf(MSG_INFO, "EAP: Invalid frame type");
1083                         return NULL;
1084                 }
1085                 *plen = len - sizeof(*hdr) - 1;
1086                 return pos + 1;
1087         }
1088 }
1089
1090
1091 /**
1092  * eap_msg_alloc - Allocate a buffer for an EAP message
1093  * @vendor: Vendor-Id (0 = IETF)
1094  * @type: EAP type
1095  * @len: Buffer for returning message length
1096  * @payload_len: Payload length in bytes (data after Type)
1097  * @code: Message Code (EAP_CODE_*)
1098  * @identifier: Identifier
1099  * @payload: Pointer to payload pointer that will be set to point to the
1100  * beginning of the payload or %NULL if payload pointer is not needed
1101  * Returns: Pointer to the allocated message buffer or %NULL on error
1102  *
1103  * This function can be used to allocate a buffer for an EAP message and fill
1104  * in the EAP header. This function is automatically using expanded EAP header
1105  * if the selected Vendor-Id is not IETF. In other words, most EAP methods do
1106  * not need to separately select which header type to use when using this
1107  * function to allocate the message buffers.
1108  */
1109 struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len,
1110                                size_t payload_len, u8 code, u8 identifier,
1111                                u8 **payload)
1112 {
1113         struct eap_hdr *hdr;
1114         u8 *pos;
1115
1116         *len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) +
1117                 payload_len;
1118         hdr = malloc(*len);
1119         if (hdr) {
1120                 hdr->code = code;
1121                 hdr->identifier = identifier;
1122                 hdr->length = host_to_be16(*len);
1123                 pos = (u8 *) (hdr + 1);
1124                 if (vendor == EAP_VENDOR_IETF) {
1125                         *pos++ = type;
1126                 } else {
1127                         *pos++ = EAP_TYPE_EXPANDED;
1128                         WPA_PUT_BE24(pos, vendor);
1129                         pos += 3;
1130                         WPA_PUT_BE32(pos, type);
1131                         pos += 4;
1132                 }
1133                 if (payload)
1134                         *payload = pos;
1135         }
1136
1137         return hdr;
1138 }