00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00032
00036 struct eapol_sm {
00037
00038 unsigned int authWhile;
00039 unsigned int heldWhile;
00040 unsigned int startWhen;
00041 unsigned int idleWhile;
00042 int timer_tick_enabled;
00043
00044
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;
00054 Boolean portValid;
00055 Boolean suppAbort;
00056 Boolean suppFail;
00057 Boolean suppStart;
00058 Boolean suppSuccess;
00059 Boolean suppTimeout;
00060
00061
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
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;
00075
00076 Boolean userLogoff;
00077 Boolean logoffSent;
00078 unsigned int startCount;
00079 Boolean eapRestart;
00080 PortControl sPortMode;
00081
00082 unsigned int heldPeriod;
00083 unsigned int startPeriod;
00084 unsigned int maxStart;
00085
00086
00087 enum {
00088 KEY_RX_UNKNOWN = 0,
00089 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
00090 } KEY_RX_state;
00091
00092 Boolean rxKey;
00093
00094
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;
00106
00107 Boolean eapNoResp;
00108 Boolean eapReq;
00109 Boolean eapResp;
00110
00111 unsigned int authPeriod;
00112
00113
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
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;
00134 Boolean altAccept;
00135 Boolean altReject;
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
00158
00159 struct ieee802_1x_eapol_key {
00160 u8 type;
00161
00162 u8 key_length[2];
00163
00164
00165 u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
00166 u8 key_iv[IEEE8021X_KEY_IV_LEN];
00167 u8 key_index;
00168
00169
00170
00171
00172
00173 u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
00174
00175
00176
00177
00178
00179
00180
00181 } STRUCT_PACKED;
00182
00183 #ifdef _MSC_VER
00184 #pragma pack(pop)
00185 #endif
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
00201
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
00284
00285
00286
00287
00288
00289 #ifdef CONFIG_WPS
00290
00291 sm->startWhen = 1;
00292 #else
00293 sm->startWhen = 3;
00294 #endif
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
00505
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
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
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
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
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
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
00760
00761
00762
00763
00764
00765
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
00820
00821
00822
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
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
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
00858
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
00900
00901
00902
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
00916
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
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
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
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
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
01208
01209
01210
01211
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
01220 data_len = plen + sizeof(*hdr);
01221
01222 switch (hdr->type) {
01223 case IEEE802_1X_TYPE_EAP_PACKET:
01224 if (sm->cached_pmk) {
01225
01226
01227
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
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
01521
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
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
01780 return NULL;
01781 #endif
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
01810 #define eapol_sm_eap_param_needed NULL
01811 #endif
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
01849 sm->heldPeriod = 60;
01850 sm->startPeriod = 30;
01851 sm->maxStart = 3;
01852
01853
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
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 }