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