$search
00001 /* 00002 * EAPOL supplicant state machines 00003 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "state_machine.h" 00019 #include "wpabuf.h" 00020 #include "eloop.h" 00021 #include "crypto/crypto.h" 00022 #include "crypto/md5.h" 00023 #include "common/eapol_common.h" 00024 #include "eap_peer/eap.h" 00025 #include "eapol_supp_sm.h" 00026 00027 #define STATE_MACHINE_DATA struct eapol_sm 00028 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL" 00029 00030 00031 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */ 00032 00036 struct eapol_sm { 00037 /* Timers */ 00038 unsigned int authWhile; 00039 unsigned int heldWhile; 00040 unsigned int startWhen; 00041 unsigned int idleWhile; /* for EAP state machine */ 00042 int timer_tick_enabled; 00043 00044 /* Global variables */ 00045 Boolean eapFail; 00046 Boolean eapolEap; 00047 Boolean eapSuccess; 00048 Boolean initialize; 00049 Boolean keyDone; 00050 Boolean keyRun; 00051 PortControl portControl; 00052 Boolean portEnabled; 00053 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ 00054 Boolean portValid; 00055 Boolean suppAbort; 00056 Boolean suppFail; 00057 Boolean suppStart; 00058 Boolean suppSuccess; 00059 Boolean suppTimeout; 00060 00061 /* Supplicant PAE state machine */ 00062 enum { 00063 SUPP_PAE_UNKNOWN = 0, 00064 SUPP_PAE_DISCONNECTED = 1, 00065 SUPP_PAE_LOGOFF = 2, 00066 SUPP_PAE_CONNECTING = 3, 00067 SUPP_PAE_AUTHENTICATING = 4, 00068 SUPP_PAE_AUTHENTICATED = 5, 00069 /* unused(6) */ 00070 SUPP_PAE_HELD = 7, 00071 SUPP_PAE_RESTART = 8, 00072 SUPP_PAE_S_FORCE_AUTH = 9, 00073 SUPP_PAE_S_FORCE_UNAUTH = 10 00074 } SUPP_PAE_state; /* dot1xSuppPaeState */ 00075 /* Variables */ 00076 Boolean userLogoff; 00077 Boolean logoffSent; 00078 unsigned int startCount; 00079 Boolean eapRestart; 00080 PortControl sPortMode; 00081 /* Constants */ 00082 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ 00083 unsigned int startPeriod; /* dot1xSuppStartPeriod */ 00084 unsigned int maxStart; /* dot1xSuppMaxStart */ 00085 00086 /* Key Receive state machine */ 00087 enum { 00088 KEY_RX_UNKNOWN = 0, 00089 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE 00090 } KEY_RX_state; 00091 /* Variables */ 00092 Boolean rxKey; 00093 00094 /* Supplicant Backend state machine */ 00095 enum { 00096 SUPP_BE_UNKNOWN = 0, 00097 SUPP_BE_INITIALIZE = 1, 00098 SUPP_BE_IDLE = 2, 00099 SUPP_BE_REQUEST = 3, 00100 SUPP_BE_RECEIVE = 4, 00101 SUPP_BE_RESPONSE = 5, 00102 SUPP_BE_FAIL = 6, 00103 SUPP_BE_TIMEOUT = 7, 00104 SUPP_BE_SUCCESS = 8 00105 } SUPP_BE_state; /* dot1xSuppBackendPaeState */ 00106 /* Variables */ 00107 Boolean eapNoResp; 00108 Boolean eapReq; 00109 Boolean eapResp; 00110 /* Constants */ 00111 unsigned int authPeriod; /* dot1xSuppAuthPeriod */ 00112 00113 /* Statistics */ 00114 unsigned int dot1xSuppEapolFramesRx; 00115 unsigned int dot1xSuppEapolFramesTx; 00116 unsigned int dot1xSuppEapolStartFramesTx; 00117 unsigned int dot1xSuppEapolLogoffFramesTx; 00118 unsigned int dot1xSuppEapolRespFramesTx; 00119 unsigned int dot1xSuppEapolReqIdFramesRx; 00120 unsigned int dot1xSuppEapolReqFramesRx; 00121 unsigned int dot1xSuppInvalidEapolFramesRx; 00122 unsigned int dot1xSuppEapLengthErrorFramesRx; 00123 unsigned int dot1xSuppLastEapolFrameVersion; 00124 unsigned char dot1xSuppLastEapolFrameSource[6]; 00125 00126 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */ 00127 Boolean changed; 00128 struct eap_sm *eap; 00129 struct eap_peer_config *config; 00130 Boolean initial_req; 00131 u8 *last_rx_key; 00132 size_t last_rx_key_len; 00133 struct wpabuf *eapReqData; /* for EAP */ 00134 Boolean altAccept; /* for EAP */ 00135 Boolean altReject; /* for EAP */ 00136 Boolean replay_counter_valid; 00137 u8 last_replay_counter[16]; 00138 struct eapol_config conf; 00139 struct eapol_ctx *ctx; 00140 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } 00141 cb_status; 00142 Boolean cached_pmk; 00143 00144 Boolean unicast_key_received, broadcast_key_received; 00145 }; 00146 00147 00148 #define IEEE8021X_REPLAY_COUNTER_LEN 8 00149 #define IEEE8021X_KEY_SIGN_LEN 16 00150 #define IEEE8021X_KEY_IV_LEN 16 00151 00152 #define IEEE8021X_KEY_INDEX_FLAG 0x80 00153 #define IEEE8021X_KEY_INDEX_MASK 0x03 00154 00155 #ifdef _MSC_VER 00156 #pragma pack(push, 1) 00157 #endif /* _MSC_VER */ 00158 00159 struct ieee802_1x_eapol_key { 00160 u8 type; 00161 /* Note: key_length is unaligned */ 00162 u8 key_length[2]; 00163 /* does not repeat within the life of the keying material used to 00164 * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ 00165 u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; 00166 u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ 00167 u8 key_index; /* key flag in the most significant bit: 00168 * 0 = broadcast (default key), 00169 * 1 = unicast (key mapping key); key index is in the 00170 * 7 least significant bits */ 00171 /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as 00172 * the key */ 00173 u8 key_signature[IEEE8021X_KEY_SIGN_LEN]; 00174 00175 /* followed by key: if packet body length = 44 + key length, then the 00176 * key field (of key_length bytes) contains the key in encrypted form; 00177 * if packet body length = 44, key field is absent and key_length 00178 * represents the number of least significant octets from 00179 * MS-MPPE-Send-Key attribute to be used as the keying material; 00180 * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ 00181 } STRUCT_PACKED; 00182 00183 #ifdef _MSC_VER 00184 #pragma pack(pop) 00185 #endif /* _MSC_VER */ 00186 00187 00188 static void eapol_sm_txLogoff(struct eapol_sm *sm); 00189 static void eapol_sm_txStart(struct eapol_sm *sm); 00190 static void eapol_sm_processKey(struct eapol_sm *sm); 00191 static void eapol_sm_getSuppRsp(struct eapol_sm *sm); 00192 static void eapol_sm_txSuppRsp(struct eapol_sm *sm); 00193 static void eapol_sm_abortSupp(struct eapol_sm *sm); 00194 static void eapol_sm_abort_cached(struct eapol_sm *sm); 00195 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx); 00196 static void eapol_sm_set_port_authorized(struct eapol_sm *sm); 00197 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm); 00198 00199 00200 /* Port Timers state machine - implemented as a function that will be called 00201 * once a second as a registered event loop timeout */ 00202 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) 00203 { 00204 struct eapol_sm *sm = timeout_ctx; 00205 00206 if (sm->authWhile > 0) { 00207 sm->authWhile--; 00208 if (sm->authWhile == 0) 00209 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0"); 00210 } 00211 if (sm->heldWhile > 0) { 00212 sm->heldWhile--; 00213 if (sm->heldWhile == 0) 00214 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0"); 00215 } 00216 if (sm->startWhen > 0) { 00217 sm->startWhen--; 00218 if (sm->startWhen == 0) 00219 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0"); 00220 } 00221 if (sm->idleWhile > 0) { 00222 sm->idleWhile--; 00223 if (sm->idleWhile == 0) 00224 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0"); 00225 } 00226 00227 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) { 00228 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, 00229 sm); 00230 } else { 00231 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick"); 00232 sm->timer_tick_enabled = 0; 00233 } 00234 eapol_sm_step(sm); 00235 } 00236 00237 00238 static void eapol_enable_timer_tick(struct eapol_sm *sm) 00239 { 00240 if (sm->timer_tick_enabled) 00241 return; 00242 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick"); 00243 sm->timer_tick_enabled = 1; 00244 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 00245 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); 00246 } 00247 00248 00249 SM_STATE(SUPP_PAE, LOGOFF) 00250 { 00251 SM_ENTRY(SUPP_PAE, LOGOFF); 00252 eapol_sm_txLogoff(sm); 00253 sm->logoffSent = TRUE; 00254 sm->suppPortStatus = Unauthorized; 00255 eapol_sm_set_port_unauthorized(sm); 00256 } 00257 00258 00259 SM_STATE(SUPP_PAE, DISCONNECTED) 00260 { 00261 SM_ENTRY(SUPP_PAE, DISCONNECTED); 00262 sm->sPortMode = Auto; 00263 sm->startCount = 0; 00264 sm->logoffSent = FALSE; 00265 sm->suppPortStatus = Unauthorized; 00266 eapol_sm_set_port_unauthorized(sm); 00267 sm->suppAbort = TRUE; 00268 00269 sm->unicast_key_received = FALSE; 00270 sm->broadcast_key_received = FALSE; 00271 } 00272 00273 00274 SM_STATE(SUPP_PAE, CONNECTING) 00275 { 00276 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING; 00277 SM_ENTRY(SUPP_PAE, CONNECTING); 00278 if (send_start) { 00279 sm->startWhen = sm->startPeriod; 00280 sm->startCount++; 00281 } else { 00282 /* 00283 * Do not send EAPOL-Start immediately since in most cases, 00284 * Authenticator is going to start authentication immediately 00285 * after association and an extra EAPOL-Start is just going to 00286 * delay authentication. Use a short timeout to send the first 00287 * EAPOL-Start if Authenticator does not start authentication. 00288 */ 00289 #ifdef CONFIG_WPS 00290 /* Reduce latency on starting WPS negotiation. */ 00291 sm->startWhen = 1; 00292 #else /* CONFIG_WPS */ 00293 sm->startWhen = 3; 00294 #endif /* CONFIG_WPS */ 00295 } 00296 eapol_enable_timer_tick(sm); 00297 sm->eapolEap = FALSE; 00298 if (send_start) 00299 eapol_sm_txStart(sm); 00300 } 00301 00302 00303 SM_STATE(SUPP_PAE, AUTHENTICATING) 00304 { 00305 SM_ENTRY(SUPP_PAE, AUTHENTICATING); 00306 sm->startCount = 0; 00307 sm->suppSuccess = FALSE; 00308 sm->suppFail = FALSE; 00309 sm->suppTimeout = FALSE; 00310 sm->keyRun = FALSE; 00311 sm->keyDone = FALSE; 00312 sm->suppStart = TRUE; 00313 } 00314 00315 00316 SM_STATE(SUPP_PAE, HELD) 00317 { 00318 SM_ENTRY(SUPP_PAE, HELD); 00319 sm->heldWhile = sm->heldPeriod; 00320 eapol_enable_timer_tick(sm); 00321 sm->suppPortStatus = Unauthorized; 00322 eapol_sm_set_port_unauthorized(sm); 00323 sm->cb_status = EAPOL_CB_FAILURE; 00324 } 00325 00326 00327 SM_STATE(SUPP_PAE, AUTHENTICATED) 00328 { 00329 SM_ENTRY(SUPP_PAE, AUTHENTICATED); 00330 sm->suppPortStatus = Authorized; 00331 eapol_sm_set_port_authorized(sm); 00332 sm->cb_status = EAPOL_CB_SUCCESS; 00333 } 00334 00335 00336 SM_STATE(SUPP_PAE, RESTART) 00337 { 00338 SM_ENTRY(SUPP_PAE, RESTART); 00339 sm->eapRestart = TRUE; 00340 } 00341 00342 00343 SM_STATE(SUPP_PAE, S_FORCE_AUTH) 00344 { 00345 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH); 00346 sm->suppPortStatus = Authorized; 00347 eapol_sm_set_port_authorized(sm); 00348 sm->sPortMode = ForceAuthorized; 00349 } 00350 00351 00352 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) 00353 { 00354 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); 00355 sm->suppPortStatus = Unauthorized; 00356 eapol_sm_set_port_unauthorized(sm); 00357 sm->sPortMode = ForceUnauthorized; 00358 eapol_sm_txLogoff(sm); 00359 } 00360 00361 00362 SM_STEP(SUPP_PAE) 00363 { 00364 if ((sm->userLogoff && !sm->logoffSent) && 00365 !(sm->initialize || !sm->portEnabled)) 00366 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF); 00367 else if (((sm->portControl == Auto) && 00368 (sm->sPortMode != sm->portControl)) || 00369 sm->initialize || !sm->portEnabled) 00370 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED); 00371 else if ((sm->portControl == ForceAuthorized) && 00372 (sm->sPortMode != sm->portControl) && 00373 !(sm->initialize || !sm->portEnabled)) 00374 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH); 00375 else if ((sm->portControl == ForceUnauthorized) && 00376 (sm->sPortMode != sm->portControl) && 00377 !(sm->initialize || !sm->portEnabled)) 00378 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH); 00379 else switch (sm->SUPP_PAE_state) { 00380 case SUPP_PAE_UNKNOWN: 00381 break; 00382 case SUPP_PAE_LOGOFF: 00383 if (!sm->userLogoff) 00384 SM_ENTER(SUPP_PAE, DISCONNECTED); 00385 break; 00386 case SUPP_PAE_DISCONNECTED: 00387 SM_ENTER(SUPP_PAE, CONNECTING); 00388 break; 00389 case SUPP_PAE_CONNECTING: 00390 if (sm->startWhen == 0 && sm->startCount < sm->maxStart) 00391 SM_ENTER(SUPP_PAE, CONNECTING); 00392 else if (sm->startWhen == 0 && 00393 sm->startCount >= sm->maxStart && 00394 sm->portValid) 00395 SM_ENTER(SUPP_PAE, AUTHENTICATED); 00396 else if (sm->eapSuccess || sm->eapFail) 00397 SM_ENTER(SUPP_PAE, AUTHENTICATING); 00398 else if (sm->eapolEap) 00399 SM_ENTER(SUPP_PAE, RESTART); 00400 else if (sm->startWhen == 0 && 00401 sm->startCount >= sm->maxStart && 00402 !sm->portValid) 00403 SM_ENTER(SUPP_PAE, HELD); 00404 break; 00405 case SUPP_PAE_AUTHENTICATING: 00406 if (sm->eapSuccess && !sm->portValid && 00407 sm->conf.accept_802_1x_keys && 00408 sm->conf.required_keys == 0) { 00409 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " 00410 "plaintext connection; no EAPOL-Key frames " 00411 "required"); 00412 sm->portValid = TRUE; 00413 if (sm->ctx->eapol_done_cb) 00414 sm->ctx->eapol_done_cb(sm->ctx->ctx); 00415 } 00416 if (sm->eapSuccess && sm->portValid) 00417 SM_ENTER(SUPP_PAE, AUTHENTICATED); 00418 else if (sm->eapFail || (sm->keyDone && !sm->portValid)) 00419 SM_ENTER(SUPP_PAE, HELD); 00420 else if (sm->suppTimeout) 00421 SM_ENTER(SUPP_PAE, CONNECTING); 00422 break; 00423 case SUPP_PAE_HELD: 00424 if (sm->heldWhile == 0) 00425 SM_ENTER(SUPP_PAE, CONNECTING); 00426 else if (sm->eapolEap) 00427 SM_ENTER(SUPP_PAE, RESTART); 00428 break; 00429 case SUPP_PAE_AUTHENTICATED: 00430 if (sm->eapolEap && sm->portValid) 00431 SM_ENTER(SUPP_PAE, RESTART); 00432 else if (!sm->portValid) 00433 SM_ENTER(SUPP_PAE, DISCONNECTED); 00434 break; 00435 case SUPP_PAE_RESTART: 00436 if (!sm->eapRestart) 00437 SM_ENTER(SUPP_PAE, AUTHENTICATING); 00438 break; 00439 case SUPP_PAE_S_FORCE_AUTH: 00440 break; 00441 case SUPP_PAE_S_FORCE_UNAUTH: 00442 break; 00443 } 00444 } 00445 00446 00447 SM_STATE(KEY_RX, NO_KEY_RECEIVE) 00448 { 00449 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE); 00450 } 00451 00452 00453 SM_STATE(KEY_RX, KEY_RECEIVE) 00454 { 00455 SM_ENTRY(KEY_RX, KEY_RECEIVE); 00456 eapol_sm_processKey(sm); 00457 sm->rxKey = FALSE; 00458 } 00459 00460 00461 SM_STEP(KEY_RX) 00462 { 00463 if (sm->initialize || !sm->portEnabled) 00464 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); 00465 switch (sm->KEY_RX_state) { 00466 case KEY_RX_UNKNOWN: 00467 break; 00468 case KEY_RX_NO_KEY_RECEIVE: 00469 if (sm->rxKey) 00470 SM_ENTER(KEY_RX, KEY_RECEIVE); 00471 break; 00472 case KEY_RX_KEY_RECEIVE: 00473 if (sm->rxKey) 00474 SM_ENTER(KEY_RX, KEY_RECEIVE); 00475 break; 00476 } 00477 } 00478 00479 00480 SM_STATE(SUPP_BE, REQUEST) 00481 { 00482 SM_ENTRY(SUPP_BE, REQUEST); 00483 sm->authWhile = 0; 00484 sm->eapReq = TRUE; 00485 eapol_sm_getSuppRsp(sm); 00486 } 00487 00488 00489 SM_STATE(SUPP_BE, RESPONSE) 00490 { 00491 SM_ENTRY(SUPP_BE, RESPONSE); 00492 eapol_sm_txSuppRsp(sm); 00493 sm->eapResp = FALSE; 00494 } 00495 00496 00497 SM_STATE(SUPP_BE, SUCCESS) 00498 { 00499 SM_ENTRY(SUPP_BE, SUCCESS); 00500 sm->keyRun = TRUE; 00501 sm->suppSuccess = TRUE; 00502 00503 if (eap_key_available(sm->eap)) { 00504 /* New key received - clear IEEE 802.1X EAPOL-Key replay 00505 * counter */ 00506 sm->replay_counter_valid = FALSE; 00507 } 00508 } 00509 00510 00511 SM_STATE(SUPP_BE, FAIL) 00512 { 00513 SM_ENTRY(SUPP_BE, FAIL); 00514 sm->suppFail = TRUE; 00515 } 00516 00517 00518 SM_STATE(SUPP_BE, TIMEOUT) 00519 { 00520 SM_ENTRY(SUPP_BE, TIMEOUT); 00521 sm->suppTimeout = TRUE; 00522 } 00523 00524 00525 SM_STATE(SUPP_BE, IDLE) 00526 { 00527 SM_ENTRY(SUPP_BE, IDLE); 00528 sm->suppStart = FALSE; 00529 sm->initial_req = TRUE; 00530 } 00531 00532 00533 SM_STATE(SUPP_BE, INITIALIZE) 00534 { 00535 SM_ENTRY(SUPP_BE, INITIALIZE); 00536 eapol_sm_abortSupp(sm); 00537 sm->suppAbort = FALSE; 00538 } 00539 00540 00541 SM_STATE(SUPP_BE, RECEIVE) 00542 { 00543 SM_ENTRY(SUPP_BE, RECEIVE); 00544 sm->authWhile = sm->authPeriod; 00545 eapol_enable_timer_tick(sm); 00546 sm->eapolEap = FALSE; 00547 sm->eapNoResp = FALSE; 00548 sm->initial_req = FALSE; 00549 } 00550 00551 00552 SM_STEP(SUPP_BE) 00553 { 00554 if (sm->initialize || sm->suppAbort) 00555 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE); 00556 else switch (sm->SUPP_BE_state) { 00557 case SUPP_BE_UNKNOWN: 00558 break; 00559 case SUPP_BE_REQUEST: 00560 /* 00561 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL 00562 * and SUCCESS based on eapFail and eapSuccess, respectively. 00563 * However, IEEE Std 802.1X-2004 is also specifying that 00564 * eapNoResp should be set in conjuction with eapSuccess and 00565 * eapFail which would mean that more than one of the 00566 * transitions here would be activated at the same time. 00567 * Skipping RESPONSE and/or RECEIVE states in these cases can 00568 * cause problems and the direct transitions to do not seem 00569 * correct. Because of this, the conditions for these 00570 * transitions are verified only after eapNoResp. They are 00571 * unlikely to be used since eapNoResp should always be set if 00572 * either of eapSuccess or eapFail is set. 00573 */ 00574 if (sm->eapResp && sm->eapNoResp) { 00575 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both " 00576 "eapResp and eapNoResp set?!"); 00577 } 00578 if (sm->eapResp) 00579 SM_ENTER(SUPP_BE, RESPONSE); 00580 else if (sm->eapNoResp) 00581 SM_ENTER(SUPP_BE, RECEIVE); 00582 else if (sm->eapFail) 00583 SM_ENTER(SUPP_BE, FAIL); 00584 else if (sm->eapSuccess) 00585 SM_ENTER(SUPP_BE, SUCCESS); 00586 break; 00587 case SUPP_BE_RESPONSE: 00588 SM_ENTER(SUPP_BE, RECEIVE); 00589 break; 00590 case SUPP_BE_SUCCESS: 00591 SM_ENTER(SUPP_BE, IDLE); 00592 break; 00593 case SUPP_BE_FAIL: 00594 SM_ENTER(SUPP_BE, IDLE); 00595 break; 00596 case SUPP_BE_TIMEOUT: 00597 SM_ENTER(SUPP_BE, IDLE); 00598 break; 00599 case SUPP_BE_IDLE: 00600 if (sm->eapFail && sm->suppStart) 00601 SM_ENTER(SUPP_BE, FAIL); 00602 else if (sm->eapolEap && sm->suppStart) 00603 SM_ENTER(SUPP_BE, REQUEST); 00604 else if (sm->eapSuccess && sm->suppStart) 00605 SM_ENTER(SUPP_BE, SUCCESS); 00606 break; 00607 case SUPP_BE_INITIALIZE: 00608 SM_ENTER(SUPP_BE, IDLE); 00609 break; 00610 case SUPP_BE_RECEIVE: 00611 if (sm->eapolEap) 00612 SM_ENTER(SUPP_BE, REQUEST); 00613 else if (sm->eapFail) 00614 SM_ENTER(SUPP_BE, FAIL); 00615 else if (sm->authWhile == 0) 00616 SM_ENTER(SUPP_BE, TIMEOUT); 00617 else if (sm->eapSuccess) 00618 SM_ENTER(SUPP_BE, SUCCESS); 00619 break; 00620 } 00621 } 00622 00623 00624 static void eapol_sm_txLogoff(struct eapol_sm *sm) 00625 { 00626 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff"); 00627 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, 00628 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0); 00629 sm->dot1xSuppEapolLogoffFramesTx++; 00630 sm->dot1xSuppEapolFramesTx++; 00631 } 00632 00633 00634 static void eapol_sm_txStart(struct eapol_sm *sm) 00635 { 00636 wpa_printf(MSG_DEBUG, "EAPOL: txStart"); 00637 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, 00638 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0); 00639 sm->dot1xSuppEapolStartFramesTx++; 00640 sm->dot1xSuppEapolFramesTx++; 00641 } 00642 00643 00644 #define IEEE8021X_ENCR_KEY_LEN 32 00645 #define IEEE8021X_SIGN_KEY_LEN 32 00646 00647 struct eap_key_data { 00648 u8 encr_key[IEEE8021X_ENCR_KEY_LEN]; 00649 u8 sign_key[IEEE8021X_SIGN_KEY_LEN]; 00650 }; 00651 00652 00653 static void eapol_sm_processKey(struct eapol_sm *sm) 00654 { 00655 struct ieee802_1x_hdr *hdr; 00656 struct ieee802_1x_eapol_key *key; 00657 struct eap_key_data keydata; 00658 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32]; 00659 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN]; 00660 int key_len, res, sign_key_len, encr_key_len; 00661 u16 rx_key_length; 00662 00663 wpa_printf(MSG_DEBUG, "EAPOL: processKey"); 00664 if (sm->last_rx_key == NULL) 00665 return; 00666 00667 if (!sm->conf.accept_802_1x_keys) { 00668 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key" 00669 " even though this was not accepted - " 00670 "ignoring this packet"); 00671 return; 00672 } 00673 00674 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key; 00675 key = (struct ieee802_1x_eapol_key *) (hdr + 1); 00676 if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) { 00677 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame"); 00678 return; 00679 } 00680 rx_key_length = WPA_GET_BE16(key->key_length); 00681 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d " 00682 "EAPOL-Key: type=%d key_length=%d key_index=0x%x", 00683 hdr->version, hdr->type, be_to_host16(hdr->length), 00684 key->type, rx_key_length, key->key_index); 00685 00686 eapol_sm_notify_lower_layer_success(sm, 1); 00687 sign_key_len = IEEE8021X_SIGN_KEY_LEN; 00688 encr_key_len = IEEE8021X_ENCR_KEY_LEN; 00689 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata)); 00690 if (res < 0) { 00691 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for " 00692 "decrypting EAPOL-Key keys"); 00693 return; 00694 } 00695 if (res == 16) { 00696 /* LEAP derives only 16 bytes of keying material. */ 00697 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16); 00698 if (res) { 00699 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP " 00700 "master key for decrypting EAPOL-Key keys"); 00701 return; 00702 } 00703 sign_key_len = 16; 00704 encr_key_len = 16; 00705 os_memcpy(keydata.sign_key, keydata.encr_key, 16); 00706 } else if (res) { 00707 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key " 00708 "data for decrypting EAPOL-Key keys (res=%d)", res); 00709 return; 00710 } 00711 00712 /* The key replay_counter must increase when same master key */ 00713 if (sm->replay_counter_valid && 00714 os_memcmp(sm->last_replay_counter, key->replay_counter, 00715 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) { 00716 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did " 00717 "not increase - ignoring key"); 00718 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter", 00719 sm->last_replay_counter, 00720 IEEE8021X_REPLAY_COUNTER_LEN); 00721 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter", 00722 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); 00723 return; 00724 } 00725 00726 /* Verify key signature (HMAC-MD5) */ 00727 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN); 00728 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN); 00729 hmac_md5(keydata.sign_key, sign_key_len, 00730 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length), 00731 key->key_signature); 00732 if (os_memcmp(orig_key_sign, key->key_signature, 00733 IEEE8021X_KEY_SIGN_LEN) != 0) { 00734 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in " 00735 "EAPOL-Key packet"); 00736 os_memcpy(key->key_signature, orig_key_sign, 00737 IEEE8021X_KEY_SIGN_LEN); 00738 return; 00739 } 00740 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified"); 00741 00742 key_len = be_to_host16(hdr->length) - sizeof(*key); 00743 if (key_len > 32 || rx_key_length > 32) { 00744 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d", 00745 key_len ? key_len : rx_key_length); 00746 return; 00747 } 00748 if (key_len == rx_key_length) { 00749 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN); 00750 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key, 00751 encr_key_len); 00752 os_memcpy(datakey, key + 1, key_len); 00753 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0, 00754 datakey, key_len); 00755 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key", 00756 datakey, key_len); 00757 } else if (key_len == 0) { 00758 /* 00759 * IEEE 802.1X-2004 specifies that least significant Key Length 00760 * octets from MS-MPPE-Send-Key are used as the key if the key 00761 * data is not present. This seems to be meaning the beginning 00762 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in 00763 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator. 00764 * Anyway, taking the beginning of the keying material from EAP 00765 * seems to interoperate with Authenticators. 00766 */ 00767 key_len = rx_key_length; 00768 os_memcpy(datakey, keydata.encr_key, key_len); 00769 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying " 00770 "material data encryption key", 00771 datakey, key_len); 00772 } else { 00773 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d " 00774 "(key_length=%d)", key_len, rx_key_length); 00775 return; 00776 } 00777 00778 sm->replay_counter_valid = TRUE; 00779 os_memcpy(sm->last_replay_counter, key->replay_counter, 00780 IEEE8021X_REPLAY_COUNTER_LEN); 00781 00782 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d " 00783 "len %d", 00784 key->key_index & IEEE8021X_KEY_INDEX_FLAG ? 00785 "unicast" : "broadcast", 00786 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len); 00787 00788 if (sm->ctx->set_wep_key && 00789 sm->ctx->set_wep_key(sm->ctx->ctx, 00790 key->key_index & IEEE8021X_KEY_INDEX_FLAG, 00791 key->key_index & IEEE8021X_KEY_INDEX_MASK, 00792 datakey, key_len) < 0) { 00793 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " 00794 " driver."); 00795 } else { 00796 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) 00797 sm->unicast_key_received = TRUE; 00798 else 00799 sm->broadcast_key_received = TRUE; 00800 00801 if ((sm->unicast_key_received || 00802 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && 00803 (sm->broadcast_key_received || 00804 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST))) 00805 { 00806 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " 00807 "frames received"); 00808 sm->portValid = TRUE; 00809 if (sm->ctx->eapol_done_cb) 00810 sm->ctx->eapol_done_cb(sm->ctx->ctx); 00811 } 00812 } 00813 } 00814 00815 00816 static void eapol_sm_getSuppRsp(struct eapol_sm *sm) 00817 { 00818 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp"); 00819 /* EAP layer processing; no special code is needed, since Supplicant 00820 * Backend state machine is waiting for eapNoResp or eapResp to be set 00821 * and these are only set in the EAP state machine when the processing 00822 * has finished. */ 00823 } 00824 00825 00826 static void eapol_sm_txSuppRsp(struct eapol_sm *sm) 00827 { 00828 struct wpabuf *resp; 00829 00830 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp"); 00831 resp = eap_get_eapRespData(sm->eap); 00832 if (resp == NULL) { 00833 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data " 00834 "not available"); 00835 return; 00836 } 00837 00838 /* Send EAP-Packet from the EAP layer to the Authenticator */ 00839 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, 00840 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp), 00841 wpabuf_len(resp)); 00842 00843 /* eapRespData is not used anymore, so free it here */ 00844 wpabuf_free(resp); 00845 00846 if (sm->initial_req) 00847 sm->dot1xSuppEapolReqIdFramesRx++; 00848 else 00849 sm->dot1xSuppEapolReqFramesRx++; 00850 sm->dot1xSuppEapolRespFramesTx++; 00851 sm->dot1xSuppEapolFramesTx++; 00852 } 00853 00854 00855 static void eapol_sm_abortSupp(struct eapol_sm *sm) 00856 { 00857 /* release system resources that may have been allocated for the 00858 * authentication session */ 00859 os_free(sm->last_rx_key); 00860 sm->last_rx_key = NULL; 00861 wpabuf_free(sm->eapReqData); 00862 sm->eapReqData = NULL; 00863 eap_sm_abort(sm->eap); 00864 } 00865 00866 00867 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx) 00868 { 00869 eapol_sm_step(timeout_ctx); 00870 } 00871 00872 00873 static void eapol_sm_set_port_authorized(struct eapol_sm *sm) 00874 { 00875 if (sm->ctx->port_cb) 00876 sm->ctx->port_cb(sm->ctx->ctx, 1); 00877 } 00878 00879 00880 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm) 00881 { 00882 if (sm->ctx->port_cb) 00883 sm->ctx->port_cb(sm->ctx->ctx, 0); 00884 } 00885 00886 00895 void eapol_sm_step(struct eapol_sm *sm) 00896 { 00897 int i; 00898 00899 /* In theory, it should be ok to run this in loop until !changed. 00900 * However, it is better to use a limit on number of iterations to 00901 * allow events (e.g., SIGTERM) to stop the program cleanly if the 00902 * state machine were to generate a busy loop. */ 00903 for (i = 0; i < 100; i++) { 00904 sm->changed = FALSE; 00905 SM_STEP_RUN(SUPP_PAE); 00906 SM_STEP_RUN(KEY_RX); 00907 SM_STEP_RUN(SUPP_BE); 00908 if (eap_peer_sm_step(sm->eap)) 00909 sm->changed = TRUE; 00910 if (!sm->changed) 00911 break; 00912 } 00913 00914 if (sm->changed) { 00915 /* restart EAPOL state machine step from timeout call in order 00916 * to allow other events to be processed. */ 00917 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); 00918 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm); 00919 } 00920 00921 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) { 00922 int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0; 00923 sm->cb_status = EAPOL_CB_IN_PROGRESS; 00924 sm->ctx->cb(sm, success, sm->ctx->cb_ctx); 00925 } 00926 } 00927 00928 00929 #ifdef CONFIG_CTRL_IFACE 00930 static const char *eapol_supp_pae_state(int state) 00931 { 00932 switch (state) { 00933 case SUPP_PAE_LOGOFF: 00934 return "LOGOFF"; 00935 case SUPP_PAE_DISCONNECTED: 00936 return "DISCONNECTED"; 00937 case SUPP_PAE_CONNECTING: 00938 return "CONNECTING"; 00939 case SUPP_PAE_AUTHENTICATING: 00940 return "AUTHENTICATING"; 00941 case SUPP_PAE_HELD: 00942 return "HELD"; 00943 case SUPP_PAE_AUTHENTICATED: 00944 return "AUTHENTICATED"; 00945 case SUPP_PAE_RESTART: 00946 return "RESTART"; 00947 default: 00948 return "UNKNOWN"; 00949 } 00950 } 00951 00952 00953 static const char *eapol_supp_be_state(int state) 00954 { 00955 switch (state) { 00956 case SUPP_BE_REQUEST: 00957 return "REQUEST"; 00958 case SUPP_BE_RESPONSE: 00959 return "RESPONSE"; 00960 case SUPP_BE_SUCCESS: 00961 return "SUCCESS"; 00962 case SUPP_BE_FAIL: 00963 return "FAIL"; 00964 case SUPP_BE_TIMEOUT: 00965 return "TIMEOUT"; 00966 case SUPP_BE_IDLE: 00967 return "IDLE"; 00968 case SUPP_BE_INITIALIZE: 00969 return "INITIALIZE"; 00970 case SUPP_BE_RECEIVE: 00971 return "RECEIVE"; 00972 default: 00973 return "UNKNOWN"; 00974 } 00975 } 00976 00977 00978 static const char * eapol_port_status(PortStatus status) 00979 { 00980 if (status == Authorized) 00981 return "Authorized"; 00982 else 00983 return "Unauthorized"; 00984 } 00985 #endif /* CONFIG_CTRL_IFACE */ 00986 00987 00988 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 00989 static const char * eapol_port_control(PortControl ctrl) 00990 { 00991 switch (ctrl) { 00992 case Auto: 00993 return "Auto"; 00994 case ForceUnauthorized: 00995 return "ForceUnauthorized"; 00996 case ForceAuthorized: 00997 return "ForceAuthorized"; 00998 default: 00999 return "Unknown"; 01000 } 01001 } 01002 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 01003 01004 01016 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, 01017 int startPeriod, int maxStart) 01018 { 01019 if (sm == NULL) 01020 return; 01021 if (heldPeriod >= 0) 01022 sm->heldPeriod = heldPeriod; 01023 if (authPeriod >= 0) 01024 sm->authPeriod = authPeriod; 01025 if (startPeriod >= 0) 01026 sm->startPeriod = startPeriod; 01027 if (maxStart >= 0) 01028 sm->maxStart = maxStart; 01029 } 01030 01031 01032 #ifdef CONFIG_CTRL_IFACE 01033 01046 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, 01047 int verbose) 01048 { 01049 int len, ret; 01050 if (sm == NULL) 01051 return 0; 01052 01053 len = os_snprintf(buf, buflen, 01054 "Supplicant PAE state=%s\n" 01055 "suppPortStatus=%s\n", 01056 eapol_supp_pae_state(sm->SUPP_PAE_state), 01057 eapol_port_status(sm->suppPortStatus)); 01058 if (len < 0 || (size_t) len >= buflen) 01059 return 0; 01060 01061 if (verbose) { 01062 ret = os_snprintf(buf + len, buflen - len, 01063 "heldPeriod=%u\n" 01064 "authPeriod=%u\n" 01065 "startPeriod=%u\n" 01066 "maxStart=%u\n" 01067 "portControl=%s\n" 01068 "Supplicant Backend state=%s\n", 01069 sm->heldPeriod, 01070 sm->authPeriod, 01071 sm->startPeriod, 01072 sm->maxStart, 01073 eapol_port_control(sm->portControl), 01074 eapol_supp_be_state(sm->SUPP_BE_state)); 01075 if (ret < 0 || (size_t) ret >= buflen - len) 01076 return len; 01077 len += ret; 01078 } 01079 01080 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose); 01081 01082 return len; 01083 } 01084 01085 01098 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen) 01099 { 01100 size_t len; 01101 int ret; 01102 01103 if (sm == NULL) 01104 return 0; 01105 ret = os_snprintf(buf, buflen, 01106 "dot1xSuppPaeState=%d\n" 01107 "dot1xSuppHeldPeriod=%u\n" 01108 "dot1xSuppAuthPeriod=%u\n" 01109 "dot1xSuppStartPeriod=%u\n" 01110 "dot1xSuppMaxStart=%u\n" 01111 "dot1xSuppSuppControlledPortStatus=%s\n" 01112 "dot1xSuppBackendPaeState=%d\n", 01113 sm->SUPP_PAE_state, 01114 sm->heldPeriod, 01115 sm->authPeriod, 01116 sm->startPeriod, 01117 sm->maxStart, 01118 sm->suppPortStatus == Authorized ? 01119 "Authorized" : "Unauthorized", 01120 sm->SUPP_BE_state); 01121 01122 if (ret < 0 || (size_t) ret >= buflen) 01123 return 0; 01124 len = ret; 01125 01126 ret = os_snprintf(buf + len, buflen - len, 01127 "dot1xSuppEapolFramesRx=%u\n" 01128 "dot1xSuppEapolFramesTx=%u\n" 01129 "dot1xSuppEapolStartFramesTx=%u\n" 01130 "dot1xSuppEapolLogoffFramesTx=%u\n" 01131 "dot1xSuppEapolRespFramesTx=%u\n" 01132 "dot1xSuppEapolReqIdFramesRx=%u\n" 01133 "dot1xSuppEapolReqFramesRx=%u\n" 01134 "dot1xSuppInvalidEapolFramesRx=%u\n" 01135 "dot1xSuppEapLengthErrorFramesRx=%u\n" 01136 "dot1xSuppLastEapolFrameVersion=%u\n" 01137 "dot1xSuppLastEapolFrameSource=" MACSTR "\n", 01138 sm->dot1xSuppEapolFramesRx, 01139 sm->dot1xSuppEapolFramesTx, 01140 sm->dot1xSuppEapolStartFramesTx, 01141 sm->dot1xSuppEapolLogoffFramesTx, 01142 sm->dot1xSuppEapolRespFramesTx, 01143 sm->dot1xSuppEapolReqIdFramesRx, 01144 sm->dot1xSuppEapolReqFramesRx, 01145 sm->dot1xSuppInvalidEapolFramesRx, 01146 sm->dot1xSuppEapLengthErrorFramesRx, 01147 sm->dot1xSuppLastEapolFrameVersion, 01148 MAC2STR(sm->dot1xSuppLastEapolFrameSource)); 01149 01150 if (ret < 0 || (size_t) ret >= buflen - len) 01151 return len; 01152 len += ret; 01153 01154 return len; 01155 } 01156 #endif /* CONFIG_CTRL_IFACE */ 01157 01158 01168 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, 01169 size_t len) 01170 { 01171 const struct ieee802_1x_hdr *hdr; 01172 const struct ieee802_1x_eapol_key *key; 01173 int data_len; 01174 int res = 1; 01175 size_t plen; 01176 01177 if (sm == NULL) 01178 return 0; 01179 sm->dot1xSuppEapolFramesRx++; 01180 if (len < sizeof(*hdr)) { 01181 sm->dot1xSuppInvalidEapolFramesRx++; 01182 return 0; 01183 } 01184 hdr = (const struct ieee802_1x_hdr *) buf; 01185 sm->dot1xSuppLastEapolFrameVersion = hdr->version; 01186 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); 01187 if (hdr->version < EAPOL_VERSION) { 01188 /* TODO: backwards compatibility */ 01189 } 01190 plen = be_to_host16(hdr->length); 01191 if (plen > len - sizeof(*hdr)) { 01192 sm->dot1xSuppEapLengthErrorFramesRx++; 01193 return 0; 01194 } 01195 #ifdef CONFIG_WPS 01196 if (sm->conf.workaround && 01197 plen < len - sizeof(*hdr) && 01198 hdr->type == IEEE802_1X_TYPE_EAP_PACKET && 01199 len - sizeof(*hdr) > sizeof(struct eap_hdr)) { 01200 const struct eap_hdr *ehdr = 01201 (const struct eap_hdr *) (hdr + 1); 01202 u16 elen; 01203 01204 elen = be_to_host16(ehdr->length); 01205 if (elen > plen && elen <= len - sizeof(*hdr)) { 01206 /* 01207 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS 01208 * packets with too short EAPOL header length field 01209 * (14 octets). This is fixed in firmware Ver.1.49. 01210 * As a workaround, fix the EAPOL header based on the 01211 * correct length in the EAP packet. 01212 */ 01213 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL " 01214 "payload length based on EAP header: " 01215 "%d -> %d", (int) plen, elen); 01216 plen = elen; 01217 } 01218 } 01219 #endif /* CONFIG_WPS */ 01220 data_len = plen + sizeof(*hdr); 01221 01222 switch (hdr->type) { 01223 case IEEE802_1X_TYPE_EAP_PACKET: 01224 if (sm->cached_pmk) { 01225 /* Trying to use PMKSA caching, but Authenticator did 01226 * not seem to have a matching entry. Need to restart 01227 * EAPOL state machines. 01228 */ 01229 eapol_sm_abort_cached(sm); 01230 } 01231 wpabuf_free(sm->eapReqData); 01232 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen); 01233 if (sm->eapReqData) { 01234 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " 01235 "frame"); 01236 sm->eapolEap = TRUE; 01237 eapol_sm_step(sm); 01238 } 01239 break; 01240 case IEEE802_1X_TYPE_EAPOL_KEY: 01241 if (plen < sizeof(*key)) { 01242 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " 01243 "frame received"); 01244 break; 01245 } 01246 key = (const struct ieee802_1x_eapol_key *) (hdr + 1); 01247 if (key->type == EAPOL_KEY_TYPE_WPA || 01248 key->type == EAPOL_KEY_TYPE_RSN) { 01249 /* WPA Supplicant takes care of this frame. */ 01250 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " 01251 "frame in EAPOL state machines"); 01252 res = 0; 01253 break; 01254 } 01255 if (key->type != EAPOL_KEY_TYPE_RC4) { 01256 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " 01257 "EAPOL-Key type %d", key->type); 01258 break; 01259 } 01260 os_free(sm->last_rx_key); 01261 sm->last_rx_key = os_malloc(data_len); 01262 if (sm->last_rx_key) { 01263 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " 01264 "frame"); 01265 os_memcpy(sm->last_rx_key, buf, data_len); 01266 sm->last_rx_key_len = data_len; 01267 sm->rxKey = TRUE; 01268 eapol_sm_step(sm); 01269 } 01270 break; 01271 default: 01272 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", 01273 hdr->type); 01274 sm->dot1xSuppInvalidEapolFramesRx++; 01275 break; 01276 } 01277 01278 return res; 01279 } 01280 01281 01289 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) 01290 { 01291 if (sm) 01292 sm->dot1xSuppEapolFramesTx++; 01293 } 01294 01295 01303 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) 01304 { 01305 if (sm == NULL) 01306 return; 01307 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 01308 "portEnabled=%d", enabled); 01309 sm->portEnabled = enabled; 01310 eapol_sm_step(sm); 01311 } 01312 01313 01321 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) 01322 { 01323 if (sm == NULL) 01324 return; 01325 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 01326 "portValid=%d", valid); 01327 sm->portValid = valid; 01328 eapol_sm_step(sm); 01329 } 01330 01331 01343 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) 01344 { 01345 if (sm == NULL) 01346 return; 01347 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 01348 "EAP success=%d", success); 01349 sm->eapSuccess = success; 01350 sm->altAccept = success; 01351 if (success) 01352 eap_notify_success(sm->eap); 01353 eapol_sm_step(sm); 01354 } 01355 01356 01365 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) 01366 { 01367 if (sm == NULL) 01368 return; 01369 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 01370 "EAP fail=%d", fail); 01371 sm->eapFail = fail; 01372 sm->altReject = fail; 01373 eapol_sm_step(sm); 01374 } 01375 01376 01389 void eapol_sm_notify_config(struct eapol_sm *sm, 01390 struct eap_peer_config *config, 01391 const struct eapol_config *conf) 01392 { 01393 if (sm == NULL) 01394 return; 01395 01396 sm->config = config; 01397 01398 if (conf == NULL) 01399 return; 01400 01401 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; 01402 sm->conf.required_keys = conf->required_keys; 01403 sm->conf.fast_reauth = conf->fast_reauth; 01404 sm->conf.workaround = conf->workaround; 01405 if (sm->eap) { 01406 eap_set_fast_reauth(sm->eap, conf->fast_reauth); 01407 eap_set_workaround(sm->eap, conf->workaround); 01408 eap_set_force_disabled(sm->eap, conf->eap_disabled); 01409 } 01410 } 01411 01412 01424 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) 01425 { 01426 const u8 *eap_key; 01427 size_t eap_len; 01428 01429 if (sm == NULL || !eap_key_available(sm->eap)) { 01430 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); 01431 return -1; 01432 } 01433 eap_key = eap_get_eapKeyData(sm->eap, &eap_len); 01434 if (eap_key == NULL) { 01435 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData"); 01436 return -1; 01437 } 01438 if (len > eap_len) { 01439 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not " 01440 "available (len=%lu)", 01441 (unsigned long) len, (unsigned long) eap_len); 01442 return eap_len; 01443 } 01444 os_memcpy(key, eap_key, len); 01445 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)", 01446 (unsigned long) len); 01447 return 0; 01448 } 01449 01450 01458 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) 01459 { 01460 if (sm) { 01461 sm->userLogoff = logoff; 01462 eapol_sm_step(sm); 01463 } 01464 } 01465 01466 01474 void eapol_sm_notify_cached(struct eapol_sm *sm) 01475 { 01476 if (sm == NULL) 01477 return; 01478 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); 01479 sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED; 01480 sm->suppPortStatus = Authorized; 01481 eapol_sm_set_port_authorized(sm); 01482 sm->portValid = TRUE; 01483 eap_notify_success(sm->eap); 01484 eapol_sm_step(sm); 01485 } 01486 01487 01495 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt) 01496 { 01497 if (sm == NULL) 01498 return; 01499 if (attempt) { 01500 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); 01501 sm->cached_pmk = TRUE; 01502 } else { 01503 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA"); 01504 sm->cached_pmk = FALSE; 01505 } 01506 } 01507 01508 01509 static void eapol_sm_abort_cached(struct eapol_sm *sm) 01510 { 01511 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, " 01512 "doing full EAP authentication"); 01513 if (sm == NULL) 01514 return; 01515 sm->cached_pmk = FALSE; 01516 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; 01517 sm->suppPortStatus = Unauthorized; 01518 eapol_sm_set_port_unauthorized(sm); 01519 01520 /* Make sure we do not start sending EAPOL-Start frames first, but 01521 * instead move to RESTART state to start EAPOL authentication. */ 01522 sm->startWhen = 3; 01523 eapol_enable_timer_tick(sm); 01524 01525 if (sm->ctx->aborted_cached) 01526 sm->ctx->aborted_cached(sm->ctx->ctx); 01527 } 01528 01529 01538 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx) 01539 { 01540 if (sm) { 01541 sm->ctx->scard_ctx = ctx; 01542 eap_register_scard_ctx(sm->eap, ctx); 01543 } 01544 } 01545 01546 01554 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl) 01555 { 01556 if (sm == NULL) 01557 return; 01558 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 01559 "portControl=%s", eapol_port_control(portControl)); 01560 sm->portControl = portControl; 01561 eapol_sm_step(sm); 01562 } 01563 01564 01572 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) 01573 { 01574 if (sm == NULL) 01575 return; 01576 eap_sm_notify_ctrl_attached(sm->eap); 01577 } 01578 01579 01587 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) 01588 { 01589 if (sm == NULL) 01590 return; 01591 if (sm->eapReqData && !sm->eapReq) { 01592 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " 01593 "input) notification - retrying pending EAP " 01594 "Request"); 01595 sm->eapolEap = TRUE; 01596 sm->eapReq = TRUE; 01597 eapol_sm_step(sm); 01598 } 01599 } 01600 01601 01609 void eapol_sm_request_reauth(struct eapol_sm *sm) 01610 { 01611 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED) 01612 return; 01613 eapol_sm_txStart(sm); 01614 } 01615 01616 01627 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm) 01628 { 01629 if (sm == NULL) 01630 return; 01631 eap_notify_lower_layer_success(sm->eap); 01632 if (!in_eapol_sm) 01633 eapol_sm_step(sm); 01634 } 01635 01636 01641 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) 01642 { 01643 if (sm) 01644 eap_invalidate_cached_session(sm->eap); 01645 } 01646 01647 01648 static struct eap_peer_config * eapol_sm_get_config(void *ctx) 01649 { 01650 struct eapol_sm *sm = ctx; 01651 return sm ? sm->config : NULL; 01652 } 01653 01654 01655 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) 01656 { 01657 struct eapol_sm *sm = ctx; 01658 if (sm == NULL || sm->eapReqData == NULL) 01659 return NULL; 01660 01661 return sm->eapReqData; 01662 } 01663 01664 01665 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) 01666 { 01667 struct eapol_sm *sm = ctx; 01668 if (sm == NULL) 01669 return FALSE; 01670 switch (variable) { 01671 case EAPOL_eapSuccess: 01672 return sm->eapSuccess; 01673 case EAPOL_eapRestart: 01674 return sm->eapRestart; 01675 case EAPOL_eapFail: 01676 return sm->eapFail; 01677 case EAPOL_eapResp: 01678 return sm->eapResp; 01679 case EAPOL_eapNoResp: 01680 return sm->eapNoResp; 01681 case EAPOL_eapReq: 01682 return sm->eapReq; 01683 case EAPOL_portEnabled: 01684 return sm->portEnabled; 01685 case EAPOL_altAccept: 01686 return sm->altAccept; 01687 case EAPOL_altReject: 01688 return sm->altReject; 01689 } 01690 return FALSE; 01691 } 01692 01693 01694 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, 01695 Boolean value) 01696 { 01697 struct eapol_sm *sm = ctx; 01698 if (sm == NULL) 01699 return; 01700 switch (variable) { 01701 case EAPOL_eapSuccess: 01702 sm->eapSuccess = value; 01703 break; 01704 case EAPOL_eapRestart: 01705 sm->eapRestart = value; 01706 break; 01707 case EAPOL_eapFail: 01708 sm->eapFail = value; 01709 break; 01710 case EAPOL_eapResp: 01711 sm->eapResp = value; 01712 break; 01713 case EAPOL_eapNoResp: 01714 sm->eapNoResp = value; 01715 break; 01716 case EAPOL_eapReq: 01717 sm->eapReq = value; 01718 break; 01719 case EAPOL_portEnabled: 01720 sm->portEnabled = value; 01721 break; 01722 case EAPOL_altAccept: 01723 sm->altAccept = value; 01724 break; 01725 case EAPOL_altReject: 01726 sm->altReject = value; 01727 break; 01728 } 01729 } 01730 01731 01732 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable) 01733 { 01734 struct eapol_sm *sm = ctx; 01735 if (sm == NULL) 01736 return 0; 01737 switch (variable) { 01738 case EAPOL_idleWhile: 01739 return sm->idleWhile; 01740 } 01741 return 0; 01742 } 01743 01744 01745 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable, 01746 unsigned int value) 01747 { 01748 struct eapol_sm *sm = ctx; 01749 if (sm == NULL) 01750 return; 01751 switch (variable) { 01752 case EAPOL_idleWhile: 01753 sm->idleWhile = value; 01754 eapol_enable_timer_tick(sm); 01755 break; 01756 } 01757 } 01758 01759 01760 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob) 01761 { 01762 #ifndef CONFIG_NO_CONFIG_BLOBS 01763 struct eapol_sm *sm = ctx; 01764 if (sm && sm->ctx && sm->ctx->set_config_blob) 01765 sm->ctx->set_config_blob(sm->ctx->ctx, blob); 01766 #endif /* CONFIG_NO_CONFIG_BLOBS */ 01767 } 01768 01769 01770 static const struct wpa_config_blob * 01771 eapol_sm_get_config_blob(void *ctx, const char *name) 01772 { 01773 #ifndef CONFIG_NO_CONFIG_BLOBS 01774 struct eapol_sm *sm = ctx; 01775 if (sm && sm->ctx && sm->ctx->get_config_blob) 01776 return sm->ctx->get_config_blob(sm->ctx->ctx, name); 01777 else 01778 return NULL; 01779 #else /* CONFIG_NO_CONFIG_BLOBS */ 01780 return NULL; 01781 #endif /* CONFIG_NO_CONFIG_BLOBS */ 01782 } 01783 01784 01785 static void eapol_sm_notify_pending(void *ctx) 01786 { 01787 struct eapol_sm *sm = ctx; 01788 if (sm == NULL) 01789 return; 01790 if (sm->eapReqData && !sm->eapReq) { 01791 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " 01792 "state machine - retrying pending EAP Request"); 01793 sm->eapolEap = TRUE; 01794 sm->eapReq = TRUE; 01795 eapol_sm_step(sm); 01796 } 01797 } 01798 01799 01800 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 01801 static void eapol_sm_eap_param_needed(void *ctx, const char *field, 01802 const char *txt) 01803 { 01804 struct eapol_sm *sm = ctx; 01805 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed"); 01806 if (sm->ctx->eap_param_needed) 01807 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt); 01808 } 01809 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 01810 #define eapol_sm_eap_param_needed NULL 01811 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 01812 01813 01814 static struct eapol_callbacks eapol_cb = 01815 { 01816 eapol_sm_get_config, 01817 eapol_sm_get_bool, 01818 eapol_sm_set_bool, 01819 eapol_sm_get_int, 01820 eapol_sm_set_int, 01821 eapol_sm_get_eapReqData, 01822 eapol_sm_set_config_blob, 01823 eapol_sm_get_config_blob, 01824 eapol_sm_notify_pending, 01825 eapol_sm_eap_param_needed 01826 }; 01827 01828 01837 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) 01838 { 01839 struct eapol_sm *sm; 01840 struct eap_config conf; 01841 sm = os_zalloc(sizeof(*sm)); 01842 if (sm == NULL) 01843 return NULL; 01844 sm->ctx = ctx; 01845 01846 sm->portControl = Auto; 01847 01848 /* Supplicant PAE state machine */ 01849 sm->heldPeriod = 60; 01850 sm->startPeriod = 30; 01851 sm->maxStart = 3; 01852 01853 /* Supplicant Backend state machine */ 01854 sm->authPeriod = 30; 01855 01856 os_memset(&conf, 0, sizeof(conf)); 01857 conf.opensc_engine_path = ctx->opensc_engine_path; 01858 conf.pkcs11_engine_path = ctx->pkcs11_engine_path; 01859 conf.pkcs11_module_path = ctx->pkcs11_module_path; 01860 conf.wps = ctx->wps; 01861 01862 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); 01863 if (sm->eap == NULL) { 01864 os_free(sm); 01865 return NULL; 01866 } 01867 01868 /* Initialize EAPOL state machines */ 01869 sm->initialize = TRUE; 01870 eapol_sm_step(sm); 01871 sm->initialize = FALSE; 01872 eapol_sm_step(sm); 01873 01874 sm->timer_tick_enabled = 1; 01875 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); 01876 01877 return sm; 01878 } 01879 01880 01887 void eapol_sm_deinit(struct eapol_sm *sm) 01888 { 01889 if (sm == NULL) 01890 return; 01891 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); 01892 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 01893 eap_peer_sm_deinit(sm->eap); 01894 os_free(sm->last_rx_key); 01895 wpabuf_free(sm->eapReqData); 01896 os_free(sm->ctx); 01897 os_free(sm); 01898 }