00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019
00020 #include "common.h"
00021 #include "eapol_sm.h"
00022 #include "eap.h"
00023 #include "eloop.h"
00024 #include "l2_packet.h"
00025 #include "wpa.h"
00026 #include "md5.h"
00027 #include "rc4.h"
00028
00029
00030
00031
00036 struct eapol_sm {
00037
00038 unsigned int authWhile;
00039 unsigned int heldWhile;
00040 unsigned int startWhen;
00041 unsigned int idleWhile;
00042
00043
00044 Boolean eapFail;
00045 Boolean eapolEap;
00046 Boolean eapSuccess;
00047 Boolean initialize;
00048 Boolean keyDone;
00049 Boolean keyRun;
00050 PortControl portControl;
00051 Boolean portEnabled;
00052 PortStatus suppPortStatus;
00053 Boolean portValid;
00054 Boolean suppAbort;
00055 Boolean suppFail;
00056 Boolean suppStart;
00057 Boolean suppSuccess;
00058 Boolean suppTimeout;
00059
00060
00061 enum {
00062 SUPP_PAE_UNKNOWN = 0,
00063 SUPP_PAE_DISCONNECTED = 1,
00064 SUPP_PAE_LOGOFF = 2,
00065 SUPP_PAE_CONNECTING = 3,
00066 SUPP_PAE_AUTHENTICATING = 4,
00067 SUPP_PAE_AUTHENTICATED = 5,
00068
00069 SUPP_PAE_HELD = 7,
00070 SUPP_PAE_RESTART = 8,
00071 SUPP_PAE_S_FORCE_AUTH = 9,
00072 SUPP_PAE_S_FORCE_UNAUTH = 10
00073 } SUPP_PAE_state;
00074
00075 Boolean userLogoff;
00076 Boolean logoffSent;
00077 unsigned int startCount;
00078 Boolean eapRestart;
00079 PortControl sPortMode;
00080
00081 unsigned int heldPeriod;
00082 unsigned int startPeriod;
00083 unsigned int maxStart;
00084
00085
00086 enum {
00087 KEY_RX_UNKNOWN = 0,
00088 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
00089 } KEY_RX_state;
00090
00091 Boolean rxKey;
00092
00093
00094 enum {
00095 SUPP_BE_UNKNOWN = 0,
00096 SUPP_BE_INITIALIZE = 1,
00097 SUPP_BE_IDLE = 2,
00098 SUPP_BE_REQUEST = 3,
00099 SUPP_BE_RECEIVE = 4,
00100 SUPP_BE_RESPONSE = 5,
00101 SUPP_BE_FAIL = 6,
00102 SUPP_BE_TIMEOUT = 7,
00103 SUPP_BE_SUCCESS = 8
00104 } SUPP_BE_state;
00105
00106 Boolean eapNoResp;
00107 Boolean eapReq;
00108 Boolean eapResp;
00109
00110 unsigned int authPeriod;
00111
00112
00113 unsigned int dot1xSuppEapolFramesRx;
00114 unsigned int dot1xSuppEapolFramesTx;
00115 unsigned int dot1xSuppEapolStartFramesTx;
00116 unsigned int dot1xSuppEapolLogoffFramesTx;
00117 unsigned int dot1xSuppEapolRespFramesTx;
00118 unsigned int dot1xSuppEapolReqIdFramesRx;
00119 unsigned int dot1xSuppEapolReqFramesRx;
00120 unsigned int dot1xSuppInvalidEapolFramesRx;
00121 unsigned int dot1xSuppEapLengthErrorFramesRx;
00122 unsigned int dot1xSuppLastEapolFrameVersion;
00123 unsigned char dot1xSuppLastEapolFrameSource[6];
00124
00125
00126 Boolean changed;
00127 struct eap_sm *eap;
00128 struct wpa_ssid *config;
00129 Boolean initial_req;
00130 u8 *last_rx_key;
00131 size_t last_rx_key_len;
00132 u8 *eapReqData;
00133 size_t eapReqDataLen;
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 struct ieee802_1x_eapol_key {
00156 u8 type;
00157
00158 u8 key_length[2];
00159
00160
00161 u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
00162 u8 key_iv[IEEE8021X_KEY_IV_LEN];
00163 u8 key_index;
00164
00165
00166
00167
00168
00169 u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
00170
00171
00172
00173
00174
00175
00176
00177 } __attribute__ ((packed));
00178
00179
00180 static void eapol_sm_txLogoff(struct eapol_sm *sm);
00181 static void eapol_sm_txStart(struct eapol_sm *sm);
00182 static void eapol_sm_processKey(struct eapol_sm *sm);
00183 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
00184 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
00185 static void eapol_sm_abortSupp(struct eapol_sm *sm);
00186 static void eapol_sm_abort_cached(struct eapol_sm *sm);
00187 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
00188
00189
00190
00191 #define SM_STATE(machine, state) \
00192 static void sm_ ## machine ## _ ## state ## _Enter(struct eapol_sm *sm, \
00193 int global)
00194
00195 #define SM_ENTRY(machine, state) \
00196 if (!global || sm->machine ## _state != machine ## _ ## state) { \
00197 sm->changed = TRUE; \
00198 wpa_printf(MSG_DEBUG, "EAPOL: " #machine " entering state " #state); \
00199 } \
00200 sm->machine ## _state = machine ## _ ## state;
00201
00202 #define SM_ENTER(machine, state) \
00203 sm_ ## machine ## _ ## state ## _Enter(sm, 0)
00204 #define SM_ENTER_GLOBAL(machine, state) \
00205 sm_ ## machine ## _ ## state ## _Enter(sm, 1)
00206
00207 #define SM_STEP(machine) \
00208 static void sm_ ## machine ## _Step(struct eapol_sm *sm)
00209
00210 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
00211
00212
00213
00214
00215 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
00216 {
00217 struct eapol_sm *sm = timeout_ctx;
00218
00219 if (sm->authWhile > 0) {
00220 sm->authWhile--;
00221 if (sm->authWhile == 0)
00222 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
00223 }
00224 if (sm->heldWhile > 0) {
00225 sm->heldWhile--;
00226 if (sm->heldWhile == 0)
00227 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
00228 }
00229 if (sm->startWhen > 0) {
00230 sm->startWhen--;
00231 if (sm->startWhen == 0)
00232 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
00233 }
00234 if (sm->idleWhile > 0) {
00235 sm->idleWhile--;
00236 if (sm->idleWhile == 0)
00237 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
00238 }
00239
00240 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, sm);
00241 eapol_sm_step(sm);
00242 }
00243
00244
00245 SM_STATE(SUPP_PAE, LOGOFF)
00246 {
00247 SM_ENTRY(SUPP_PAE, LOGOFF);
00248 eapol_sm_txLogoff(sm);
00249 sm->logoffSent = TRUE;
00250 sm->suppPortStatus = Unauthorized;
00251 }
00252
00253
00254 SM_STATE(SUPP_PAE, DISCONNECTED)
00255 {
00256 SM_ENTRY(SUPP_PAE, DISCONNECTED);
00257 sm->sPortMode = Auto;
00258 sm->startCount = 0;
00259 sm->logoffSent = FALSE;
00260 sm->suppPortStatus = Unauthorized;
00261 sm->suppAbort = TRUE;
00262
00263 sm->unicast_key_received = FALSE;
00264 sm->broadcast_key_received = FALSE;
00265 }
00266
00267
00268 SM_STATE(SUPP_PAE, CONNECTING)
00269 {
00270 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;
00271 SM_ENTRY(SUPP_PAE, CONNECTING);
00272 if (send_start) {
00273 sm->startWhen = sm->startPeriod;
00274 sm->startCount++;
00275 } else {
00276
00277
00278
00279
00280
00281
00282
00283 sm->startWhen = 3;
00284 }
00285 sm->eapolEap = FALSE;
00286 if (send_start)
00287 eapol_sm_txStart(sm);
00288 }
00289
00290
00291 SM_STATE(SUPP_PAE, AUTHENTICATING)
00292 {
00293 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
00294 sm->startCount = 0;
00295 sm->suppSuccess = FALSE;
00296 sm->suppFail = FALSE;
00297 sm->suppTimeout = FALSE;
00298 sm->keyRun = FALSE;
00299 sm->keyDone = FALSE;
00300 sm->suppStart = TRUE;
00301 }
00302
00303
00304 SM_STATE(SUPP_PAE, HELD)
00305 {
00306 SM_ENTRY(SUPP_PAE, HELD);
00307 sm->heldWhile = sm->heldPeriod;
00308 sm->suppPortStatus = Unauthorized;
00309 sm->cb_status = EAPOL_CB_FAILURE;
00310 }
00311
00312
00313 SM_STATE(SUPP_PAE, AUTHENTICATED)
00314 {
00315 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
00316 sm->suppPortStatus = Authorized;
00317 sm->cb_status = EAPOL_CB_SUCCESS;
00318 }
00319
00320
00321 SM_STATE(SUPP_PAE, RESTART)
00322 {
00323 SM_ENTRY(SUPP_PAE, RESTART);
00324 sm->eapRestart = TRUE;
00325 }
00326
00327
00328 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
00329 {
00330 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
00331 sm->suppPortStatus = Authorized;
00332 sm->sPortMode = ForceAuthorized;
00333 }
00334
00335
00336 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
00337 {
00338 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
00339 sm->suppPortStatus = Unauthorized;
00340 sm->sPortMode = ForceUnauthorized;
00341 eapol_sm_txLogoff(sm);
00342 }
00343
00344
00345 SM_STEP(SUPP_PAE)
00346 {
00347 if ((sm->userLogoff && !sm->logoffSent) &&
00348 !(sm->initialize || !sm->portEnabled))
00349 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
00350 else if (((sm->portControl == Auto) &&
00351 (sm->sPortMode != sm->portControl)) ||
00352 sm->initialize || !sm->portEnabled)
00353 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
00354 else if ((sm->portControl == ForceAuthorized) &&
00355 (sm->sPortMode != sm->portControl) &&
00356 !(sm->initialize || !sm->portEnabled))
00357 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
00358 else if ((sm->portControl == ForceUnauthorized) &&
00359 (sm->sPortMode != sm->portControl) &&
00360 !(sm->initialize || !sm->portEnabled))
00361 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
00362 else switch (sm->SUPP_PAE_state) {
00363 case SUPP_PAE_UNKNOWN:
00364 break;
00365 case SUPP_PAE_LOGOFF:
00366 if (!sm->userLogoff)
00367 SM_ENTER(SUPP_PAE, DISCONNECTED);
00368 break;
00369 case SUPP_PAE_DISCONNECTED:
00370 SM_ENTER(SUPP_PAE, CONNECTING);
00371 break;
00372 case SUPP_PAE_CONNECTING:
00373 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
00374 SM_ENTER(SUPP_PAE, CONNECTING);
00375 else if (sm->startWhen == 0 &&
00376 sm->startCount >= sm->maxStart &&
00377 sm->portValid)
00378 SM_ENTER(SUPP_PAE, AUTHENTICATED);
00379 else if (sm->eapSuccess || sm->eapFail)
00380 SM_ENTER(SUPP_PAE, AUTHENTICATING);
00381 else if (sm->eapolEap)
00382 SM_ENTER(SUPP_PAE, RESTART);
00383 else if (sm->startWhen == 0 &&
00384 sm->startCount >= sm->maxStart &&
00385 !sm->portValid)
00386 SM_ENTER(SUPP_PAE, HELD);
00387 break;
00388 case SUPP_PAE_AUTHENTICATING:
00389 if (sm->eapSuccess && !sm->portValid &&
00390 sm->conf.accept_802_1x_keys &&
00391 sm->conf.required_keys == 0) {
00392 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
00393 "plaintext connection; no EAPOL-Key frames "
00394 "required");
00395 sm->portValid = TRUE;
00396 if (sm->ctx->eapol_done_cb)
00397 sm->ctx->eapol_done_cb(sm->ctx->ctx);
00398 }
00399 if (sm->eapSuccess && sm->portValid)
00400 SM_ENTER(SUPP_PAE, AUTHENTICATED);
00401 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
00402 SM_ENTER(SUPP_PAE, HELD);
00403 else if (sm->suppTimeout)
00404 SM_ENTER(SUPP_PAE, CONNECTING);
00405 break;
00406 case SUPP_PAE_HELD:
00407 if (sm->heldWhile == 0)
00408 SM_ENTER(SUPP_PAE, CONNECTING);
00409 else if (sm->eapolEap)
00410 SM_ENTER(SUPP_PAE, RESTART);
00411 break;
00412 case SUPP_PAE_AUTHENTICATED:
00413 if (sm->eapolEap && sm->portValid)
00414 SM_ENTER(SUPP_PAE, RESTART);
00415 else if (!sm->portValid)
00416 SM_ENTER(SUPP_PAE, DISCONNECTED);
00417 break;
00418 case SUPP_PAE_RESTART:
00419 if (!sm->eapRestart)
00420 SM_ENTER(SUPP_PAE, AUTHENTICATING);
00421 break;
00422 case SUPP_PAE_S_FORCE_AUTH:
00423 break;
00424 case SUPP_PAE_S_FORCE_UNAUTH:
00425 break;
00426 }
00427 }
00428
00429
00430 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
00431 {
00432 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
00433 }
00434
00435
00436 SM_STATE(KEY_RX, KEY_RECEIVE)
00437 {
00438 SM_ENTRY(KEY_RX, KEY_RECEIVE);
00439 eapol_sm_processKey(sm);
00440 sm->rxKey = FALSE;
00441 }
00442
00443
00444 SM_STEP(KEY_RX)
00445 {
00446 if (sm->initialize || !sm->portEnabled)
00447 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
00448 switch (sm->KEY_RX_state) {
00449 case KEY_RX_UNKNOWN:
00450 break;
00451 case KEY_RX_NO_KEY_RECEIVE:
00452 if (sm->rxKey)
00453 SM_ENTER(KEY_RX, KEY_RECEIVE);
00454 break;
00455 case KEY_RX_KEY_RECEIVE:
00456 if (sm->rxKey)
00457 SM_ENTER(KEY_RX, KEY_RECEIVE);
00458 break;
00459 }
00460 }
00461
00462
00463 SM_STATE(SUPP_BE, REQUEST)
00464 {
00465 SM_ENTRY(SUPP_BE, REQUEST);
00466 sm->authWhile = 0;
00467 sm->eapReq = TRUE;
00468 eapol_sm_getSuppRsp(sm);
00469 }
00470
00471
00472 SM_STATE(SUPP_BE, RESPONSE)
00473 {
00474 SM_ENTRY(SUPP_BE, RESPONSE);
00475 eapol_sm_txSuppRsp(sm);
00476 sm->eapResp = FALSE;
00477 }
00478
00479
00480 SM_STATE(SUPP_BE, SUCCESS)
00481 {
00482 SM_ENTRY(SUPP_BE, SUCCESS);
00483 sm->keyRun = TRUE;
00484 sm->suppSuccess = TRUE;
00485
00486 if (eap_key_available(sm->eap)) {
00487
00488
00489 sm->replay_counter_valid = FALSE;
00490 }
00491 }
00492
00493
00494 SM_STATE(SUPP_BE, FAIL)
00495 {
00496 SM_ENTRY(SUPP_BE, FAIL);
00497 sm->suppFail = TRUE;
00498 }
00499
00500
00501 SM_STATE(SUPP_BE, TIMEOUT)
00502 {
00503 SM_ENTRY(SUPP_BE, TIMEOUT);
00504 sm->suppTimeout = TRUE;
00505 }
00506
00507
00508 SM_STATE(SUPP_BE, IDLE)
00509 {
00510 SM_ENTRY(SUPP_BE, IDLE);
00511 sm->suppStart = FALSE;
00512 sm->initial_req = TRUE;
00513 }
00514
00515
00516 SM_STATE(SUPP_BE, INITIALIZE)
00517 {
00518 SM_ENTRY(SUPP_BE, INITIALIZE);
00519 eapol_sm_abortSupp(sm);
00520 sm->suppAbort = FALSE;
00521 }
00522
00523
00524 SM_STATE(SUPP_BE, RECEIVE)
00525 {
00526 SM_ENTRY(SUPP_BE, RECEIVE);
00527 sm->authWhile = sm->authPeriod;
00528 sm->eapolEap = FALSE;
00529 sm->eapNoResp = FALSE;
00530 sm->initial_req = FALSE;
00531 }
00532
00533
00534 SM_STEP(SUPP_BE)
00535 {
00536 if (sm->initialize || sm->suppAbort)
00537 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
00538 else switch (sm->SUPP_BE_state) {
00539 case SUPP_BE_UNKNOWN:
00540 break;
00541 case SUPP_BE_REQUEST:
00542 if (sm->eapResp && sm->eapNoResp) {
00543 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
00544 "eapResp and eapNoResp set?!");
00545 }
00546 if (sm->eapResp)
00547 SM_ENTER(SUPP_BE, RESPONSE);
00548 else if (sm->eapNoResp)
00549 SM_ENTER(SUPP_BE, RECEIVE);
00550 break;
00551 case SUPP_BE_RESPONSE:
00552 SM_ENTER(SUPP_BE, RECEIVE);
00553 break;
00554 case SUPP_BE_SUCCESS:
00555 SM_ENTER(SUPP_BE, IDLE);
00556 break;
00557 case SUPP_BE_FAIL:
00558 SM_ENTER(SUPP_BE, IDLE);
00559 break;
00560 case SUPP_BE_TIMEOUT:
00561 SM_ENTER(SUPP_BE, IDLE);
00562 break;
00563 case SUPP_BE_IDLE:
00564 if (sm->eapFail && sm->suppStart)
00565 SM_ENTER(SUPP_BE, FAIL);
00566 else if (sm->eapolEap && sm->suppStart)
00567 SM_ENTER(SUPP_BE, REQUEST);
00568 else if (sm->eapSuccess && sm->suppStart)
00569 SM_ENTER(SUPP_BE, SUCCESS);
00570 break;
00571 case SUPP_BE_INITIALIZE:
00572 SM_ENTER(SUPP_BE, IDLE);
00573 break;
00574 case SUPP_BE_RECEIVE:
00575 if (sm->eapolEap)
00576 SM_ENTER(SUPP_BE, REQUEST);
00577 else if (sm->eapFail)
00578 SM_ENTER(SUPP_BE, FAIL);
00579 else if (sm->authWhile == 0)
00580 SM_ENTER(SUPP_BE, TIMEOUT);
00581 else if (sm->eapSuccess)
00582 SM_ENTER(SUPP_BE, SUCCESS);
00583 break;
00584 }
00585 }
00586
00587
00588 static void eapol_sm_txLogoff(struct eapol_sm *sm)
00589 {
00590 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
00591 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
00592 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
00593 sm->dot1xSuppEapolLogoffFramesTx++;
00594 sm->dot1xSuppEapolFramesTx++;
00595 }
00596
00597
00598 static void eapol_sm_txStart(struct eapol_sm *sm)
00599 {
00600 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
00601 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
00602 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
00603 sm->dot1xSuppEapolStartFramesTx++;
00604 sm->dot1xSuppEapolFramesTx++;
00605 }
00606
00607
00608 #define IEEE8021X_ENCR_KEY_LEN 32
00609 #define IEEE8021X_SIGN_KEY_LEN 32
00610
00611 struct eap_key_data {
00612 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
00613 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
00614 };
00615
00616
00617 static void eapol_sm_processKey(struct eapol_sm *sm)
00618 {
00619 struct ieee802_1x_hdr *hdr;
00620 struct ieee802_1x_eapol_key *key;
00621 struct eap_key_data keydata;
00622 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
00623 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
00624 int key_len, res, sign_key_len, encr_key_len;
00625 u16 rx_key_length;
00626
00627 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
00628 if (sm->last_rx_key == NULL)
00629 return;
00630
00631 if (!sm->conf.accept_802_1x_keys) {
00632 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
00633 " even though this was not accepted - "
00634 "ignoring this packet");
00635 return;
00636 }
00637
00638 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
00639 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
00640 if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) {
00641 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
00642 return;
00643 }
00644 rx_key_length = WPA_GET_BE16(key->key_length);
00645 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
00646 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
00647 hdr->version, hdr->type, be_to_host16(hdr->length),
00648 key->type, rx_key_length, key->key_index);
00649
00650 eapol_sm_notify_lower_layer_success(sm);
00651 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
00652 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
00653 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
00654 if (res < 0) {
00655 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
00656 "decrypting EAPOL-Key keys");
00657 return;
00658 }
00659 if (res == 16) {
00660
00661 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
00662 if (res) {
00663 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
00664 "master key for decrypting EAPOL-Key keys");
00665 return;
00666 }
00667 sign_key_len = 16;
00668 encr_key_len = 16;
00669 memcpy(keydata.sign_key, keydata.encr_key, 16);
00670 } else if (res) {
00671 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
00672 "data for decrypting EAPOL-Key keys (res=%d)", res);
00673 return;
00674 }
00675
00676
00677 if (sm->replay_counter_valid &&
00678 memcmp(sm->last_replay_counter, key->replay_counter,
00679 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
00680 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
00681 "not increase - ignoring key");
00682 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
00683 sm->last_replay_counter,
00684 IEEE8021X_REPLAY_COUNTER_LEN);
00685 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
00686 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
00687 return;
00688 }
00689
00690
00691 memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
00692 memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
00693 hmac_md5(keydata.sign_key, sign_key_len,
00694 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
00695 key->key_signature);
00696 if (memcmp(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN)
00697 != 0) {
00698 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
00699 "EAPOL-Key packet");
00700 memcpy(key->key_signature, orig_key_sign,
00701 IEEE8021X_KEY_SIGN_LEN);
00702 return;
00703 }
00704 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
00705
00706 key_len = be_to_host16(hdr->length) - sizeof(*key);
00707 if (key_len > 32 || rx_key_length > 32) {
00708 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
00709 key_len ? key_len : rx_key_length);
00710 return;
00711 }
00712 if (key_len == rx_key_length) {
00713 memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
00714 memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
00715 encr_key_len);
00716 memcpy(datakey, key + 1, key_len);
00717 rc4(datakey, key_len, ekey,
00718 IEEE8021X_KEY_IV_LEN + encr_key_len);
00719 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
00720 datakey, key_len);
00721 } else if (key_len == 0) {
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 key_len = rx_key_length;
00732 memcpy(datakey, keydata.encr_key, key_len);
00733 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
00734 "material data encryption key",
00735 datakey, key_len);
00736 } else {
00737 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
00738 "(key_length=%d)", key_len, rx_key_length);
00739 return;
00740 }
00741
00742 sm->replay_counter_valid = TRUE;
00743 memcpy(sm->last_replay_counter, key->replay_counter,
00744 IEEE8021X_REPLAY_COUNTER_LEN);
00745
00746 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
00747 "len %d",
00748 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
00749 "unicast" : "broadcast",
00750 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
00751
00752 if (sm->ctx->set_wep_key &&
00753 sm->ctx->set_wep_key(sm->ctx->ctx,
00754 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
00755 key->key_index & IEEE8021X_KEY_INDEX_MASK,
00756 datakey, key_len) < 0) {
00757 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
00758 " driver.");
00759 } else {
00760 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
00761 sm->unicast_key_received = TRUE;
00762 else
00763 sm->broadcast_key_received = TRUE;
00764
00765 if ((sm->unicast_key_received ||
00766 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
00767 (sm->broadcast_key_received ||
00768 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
00769 {
00770 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
00771 "frames received");
00772 sm->portValid = TRUE;
00773 if (sm->ctx->eapol_done_cb)
00774 sm->ctx->eapol_done_cb(sm->ctx->ctx);
00775 }
00776 }
00777 }
00778
00779
00780 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
00781 {
00782 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
00783
00784
00785
00786
00787 }
00788
00789
00790 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
00791 {
00792 u8 *resp;
00793 size_t resp_len;
00794
00795 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
00796 resp = eap_get_eapRespData(sm->eap, &resp_len);
00797 if (resp == NULL) {
00798 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
00799 "not available");
00800 return;
00801 }
00802
00803
00804 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
00805 IEEE802_1X_TYPE_EAP_PACKET, resp, resp_len);
00806
00807
00808 free(resp);
00809
00810 if (sm->initial_req)
00811 sm->dot1xSuppEapolReqIdFramesRx++;
00812 else
00813 sm->dot1xSuppEapolReqFramesRx++;
00814 sm->dot1xSuppEapolRespFramesTx++;
00815 sm->dot1xSuppEapolFramesTx++;
00816 }
00817
00818
00819 static void eapol_sm_abortSupp(struct eapol_sm *sm)
00820 {
00821
00822
00823 free(sm->last_rx_key);
00824 sm->last_rx_key = NULL;
00825 free(sm->eapReqData);
00826 sm->eapReqData = NULL;
00827 eap_sm_abort(sm->eap);
00828 }
00829
00830
00831 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
00832 {
00833 eapol_sm_step(timeout_ctx);
00834 }
00835
00836
00846 void eapol_sm_step(struct eapol_sm *sm)
00847 {
00848 int i;
00849
00850
00851
00852
00853
00854 for (i = 0; i < 100; i++) {
00855 sm->changed = FALSE;
00856 SM_STEP_RUN(SUPP_PAE);
00857 SM_STEP_RUN(KEY_RX);
00858 SM_STEP_RUN(SUPP_BE);
00859 if (eap_sm_step(sm->eap))
00860 sm->changed = TRUE;
00861 }
00862
00863 if (sm->changed) {
00864
00865
00866 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
00867 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
00868 }
00869
00870 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
00871 int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0;
00872 sm->cb_status = EAPOL_CB_IN_PROGRESS;
00873 sm->ctx->cb(sm, success, sm->ctx->cb_ctx);
00874 }
00875 }
00876
00877
00878 static const char *eapol_supp_pae_state(int state)
00879 {
00880 switch (state) {
00881 case SUPP_PAE_LOGOFF:
00882 return "LOGOFF";
00883 case SUPP_PAE_DISCONNECTED:
00884 return "DISCONNECTED";
00885 case SUPP_PAE_CONNECTING:
00886 return "CONNECTING";
00887 case SUPP_PAE_AUTHENTICATING:
00888 return "AUTHENTICATING";
00889 case SUPP_PAE_HELD:
00890 return "HELD";
00891 case SUPP_PAE_AUTHENTICATED:
00892 return "AUTHENTICATED";
00893 case SUPP_PAE_RESTART:
00894 return "RESTART";
00895 default:
00896 return "UNKNOWN";
00897 }
00898 }
00899
00900
00901 static const char *eapol_supp_be_state(int state)
00902 {
00903 switch (state) {
00904 case SUPP_BE_REQUEST:
00905 return "REQUEST";
00906 case SUPP_BE_RESPONSE:
00907 return "RESPONSE";
00908 case SUPP_BE_SUCCESS:
00909 return "SUCCESS";
00910 case SUPP_BE_FAIL:
00911 return "FAIL";
00912 case SUPP_BE_TIMEOUT:
00913 return "TIMEOUT";
00914 case SUPP_BE_IDLE:
00915 return "IDLE";
00916 case SUPP_BE_INITIALIZE:
00917 return "INITIALIZE";
00918 case SUPP_BE_RECEIVE:
00919 return "RECEIVE";
00920 default:
00921 return "UNKNOWN";
00922 }
00923 }
00924
00925
00926 static const char * eapol_port_status(PortStatus status)
00927 {
00928 if (status == Authorized)
00929 return "Authorized";
00930 else
00931 return "Unauthorized";
00932 }
00933
00934
00935 static const char * eapol_port_control(PortControl ctrl)
00936 {
00937 switch (ctrl) {
00938 case Auto:
00939 return "Auto";
00940 case ForceUnauthorized:
00941 return "ForceUnauthorized";
00942 case ForceAuthorized:
00943 return "ForceAuthorized";
00944 default:
00945 return "Unknown";
00946 }
00947 }
00948
00949
00962 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
00963 int startPeriod, int maxStart)
00964 {
00965 if (sm == NULL)
00966 return;
00967 if (heldPeriod >= 0)
00968 sm->heldPeriod = heldPeriod;
00969 if (authPeriod >= 0)
00970 sm->authPeriod = authPeriod;
00971 if (startPeriod >= 0)
00972 sm->startPeriod = startPeriod;
00973 if (maxStart >= 0)
00974 sm->maxStart = maxStart;
00975 }
00976
00977
00992 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
00993 int verbose)
00994 {
00995 int len;
00996 if (sm == NULL)
00997 return 0;
00998
00999 len = snprintf(buf, buflen,
01000 "Supplicant PAE state=%s\n"
01001 "suppPortStatus=%s\n",
01002 eapol_supp_pae_state(sm->SUPP_PAE_state),
01003 eapol_port_status(sm->suppPortStatus));
01004
01005 if (verbose) {
01006 len += snprintf(buf + len, buflen - len,
01007 "heldPeriod=%u\n"
01008 "authPeriod=%u\n"
01009 "startPeriod=%u\n"
01010 "maxStart=%u\n"
01011 "portControl=%s\n"
01012 "Supplicant Backend state=%s\n",
01013 sm->heldPeriod,
01014 sm->authPeriod,
01015 sm->startPeriod,
01016 sm->maxStart,
01017 eapol_port_control(sm->portControl),
01018 eapol_supp_be_state(sm->SUPP_BE_state));
01019 }
01020
01021 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
01022
01023 return len;
01024 }
01025
01026
01040 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
01041 {
01042 int len;
01043 if (sm == NULL)
01044 return 0;
01045 len = snprintf(buf, buflen,
01046 "dot1xSuppPaeState=%d\n"
01047 "dot1xSuppHeldPeriod=%u\n"
01048 "dot1xSuppAuthPeriod=%u\n"
01049 "dot1xSuppStartPeriod=%u\n"
01050 "dot1xSuppMaxStart=%u\n"
01051 "dot1xSuppSuppControlledPortStatus=%s\n"
01052 "dot1xSuppBackendPaeState=%d\n"
01053 "dot1xSuppEapolFramesRx=%u\n"
01054 "dot1xSuppEapolFramesTx=%u\n"
01055 "dot1xSuppEapolStartFramesTx=%u\n"
01056 "dot1xSuppEapolLogoffFramesTx=%u\n"
01057 "dot1xSuppEapolRespFramesTx=%u\n"
01058 "dot1xSuppEapolReqIdFramesRx=%u\n"
01059 "dot1xSuppEapolReqFramesRx=%u\n"
01060 "dot1xSuppInvalidEapolFramesRx=%u\n"
01061 "dot1xSuppEapLengthErrorFramesRx=%u\n"
01062 "dot1xSuppLastEapolFrameVersion=%u\n"
01063 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
01064 sm->SUPP_PAE_state,
01065 sm->heldPeriod,
01066 sm->authPeriod,
01067 sm->startPeriod,
01068 sm->maxStart,
01069 sm->suppPortStatus == Authorized ?
01070 "Authorized" : "Unauthorized",
01071 sm->SUPP_BE_state,
01072 sm->dot1xSuppEapolFramesRx,
01073 sm->dot1xSuppEapolFramesTx,
01074 sm->dot1xSuppEapolStartFramesTx,
01075 sm->dot1xSuppEapolLogoffFramesTx,
01076 sm->dot1xSuppEapolRespFramesTx,
01077 sm->dot1xSuppEapolReqIdFramesRx,
01078 sm->dot1xSuppEapolReqFramesRx,
01079 sm->dot1xSuppInvalidEapolFramesRx,
01080 sm->dot1xSuppEapLengthErrorFramesRx,
01081 sm->dot1xSuppLastEapolFrameVersion,
01082 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
01083 return len;
01084 }
01085
01086
01097 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
01098 size_t len)
01099 {
01100 const struct ieee802_1x_hdr *hdr;
01101 const struct ieee802_1x_eapol_key *key;
01102 int plen, data_len;
01103 int res = 1;
01104
01105 if (sm == NULL)
01106 return 0;
01107 sm->dot1xSuppEapolFramesRx++;
01108 if (len < sizeof(*hdr)) {
01109 sm->dot1xSuppInvalidEapolFramesRx++;
01110 return 0;
01111 }
01112 hdr = (const struct ieee802_1x_hdr *) buf;
01113 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
01114 memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
01115 if (hdr->version < EAPOL_VERSION) {
01116
01117 }
01118 plen = be_to_host16(hdr->length);
01119 if (plen > len - sizeof(*hdr)) {
01120 sm->dot1xSuppEapLengthErrorFramesRx++;
01121 return 0;
01122 }
01123 data_len = plen + sizeof(*hdr);
01124
01125 switch (hdr->type) {
01126 case IEEE802_1X_TYPE_EAP_PACKET:
01127 if (sm->cached_pmk) {
01128
01129
01130
01131
01132 eapol_sm_abort_cached(sm);
01133 }
01134 free(sm->eapReqData);
01135 sm->eapReqDataLen = plen;
01136 sm->eapReqData = malloc(sm->eapReqDataLen);
01137 if (sm->eapReqData) {
01138 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
01139 "frame");
01140 memcpy(sm->eapReqData, (u8 *) (hdr + 1),
01141 sm->eapReqDataLen);
01142 sm->eapolEap = TRUE;
01143 eapol_sm_step(sm);
01144 }
01145 break;
01146 case IEEE802_1X_TYPE_EAPOL_KEY:
01147 if (plen < sizeof(*key)) {
01148 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
01149 "frame received");
01150 break;
01151 }
01152 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
01153 if (key->type == EAPOL_KEY_TYPE_WPA ||
01154 key->type == EAPOL_KEY_TYPE_RSN) {
01155
01156 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
01157 "frame in EAPOL state machines");
01158 res = 0;
01159 break;
01160 }
01161 if (key->type != EAPOL_KEY_TYPE_RC4) {
01162 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
01163 "EAPOL-Key type %d", key->type);
01164 break;
01165 }
01166 free(sm->last_rx_key);
01167 sm->last_rx_key = malloc(data_len);
01168 if (sm->last_rx_key) {
01169 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
01170 "frame");
01171 memcpy(sm->last_rx_key, buf, data_len);
01172 sm->last_rx_key_len = data_len;
01173 sm->rxKey = TRUE;
01174 eapol_sm_step(sm);
01175 }
01176 break;
01177 default:
01178 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
01179 hdr->type);
01180 sm->dot1xSuppInvalidEapolFramesRx++;
01181 break;
01182 }
01183
01184 return res;
01185 }
01186
01187
01196 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
01197 {
01198 if (sm)
01199 sm->dot1xSuppEapolFramesTx++;
01200 }
01201
01202
01211 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
01212 {
01213 if (sm == NULL)
01214 return;
01215 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
01216 "portEnabled=%d", enabled);
01217 sm->portEnabled = enabled;
01218 eapol_sm_step(sm);
01219 }
01220
01221
01230 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
01231 {
01232 if (sm == NULL)
01233 return;
01234 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
01235 "portValid=%d", valid);
01236 sm->portValid = valid;
01237 eapol_sm_step(sm);
01238 }
01239
01240
01253 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
01254 {
01255 if (sm == NULL)
01256 return;
01257 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
01258 "EAP success=%d", success);
01259 sm->eapSuccess = success;
01260 sm->altAccept = success;
01261 if (success)
01262 eap_notify_success(sm->eap);
01263 eapol_sm_step(sm);
01264 }
01265
01266
01276 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
01277 {
01278 if (sm == NULL)
01279 return;
01280 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
01281 "EAP fail=%d", fail);
01282 sm->eapFail = fail;
01283 sm->altReject = fail;
01284 eapol_sm_step(sm);
01285 }
01286
01287
01301 void eapol_sm_notify_config(struct eapol_sm *sm, struct wpa_ssid *config,
01302 const struct eapol_config *conf)
01303 {
01304 if (sm == NULL)
01305 return;
01306
01307 sm->config = config;
01308
01309 if (conf == NULL)
01310 return;
01311
01312 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
01313 sm->conf.required_keys = conf->required_keys;
01314 sm->conf.fast_reauth = conf->fast_reauth;
01315 if (sm->eap) {
01316 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
01317 eap_set_workaround(sm->eap, conf->workaround);
01318 eap_set_force_disabled(sm->eap, conf->eap_disabled);
01319 }
01320 }
01321
01322
01335 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
01336 {
01337 const u8 *eap_key;
01338 size_t eap_len;
01339
01340 if (sm == NULL || !eap_key_available(sm->eap))
01341 return -1;
01342 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
01343 if (eap_key == NULL)
01344 return -1;
01345 if (len > eap_len)
01346 return eap_len;
01347 memcpy(key, eap_key, len);
01348 return 0;
01349 }
01350
01351
01360 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
01361 {
01362 if (sm) {
01363 sm->userLogoff = logoff;
01364 eapol_sm_step(sm);
01365 }
01366 }
01367
01368
01377 void eapol_sm_notify_cached(struct eapol_sm *sm)
01378 {
01379 if (sm == NULL)
01380 return;
01381 sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED;
01382 sm->suppPortStatus = Authorized;
01383 eap_notify_success(sm->eap);
01384 }
01385
01386
01395 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
01396 {
01397 if (sm == NULL)
01398 return;
01399 if (attempt) {
01400 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
01401 sm->cached_pmk = TRUE;
01402 } else {
01403 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
01404 sm->cached_pmk = FALSE;
01405 }
01406 }
01407
01408
01409 static void eapol_sm_abort_cached(struct eapol_sm *sm)
01410 {
01411 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
01412 "doing full EAP authentication");
01413 if (sm == NULL)
01414 return;
01415 sm->cached_pmk = FALSE;
01416 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
01417 sm->suppPortStatus = Unauthorized;
01418
01419
01420
01421 sm->startWhen = 3;
01422
01423 if (sm->ctx->aborted_cached)
01424 sm->ctx->aborted_cached(sm->ctx->ctx);
01425 }
01426
01427
01437 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
01438 {
01439 if (sm) {
01440 sm->ctx->scard_ctx = ctx;
01441 eap_register_scard_ctx(sm->eap, ctx);
01442 }
01443 }
01444
01445
01454 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
01455 {
01456 if (sm == NULL)
01457 return;
01458 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
01459 "portControl=%s", eapol_port_control(portControl));
01460 sm->portControl = portControl;
01461 eapol_sm_step(sm);
01462 }
01463
01464
01473 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
01474 {
01475 if (sm == NULL)
01476 return;
01477 eap_sm_notify_ctrl_attached(sm->eap);
01478 }
01479
01480
01489 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
01490 {
01491 if (sm == NULL)
01492 return;
01493 if (sm->eapReqData && !sm->eapReq) {
01494 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
01495 "input) notification - retrying pending EAP "
01496 "Request");
01497 sm->eapolEap = TRUE;
01498 sm->eapReq = TRUE;
01499 eapol_sm_step(sm);
01500 }
01501 }
01502
01503
01512 void eapol_sm_request_reauth(struct eapol_sm *sm)
01513 {
01514 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
01515 return;
01516 eapol_sm_txStart(sm);
01517 }
01518
01519
01529 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm)
01530 {
01531 if (sm == NULL)
01532 return;
01533 eap_notify_lower_layer_success(sm->eap);
01534 }
01535
01536
01537 static struct wpa_ssid * eapol_sm_get_config(void *ctx)
01538 {
01539 struct eapol_sm *sm = ctx;
01540 return sm ? sm->config : NULL;
01541 }
01542
01543
01544 static u8 * eapol_sm_get_eapReqData(void *ctx, size_t *len)
01545 {
01546 struct eapol_sm *sm = ctx;
01547 if (sm == NULL || sm->eapReqData == NULL) {
01548 *len = 0;
01549 return NULL;
01550 }
01551
01552 *len = sm->eapReqDataLen;
01553 return sm->eapReqData;
01554 }
01555
01556
01557 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
01558 {
01559 struct eapol_sm *sm = ctx;
01560 if (sm == NULL)
01561 return FALSE;
01562 switch (variable) {
01563 case EAPOL_eapSuccess:
01564 return sm->eapSuccess;
01565 case EAPOL_eapRestart:
01566 return sm->eapRestart;
01567 case EAPOL_eapFail:
01568 return sm->eapFail;
01569 case EAPOL_eapResp:
01570 return sm->eapResp;
01571 case EAPOL_eapNoResp:
01572 return sm->eapNoResp;
01573 case EAPOL_eapReq:
01574 return sm->eapReq;
01575 case EAPOL_portEnabled:
01576 return sm->portEnabled;
01577 case EAPOL_altAccept:
01578 return sm->altAccept;
01579 case EAPOL_altReject:
01580 return sm->altReject;
01581 }
01582 return FALSE;
01583 }
01584
01585
01586 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
01587 Boolean value)
01588 {
01589 struct eapol_sm *sm = ctx;
01590 if (sm == NULL)
01591 return;
01592 switch (variable) {
01593 case EAPOL_eapSuccess:
01594 sm->eapSuccess = value;
01595 break;
01596 case EAPOL_eapRestart:
01597 sm->eapRestart = value;
01598 break;
01599 case EAPOL_eapFail:
01600 sm->eapFail = value;
01601 break;
01602 case EAPOL_eapResp:
01603 sm->eapResp = value;
01604 break;
01605 case EAPOL_eapNoResp:
01606 sm->eapNoResp = value;
01607 break;
01608 case EAPOL_eapReq:
01609 sm->eapReq = value;
01610 break;
01611 case EAPOL_portEnabled:
01612 sm->portEnabled = value;
01613 break;
01614 case EAPOL_altAccept:
01615 sm->altAccept = value;
01616 break;
01617 case EAPOL_altReject:
01618 sm->altReject = value;
01619 break;
01620 }
01621 }
01622
01623
01624 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
01625 {
01626 struct eapol_sm *sm = ctx;
01627 if (sm == NULL)
01628 return 0;
01629 switch (variable) {
01630 case EAPOL_idleWhile:
01631 return sm->idleWhile;
01632 }
01633 return 0;
01634 }
01635
01636
01637 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
01638 unsigned int value)
01639 {
01640 struct eapol_sm *sm = ctx;
01641 if (sm == NULL)
01642 return;
01643 switch (variable) {
01644 case EAPOL_idleWhile:
01645 sm->idleWhile = value;
01646 break;
01647 }
01648 }
01649
01650
01651 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
01652 {
01653 struct eapol_sm *sm = ctx;
01654 if (sm && sm->ctx && sm->ctx->set_config_blob)
01655 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
01656 }
01657
01658
01659 static const struct wpa_config_blob *
01660 eapol_sm_get_config_blob(void *ctx, const char *name)
01661 {
01662 struct eapol_sm *sm = ctx;
01663 if (sm && sm->ctx && sm->ctx->get_config_blob)
01664 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
01665 else
01666 return NULL;
01667 }
01668
01669
01670 static struct eapol_callbacks eapol_cb =
01671 {
01672 .get_config = eapol_sm_get_config,
01673 .get_bool = eapol_sm_get_bool,
01674 .set_bool = eapol_sm_set_bool,
01675 .get_int = eapol_sm_get_int,
01676 .set_int = eapol_sm_set_int,
01677 .get_eapReqData = eapol_sm_get_eapReqData,
01678 .set_config_blob = eapol_sm_set_config_blob,
01679 .get_config_blob = eapol_sm_get_config_blob,
01680 };
01681
01682
01692 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
01693 {
01694 struct eapol_sm *sm;
01695 struct eap_config conf;
01696 sm = malloc(sizeof(*sm));
01697 if (sm == NULL)
01698 return NULL;
01699 memset(sm, 0, sizeof(*sm));
01700 sm->ctx = ctx;
01701
01702 sm->portControl = Auto;
01703
01704
01705 sm->heldPeriod = 60;
01706 sm->startPeriod = 30;
01707 sm->maxStart = 3;
01708
01709
01710 sm->authPeriod = 30;
01711
01712 memset(&conf, 0, sizeof(conf));
01713 conf.opensc_engine_path = ctx->opensc_engine_path;
01714 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
01715 conf.pkcs11_module_path = ctx->pkcs11_module_path;
01716
01717 sm->eap = eap_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
01718 if (sm->eap == NULL) {
01719 free(sm);
01720 return NULL;
01721 }
01722
01723
01724 sm->initialize = TRUE;
01725 eapol_sm_step(sm);
01726 sm->initialize = FALSE;
01727 eapol_sm_step(sm);
01728
01729 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
01730
01731 return sm;
01732 }
01733
01734
01742 void eapol_sm_deinit(struct eapol_sm *sm)
01743 {
01744 if (sm == NULL)
01745 return;
01746 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
01747 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
01748 eap_sm_deinit(sm->eap);
01749 free(sm->last_rx_key);
01750 free(sm->eapReqData);
01751 free(sm->ctx);
01752 free(sm);
01753 }
01754