]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/eapol_supp/eapol_supp_sm.c
STA: Allow PTK rekeying without Ext KeyID to be disabled as a workaround
[thirdparty/hostap.git] / src / eapol_supp / eapol_supp_sm.c
1 /*
2 * EAPOL supplicant state machines
3 * Copyright (c) 2004-2012, 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
9 #include "includes.h"
10
11 #include "common.h"
12 #include "state_machine.h"
13 #include "wpabuf.h"
14 #include "eloop.h"
15 #include "crypto/crypto.h"
16 #include "crypto/md5.h"
17 #include "common/eapol_common.h"
18 #include "eap_peer/eap.h"
19 #include "eap_peer/eap_config.h"
20 #include "eap_peer/eap_proxy.h"
21 #include "eapol_supp_sm.h"
22
23 #define STATE_MACHINE_DATA struct eapol_sm
24 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
25
26
27 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
28
29 /**
30 * struct eapol_sm - Internal data for EAPOL state machines
31 */
32 struct eapol_sm {
33 /* Timers */
34 unsigned int authWhile;
35 unsigned int heldWhile;
36 unsigned int startWhen;
37 unsigned int idleWhile; /* for EAP state machine */
38 int timer_tick_enabled;
39
40 /* Global variables */
41 Boolean eapFail;
42 Boolean eapolEap;
43 Boolean eapSuccess;
44 Boolean initialize;
45 Boolean keyDone;
46 Boolean keyRun;
47 PortControl portControl;
48 Boolean portEnabled;
49 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */
50 Boolean portValid;
51 Boolean suppAbort;
52 Boolean suppFail;
53 Boolean suppStart;
54 Boolean suppSuccess;
55 Boolean suppTimeout;
56
57 /* Supplicant PAE state machine */
58 enum {
59 SUPP_PAE_UNKNOWN = 0,
60 SUPP_PAE_DISCONNECTED = 1,
61 SUPP_PAE_LOGOFF = 2,
62 SUPP_PAE_CONNECTING = 3,
63 SUPP_PAE_AUTHENTICATING = 4,
64 SUPP_PAE_AUTHENTICATED = 5,
65 /* unused(6) */
66 SUPP_PAE_HELD = 7,
67 SUPP_PAE_RESTART = 8,
68 SUPP_PAE_S_FORCE_AUTH = 9,
69 SUPP_PAE_S_FORCE_UNAUTH = 10
70 } SUPP_PAE_state; /* dot1xSuppPaeState */
71 /* Variables */
72 Boolean userLogoff;
73 Boolean logoffSent;
74 unsigned int startCount;
75 Boolean eapRestart;
76 PortControl sPortMode;
77 /* Constants */
78 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
79 unsigned int startPeriod; /* dot1xSuppStartPeriod */
80 unsigned int maxStart; /* dot1xSuppMaxStart */
81
82 /* Key Receive state machine */
83 enum {
84 KEY_RX_UNKNOWN = 0,
85 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
86 } KEY_RX_state;
87 /* Variables */
88 Boolean rxKey;
89
90 /* Supplicant Backend state machine */
91 enum {
92 SUPP_BE_UNKNOWN = 0,
93 SUPP_BE_INITIALIZE = 1,
94 SUPP_BE_IDLE = 2,
95 SUPP_BE_REQUEST = 3,
96 SUPP_BE_RECEIVE = 4,
97 SUPP_BE_RESPONSE = 5,
98 SUPP_BE_FAIL = 6,
99 SUPP_BE_TIMEOUT = 7,
100 SUPP_BE_SUCCESS = 8
101 } SUPP_BE_state; /* dot1xSuppBackendPaeState */
102 /* Variables */
103 Boolean eapNoResp;
104 Boolean eapReq;
105 Boolean eapResp;
106 /* Constants */
107 unsigned int authPeriod; /* dot1xSuppAuthPeriod */
108
109 /* Statistics */
110 unsigned int dot1xSuppEapolFramesRx;
111 unsigned int dot1xSuppEapolFramesTx;
112 unsigned int dot1xSuppEapolStartFramesTx;
113 unsigned int dot1xSuppEapolLogoffFramesTx;
114 unsigned int dot1xSuppEapolRespFramesTx;
115 unsigned int dot1xSuppEapolReqIdFramesRx;
116 unsigned int dot1xSuppEapolReqFramesRx;
117 unsigned int dot1xSuppInvalidEapolFramesRx;
118 unsigned int dot1xSuppEapLengthErrorFramesRx;
119 unsigned int dot1xSuppLastEapolFrameVersion;
120 unsigned char dot1xSuppLastEapolFrameSource[6];
121
122 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
123 Boolean changed;
124 struct eap_sm *eap;
125 struct eap_peer_config *config;
126 Boolean initial_req;
127 u8 *last_rx_key;
128 size_t last_rx_key_len;
129 struct wpabuf *eapReqData; /* for EAP */
130 Boolean altAccept; /* for EAP */
131 Boolean altReject; /* for EAP */
132 Boolean eapTriggerStart;
133 Boolean replay_counter_valid;
134 u8 last_replay_counter[16];
135 struct eapol_config conf;
136 struct eapol_ctx *ctx;
137 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
138 cb_status;
139 Boolean cached_pmk;
140
141 Boolean unicast_key_received, broadcast_key_received;
142
143 Boolean force_authorized_update;
144
145 #ifdef CONFIG_EAP_PROXY
146 Boolean use_eap_proxy;
147 struct eap_proxy_sm *eap_proxy;
148 #endif /* CONFIG_EAP_PROXY */
149 };
150
151
152 static void eapol_sm_txLogoff(struct eapol_sm *sm);
153 static void eapol_sm_txStart(struct eapol_sm *sm);
154 static void eapol_sm_processKey(struct eapol_sm *sm);
155 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
156 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
157 static void eapol_sm_abortSupp(struct eapol_sm *sm);
158 static void eapol_sm_abort_cached(struct eapol_sm *sm);
159 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
160 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
161 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
162
163
164 /* Port Timers state machine - implemented as a function that will be called
165 * once a second as a registered event loop timeout */
166 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
167 {
168 struct eapol_sm *sm = timeout_ctx;
169
170 if (sm->authWhile > 0) {
171 sm->authWhile--;
172 if (sm->authWhile == 0)
173 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
174 }
175 if (sm->heldWhile > 0) {
176 sm->heldWhile--;
177 if (sm->heldWhile == 0)
178 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
179 }
180 if (sm->startWhen > 0) {
181 sm->startWhen--;
182 if (sm->startWhen == 0)
183 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
184 }
185 if (sm->idleWhile > 0) {
186 sm->idleWhile--;
187 if (sm->idleWhile == 0)
188 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
189 }
190
191 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
192 if (eloop_register_timeout(1, 0, eapol_port_timers_tick,
193 eloop_ctx, sm) < 0)
194 sm->timer_tick_enabled = 0;
195 } else {
196 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
197 sm->timer_tick_enabled = 0;
198 }
199 eapol_sm_step(sm);
200 }
201
202
203 static int eapol_sm_confirm_auth(struct eapol_sm *sm)
204 {
205 if (!sm->ctx->confirm_auth_cb)
206 return 0;
207
208 return sm->ctx->confirm_auth_cb(sm->ctx->ctx);
209 }
210
211
212 static void eapol_enable_timer_tick(struct eapol_sm *sm)
213 {
214 if (sm->timer_tick_enabled)
215 return;
216 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
217 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
218 if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0)
219 sm->timer_tick_enabled = 1;
220 }
221
222
223 SM_STATE(SUPP_PAE, LOGOFF)
224 {
225 SM_ENTRY(SUPP_PAE, LOGOFF);
226 eapol_sm_txLogoff(sm);
227 sm->logoffSent = TRUE;
228 eapol_sm_set_port_unauthorized(sm);
229 }
230
231
232 SM_STATE(SUPP_PAE, DISCONNECTED)
233 {
234 SM_ENTRY(SUPP_PAE, DISCONNECTED);
235 sm->sPortMode = Auto;
236 sm->startCount = 0;
237 sm->eapTriggerStart = FALSE;
238 sm->logoffSent = FALSE;
239 eapol_sm_set_port_unauthorized(sm);
240 sm->suppAbort = TRUE;
241
242 sm->unicast_key_received = FALSE;
243 sm->broadcast_key_received = FALSE;
244
245 /*
246 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
247 * allows the timer tick to be stopped more quickly when the port is
248 * not enabled. Since this variable is used only within HELD state,
249 * clearing it on initialization does not change actual state machine
250 * behavior.
251 */
252 sm->heldWhile = 0;
253 }
254
255
256 SM_STATE(SUPP_PAE, CONNECTING)
257 {
258 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING ||
259 sm->SUPP_PAE_state == SUPP_PAE_HELD;
260 SM_ENTRY(SUPP_PAE, CONNECTING);
261
262 if (sm->eapTriggerStart)
263 send_start = 1;
264 if (sm->ctx->preauth)
265 send_start = 1;
266 sm->eapTriggerStart = FALSE;
267
268 if (send_start) {
269 sm->startWhen = sm->startPeriod;
270 sm->startCount++;
271 } else {
272 /*
273 * Do not send EAPOL-Start immediately since in most cases,
274 * Authenticator is going to start authentication immediately
275 * after association and an extra EAPOL-Start is just going to
276 * delay authentication. Use a short timeout to send the first
277 * EAPOL-Start if Authenticator does not start authentication.
278 */
279 if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) {
280 /* Reduce latency on starting WPS negotiation. */
281 wpa_printf(MSG_DEBUG,
282 "EAPOL: Using shorter startWhen for WPS");
283 sm->startWhen = 1;
284 } else {
285 sm->startWhen = 2;
286 }
287 }
288 eapol_enable_timer_tick(sm);
289 sm->eapolEap = FALSE;
290 if (send_start)
291 eapol_sm_txStart(sm);
292 }
293
294
295 SM_STATE(SUPP_PAE, AUTHENTICATING)
296 {
297 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
298 sm->startCount = 0;
299 sm->suppSuccess = FALSE;
300 sm->suppFail = FALSE;
301 sm->suppTimeout = FALSE;
302 sm->keyRun = FALSE;
303 sm->keyDone = FALSE;
304 sm->suppStart = TRUE;
305 }
306
307
308 SM_STATE(SUPP_PAE, HELD)
309 {
310 SM_ENTRY(SUPP_PAE, HELD);
311 sm->heldWhile = sm->heldPeriod;
312 eapol_enable_timer_tick(sm);
313 eapol_sm_set_port_unauthorized(sm);
314 sm->cb_status = EAPOL_CB_FAILURE;
315 }
316
317
318 SM_STATE(SUPP_PAE, AUTHENTICATED)
319 {
320 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
321 eapol_sm_set_port_authorized(sm);
322 sm->cb_status = EAPOL_CB_SUCCESS;
323 }
324
325
326 SM_STATE(SUPP_PAE, RESTART)
327 {
328 if (eapol_sm_confirm_auth(sm)) {
329 /* Don't process restart, we are already reconnecting */
330 return;
331 }
332
333 SM_ENTRY(SUPP_PAE, RESTART);
334 sm->eapRestart = TRUE;
335 if (sm->altAccept) {
336 /*
337 * Prevent EAP peer state machine from failing due to prior
338 * external EAP success notification (altSuccess=TRUE in the
339 * IDLE state could result in a transition to the FAILURE state.
340 */
341 wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
342 sm->eapSuccess = FALSE;
343 sm->altAccept = FALSE;
344 }
345 }
346
347
348 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
349 {
350 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
351 eapol_sm_set_port_authorized(sm);
352 sm->sPortMode = ForceAuthorized;
353 }
354
355
356 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
357 {
358 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
359 eapol_sm_set_port_unauthorized(sm);
360 sm->sPortMode = ForceUnauthorized;
361 eapol_sm_txLogoff(sm);
362 }
363
364
365 SM_STEP(SUPP_PAE)
366 {
367 if ((sm->userLogoff && !sm->logoffSent) &&
368 !(sm->initialize || !sm->portEnabled))
369 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
370 else if (((sm->portControl == Auto) &&
371 (sm->sPortMode != sm->portControl)) ||
372 sm->initialize || !sm->portEnabled)
373 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
374 else if ((sm->portControl == ForceAuthorized) &&
375 (sm->sPortMode != sm->portControl) &&
376 !(sm->initialize || !sm->portEnabled))
377 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
378 else if ((sm->portControl == ForceUnauthorized) &&
379 (sm->sPortMode != sm->portControl) &&
380 !(sm->initialize || !sm->portEnabled))
381 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
382 else switch (sm->SUPP_PAE_state) {
383 case SUPP_PAE_UNKNOWN:
384 break;
385 case SUPP_PAE_LOGOFF:
386 if (!sm->userLogoff)
387 SM_ENTER(SUPP_PAE, DISCONNECTED);
388 break;
389 case SUPP_PAE_DISCONNECTED:
390 SM_ENTER(SUPP_PAE, CONNECTING);
391 break;
392 case SUPP_PAE_CONNECTING:
393 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
394 SM_ENTER(SUPP_PAE, CONNECTING);
395 else if (sm->startWhen == 0 &&
396 sm->startCount >= sm->maxStart &&
397 sm->portValid)
398 SM_ENTER(SUPP_PAE, AUTHENTICATED);
399 else if (sm->eapSuccess || sm->eapFail)
400 SM_ENTER(SUPP_PAE, AUTHENTICATING);
401 else if (sm->eapolEap)
402 SM_ENTER(SUPP_PAE, RESTART);
403 else if (sm->startWhen == 0 &&
404 sm->startCount >= sm->maxStart &&
405 !sm->portValid)
406 SM_ENTER(SUPP_PAE, HELD);
407 break;
408 case SUPP_PAE_AUTHENTICATING:
409 if (sm->eapSuccess && !sm->portValid &&
410 sm->conf.accept_802_1x_keys &&
411 sm->conf.required_keys == 0) {
412 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
413 "plaintext connection; no EAPOL-Key frames "
414 "required");
415 sm->portValid = TRUE;
416 if (sm->ctx->eapol_done_cb)
417 sm->ctx->eapol_done_cb(sm->ctx->ctx);
418 }
419 if (sm->eapSuccess && sm->portValid)
420 SM_ENTER(SUPP_PAE, AUTHENTICATED);
421 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
422 SM_ENTER(SUPP_PAE, HELD);
423 else if (sm->suppTimeout)
424 SM_ENTER(SUPP_PAE, CONNECTING);
425 else if (sm->eapTriggerStart)
426 SM_ENTER(SUPP_PAE, CONNECTING);
427 break;
428 case SUPP_PAE_HELD:
429 if (sm->heldWhile == 0)
430 SM_ENTER(SUPP_PAE, CONNECTING);
431 else if (sm->eapolEap)
432 SM_ENTER(SUPP_PAE, RESTART);
433 break;
434 case SUPP_PAE_AUTHENTICATED:
435 if (sm->eapolEap && sm->portValid)
436 SM_ENTER(SUPP_PAE, RESTART);
437 else if (!sm->portValid)
438 SM_ENTER(SUPP_PAE, DISCONNECTED);
439 break;
440 case SUPP_PAE_RESTART:
441 if (!sm->eapRestart)
442 SM_ENTER(SUPP_PAE, AUTHENTICATING);
443 break;
444 case SUPP_PAE_S_FORCE_AUTH:
445 break;
446 case SUPP_PAE_S_FORCE_UNAUTH:
447 break;
448 }
449 }
450
451
452 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
453 {
454 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
455 }
456
457
458 SM_STATE(KEY_RX, KEY_RECEIVE)
459 {
460 SM_ENTRY(KEY_RX, KEY_RECEIVE);
461 eapol_sm_processKey(sm);
462 sm->rxKey = FALSE;
463 }
464
465
466 SM_STEP(KEY_RX)
467 {
468 if (sm->initialize || !sm->portEnabled)
469 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
470 switch (sm->KEY_RX_state) {
471 case KEY_RX_UNKNOWN:
472 break;
473 case KEY_RX_NO_KEY_RECEIVE:
474 if (sm->rxKey)
475 SM_ENTER(KEY_RX, KEY_RECEIVE);
476 break;
477 case KEY_RX_KEY_RECEIVE:
478 if (sm->rxKey)
479 SM_ENTER(KEY_RX, KEY_RECEIVE);
480 break;
481 }
482 }
483
484
485 SM_STATE(SUPP_BE, REQUEST)
486 {
487 SM_ENTRY(SUPP_BE, REQUEST);
488 sm->authWhile = 0;
489 sm->eapReq = TRUE;
490 eapol_sm_getSuppRsp(sm);
491 }
492
493
494 SM_STATE(SUPP_BE, RESPONSE)
495 {
496 SM_ENTRY(SUPP_BE, RESPONSE);
497 eapol_sm_txSuppRsp(sm);
498 sm->eapResp = FALSE;
499 }
500
501
502 SM_STATE(SUPP_BE, SUCCESS)
503 {
504 SM_ENTRY(SUPP_BE, SUCCESS);
505 sm->keyRun = TRUE;
506 sm->suppSuccess = TRUE;
507
508 #ifdef CONFIG_EAP_PROXY
509 if (sm->use_eap_proxy) {
510 if (eap_proxy_key_available(sm->eap_proxy)) {
511 u8 *session_id, *emsk;
512 size_t session_id_len, emsk_len;
513
514 /* New key received - clear IEEE 802.1X EAPOL-Key replay
515 * counter */
516 sm->replay_counter_valid = FALSE;
517
518 session_id = eap_proxy_get_eap_session_id(
519 sm->eap_proxy, &session_id_len);
520 emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len);
521 if (sm->config->erp && session_id && emsk) {
522 eap_peer_erp_init(sm->eap, session_id,
523 session_id_len, emsk,
524 emsk_len);
525 } else {
526 os_free(session_id);
527 bin_clear_free(emsk, emsk_len);
528 }
529 }
530 return;
531 }
532 #endif /* CONFIG_EAP_PROXY */
533
534 if (eap_key_available(sm->eap)) {
535 /* New key received - clear IEEE 802.1X EAPOL-Key replay
536 * counter */
537 sm->replay_counter_valid = FALSE;
538 }
539 }
540
541
542 SM_STATE(SUPP_BE, FAIL)
543 {
544 SM_ENTRY(SUPP_BE, FAIL);
545 sm->suppFail = TRUE;
546 }
547
548
549 SM_STATE(SUPP_BE, TIMEOUT)
550 {
551 SM_ENTRY(SUPP_BE, TIMEOUT);
552 sm->suppTimeout = TRUE;
553 }
554
555
556 SM_STATE(SUPP_BE, IDLE)
557 {
558 SM_ENTRY(SUPP_BE, IDLE);
559 sm->suppStart = FALSE;
560 sm->initial_req = TRUE;
561 }
562
563
564 SM_STATE(SUPP_BE, INITIALIZE)
565 {
566 SM_ENTRY(SUPP_BE, INITIALIZE);
567 eapol_sm_abortSupp(sm);
568 sm->suppAbort = FALSE;
569
570 /*
571 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
572 * allows the timer tick to be stopped more quickly when the port is
573 * not enabled. Since this variable is used only within RECEIVE state,
574 * clearing it on initialization does not change actual state machine
575 * behavior.
576 */
577 sm->authWhile = 0;
578 }
579
580
581 SM_STATE(SUPP_BE, RECEIVE)
582 {
583 SM_ENTRY(SUPP_BE, RECEIVE);
584 sm->authWhile = sm->authPeriod;
585 eapol_enable_timer_tick(sm);
586 sm->eapolEap = FALSE;
587 sm->eapNoResp = FALSE;
588 sm->initial_req = FALSE;
589 }
590
591
592 SM_STEP(SUPP_BE)
593 {
594 if (sm->initialize || sm->suppAbort)
595 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
596 else switch (sm->SUPP_BE_state) {
597 case SUPP_BE_UNKNOWN:
598 break;
599 case SUPP_BE_REQUEST:
600 /*
601 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
602 * and SUCCESS based on eapFail and eapSuccess, respectively.
603 * However, IEEE Std 802.1X-2004 is also specifying that
604 * eapNoResp should be set in conjunction with eapSuccess and
605 * eapFail which would mean that more than one of the
606 * transitions here would be activated at the same time.
607 * Skipping RESPONSE and/or RECEIVE states in these cases can
608 * cause problems and the direct transitions to do not seem
609 * correct. Because of this, the conditions for these
610 * transitions are verified only after eapNoResp. They are
611 * unlikely to be used since eapNoResp should always be set if
612 * either of eapSuccess or eapFail is set.
613 */
614 if (sm->eapResp && sm->eapNoResp) {
615 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
616 "eapResp and eapNoResp set?!");
617 }
618 if (sm->eapResp)
619 SM_ENTER(SUPP_BE, RESPONSE);
620 else if (sm->eapNoResp)
621 SM_ENTER(SUPP_BE, RECEIVE);
622 else if (sm->eapFail)
623 SM_ENTER(SUPP_BE, FAIL);
624 else if (sm->eapSuccess)
625 SM_ENTER(SUPP_BE, SUCCESS);
626 break;
627 case SUPP_BE_RESPONSE:
628 SM_ENTER(SUPP_BE, RECEIVE);
629 break;
630 case SUPP_BE_SUCCESS:
631 SM_ENTER(SUPP_BE, IDLE);
632 break;
633 case SUPP_BE_FAIL:
634 SM_ENTER(SUPP_BE, IDLE);
635 break;
636 case SUPP_BE_TIMEOUT:
637 SM_ENTER(SUPP_BE, IDLE);
638 break;
639 case SUPP_BE_IDLE:
640 if (sm->eapFail && sm->suppStart)
641 SM_ENTER(SUPP_BE, FAIL);
642 else if (sm->eapolEap && sm->suppStart)
643 SM_ENTER(SUPP_BE, REQUEST);
644 else if (sm->eapSuccess && sm->suppStart)
645 SM_ENTER(SUPP_BE, SUCCESS);
646 break;
647 case SUPP_BE_INITIALIZE:
648 SM_ENTER(SUPP_BE, IDLE);
649 break;
650 case SUPP_BE_RECEIVE:
651 if (sm->eapolEap)
652 SM_ENTER(SUPP_BE, REQUEST);
653 else if (sm->eapFail)
654 SM_ENTER(SUPP_BE, FAIL);
655 else if (sm->authWhile == 0)
656 SM_ENTER(SUPP_BE, TIMEOUT);
657 else if (sm->eapSuccess)
658 SM_ENTER(SUPP_BE, SUCCESS);
659 break;
660 }
661 }
662
663
664 static void eapol_sm_txLogoff(struct eapol_sm *sm)
665 {
666 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
667 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
668 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
669 sm->dot1xSuppEapolLogoffFramesTx++;
670 sm->dot1xSuppEapolFramesTx++;
671 }
672
673
674 static void eapol_sm_txStart(struct eapol_sm *sm)
675 {
676 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
677 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
678 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
679 sm->dot1xSuppEapolStartFramesTx++;
680 sm->dot1xSuppEapolFramesTx++;
681 }
682
683
684 #define IEEE8021X_ENCR_KEY_LEN 32
685 #define IEEE8021X_SIGN_KEY_LEN 32
686
687 struct eap_key_data {
688 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
689 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
690 };
691
692
693 static void eapol_sm_processKey(struct eapol_sm *sm)
694 {
695 #ifndef CONFIG_FIPS
696 struct ieee802_1x_hdr *hdr;
697 struct ieee802_1x_eapol_key *key;
698 struct eap_key_data keydata;
699 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
700 #ifndef CONFIG_NO_RC4
701 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
702 #endif /* CONFIG_NO_RC4 */
703 int key_len, res, sign_key_len, encr_key_len;
704 u16 rx_key_length;
705 size_t plen;
706
707 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
708 if (sm->last_rx_key == NULL)
709 return;
710
711 if (!sm->conf.accept_802_1x_keys) {
712 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
713 " even though this was not accepted - "
714 "ignoring this packet");
715 return;
716 }
717
718 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
719 return;
720 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
721 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
722 plen = be_to_host16(hdr->length);
723 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
724 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
725 return;
726 }
727 rx_key_length = WPA_GET_BE16(key->key_length);
728 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
729 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
730 hdr->version, hdr->type, be_to_host16(hdr->length),
731 key->type, rx_key_length, key->key_index);
732
733 eapol_sm_notify_lower_layer_success(sm, 1);
734 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
735 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
736 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
737 if (res < 0) {
738 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
739 "decrypting EAPOL-Key keys");
740 return;
741 }
742 if (res == 16) {
743 /* LEAP derives only 16 bytes of keying material. */
744 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
745 if (res) {
746 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
747 "master key for decrypting EAPOL-Key keys");
748 return;
749 }
750 sign_key_len = 16;
751 encr_key_len = 16;
752 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
753 } else if (res) {
754 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
755 "data for decrypting EAPOL-Key keys (res=%d)", res);
756 return;
757 }
758
759 /* The key replay_counter must increase when same master key */
760 if (sm->replay_counter_valid &&
761 os_memcmp(sm->last_replay_counter, key->replay_counter,
762 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
763 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
764 "not increase - ignoring key");
765 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
766 sm->last_replay_counter,
767 IEEE8021X_REPLAY_COUNTER_LEN);
768 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
769 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
770 return;
771 }
772
773 /* Verify key signature (HMAC-MD5) */
774 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
775 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
776 hmac_md5(keydata.sign_key, sign_key_len,
777 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
778 key->key_signature);
779 if (os_memcmp_const(orig_key_sign, key->key_signature,
780 IEEE8021X_KEY_SIGN_LEN) != 0) {
781 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
782 "EAPOL-Key packet");
783 os_memcpy(key->key_signature, orig_key_sign,
784 IEEE8021X_KEY_SIGN_LEN);
785 return;
786 }
787 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
788
789 key_len = plen - sizeof(*key);
790 if (key_len > 32 || rx_key_length > 32) {
791 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
792 key_len ? key_len : rx_key_length);
793 return;
794 }
795 if (key_len == rx_key_length) {
796 #ifdef CONFIG_NO_RC4
797 if (encr_key_len) {
798 /* otherwise unused */
799 }
800 wpa_printf(MSG_ERROR, "EAPOL: RC4 not supported in the build");
801 return;
802 #else /* CONFIG_NO_RC4 */
803 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
804 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
805 encr_key_len);
806 os_memcpy(datakey, key + 1, key_len);
807 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
808 datakey, key_len);
809 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
810 datakey, key_len);
811 #endif /* CONFIG_NO_RC4 */
812 } else if (key_len == 0) {
813 /*
814 * IEEE 802.1X-2004 specifies that least significant Key Length
815 * octets from MS-MPPE-Send-Key are used as the key if the key
816 * data is not present. This seems to be meaning the beginning
817 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
818 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
819 * Anyway, taking the beginning of the keying material from EAP
820 * seems to interoperate with Authenticators.
821 */
822 key_len = rx_key_length;
823 os_memcpy(datakey, keydata.encr_key, key_len);
824 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
825 "material data encryption key",
826 datakey, key_len);
827 } else {
828 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
829 "(key_length=%d)", key_len, rx_key_length);
830 return;
831 }
832
833 sm->replay_counter_valid = TRUE;
834 os_memcpy(sm->last_replay_counter, key->replay_counter,
835 IEEE8021X_REPLAY_COUNTER_LEN);
836
837 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
838 "len %d",
839 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
840 "unicast" : "broadcast",
841 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
842
843 if (sm->ctx->set_wep_key &&
844 sm->ctx->set_wep_key(sm->ctx->ctx,
845 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
846 key->key_index & IEEE8021X_KEY_INDEX_MASK,
847 datakey, key_len) < 0) {
848 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
849 " driver.");
850 } else {
851 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
852 sm->unicast_key_received = TRUE;
853 else
854 sm->broadcast_key_received = TRUE;
855
856 if ((sm->unicast_key_received ||
857 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
858 (sm->broadcast_key_received ||
859 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
860 {
861 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
862 "frames received");
863 sm->portValid = TRUE;
864 if (sm->ctx->eapol_done_cb)
865 sm->ctx->eapol_done_cb(sm->ctx->ctx);
866 }
867 }
868 #endif /* CONFIG_FIPS */
869 }
870
871
872 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
873 {
874 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
875 /* EAP layer processing; no special code is needed, since Supplicant
876 * Backend state machine is waiting for eapNoResp or eapResp to be set
877 * and these are only set in the EAP state machine when the processing
878 * has finished. */
879 }
880
881
882 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
883 {
884 struct wpabuf *resp;
885
886 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
887
888 #ifdef CONFIG_EAP_PROXY
889 if (sm->use_eap_proxy) {
890 /* Get EAP Response from EAP Proxy */
891 resp = eap_proxy_get_eapRespData(sm->eap_proxy);
892 if (resp == NULL) {
893 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
894 "response data not available");
895 return;
896 }
897 } else
898 #endif /* CONFIG_EAP_PROXY */
899
900 resp = eap_get_eapRespData(sm->eap);
901 if (resp == NULL) {
902 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
903 "not available");
904 return;
905 }
906
907 /* Send EAP-Packet from the EAP layer to the Authenticator */
908 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
909 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
910 wpabuf_len(resp));
911
912 /* eapRespData is not used anymore, so free it here */
913 wpabuf_free(resp);
914
915 if (sm->initial_req)
916 sm->dot1xSuppEapolReqIdFramesRx++;
917 else
918 sm->dot1xSuppEapolReqFramesRx++;
919 sm->dot1xSuppEapolRespFramesTx++;
920 sm->dot1xSuppEapolFramesTx++;
921 }
922
923
924 static void eapol_sm_abortSupp(struct eapol_sm *sm)
925 {
926 /* release system resources that may have been allocated for the
927 * authentication session */
928 os_free(sm->last_rx_key);
929 sm->last_rx_key = NULL;
930 wpabuf_free(sm->eapReqData);
931 sm->eapReqData = NULL;
932 eap_sm_abort(sm->eap);
933 #ifdef CONFIG_EAP_PROXY
934 eap_proxy_sm_abort(sm->eap_proxy);
935 #endif /* CONFIG_EAP_PROXY */
936 }
937
938
939 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
940 {
941 eapol_sm_step(timeout_ctx);
942 }
943
944
945 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
946 {
947 int cb;
948
949 cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
950 sm->force_authorized_update = FALSE;
951 sm->suppPortStatus = Authorized;
952 if (cb && sm->ctx->port_cb)
953 sm->ctx->port_cb(sm->ctx->ctx, 1);
954 }
955
956
957 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
958 {
959 int cb;
960
961 cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
962 sm->force_authorized_update = FALSE;
963 sm->suppPortStatus = Unauthorized;
964 if (cb && sm->ctx->port_cb)
965 sm->ctx->port_cb(sm->ctx->ctx, 0);
966 }
967
968
969 /**
970 * eapol_sm_step - EAPOL state machine step function
971 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
972 *
973 * This function is called to notify the state machine about changed external
974 * variables. It will step through the EAPOL state machines in loop to process
975 * all triggered state changes.
976 */
977 void eapol_sm_step(struct eapol_sm *sm)
978 {
979 int i;
980
981 /* In theory, it should be ok to run this in loop until !changed.
982 * However, it is better to use a limit on number of iterations to
983 * allow events (e.g., SIGTERM) to stop the program cleanly if the
984 * state machine were to generate a busy loop. */
985 for (i = 0; i < 100; i++) {
986 sm->changed = FALSE;
987 SM_STEP_RUN(SUPP_PAE);
988 SM_STEP_RUN(KEY_RX);
989 SM_STEP_RUN(SUPP_BE);
990 #ifdef CONFIG_EAP_PROXY
991 if (sm->use_eap_proxy) {
992 /* Drive the EAP proxy state machine */
993 if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
994 sm->changed = TRUE;
995 } else
996 #endif /* CONFIG_EAP_PROXY */
997 if (eap_peer_sm_step(sm->eap))
998 sm->changed = TRUE;
999 if (!sm->changed)
1000 break;
1001 }
1002
1003 if (sm->changed) {
1004 /* restart EAPOL state machine step from timeout call in order
1005 * to allow other events to be processed. */
1006 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
1007 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
1008 }
1009
1010 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
1011 enum eapol_supp_result result;
1012 if (sm->cb_status == EAPOL_CB_SUCCESS)
1013 result = EAPOL_SUPP_RESULT_SUCCESS;
1014 else if (eap_peer_was_failure_expected(sm->eap))
1015 result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
1016 else
1017 result = EAPOL_SUPP_RESULT_FAILURE;
1018 sm->cb_status = EAPOL_CB_IN_PROGRESS;
1019 sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
1020 }
1021 }
1022
1023
1024 #ifdef CONFIG_CTRL_IFACE
1025 static const char *eapol_supp_pae_state(int state)
1026 {
1027 switch (state) {
1028 case SUPP_PAE_LOGOFF:
1029 return "LOGOFF";
1030 case SUPP_PAE_DISCONNECTED:
1031 return "DISCONNECTED";
1032 case SUPP_PAE_CONNECTING:
1033 return "CONNECTING";
1034 case SUPP_PAE_AUTHENTICATING:
1035 return "AUTHENTICATING";
1036 case SUPP_PAE_HELD:
1037 return "HELD";
1038 case SUPP_PAE_AUTHENTICATED:
1039 return "AUTHENTICATED";
1040 case SUPP_PAE_RESTART:
1041 return "RESTART";
1042 default:
1043 return "UNKNOWN";
1044 }
1045 }
1046
1047
1048 static const char *eapol_supp_be_state(int state)
1049 {
1050 switch (state) {
1051 case SUPP_BE_REQUEST:
1052 return "REQUEST";
1053 case SUPP_BE_RESPONSE:
1054 return "RESPONSE";
1055 case SUPP_BE_SUCCESS:
1056 return "SUCCESS";
1057 case SUPP_BE_FAIL:
1058 return "FAIL";
1059 case SUPP_BE_TIMEOUT:
1060 return "TIMEOUT";
1061 case SUPP_BE_IDLE:
1062 return "IDLE";
1063 case SUPP_BE_INITIALIZE:
1064 return "INITIALIZE";
1065 case SUPP_BE_RECEIVE:
1066 return "RECEIVE";
1067 default:
1068 return "UNKNOWN";
1069 }
1070 }
1071
1072
1073 static const char * eapol_port_status(PortStatus status)
1074 {
1075 if (status == Authorized)
1076 return "Authorized";
1077 else
1078 return "Unauthorized";
1079 }
1080 #endif /* CONFIG_CTRL_IFACE */
1081
1082
1083 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1084 static const char * eapol_port_control(PortControl ctrl)
1085 {
1086 switch (ctrl) {
1087 case Auto:
1088 return "Auto";
1089 case ForceUnauthorized:
1090 return "ForceUnauthorized";
1091 case ForceAuthorized:
1092 return "ForceAuthorized";
1093 default:
1094 return "Unknown";
1095 }
1096 }
1097 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1098
1099
1100 /**
1101 * eapol_sm_configure - Set EAPOL variables
1102 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1103 * @heldPeriod: dot1xSuppHeldPeriod
1104 * @authPeriod: dot1xSuppAuthPeriod
1105 * @startPeriod: dot1xSuppStartPeriod
1106 * @maxStart: dot1xSuppMaxStart
1107 *
1108 * Set configurable EAPOL state machine variables. Each variable can be set to
1109 * the given value or ignored if set to -1 (to set only some of the variables).
1110 */
1111 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1112 int startPeriod, int maxStart)
1113 {
1114 if (sm == NULL)
1115 return;
1116 if (heldPeriod >= 0)
1117 sm->heldPeriod = heldPeriod;
1118 if (authPeriod >= 0)
1119 sm->authPeriod = authPeriod;
1120 if (startPeriod >= 0)
1121 sm->startPeriod = startPeriod;
1122 if (maxStart >= 0)
1123 sm->maxStart = maxStart;
1124 }
1125
1126
1127 /**
1128 * eapol_sm_get_method_name - Get EAPOL method name
1129 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1130 * Returns: Static string containing name of current eap method or NULL
1131 */
1132 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1133 {
1134 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1135 sm->suppPortStatus != Authorized)
1136 return NULL;
1137
1138 return eap_sm_get_method_name(sm->eap);
1139 }
1140
1141
1142 #ifdef CONFIG_CTRL_IFACE
1143 /**
1144 * eapol_sm_get_status - Get EAPOL state machine status
1145 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1146 * @buf: Buffer for status information
1147 * @buflen: Maximum buffer length
1148 * @verbose: Whether to include verbose status information
1149 * Returns: Number of bytes written to buf.
1150 *
1151 * Query EAPOL state machine for status information. This function fills in a
1152 * text area with current status information from the EAPOL state machine. If
1153 * the buffer (buf) is not large enough, status information will be truncated
1154 * to fit the buffer.
1155 */
1156 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1157 int verbose)
1158 {
1159 int len, ret;
1160 if (sm == NULL)
1161 return 0;
1162
1163 len = os_snprintf(buf, buflen,
1164 "Supplicant PAE state=%s\n"
1165 "suppPortStatus=%s\n",
1166 eapol_supp_pae_state(sm->SUPP_PAE_state),
1167 eapol_port_status(sm->suppPortStatus));
1168 if (os_snprintf_error(buflen, len))
1169 return 0;
1170
1171 if (verbose) {
1172 ret = os_snprintf(buf + len, buflen - len,
1173 "heldPeriod=%u\n"
1174 "authPeriod=%u\n"
1175 "startPeriod=%u\n"
1176 "maxStart=%u\n"
1177 "portControl=%s\n"
1178 "Supplicant Backend state=%s\n",
1179 sm->heldPeriod,
1180 sm->authPeriod,
1181 sm->startPeriod,
1182 sm->maxStart,
1183 eapol_port_control(sm->portControl),
1184 eapol_supp_be_state(sm->SUPP_BE_state));
1185 if (os_snprintf_error(buflen - len, ret))
1186 return len;
1187 len += ret;
1188 }
1189
1190 #ifdef CONFIG_EAP_PROXY
1191 if (sm->use_eap_proxy)
1192 len += eap_proxy_sm_get_status(sm->eap_proxy,
1193 buf + len, buflen - len,
1194 verbose);
1195 else
1196 #endif /* CONFIG_EAP_PROXY */
1197 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1198
1199 return len;
1200 }
1201
1202
1203 /**
1204 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1205 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1206 * @buf: Buffer for MIB information
1207 * @buflen: Maximum buffer length
1208 * Returns: Number of bytes written to buf.
1209 *
1210 * Query EAPOL state machine for MIB information. This function fills in a
1211 * text area with current MIB information from the EAPOL state machine. If
1212 * the buffer (buf) is not large enough, MIB information will be truncated to
1213 * fit the buffer.
1214 */
1215 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1216 {
1217 size_t len;
1218 int ret;
1219
1220 if (sm == NULL)
1221 return 0;
1222 ret = os_snprintf(buf, buflen,
1223 "dot1xSuppPaeState=%d\n"
1224 "dot1xSuppHeldPeriod=%u\n"
1225 "dot1xSuppAuthPeriod=%u\n"
1226 "dot1xSuppStartPeriod=%u\n"
1227 "dot1xSuppMaxStart=%u\n"
1228 "dot1xSuppSuppControlledPortStatus=%s\n"
1229 "dot1xSuppBackendPaeState=%d\n",
1230 sm->SUPP_PAE_state,
1231 sm->heldPeriod,
1232 sm->authPeriod,
1233 sm->startPeriod,
1234 sm->maxStart,
1235 sm->suppPortStatus == Authorized ?
1236 "Authorized" : "Unauthorized",
1237 sm->SUPP_BE_state);
1238
1239 if (os_snprintf_error(buflen, ret))
1240 return 0;
1241 len = ret;
1242
1243 ret = os_snprintf(buf + len, buflen - len,
1244 "dot1xSuppEapolFramesRx=%u\n"
1245 "dot1xSuppEapolFramesTx=%u\n"
1246 "dot1xSuppEapolStartFramesTx=%u\n"
1247 "dot1xSuppEapolLogoffFramesTx=%u\n"
1248 "dot1xSuppEapolRespFramesTx=%u\n"
1249 "dot1xSuppEapolReqIdFramesRx=%u\n"
1250 "dot1xSuppEapolReqFramesRx=%u\n"
1251 "dot1xSuppInvalidEapolFramesRx=%u\n"
1252 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1253 "dot1xSuppLastEapolFrameVersion=%u\n"
1254 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1255 sm->dot1xSuppEapolFramesRx,
1256 sm->dot1xSuppEapolFramesTx,
1257 sm->dot1xSuppEapolStartFramesTx,
1258 sm->dot1xSuppEapolLogoffFramesTx,
1259 sm->dot1xSuppEapolRespFramesTx,
1260 sm->dot1xSuppEapolReqIdFramesRx,
1261 sm->dot1xSuppEapolReqFramesRx,
1262 sm->dot1xSuppInvalidEapolFramesRx,
1263 sm->dot1xSuppEapLengthErrorFramesRx,
1264 sm->dot1xSuppLastEapolFrameVersion,
1265 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1266
1267 if (os_snprintf_error(buflen - len, ret))
1268 return len;
1269 len += ret;
1270
1271 return len;
1272 }
1273 #endif /* CONFIG_CTRL_IFACE */
1274
1275
1276 /**
1277 * eapol_sm_rx_eapol - Process received EAPOL frames
1278 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1279 * @src: Source MAC address of the EAPOL packet
1280 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1281 * @len: Length of the EAPOL frame
1282 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1283 * -1 failure
1284 */
1285 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1286 size_t len)
1287 {
1288 const struct ieee802_1x_hdr *hdr;
1289 const struct ieee802_1x_eapol_key *key;
1290 int data_len;
1291 int res = 1;
1292 size_t plen;
1293
1294 if (sm == NULL)
1295 return 0;
1296 sm->dot1xSuppEapolFramesRx++;
1297 if (len < sizeof(*hdr)) {
1298 sm->dot1xSuppInvalidEapolFramesRx++;
1299 return 0;
1300 }
1301 hdr = (const struct ieee802_1x_hdr *) buf;
1302 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1303 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1304 if (hdr->version < EAPOL_VERSION) {
1305 /* TODO: backwards compatibility */
1306 }
1307 plen = be_to_host16(hdr->length);
1308 if (plen > len - sizeof(*hdr)) {
1309 sm->dot1xSuppEapLengthErrorFramesRx++;
1310 return 0;
1311 }
1312 #ifdef CONFIG_WPS
1313 if (sm->conf.wps && sm->conf.workaround &&
1314 plen < len - sizeof(*hdr) &&
1315 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1316 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1317 const struct eap_hdr *ehdr =
1318 (const struct eap_hdr *) (hdr + 1);
1319 u16 elen;
1320
1321 elen = be_to_host16(ehdr->length);
1322 if (elen > plen && elen <= len - sizeof(*hdr)) {
1323 /*
1324 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1325 * packets with too short EAPOL header length field
1326 * (14 octets). This is fixed in firmware Ver.1.49.
1327 * As a workaround, fix the EAPOL header based on the
1328 * correct length in the EAP packet.
1329 */
1330 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1331 "payload length based on EAP header: "
1332 "%d -> %d", (int) plen, elen);
1333 plen = elen;
1334 }
1335 }
1336 #endif /* CONFIG_WPS */
1337 data_len = plen + sizeof(*hdr);
1338
1339 switch (hdr->type) {
1340 case IEEE802_1X_TYPE_EAP_PACKET:
1341 if (sm->conf.workaround) {
1342 /*
1343 * An AP has been reported to send out EAP message with
1344 * undocumented code 10 at some point near the
1345 * completion of EAP authentication. This can result in
1346 * issues with the unexpected EAP message triggering
1347 * restart of EAPOL authentication. Avoid this by
1348 * skipping the message without advancing the state
1349 * machine.
1350 */
1351 const struct eap_hdr *ehdr =
1352 (const struct eap_hdr *) (hdr + 1);
1353 if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1354 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1355 break;
1356 }
1357 }
1358
1359 if (sm->cached_pmk) {
1360 /* Trying to use PMKSA caching, but Authenticator did
1361 * not seem to have a matching entry. Need to restart
1362 * EAPOL state machines.
1363 */
1364 eapol_sm_abort_cached(sm);
1365 }
1366 wpabuf_free(sm->eapReqData);
1367 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1368 if (sm->eapReqData) {
1369 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1370 "frame");
1371 sm->eapolEap = TRUE;
1372 #ifdef CONFIG_EAP_PROXY
1373 if (sm->use_eap_proxy) {
1374 eap_proxy_packet_update(
1375 sm->eap_proxy,
1376 wpabuf_mhead_u8(sm->eapReqData),
1377 wpabuf_len(sm->eapReqData));
1378 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1379 "EAP Req updated");
1380 }
1381 #endif /* CONFIG_EAP_PROXY */
1382 eapol_sm_step(sm);
1383 }
1384 break;
1385 case IEEE802_1X_TYPE_EAPOL_KEY:
1386 if (plen < sizeof(*key)) {
1387 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1388 "frame received");
1389 break;
1390 }
1391 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1392 if (key->type == EAPOL_KEY_TYPE_WPA ||
1393 key->type == EAPOL_KEY_TYPE_RSN) {
1394 /* WPA Supplicant takes care of this frame. */
1395 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1396 "frame in EAPOL state machines");
1397 res = 0;
1398 break;
1399 }
1400 if (key->type != EAPOL_KEY_TYPE_RC4) {
1401 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1402 "EAPOL-Key type %d", key->type);
1403 break;
1404 }
1405 os_free(sm->last_rx_key);
1406 sm->last_rx_key = os_malloc(data_len);
1407 if (sm->last_rx_key) {
1408 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1409 "frame");
1410 os_memcpy(sm->last_rx_key, buf, data_len);
1411 sm->last_rx_key_len = data_len;
1412 sm->rxKey = TRUE;
1413 eapol_sm_step(sm);
1414 }
1415 break;
1416 #ifdef CONFIG_MACSEC
1417 case IEEE802_1X_TYPE_EAPOL_MKA:
1418 wpa_printf(MSG_EXCESSIVE,
1419 "EAPOL type %d will be handled by MKA",
1420 hdr->type);
1421 break;
1422 #endif /* CONFIG_MACSEC */
1423 default:
1424 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1425 hdr->type);
1426 sm->dot1xSuppInvalidEapolFramesRx++;
1427 break;
1428 }
1429
1430 return res;
1431 }
1432
1433
1434 /**
1435 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1436 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1437 *
1438 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1439 * component, e.g., WPA. This will update the statistics.
1440 */
1441 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1442 {
1443 if (sm)
1444 sm->dot1xSuppEapolFramesTx++;
1445 }
1446
1447
1448 /**
1449 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1450 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1451 * @enabled: New portEnabled value
1452 *
1453 * Notify EAPOL state machine about new portEnabled value.
1454 */
1455 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1456 {
1457 if (sm == NULL)
1458 return;
1459 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1460 "portEnabled=%d", enabled);
1461 if (sm->portEnabled != enabled)
1462 sm->force_authorized_update = TRUE;
1463 sm->portEnabled = enabled;
1464 eapol_sm_step(sm);
1465 }
1466
1467
1468 /**
1469 * eapol_sm_notify_portValid - Notification about portValid change
1470 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1471 * @valid: New portValid value
1472 *
1473 * Notify EAPOL state machine about new portValid value.
1474 */
1475 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1476 {
1477 if (sm == NULL)
1478 return;
1479 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1480 "portValid=%d", valid);
1481 sm->portValid = valid;
1482 eapol_sm_step(sm);
1483 }
1484
1485
1486 /**
1487 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1488 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1489 * @success: %TRUE = set success, %FALSE = clear success
1490 *
1491 * Notify the EAPOL state machine that external event has forced EAP state to
1492 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1493 *
1494 * This function is called to update EAP state when WPA-PSK key handshake has
1495 * been completed successfully since WPA-PSK does not use EAP state machine.
1496 */
1497 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1498 {
1499 if (sm == NULL)
1500 return;
1501 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1502 "EAP success=%d", success);
1503 sm->eapSuccess = success;
1504 sm->altAccept = success;
1505 if (success)
1506 eap_notify_success(sm->eap);
1507 eapol_sm_step(sm);
1508 }
1509
1510
1511 /**
1512 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1513 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1514 * @fail: %TRUE = set failure, %FALSE = clear failure
1515 *
1516 * Notify EAPOL state machine that external event has forced EAP state to
1517 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1518 */
1519 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1520 {
1521 if (sm == NULL)
1522 return;
1523 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1524 "EAP fail=%d", fail);
1525 sm->eapFail = fail;
1526 sm->altReject = fail;
1527 eapol_sm_step(sm);
1528 }
1529
1530
1531 /**
1532 * eapol_sm_notify_config - Notification of EAPOL configuration change
1533 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1534 * @config: Pointer to current network EAP configuration
1535 * @conf: Pointer to EAPOL configuration data
1536 *
1537 * Notify EAPOL state machine that configuration has changed. config will be
1538 * stored as a backpointer to network configuration. This can be %NULL to clear
1539 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1540 * data. If conf is %NULL, this part of the configuration change will be
1541 * skipped.
1542 */
1543 void eapol_sm_notify_config(struct eapol_sm *sm,
1544 struct eap_peer_config *config,
1545 const struct eapol_config *conf)
1546 {
1547 if (sm == NULL)
1548 return;
1549
1550 sm->config = config;
1551 #ifdef CONFIG_EAP_PROXY
1552 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1553 #endif /* CONFIG_EAP_PROXY */
1554
1555 if (conf == NULL)
1556 return;
1557
1558 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1559 sm->conf.required_keys = conf->required_keys;
1560 sm->conf.fast_reauth = conf->fast_reauth;
1561 sm->conf.workaround = conf->workaround;
1562 sm->conf.wps = conf->wps;
1563 #ifdef CONFIG_EAP_PROXY
1564 if (sm->use_eap_proxy) {
1565 /* Using EAP Proxy, so skip EAP state machine update */
1566 return;
1567 }
1568 #endif /* CONFIG_EAP_PROXY */
1569 if (sm->eap) {
1570 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1571 eap_set_workaround(sm->eap, conf->workaround);
1572 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1573 eap_set_external_sim(sm->eap, conf->external_sim);
1574 }
1575 }
1576
1577
1578 /**
1579 * eapol_sm_get_key - Get master session key (MSK) from EAP
1580 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1581 * @key: Pointer for key buffer
1582 * @len: Number of bytes to copy to key
1583 * Returns: 0 on success (len of key available), maximum available key len
1584 * (>0) if key is available but it is shorter than len, or -1 on failure.
1585 *
1586 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1587 * is available only after a successful authentication.
1588 */
1589 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1590 {
1591 const u8 *eap_key;
1592 size_t eap_len;
1593
1594 #ifdef CONFIG_EAP_PROXY
1595 if (sm && sm->use_eap_proxy) {
1596 /* Get key from EAP proxy */
1597 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1598 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1599 return -1;
1600 }
1601 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1602 if (eap_key == NULL) {
1603 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1604 "eapKeyData");
1605 return -1;
1606 }
1607 goto key_fetched;
1608 }
1609 #endif /* CONFIG_EAP_PROXY */
1610 if (sm == NULL || !eap_key_available(sm->eap)) {
1611 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1612 return -1;
1613 }
1614 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1615 if (eap_key == NULL) {
1616 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1617 return -1;
1618 }
1619 #ifdef CONFIG_EAP_PROXY
1620 key_fetched:
1621 #endif /* CONFIG_EAP_PROXY */
1622 if (len > eap_len) {
1623 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1624 "available (len=%lu)",
1625 (unsigned long) len, (unsigned long) eap_len);
1626 return eap_len;
1627 }
1628 os_memcpy(key, eap_key, len);
1629 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1630 (unsigned long) len);
1631 return 0;
1632 }
1633
1634
1635 /**
1636 * eapol_sm_get_session_id - Get EAP Session-Id
1637 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1638 * @len: Pointer to variable that will be set to number of bytes in the session
1639 * Returns: Pointer to the EAP Session-Id or %NULL on failure
1640 *
1641 * The Session-Id is available only after a successful authentication.
1642 */
1643 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len)
1644 {
1645 if (sm == NULL || !eap_key_available(sm->eap)) {
1646 wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available");
1647 return NULL;
1648 }
1649 return eap_get_eapSessionId(sm->eap, len);
1650 }
1651
1652
1653 /**
1654 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1655 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1656 * @logoff: Whether command was logoff
1657 *
1658 * Notify EAPOL state machines that user requested logon/logoff.
1659 */
1660 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1661 {
1662 if (sm) {
1663 sm->userLogoff = logoff;
1664 if (!logoff) {
1665 /* If there is a delayed txStart queued, start now. */
1666 sm->startWhen = 0;
1667 }
1668 eapol_sm_step(sm);
1669 }
1670 }
1671
1672
1673 /**
1674 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1675 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1676 *
1677 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1678 * to move EAPOL and EAP state machines into authenticated/successful state.
1679 */
1680 void eapol_sm_notify_cached(struct eapol_sm *sm)
1681 {
1682 if (sm == NULL)
1683 return;
1684 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1685 sm->eapSuccess = TRUE;
1686 eap_notify_success(sm->eap);
1687 eapol_sm_step(sm);
1688 }
1689
1690
1691 /**
1692 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1693 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1694 *
1695 * Notify EAPOL state machines if PMKSA caching is used.
1696 */
1697 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm)
1698 {
1699 if (sm == NULL)
1700 return;
1701 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1702 sm->cached_pmk = TRUE;
1703 }
1704
1705
1706 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1707 {
1708 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1709 "doing full EAP authentication");
1710 if (sm == NULL)
1711 return;
1712 sm->cached_pmk = FALSE;
1713 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1714 eapol_sm_set_port_unauthorized(sm);
1715
1716 /* Make sure we do not start sending EAPOL-Start frames first, but
1717 * instead move to RESTART state to start EAPOL authentication. */
1718 sm->startWhen = 3;
1719 eapol_enable_timer_tick(sm);
1720
1721 if (sm->ctx->aborted_cached)
1722 sm->ctx->aborted_cached(sm->ctx->ctx);
1723 }
1724
1725
1726 /**
1727 * eapol_sm_register_scard_ctx - Notification of smart card context
1728 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1729 * @ctx: Context data for smart card operations
1730 *
1731 * Notify EAPOL state machines of context data for smart card operations. This
1732 * context data will be used as a parameter for scard_*() functions.
1733 */
1734 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1735 {
1736 if (sm) {
1737 sm->ctx->scard_ctx = ctx;
1738 eap_register_scard_ctx(sm->eap, ctx);
1739 }
1740 }
1741
1742
1743 /**
1744 * eapol_sm_notify_portControl - Notification of portControl changes
1745 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1746 * @portControl: New value for portControl variable
1747 *
1748 * Notify EAPOL state machines that portControl variable has changed.
1749 */
1750 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1751 {
1752 if (sm == NULL)
1753 return;
1754 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1755 "portControl=%s", eapol_port_control(portControl));
1756 sm->portControl = portControl;
1757 eapol_sm_step(sm);
1758 }
1759
1760
1761 /**
1762 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1763 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1764 *
1765 * Notify EAPOL state machines that a monitor was attached to the control
1766 * interface to trigger re-sending of pending requests for user input.
1767 */
1768 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1769 {
1770 if (sm == NULL)
1771 return;
1772 eap_sm_notify_ctrl_attached(sm->eap);
1773 }
1774
1775
1776 /**
1777 * eapol_sm_notify_ctrl_response - Notification of received user input
1778 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1779 *
1780 * Notify EAPOL state machines that a control response, i.e., user
1781 * input, was received in order to trigger retrying of a pending EAP request.
1782 */
1783 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1784 {
1785 if (sm == NULL)
1786 return;
1787 if (sm->eapReqData && !sm->eapReq) {
1788 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1789 "input) notification - retrying pending EAP "
1790 "Request");
1791 sm->eapolEap = TRUE;
1792 sm->eapReq = TRUE;
1793 eapol_sm_step(sm);
1794 }
1795 }
1796
1797
1798 /**
1799 * eapol_sm_request_reauth - Request reauthentication
1800 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1801 *
1802 * This function can be used to request EAPOL reauthentication, e.g., when the
1803 * current PMKSA entry is nearing expiration.
1804 */
1805 void eapol_sm_request_reauth(struct eapol_sm *sm)
1806 {
1807 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1808 return;
1809 eapol_sm_txStart(sm);
1810 }
1811
1812
1813 /**
1814 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1815 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1816 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1817 * machine loop (eapol_sm_step())
1818 *
1819 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1820 * successful authentication. This is used to recover from dropped EAP-Success
1821 * messages.
1822 */
1823 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1824 {
1825 if (sm == NULL)
1826 return;
1827 eap_notify_lower_layer_success(sm->eap);
1828 if (!in_eapol_sm)
1829 eapol_sm_step(sm);
1830 }
1831
1832
1833 /**
1834 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1835 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1836 */
1837 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1838 {
1839 if (sm)
1840 eap_invalidate_cached_session(sm->eap);
1841 }
1842
1843
1844 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1845 {
1846 struct eapol_sm *sm = ctx;
1847 return sm ? sm->config : NULL;
1848 }
1849
1850
1851 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1852 {
1853 struct eapol_sm *sm = ctx;
1854 if (sm == NULL || sm->eapReqData == NULL)
1855 return NULL;
1856
1857 return sm->eapReqData;
1858 }
1859
1860
1861 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1862 {
1863 struct eapol_sm *sm = ctx;
1864 if (sm == NULL)
1865 return FALSE;
1866 switch (variable) {
1867 case EAPOL_eapSuccess:
1868 return sm->eapSuccess;
1869 case EAPOL_eapRestart:
1870 return sm->eapRestart;
1871 case EAPOL_eapFail:
1872 return sm->eapFail;
1873 case EAPOL_eapResp:
1874 return sm->eapResp;
1875 case EAPOL_eapNoResp:
1876 return sm->eapNoResp;
1877 case EAPOL_eapReq:
1878 return sm->eapReq;
1879 case EAPOL_portEnabled:
1880 return sm->portEnabled;
1881 case EAPOL_altAccept:
1882 return sm->altAccept;
1883 case EAPOL_altReject:
1884 return sm->altReject;
1885 case EAPOL_eapTriggerStart:
1886 return sm->eapTriggerStart;
1887 }
1888 return FALSE;
1889 }
1890
1891
1892 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1893 Boolean value)
1894 {
1895 struct eapol_sm *sm = ctx;
1896 if (sm == NULL)
1897 return;
1898 switch (variable) {
1899 case EAPOL_eapSuccess:
1900 sm->eapSuccess = value;
1901 break;
1902 case EAPOL_eapRestart:
1903 sm->eapRestart = value;
1904 break;
1905 case EAPOL_eapFail:
1906 sm->eapFail = value;
1907 break;
1908 case EAPOL_eapResp:
1909 sm->eapResp = value;
1910 break;
1911 case EAPOL_eapNoResp:
1912 sm->eapNoResp = value;
1913 break;
1914 case EAPOL_eapReq:
1915 sm->eapReq = value;
1916 break;
1917 case EAPOL_portEnabled:
1918 sm->portEnabled = value;
1919 break;
1920 case EAPOL_altAccept:
1921 sm->altAccept = value;
1922 break;
1923 case EAPOL_altReject:
1924 sm->altReject = value;
1925 break;
1926 case EAPOL_eapTriggerStart:
1927 sm->eapTriggerStart = value;
1928 break;
1929 }
1930 }
1931
1932
1933 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1934 {
1935 struct eapol_sm *sm = ctx;
1936 if (sm == NULL)
1937 return 0;
1938 switch (variable) {
1939 case EAPOL_idleWhile:
1940 return sm->idleWhile;
1941 }
1942 return 0;
1943 }
1944
1945
1946 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1947 unsigned int value)
1948 {
1949 struct eapol_sm *sm = ctx;
1950 if (sm == NULL)
1951 return;
1952 switch (variable) {
1953 case EAPOL_idleWhile:
1954 sm->idleWhile = value;
1955 if (sm->idleWhile > 0)
1956 eapol_enable_timer_tick(sm);
1957 break;
1958 }
1959 }
1960
1961
1962 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1963 {
1964 #ifndef CONFIG_NO_CONFIG_BLOBS
1965 struct eapol_sm *sm = ctx;
1966 if (sm && sm->ctx && sm->ctx->set_config_blob)
1967 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1968 #endif /* CONFIG_NO_CONFIG_BLOBS */
1969 }
1970
1971
1972 static const struct wpa_config_blob *
1973 eapol_sm_get_config_blob(void *ctx, const char *name)
1974 {
1975 #ifndef CONFIG_NO_CONFIG_BLOBS
1976 struct eapol_sm *sm = ctx;
1977 if (sm && sm->ctx && sm->ctx->get_config_blob)
1978 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1979 else
1980 return NULL;
1981 #else /* CONFIG_NO_CONFIG_BLOBS */
1982 return NULL;
1983 #endif /* CONFIG_NO_CONFIG_BLOBS */
1984 }
1985
1986
1987 static void eapol_sm_notify_pending(void *ctx)
1988 {
1989 struct eapol_sm *sm = ctx;
1990 if (sm == NULL)
1991 return;
1992 if (sm->eapReqData && !sm->eapReq) {
1993 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1994 "state machine - retrying pending EAP Request");
1995 sm->eapolEap = TRUE;
1996 sm->eapReq = TRUE;
1997 eapol_sm_step(sm);
1998 }
1999 }
2000
2001
2002 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
2003 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
2004 const char *txt)
2005 {
2006 struct eapol_sm *sm = ctx;
2007 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
2008 if (sm->ctx->eap_param_needed)
2009 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
2010 }
2011 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
2012 #define eapol_sm_eap_param_needed NULL
2013 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
2014
2015 static void eapol_sm_notify_cert(void *ctx, struct tls_cert_data *cert,
2016 const char *cert_hash)
2017 {
2018 struct eapol_sm *sm = ctx;
2019 if (sm->ctx->cert_cb)
2020 sm->ctx->cert_cb(sm->ctx->ctx, cert, cert_hash);
2021 }
2022
2023
2024 static void eapol_sm_notify_status(void *ctx, const char *status,
2025 const char *parameter)
2026 {
2027 struct eapol_sm *sm = ctx;
2028
2029 if (sm->ctx->status_cb)
2030 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
2031 }
2032
2033
2034 static void eapol_sm_notify_eap_error(void *ctx, int error_code)
2035 {
2036 struct eapol_sm *sm = ctx;
2037
2038 if (sm->ctx->eap_error_cb)
2039 sm->ctx->eap_error_cb(sm->ctx->ctx, error_code);
2040 }
2041
2042
2043 #ifdef CONFIG_EAP_PROXY
2044
2045 static void eapol_sm_eap_proxy_cb(void *ctx)
2046 {
2047 struct eapol_sm *sm = ctx;
2048
2049 if (sm->ctx->eap_proxy_cb)
2050 sm->ctx->eap_proxy_cb(sm->ctx->ctx);
2051 }
2052
2053
2054 static void
2055 eapol_sm_eap_proxy_notify_sim_status(void *ctx,
2056 enum eap_proxy_sim_state sim_state)
2057 {
2058 struct eapol_sm *sm = ctx;
2059
2060 if (sm->ctx->eap_proxy_notify_sim_status)
2061 sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state);
2062 }
2063
2064 #endif /* CONFIG_EAP_PROXY */
2065
2066
2067 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
2068 {
2069 struct eapol_sm *sm = ctx;
2070
2071 if (sm->ctx->set_anon_id)
2072 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
2073 }
2074
2075
2076 static const struct eapol_callbacks eapol_cb =
2077 {
2078 eapol_sm_get_config,
2079 eapol_sm_get_bool,
2080 eapol_sm_set_bool,
2081 eapol_sm_get_int,
2082 eapol_sm_set_int,
2083 eapol_sm_get_eapReqData,
2084 eapol_sm_set_config_blob,
2085 eapol_sm_get_config_blob,
2086 eapol_sm_notify_pending,
2087 eapol_sm_eap_param_needed,
2088 eapol_sm_notify_cert,
2089 eapol_sm_notify_status,
2090 eapol_sm_notify_eap_error,
2091 #ifdef CONFIG_EAP_PROXY
2092 eapol_sm_eap_proxy_cb,
2093 eapol_sm_eap_proxy_notify_sim_status,
2094 eapol_sm_get_eap_proxy_imsi,
2095 #endif /* CONFIG_EAP_PROXY */
2096 eapol_sm_set_anon_id
2097 };
2098
2099
2100 /**
2101 * eapol_sm_init - Initialize EAPOL state machine
2102 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
2103 * and EAPOL state machine will free it in eapol_sm_deinit()
2104 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
2105 *
2106 * Allocate and initialize an EAPOL state machine.
2107 */
2108 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
2109 {
2110 struct eapol_sm *sm;
2111 struct eap_config conf;
2112 sm = os_zalloc(sizeof(*sm));
2113 if (sm == NULL)
2114 return NULL;
2115 sm->ctx = ctx;
2116
2117 sm->portControl = Auto;
2118
2119 /* Supplicant PAE state machine */
2120 sm->heldPeriod = 60;
2121 sm->startPeriod = 30;
2122 sm->maxStart = 3;
2123
2124 /* Supplicant Backend state machine */
2125 sm->authPeriod = 30;
2126
2127 os_memset(&conf, 0, sizeof(conf));
2128 conf.opensc_engine_path = ctx->opensc_engine_path;
2129 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2130 conf.pkcs11_module_path = ctx->pkcs11_module_path;
2131 conf.openssl_ciphers = ctx->openssl_ciphers;
2132 conf.wps = ctx->wps;
2133 conf.cert_in_cb = ctx->cert_in_cb;
2134
2135 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2136 if (sm->eap == NULL) {
2137 os_free(sm);
2138 return NULL;
2139 }
2140
2141 #ifdef CONFIG_EAP_PROXY
2142 sm->use_eap_proxy = FALSE;
2143 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2144 if (sm->eap_proxy == NULL) {
2145 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2146 }
2147 #endif /* CONFIG_EAP_PROXY */
2148
2149 /* Initialize EAPOL state machines */
2150 sm->force_authorized_update = TRUE;
2151 sm->initialize = TRUE;
2152 eapol_sm_step(sm);
2153 sm->initialize = FALSE;
2154 eapol_sm_step(sm);
2155
2156 if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0)
2157 sm->timer_tick_enabled = 1;
2158
2159 return sm;
2160 }
2161
2162
2163 /**
2164 * eapol_sm_deinit - Deinitialize EAPOL state machine
2165 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2166 *
2167 * Deinitialize and free EAPOL state machine.
2168 */
2169 void eapol_sm_deinit(struct eapol_sm *sm)
2170 {
2171 if (sm == NULL)
2172 return;
2173 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2174 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2175 eap_peer_sm_deinit(sm->eap);
2176 #ifdef CONFIG_EAP_PROXY
2177 eap_proxy_deinit(sm->eap_proxy);
2178 #endif /* CONFIG_EAP_PROXY */
2179 os_free(sm->last_rx_key);
2180 wpabuf_free(sm->eapReqData);
2181 os_free(sm->ctx);
2182 os_free(sm);
2183 }
2184
2185
2186 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2187 struct ext_password_data *ext)
2188 {
2189 if (sm && sm->eap)
2190 eap_sm_set_ext_pw_ctx(sm->eap, ext);
2191 }
2192
2193
2194 int eapol_sm_failed(struct eapol_sm *sm)
2195 {
2196 if (sm == NULL)
2197 return 0;
2198 return !sm->eapSuccess && sm->eapFail;
2199 }
2200
2201
2202 #ifdef CONFIG_EAP_PROXY
2203 int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len)
2204 {
2205 struct eapol_sm *sm = ctx;
2206
2207 if (sm->eap_proxy == NULL)
2208 return -1;
2209 return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len);
2210 }
2211 #endif /* CONFIG_EAP_PROXY */
2212
2213
2214 void eapol_sm_erp_flush(struct eapol_sm *sm)
2215 {
2216 if (sm)
2217 eap_peer_erp_free_keys(sm->eap);
2218 }
2219
2220
2221 struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm)
2222 {
2223 #ifdef CONFIG_ERP
2224 if (!sm)
2225 return NULL;
2226 return eap_peer_build_erp_reauth_start(sm->eap, 0);
2227 #else /* CONFIG_ERP */
2228 return NULL;
2229 #endif /* CONFIG_ERP */
2230 }
2231
2232
2233 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
2234 size_t len)
2235 {
2236 #ifdef CONFIG_ERP
2237 if (!sm)
2238 return;
2239 eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len);
2240 #endif /* CONFIG_ERP */
2241 }
2242
2243
2244 int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num)
2245 {
2246 #ifdef CONFIG_ERP
2247 if (!sm)
2248 return -1;
2249 return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num);
2250 #else /* CONFIG_ERP */
2251 return -1;
2252 #endif /* CONFIG_ERP */
2253 }
2254
2255
2256 int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
2257 const u8 **username, size_t *username_len,
2258 const u8 **realm, size_t *realm_len,
2259 u16 *erp_next_seq_num, const u8 **rrk,
2260 size_t *rrk_len)
2261 {
2262 #ifdef CONFIG_ERP
2263 if (!sm)
2264 return -1;
2265 return eap_peer_get_erp_info(sm->eap, config, username, username_len,
2266 realm, realm_len, erp_next_seq_num, rrk,
2267 rrk_len);
2268 #else /* CONFIG_ERP */
2269 return -1;
2270 #endif /* CONFIG_ERP */
2271 }