$search
00001 /* 00002 * EAP peer state machines (RFC 4137) 00003 * Copyright (c) 2004-2010, 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 * This file implements the Peer State Machine as defined in RFC 4137. The used 00015 * states and state transitions match mostly with the RFC. However, there are 00016 * couple of additional transitions for working around small issues noticed 00017 * during testing. These exceptions are explained in comments within the 00018 * functions in this file. The method functions, m.func(), are similar to the 00019 * ones used in RFC 4137, but some small changes have used here to optimize 00020 * operations and to add functionality needed for fast re-authentication 00021 * (session resumption). 00022 */ 00023 00024 #include "includes.h" 00025 00026 #include "common.h" 00027 #include "pcsc_funcs.h" 00028 #include "state_machine.h" 00029 #include "crypto/crypto.h" 00030 #include "crypto/tls.h" 00031 #include "common/wpa_ctrl.h" 00032 #include "eap_common/eap_wsc_common.h" 00033 #include "eap_i.h" 00034 #include "eap_config.h" 00035 00036 #define STATE_MACHINE_DATA struct eap_sm 00037 #define STATE_MACHINE_DEBUG_PREFIX "EAP" 00038 00039 #define EAP_MAX_AUTH_ROUNDS 50 00040 00041 00042 static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, 00043 EapType method); 00044 static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id); 00045 static void eap_sm_processIdentity(struct eap_sm *sm, 00046 const struct wpabuf *req); 00047 static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req); 00048 static struct wpabuf * eap_sm_buildNotify(int id); 00049 static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req); 00050 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 00051 static const char * eap_sm_method_state_txt(EapMethodState state); 00052 static const char * eap_sm_decision_txt(EapDecision decision); 00053 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 00054 00055 00056 00057 static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) 00058 { 00059 return sm->eapol_cb->get_bool(sm->eapol_ctx, var); 00060 } 00061 00062 00063 static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var, 00064 Boolean value) 00065 { 00066 sm->eapol_cb->set_bool(sm->eapol_ctx, var, value); 00067 } 00068 00069 00070 static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var) 00071 { 00072 return sm->eapol_cb->get_int(sm->eapol_ctx, var); 00073 } 00074 00075 00076 static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var, 00077 unsigned int value) 00078 { 00079 sm->eapol_cb->set_int(sm->eapol_ctx, var, value); 00080 } 00081 00082 00083 static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm) 00084 { 00085 return sm->eapol_cb->get_eapReqData(sm->eapol_ctx); 00086 } 00087 00088 00089 static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) 00090 { 00091 if (sm->m == NULL || sm->eap_method_priv == NULL) 00092 return; 00093 00094 wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method " 00095 "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt); 00096 sm->m->deinit(sm, sm->eap_method_priv); 00097 sm->eap_method_priv = NULL; 00098 sm->m = NULL; 00099 } 00100 00101 00109 int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method) 00110 { 00111 struct eap_peer_config *config = eap_get_config(sm); 00112 int i; 00113 struct eap_method_type *m; 00114 00115 if (config == NULL || config->eap_methods == NULL) 00116 return 1; 00117 00118 m = config->eap_methods; 00119 for (i = 0; m[i].vendor != EAP_VENDOR_IETF || 00120 m[i].method != EAP_TYPE_NONE; i++) { 00121 if (m[i].vendor == vendor && m[i].method == method) 00122 return 1; 00123 } 00124 return 0; 00125 } 00126 00127 00128 /* 00129 * This state initializes state machine variables when the machine is 00130 * activated (portEnabled = TRUE). This is also used when re-starting 00131 * authentication (eapRestart == TRUE). 00132 */ 00133 SM_STATE(EAP, INITIALIZE) 00134 { 00135 SM_ENTRY(EAP, INITIALIZE); 00136 if (sm->fast_reauth && sm->m && sm->m->has_reauth_data && 00137 sm->m->has_reauth_data(sm, sm->eap_method_priv) && 00138 !sm->prev_failure) { 00139 wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for " 00140 "fast reauthentication"); 00141 sm->m->deinit_for_reauth(sm, sm->eap_method_priv); 00142 } else { 00143 eap_deinit_prev_method(sm, "INITIALIZE"); 00144 } 00145 sm->selectedMethod = EAP_TYPE_NONE; 00146 sm->methodState = METHOD_NONE; 00147 sm->allowNotifications = TRUE; 00148 sm->decision = DECISION_FAIL; 00149 eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); 00150 eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); 00151 eapol_set_bool(sm, EAPOL_eapFail, FALSE); 00152 os_free(sm->eapKeyData); 00153 sm->eapKeyData = NULL; 00154 sm->eapKeyAvailable = FALSE; 00155 eapol_set_bool(sm, EAPOL_eapRestart, FALSE); 00156 sm->lastId = -1; /* new session - make sure this does not match with 00157 * the first EAP-Packet */ 00158 /* 00159 * RFC 4137 does not reset eapResp and eapNoResp here. However, this 00160 * seemed to be able to trigger cases where both were set and if EAPOL 00161 * state machine uses eapNoResp first, it may end up not sending a real 00162 * reply correctly. This occurred when the workaround in FAIL state set 00163 * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do 00164 * something else(?) 00165 */ 00166 eapol_set_bool(sm, EAPOL_eapResp, FALSE); 00167 eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); 00168 sm->num_rounds = 0; 00169 sm->prev_failure = 0; 00170 } 00171 00172 00173 /* 00174 * This state is reached whenever service from the lower layer is interrupted 00175 * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE 00176 * occurs when the port becomes enabled. 00177 */ 00178 SM_STATE(EAP, DISABLED) 00179 { 00180 SM_ENTRY(EAP, DISABLED); 00181 sm->num_rounds = 0; 00182 } 00183 00184 00185 /* 00186 * The state machine spends most of its time here, waiting for something to 00187 * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and 00188 * SEND_RESPONSE states. 00189 */ 00190 SM_STATE(EAP, IDLE) 00191 { 00192 SM_ENTRY(EAP, IDLE); 00193 } 00194 00195 00196 /* 00197 * This state is entered when an EAP packet is received (eapReq == TRUE) to 00198 * parse the packet header. 00199 */ 00200 SM_STATE(EAP, RECEIVED) 00201 { 00202 const struct wpabuf *eapReqData; 00203 00204 SM_ENTRY(EAP, RECEIVED); 00205 eapReqData = eapol_get_eapReqData(sm); 00206 /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */ 00207 eap_sm_parseEapReq(sm, eapReqData); 00208 sm->num_rounds++; 00209 } 00210 00211 00212 /* 00213 * This state is entered when a request for a new type comes in. Either the 00214 * correct method is started, or a Nak response is built. 00215 */ 00216 SM_STATE(EAP, GET_METHOD) 00217 { 00218 int reinit; 00219 EapType method; 00220 00221 SM_ENTRY(EAP, GET_METHOD); 00222 00223 if (sm->reqMethod == EAP_TYPE_EXPANDED) 00224 method = sm->reqVendorMethod; 00225 else 00226 method = sm->reqMethod; 00227 00228 if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) { 00229 wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed", 00230 sm->reqVendor, method); 00231 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD 00232 "vendor=%u method=%u -> NAK", 00233 sm->reqVendor, method); 00234 goto nak; 00235 } 00236 00237 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD 00238 "vendor=%u method=%u", sm->reqVendor, method); 00239 00240 /* 00241 * RFC 4137 does not define specific operation for fast 00242 * re-authentication (session resumption). The design here is to allow 00243 * the previously used method data to be maintained for 00244 * re-authentication if the method support session resumption. 00245 * Otherwise, the previously used method data is freed and a new method 00246 * is allocated here. 00247 */ 00248 if (sm->fast_reauth && 00249 sm->m && sm->m->vendor == sm->reqVendor && 00250 sm->m->method == method && 00251 sm->m->has_reauth_data && 00252 sm->m->has_reauth_data(sm, sm->eap_method_priv)) { 00253 wpa_printf(MSG_DEBUG, "EAP: Using previous method data" 00254 " for fast re-authentication"); 00255 reinit = 1; 00256 } else { 00257 eap_deinit_prev_method(sm, "GET_METHOD"); 00258 reinit = 0; 00259 } 00260 00261 sm->selectedMethod = sm->reqMethod; 00262 if (sm->m == NULL) 00263 sm->m = eap_peer_get_eap_method(sm->reqVendor, method); 00264 if (!sm->m) { 00265 wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: " 00266 "vendor %d method %d", 00267 sm->reqVendor, method); 00268 goto nak; 00269 } 00270 00271 wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: " 00272 "vendor %u method %u (%s)", 00273 sm->reqVendor, method, sm->m->name); 00274 if (reinit) 00275 sm->eap_method_priv = sm->m->init_for_reauth( 00276 sm, sm->eap_method_priv); 00277 else 00278 sm->eap_method_priv = sm->m->init(sm); 00279 00280 if (sm->eap_method_priv == NULL) { 00281 struct eap_peer_config *config = eap_get_config(sm); 00282 wpa_msg(sm->msg_ctx, MSG_INFO, 00283 "EAP: Failed to initialize EAP method: vendor %u " 00284 "method %u (%s)", 00285 sm->reqVendor, method, sm->m->name); 00286 sm->m = NULL; 00287 sm->methodState = METHOD_NONE; 00288 sm->selectedMethod = EAP_TYPE_NONE; 00289 if (sm->reqMethod == EAP_TYPE_TLS && config && 00290 (config->pending_req_pin || 00291 config->pending_req_passphrase)) { 00292 /* 00293 * Return without generating Nak in order to allow 00294 * entering of PIN code or passphrase to retry the 00295 * current EAP packet. 00296 */ 00297 wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase " 00298 "request - skip Nak"); 00299 return; 00300 } 00301 00302 goto nak; 00303 } 00304 00305 sm->methodState = METHOD_INIT; 00306 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD 00307 "EAP vendor %u method %u (%s) selected", 00308 sm->reqVendor, method, sm->m->name); 00309 return; 00310 00311 nak: 00312 wpabuf_free(sm->eapRespData); 00313 sm->eapRespData = NULL; 00314 sm->eapRespData = eap_sm_buildNak(sm, sm->reqId); 00315 } 00316 00317 00318 /* 00319 * The method processing happens here. The request from the authenticator is 00320 * processed, and an appropriate response packet is built. 00321 */ 00322 SM_STATE(EAP, METHOD) 00323 { 00324 struct wpabuf *eapReqData; 00325 struct eap_method_ret ret; 00326 00327 SM_ENTRY(EAP, METHOD); 00328 if (sm->m == NULL) { 00329 wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected"); 00330 return; 00331 } 00332 00333 eapReqData = eapol_get_eapReqData(sm); 00334 00335 /* 00336 * Get ignore, methodState, decision, allowNotifications, and 00337 * eapRespData. RFC 4137 uses three separate method procedure (check, 00338 * process, and buildResp) in this state. These have been combined into 00339 * a single function call to m->process() in order to optimize EAP 00340 * method implementation interface a bit. These procedures are only 00341 * used from within this METHOD state, so there is no need to keep 00342 * these as separate C functions. 00343 * 00344 * The RFC 4137 procedures return values as follows: 00345 * ignore = m.check(eapReqData) 00346 * (methodState, decision, allowNotifications) = m.process(eapReqData) 00347 * eapRespData = m.buildResp(reqId) 00348 */ 00349 os_memset(&ret, 0, sizeof(ret)); 00350 ret.ignore = sm->ignore; 00351 ret.methodState = sm->methodState; 00352 ret.decision = sm->decision; 00353 ret.allowNotifications = sm->allowNotifications; 00354 wpabuf_free(sm->eapRespData); 00355 sm->eapRespData = NULL; 00356 sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret, 00357 eapReqData); 00358 wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s " 00359 "methodState=%s decision=%s", 00360 ret.ignore ? "TRUE" : "FALSE", 00361 eap_sm_method_state_txt(ret.methodState), 00362 eap_sm_decision_txt(ret.decision)); 00363 00364 sm->ignore = ret.ignore; 00365 if (sm->ignore) 00366 return; 00367 sm->methodState = ret.methodState; 00368 sm->decision = ret.decision; 00369 sm->allowNotifications = ret.allowNotifications; 00370 00371 if (sm->m->isKeyAvailable && sm->m->getKey && 00372 sm->m->isKeyAvailable(sm, sm->eap_method_priv)) { 00373 os_free(sm->eapKeyData); 00374 sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv, 00375 &sm->eapKeyDataLen); 00376 } 00377 } 00378 00379 00380 /* 00381 * This state signals the lower layer that a response packet is ready to be 00382 * sent. 00383 */ 00384 SM_STATE(EAP, SEND_RESPONSE) 00385 { 00386 SM_ENTRY(EAP, SEND_RESPONSE); 00387 wpabuf_free(sm->lastRespData); 00388 if (sm->eapRespData) { 00389 if (sm->workaround) 00390 os_memcpy(sm->last_md5, sm->req_md5, 16); 00391 sm->lastId = sm->reqId; 00392 sm->lastRespData = wpabuf_dup(sm->eapRespData); 00393 eapol_set_bool(sm, EAPOL_eapResp, TRUE); 00394 } else 00395 sm->lastRespData = NULL; 00396 eapol_set_bool(sm, EAPOL_eapReq, FALSE); 00397 eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); 00398 } 00399 00400 00401 /* 00402 * This state signals the lower layer that the request was discarded, and no 00403 * response packet will be sent at this time. 00404 */ 00405 SM_STATE(EAP, DISCARD) 00406 { 00407 SM_ENTRY(EAP, DISCARD); 00408 eapol_set_bool(sm, EAPOL_eapReq, FALSE); 00409 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); 00410 } 00411 00412 00413 /* 00414 * Handles requests for Identity method and builds a response. 00415 */ 00416 SM_STATE(EAP, IDENTITY) 00417 { 00418 const struct wpabuf *eapReqData; 00419 00420 SM_ENTRY(EAP, IDENTITY); 00421 eapReqData = eapol_get_eapReqData(sm); 00422 eap_sm_processIdentity(sm, eapReqData); 00423 wpabuf_free(sm->eapRespData); 00424 sm->eapRespData = NULL; 00425 sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0); 00426 } 00427 00428 00429 /* 00430 * Handles requests for Notification method and builds a response. 00431 */ 00432 SM_STATE(EAP, NOTIFICATION) 00433 { 00434 const struct wpabuf *eapReqData; 00435 00436 SM_ENTRY(EAP, NOTIFICATION); 00437 eapReqData = eapol_get_eapReqData(sm); 00438 eap_sm_processNotify(sm, eapReqData); 00439 wpabuf_free(sm->eapRespData); 00440 sm->eapRespData = NULL; 00441 sm->eapRespData = eap_sm_buildNotify(sm->reqId); 00442 } 00443 00444 00445 /* 00446 * This state retransmits the previous response packet. 00447 */ 00448 SM_STATE(EAP, RETRANSMIT) 00449 { 00450 SM_ENTRY(EAP, RETRANSMIT); 00451 wpabuf_free(sm->eapRespData); 00452 if (sm->lastRespData) 00453 sm->eapRespData = wpabuf_dup(sm->lastRespData); 00454 else 00455 sm->eapRespData = NULL; 00456 } 00457 00458 00459 /* 00460 * This state is entered in case of a successful completion of authentication 00461 * and state machine waits here until port is disabled or EAP authentication is 00462 * restarted. 00463 */ 00464 SM_STATE(EAP, SUCCESS) 00465 { 00466 SM_ENTRY(EAP, SUCCESS); 00467 if (sm->eapKeyData != NULL) 00468 sm->eapKeyAvailable = TRUE; 00469 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); 00470 00471 /* 00472 * RFC 4137 does not clear eapReq here, but this seems to be required 00473 * to avoid processing the same request twice when state machine is 00474 * initialized. 00475 */ 00476 eapol_set_bool(sm, EAPOL_eapReq, FALSE); 00477 00478 /* 00479 * RFC 4137 does not set eapNoResp here, but this seems to be required 00480 * to get EAPOL Supplicant backend state machine into SUCCESS state. In 00481 * addition, either eapResp or eapNoResp is required to be set after 00482 * processing the received EAP frame. 00483 */ 00484 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); 00485 00486 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS 00487 "EAP authentication completed successfully"); 00488 } 00489 00490 00491 /* 00492 * This state is entered in case of a failure and state machine waits here 00493 * until port is disabled or EAP authentication is restarted. 00494 */ 00495 SM_STATE(EAP, FAILURE) 00496 { 00497 SM_ENTRY(EAP, FAILURE); 00498 eapol_set_bool(sm, EAPOL_eapFail, TRUE); 00499 00500 /* 00501 * RFC 4137 does not clear eapReq here, but this seems to be required 00502 * to avoid processing the same request twice when state machine is 00503 * initialized. 00504 */ 00505 eapol_set_bool(sm, EAPOL_eapReq, FALSE); 00506 00507 /* 00508 * RFC 4137 does not set eapNoResp here. However, either eapResp or 00509 * eapNoResp is required to be set after processing the received EAP 00510 * frame. 00511 */ 00512 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); 00513 00514 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE 00515 "EAP authentication failed"); 00516 00517 sm->prev_failure = 1; 00518 } 00519 00520 00521 static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId) 00522 { 00523 /* 00524 * At least Microsoft IAS and Meetinghouse Aegis seem to be sending 00525 * EAP-Success/Failure with lastId + 1 even though RFC 3748 and 00526 * RFC 4137 require that reqId == lastId. In addition, it looks like 00527 * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success. 00528 * 00529 * Accept this kind of Id if EAP workarounds are enabled. These are 00530 * unauthenticated plaintext messages, so this should have minimal 00531 * security implications (bit easier to fake EAP-Success/Failure). 00532 */ 00533 if (sm->workaround && (reqId == ((lastId + 1) & 0xff) || 00534 reqId == ((lastId + 2) & 0xff))) { 00535 wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected " 00536 "identifier field in EAP Success: " 00537 "reqId=%d lastId=%d (these are supposed to be " 00538 "same)", reqId, lastId); 00539 return 1; 00540 } 00541 wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d " 00542 "lastId=%d", reqId, lastId); 00543 return 0; 00544 } 00545 00546 00547 /* 00548 * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions 00549 */ 00550 00551 static void eap_peer_sm_step_idle(struct eap_sm *sm) 00552 { 00553 /* 00554 * The first three transitions are from RFC 4137. The last two are 00555 * local additions to handle special cases with LEAP and PEAP server 00556 * not sending EAP-Success in some cases. 00557 */ 00558 if (eapol_get_bool(sm, EAPOL_eapReq)) 00559 SM_ENTER(EAP, RECEIVED); 00560 else if ((eapol_get_bool(sm, EAPOL_altAccept) && 00561 sm->decision != DECISION_FAIL) || 00562 (eapol_get_int(sm, EAPOL_idleWhile) == 0 && 00563 sm->decision == DECISION_UNCOND_SUCC)) 00564 SM_ENTER(EAP, SUCCESS); 00565 else if (eapol_get_bool(sm, EAPOL_altReject) || 00566 (eapol_get_int(sm, EAPOL_idleWhile) == 0 && 00567 sm->decision != DECISION_UNCOND_SUCC) || 00568 (eapol_get_bool(sm, EAPOL_altAccept) && 00569 sm->methodState != METHOD_CONT && 00570 sm->decision == DECISION_FAIL)) 00571 SM_ENTER(EAP, FAILURE); 00572 else if (sm->selectedMethod == EAP_TYPE_LEAP && 00573 sm->leap_done && sm->decision != DECISION_FAIL && 00574 sm->methodState == METHOD_DONE) 00575 SM_ENTER(EAP, SUCCESS); 00576 else if (sm->selectedMethod == EAP_TYPE_PEAP && 00577 sm->peap_done && sm->decision != DECISION_FAIL && 00578 sm->methodState == METHOD_DONE) 00579 SM_ENTER(EAP, SUCCESS); 00580 } 00581 00582 00583 static int eap_peer_req_is_duplicate(struct eap_sm *sm) 00584 { 00585 int duplicate; 00586 00587 duplicate = (sm->reqId == sm->lastId) && sm->rxReq; 00588 if (sm->workaround && duplicate && 00589 os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) { 00590 /* 00591 * RFC 4137 uses (reqId == lastId) as the only verification for 00592 * duplicate EAP requests. However, this misses cases where the 00593 * AS is incorrectly using the same id again; and 00594 * unfortunately, such implementations exist. Use MD5 hash as 00595 * an extra verification for the packets being duplicate to 00596 * workaround these issues. 00597 */ 00598 wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but " 00599 "EAP packets were not identical"); 00600 wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a " 00601 "duplicate packet"); 00602 duplicate = 0; 00603 } 00604 00605 return duplicate; 00606 } 00607 00608 00609 static void eap_peer_sm_step_received(struct eap_sm *sm) 00610 { 00611 int duplicate = eap_peer_req_is_duplicate(sm); 00612 00613 /* 00614 * Two special cases below for LEAP are local additions to work around 00615 * odd LEAP behavior (EAP-Success in the middle of authentication and 00616 * then swapped roles). Other transitions are based on RFC 4137. 00617 */ 00618 if (sm->rxSuccess && sm->decision != DECISION_FAIL && 00619 (sm->reqId == sm->lastId || 00620 eap_success_workaround(sm, sm->reqId, sm->lastId))) 00621 SM_ENTER(EAP, SUCCESS); 00622 else if (sm->methodState != METHOD_CONT && 00623 ((sm->rxFailure && 00624 sm->decision != DECISION_UNCOND_SUCC) || 00625 (sm->rxSuccess && sm->decision == DECISION_FAIL && 00626 (sm->selectedMethod != EAP_TYPE_LEAP || 00627 sm->methodState != METHOD_MAY_CONT))) && 00628 (sm->reqId == sm->lastId || 00629 eap_success_workaround(sm, sm->reqId, sm->lastId))) 00630 SM_ENTER(EAP, FAILURE); 00631 else if (sm->rxReq && duplicate) 00632 SM_ENTER(EAP, RETRANSMIT); 00633 else if (sm->rxReq && !duplicate && 00634 sm->reqMethod == EAP_TYPE_NOTIFICATION && 00635 sm->allowNotifications) 00636 SM_ENTER(EAP, NOTIFICATION); 00637 else if (sm->rxReq && !duplicate && 00638 sm->selectedMethod == EAP_TYPE_NONE && 00639 sm->reqMethod == EAP_TYPE_IDENTITY) 00640 SM_ENTER(EAP, IDENTITY); 00641 else if (sm->rxReq && !duplicate && 00642 sm->selectedMethod == EAP_TYPE_NONE && 00643 sm->reqMethod != EAP_TYPE_IDENTITY && 00644 sm->reqMethod != EAP_TYPE_NOTIFICATION) 00645 SM_ENTER(EAP, GET_METHOD); 00646 else if (sm->rxReq && !duplicate && 00647 sm->reqMethod == sm->selectedMethod && 00648 sm->methodState != METHOD_DONE) 00649 SM_ENTER(EAP, METHOD); 00650 else if (sm->selectedMethod == EAP_TYPE_LEAP && 00651 (sm->rxSuccess || sm->rxResp)) 00652 SM_ENTER(EAP, METHOD); 00653 else 00654 SM_ENTER(EAP, DISCARD); 00655 } 00656 00657 00658 static void eap_peer_sm_step_local(struct eap_sm *sm) 00659 { 00660 switch (sm->EAP_state) { 00661 case EAP_INITIALIZE: 00662 SM_ENTER(EAP, IDLE); 00663 break; 00664 case EAP_DISABLED: 00665 if (eapol_get_bool(sm, EAPOL_portEnabled) && 00666 !sm->force_disabled) 00667 SM_ENTER(EAP, INITIALIZE); 00668 break; 00669 case EAP_IDLE: 00670 eap_peer_sm_step_idle(sm); 00671 break; 00672 case EAP_RECEIVED: 00673 eap_peer_sm_step_received(sm); 00674 break; 00675 case EAP_GET_METHOD: 00676 if (sm->selectedMethod == sm->reqMethod) 00677 SM_ENTER(EAP, METHOD); 00678 else 00679 SM_ENTER(EAP, SEND_RESPONSE); 00680 break; 00681 case EAP_METHOD: 00682 if (sm->ignore) 00683 SM_ENTER(EAP, DISCARD); 00684 else 00685 SM_ENTER(EAP, SEND_RESPONSE); 00686 break; 00687 case EAP_SEND_RESPONSE: 00688 SM_ENTER(EAP, IDLE); 00689 break; 00690 case EAP_DISCARD: 00691 SM_ENTER(EAP, IDLE); 00692 break; 00693 case EAP_IDENTITY: 00694 SM_ENTER(EAP, SEND_RESPONSE); 00695 break; 00696 case EAP_NOTIFICATION: 00697 SM_ENTER(EAP, SEND_RESPONSE); 00698 break; 00699 case EAP_RETRANSMIT: 00700 SM_ENTER(EAP, SEND_RESPONSE); 00701 break; 00702 case EAP_SUCCESS: 00703 break; 00704 case EAP_FAILURE: 00705 break; 00706 } 00707 } 00708 00709 00710 SM_STEP(EAP) 00711 { 00712 /* Global transitions */ 00713 if (eapol_get_bool(sm, EAPOL_eapRestart) && 00714 eapol_get_bool(sm, EAPOL_portEnabled)) 00715 SM_ENTER_GLOBAL(EAP, INITIALIZE); 00716 else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled) 00717 SM_ENTER_GLOBAL(EAP, DISABLED); 00718 else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { 00719 /* RFC 4137 does not place any limit on number of EAP messages 00720 * in an authentication session. However, some error cases have 00721 * ended up in a state were EAP messages were sent between the 00722 * peer and server in a loop (e.g., TLS ACK frame in both 00723 * direction). Since this is quite undesired outcome, limit the 00724 * total number of EAP round-trips and abort authentication if 00725 * this limit is exceeded. 00726 */ 00727 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { 00728 wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d " 00729 "authentication rounds - abort", 00730 EAP_MAX_AUTH_ROUNDS); 00731 sm->num_rounds++; 00732 SM_ENTER_GLOBAL(EAP, FAILURE); 00733 } 00734 } else { 00735 /* Local transitions */ 00736 eap_peer_sm_step_local(sm); 00737 } 00738 } 00739 00740 00741 static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, 00742 EapType method) 00743 { 00744 if (!eap_allowed_method(sm, vendor, method)) { 00745 wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " 00746 "vendor %u method %u", vendor, method); 00747 return FALSE; 00748 } 00749 if (eap_peer_get_eap_method(vendor, method)) 00750 return TRUE; 00751 wpa_printf(MSG_DEBUG, "EAP: not included in build: " 00752 "vendor %u method %u", vendor, method); 00753 return FALSE; 00754 } 00755 00756 00757 static struct wpabuf * eap_sm_build_expanded_nak( 00758 struct eap_sm *sm, int id, const struct eap_method *methods, 00759 size_t count) 00760 { 00761 struct wpabuf *resp; 00762 int found = 0; 00763 const struct eap_method *m; 00764 00765 wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak"); 00766 00767 /* RFC 3748 - 5.3.2: Expanded Nak */ 00768 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED, 00769 8 + 8 * (count + 1), EAP_CODE_RESPONSE, id); 00770 if (resp == NULL) 00771 return NULL; 00772 00773 wpabuf_put_be24(resp, EAP_VENDOR_IETF); 00774 wpabuf_put_be32(resp, EAP_TYPE_NAK); 00775 00776 for (m = methods; m; m = m->next) { 00777 if (sm->reqVendor == m->vendor && 00778 sm->reqVendorMethod == m->method) 00779 continue; /* do not allow the current method again */ 00780 if (eap_allowed_method(sm, m->vendor, m->method)) { 00781 wpa_printf(MSG_DEBUG, "EAP: allowed type: " 00782 "vendor=%u method=%u", 00783 m->vendor, m->method); 00784 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); 00785 wpabuf_put_be24(resp, m->vendor); 00786 wpabuf_put_be32(resp, m->method); 00787 00788 found++; 00789 } 00790 } 00791 if (!found) { 00792 wpa_printf(MSG_DEBUG, "EAP: no more allowed methods"); 00793 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); 00794 wpabuf_put_be24(resp, EAP_VENDOR_IETF); 00795 wpabuf_put_be32(resp, EAP_TYPE_NONE); 00796 } 00797 00798 eap_update_len(resp); 00799 00800 return resp; 00801 } 00802 00803 00804 static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id) 00805 { 00806 struct wpabuf *resp; 00807 u8 *start; 00808 int found = 0, expanded_found = 0; 00809 size_t count; 00810 const struct eap_method *methods, *m; 00811 00812 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u " 00813 "vendor=%u method=%u not allowed)", sm->reqMethod, 00814 sm->reqVendor, sm->reqVendorMethod); 00815 methods = eap_peer_get_methods(&count); 00816 if (methods == NULL) 00817 return NULL; 00818 if (sm->reqMethod == EAP_TYPE_EXPANDED) 00819 return eap_sm_build_expanded_nak(sm, id, methods, count); 00820 00821 /* RFC 3748 - 5.3.1: Legacy Nak */ 00822 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, 00823 sizeof(struct eap_hdr) + 1 + count + 1, 00824 EAP_CODE_RESPONSE, id); 00825 if (resp == NULL) 00826 return NULL; 00827 00828 start = wpabuf_put(resp, 0); 00829 for (m = methods; m; m = m->next) { 00830 if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod) 00831 continue; /* do not allow the current method again */ 00832 if (eap_allowed_method(sm, m->vendor, m->method)) { 00833 if (m->vendor != EAP_VENDOR_IETF) { 00834 if (expanded_found) 00835 continue; 00836 expanded_found = 1; 00837 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); 00838 } else 00839 wpabuf_put_u8(resp, m->method); 00840 found++; 00841 } 00842 } 00843 if (!found) 00844 wpabuf_put_u8(resp, EAP_TYPE_NONE); 00845 wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found); 00846 00847 eap_update_len(resp); 00848 00849 return resp; 00850 } 00851 00852 00853 static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req) 00854 { 00855 const struct eap_hdr *hdr = wpabuf_head(req); 00856 const u8 *pos = (const u8 *) (hdr + 1); 00857 pos++; 00858 00859 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED 00860 "EAP authentication started"); 00861 00862 /* 00863 * RFC 3748 - 5.1: Identity 00864 * Data field may contain a displayable message in UTF-8. If this 00865 * includes NUL-character, only the data before that should be 00866 * displayed. Some EAP implementasitons may piggy-back additional 00867 * options after the NUL. 00868 */ 00869 /* TODO: could save displayable message so that it can be shown to the 00870 * user in case of interaction is required */ 00871 wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data", 00872 pos, be_to_host16(hdr->length) - 5); 00873 } 00874 00875 00876 #ifdef PCSC_FUNCS 00877 static int eap_sm_imsi_identity(struct eap_sm *sm, 00878 struct eap_peer_config *conf) 00879 { 00880 int aka = 0; 00881 char imsi[100]; 00882 size_t imsi_len; 00883 struct eap_method_type *m = conf->eap_methods; 00884 int i; 00885 00886 imsi_len = sizeof(imsi); 00887 if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) { 00888 wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); 00889 return -1; 00890 } 00891 00892 wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len); 00893 00894 for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF || 00895 m[i].method != EAP_TYPE_NONE); i++) { 00896 if (m[i].vendor == EAP_VENDOR_IETF && 00897 m[i].method == EAP_TYPE_AKA) { 00898 aka = 1; 00899 break; 00900 } 00901 } 00902 00903 os_free(conf->identity); 00904 conf->identity = os_malloc(1 + imsi_len); 00905 if (conf->identity == NULL) { 00906 wpa_printf(MSG_WARNING, "Failed to allocate buffer for " 00907 "IMSI-based identity"); 00908 return -1; 00909 } 00910 00911 conf->identity[0] = aka ? '0' : '1'; 00912 os_memcpy(conf->identity + 1, imsi, imsi_len); 00913 conf->identity_len = 1 + imsi_len; 00914 00915 return 0; 00916 } 00917 #endif /* PCSC_FUNCS */ 00918 00919 00920 static int eap_sm_set_scard_pin(struct eap_sm *sm, 00921 struct eap_peer_config *conf) 00922 { 00923 #ifdef PCSC_FUNCS 00924 if (scard_set_pin(sm->scard_ctx, conf->pin)) { 00925 /* 00926 * Make sure the same PIN is not tried again in order to avoid 00927 * blocking SIM. 00928 */ 00929 os_free(conf->pin); 00930 conf->pin = NULL; 00931 00932 wpa_printf(MSG_WARNING, "PIN validation failed"); 00933 eap_sm_request_pin(sm); 00934 return -1; 00935 } 00936 return 0; 00937 #else /* PCSC_FUNCS */ 00938 return -1; 00939 #endif /* PCSC_FUNCS */ 00940 } 00941 00942 static int eap_sm_get_scard_identity(struct eap_sm *sm, 00943 struct eap_peer_config *conf) 00944 { 00945 #ifdef PCSC_FUNCS 00946 if (eap_sm_set_scard_pin(sm, conf)) 00947 return -1; 00948 00949 return eap_sm_imsi_identity(sm, conf); 00950 #else /* PCSC_FUNCS */ 00951 return -1; 00952 #endif /* PCSC_FUNCS */ 00953 } 00954 00955 00967 struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted) 00968 { 00969 struct eap_peer_config *config = eap_get_config(sm); 00970 struct wpabuf *resp; 00971 const u8 *identity; 00972 size_t identity_len; 00973 00974 if (config == NULL) { 00975 wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration " 00976 "was not available"); 00977 return NULL; 00978 } 00979 00980 if (sm->m && sm->m->get_identity && 00981 (identity = sm->m->get_identity(sm, sm->eap_method_priv, 00982 &identity_len)) != NULL) { 00983 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth " 00984 "identity", identity, identity_len); 00985 } else if (!encrypted && config->anonymous_identity) { 00986 identity = config->anonymous_identity; 00987 identity_len = config->anonymous_identity_len; 00988 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity", 00989 identity, identity_len); 00990 } else { 00991 identity = config->identity; 00992 identity_len = config->identity_len; 00993 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity", 00994 identity, identity_len); 00995 } 00996 00997 if (identity == NULL) { 00998 wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity " 00999 "configuration was not available"); 01000 if (config->pcsc) { 01001 if (eap_sm_get_scard_identity(sm, config) < 0) 01002 return NULL; 01003 identity = config->identity; 01004 identity_len = config->identity_len; 01005 wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " 01006 "IMSI", identity, identity_len); 01007 } else { 01008 eap_sm_request_identity(sm); 01009 return NULL; 01010 } 01011 } else if (config->pcsc) { 01012 if (eap_sm_set_scard_pin(sm, config) < 0) 01013 return NULL; 01014 } 01015 01016 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len, 01017 EAP_CODE_RESPONSE, id); 01018 if (resp == NULL) 01019 return NULL; 01020 01021 wpabuf_put_data(resp, identity, identity_len); 01022 01023 return resp; 01024 } 01025 01026 01027 static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req) 01028 { 01029 const u8 *pos; 01030 char *msg; 01031 size_t i, msg_len; 01032 01033 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req, 01034 &msg_len); 01035 if (pos == NULL) 01036 return; 01037 wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data", 01038 pos, msg_len); 01039 01040 msg = os_malloc(msg_len + 1); 01041 if (msg == NULL) 01042 return; 01043 for (i = 0; i < msg_len; i++) 01044 msg[i] = isprint(pos[i]) ? (char) pos[i] : '_'; 01045 msg[msg_len] = '\0'; 01046 wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s", 01047 WPA_EVENT_EAP_NOTIFICATION, msg); 01048 os_free(msg); 01049 } 01050 01051 01052 static struct wpabuf * eap_sm_buildNotify(int id) 01053 { 01054 struct wpabuf *resp; 01055 01056 wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); 01057 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0, 01058 EAP_CODE_RESPONSE, id); 01059 if (resp == NULL) 01060 return NULL; 01061 01062 return resp; 01063 } 01064 01065 01066 static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) 01067 { 01068 const struct eap_hdr *hdr; 01069 size_t plen; 01070 const u8 *pos; 01071 01072 sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE; 01073 sm->reqId = 0; 01074 sm->reqMethod = EAP_TYPE_NONE; 01075 sm->reqVendor = EAP_VENDOR_IETF; 01076 sm->reqVendorMethod = EAP_TYPE_NONE; 01077 01078 if (req == NULL || wpabuf_len(req) < sizeof(*hdr)) 01079 return; 01080 01081 hdr = wpabuf_head(req); 01082 plen = be_to_host16(hdr->length); 01083 if (plen > wpabuf_len(req)) { 01084 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " 01085 "(len=%lu plen=%lu)", 01086 (unsigned long) wpabuf_len(req), 01087 (unsigned long) plen); 01088 return; 01089 } 01090 01091 sm->reqId = hdr->identifier; 01092 01093 if (sm->workaround) { 01094 const u8 *addr[1]; 01095 addr[0] = wpabuf_head(req); 01096 md5_vector(1, addr, &plen, sm->req_md5); 01097 } 01098 01099 switch (hdr->code) { 01100 case EAP_CODE_REQUEST: 01101 if (plen < sizeof(*hdr) + 1) { 01102 wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - " 01103 "no Type field"); 01104 return; 01105 } 01106 sm->rxReq = TRUE; 01107 pos = (const u8 *) (hdr + 1); 01108 sm->reqMethod = *pos++; 01109 if (sm->reqMethod == EAP_TYPE_EXPANDED) { 01110 if (plen < sizeof(*hdr) + 8) { 01111 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " 01112 "expanded EAP-Packet (plen=%lu)", 01113 (unsigned long) plen); 01114 return; 01115 } 01116 sm->reqVendor = WPA_GET_BE24(pos); 01117 pos += 3; 01118 sm->reqVendorMethod = WPA_GET_BE32(pos); 01119 } 01120 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d " 01121 "method=%u vendor=%u vendorMethod=%u", 01122 sm->reqId, sm->reqMethod, sm->reqVendor, 01123 sm->reqVendorMethod); 01124 break; 01125 case EAP_CODE_RESPONSE: 01126 if (sm->selectedMethod == EAP_TYPE_LEAP) { 01127 /* 01128 * LEAP differs from RFC 4137 by using reversed roles 01129 * for mutual authentication and because of this, we 01130 * need to accept EAP-Response frames if LEAP is used. 01131 */ 01132 if (plen < sizeof(*hdr) + 1) { 01133 wpa_printf(MSG_DEBUG, "EAP: Too short " 01134 "EAP-Response - no Type field"); 01135 return; 01136 } 01137 sm->rxResp = TRUE; 01138 pos = (const u8 *) (hdr + 1); 01139 sm->reqMethod = *pos; 01140 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " 01141 "LEAP method=%d id=%d", 01142 sm->reqMethod, sm->reqId); 01143 break; 01144 } 01145 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response"); 01146 break; 01147 case EAP_CODE_SUCCESS: 01148 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); 01149 sm->rxSuccess = TRUE; 01150 break; 01151 case EAP_CODE_FAILURE: 01152 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); 01153 sm->rxFailure = TRUE; 01154 break; 01155 default: 01156 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown " 01157 "code %d", hdr->code); 01158 break; 01159 } 01160 } 01161 01162 01163 static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev, 01164 union tls_event_data *data) 01165 { 01166 struct eap_sm *sm = ctx; 01167 char *hash_hex = NULL; 01168 char *cert_hex = NULL; 01169 01170 switch (ev) { 01171 case TLS_CERT_CHAIN_FAILURE: 01172 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR 01173 "reason=%d depth=%d subject='%s' err='%s'", 01174 data->cert_fail.reason, 01175 data->cert_fail.depth, 01176 data->cert_fail.subject, 01177 data->cert_fail.reason_txt); 01178 break; 01179 case TLS_PEER_CERTIFICATE: 01180 if (data->peer_cert.hash) { 01181 size_t len = data->peer_cert.hash_len * 2 + 1; 01182 hash_hex = os_malloc(len); 01183 if (hash_hex) { 01184 wpa_snprintf_hex(hash_hex, len, 01185 data->peer_cert.hash, 01186 data->peer_cert.hash_len); 01187 } 01188 } 01189 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PEER_CERT 01190 "depth=%d subject='%s'%s%s", 01191 data->peer_cert.depth, data->peer_cert.subject, 01192 hash_hex ? " hash=" : "", hash_hex ? hash_hex : ""); 01193 01194 if (data->peer_cert.cert) { 01195 size_t len = wpabuf_len(data->peer_cert.cert) * 2 + 1; 01196 cert_hex = os_malloc(len); 01197 if (cert_hex == NULL) 01198 break; 01199 wpa_snprintf_hex(cert_hex, len, 01200 wpabuf_head(data->peer_cert.cert), 01201 wpabuf_len(data->peer_cert.cert)); 01202 wpa_msg_ctrl(sm->msg_ctx, MSG_INFO, 01203 WPA_EVENT_EAP_PEER_CERT 01204 "depth=%d subject='%s' cert=%s", 01205 data->peer_cert.depth, 01206 data->peer_cert.subject, 01207 cert_hex); 01208 } 01209 break; 01210 } 01211 01212 os_free(hash_hex); 01213 os_free(cert_hex); 01214 } 01215 01216 01231 struct eap_sm * eap_peer_sm_init(void *eapol_ctx, 01232 struct eapol_callbacks *eapol_cb, 01233 void *msg_ctx, struct eap_config *conf) 01234 { 01235 struct eap_sm *sm; 01236 struct tls_config tlsconf; 01237 01238 sm = os_zalloc(sizeof(*sm)); 01239 if (sm == NULL) 01240 return NULL; 01241 sm->eapol_ctx = eapol_ctx; 01242 sm->eapol_cb = eapol_cb; 01243 sm->msg_ctx = msg_ctx; 01244 sm->ClientTimeout = 60; 01245 sm->wps = conf->wps; 01246 01247 os_memset(&tlsconf, 0, sizeof(tlsconf)); 01248 tlsconf.opensc_engine_path = conf->opensc_engine_path; 01249 tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path; 01250 tlsconf.pkcs11_module_path = conf->pkcs11_module_path; 01251 #ifdef CONFIG_FIPS 01252 tlsconf.fips_mode = 1; 01253 #endif /* CONFIG_FIPS */ 01254 tlsconf.event_cb = eap_peer_sm_tls_event; 01255 tlsconf.cb_ctx = sm; 01256 sm->ssl_ctx = tls_init(&tlsconf); 01257 if (sm->ssl_ctx == NULL) { 01258 wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS " 01259 "context."); 01260 os_free(sm); 01261 return NULL; 01262 } 01263 01264 return sm; 01265 } 01266 01267 01275 void eap_peer_sm_deinit(struct eap_sm *sm) 01276 { 01277 if (sm == NULL) 01278 return; 01279 eap_deinit_prev_method(sm, "EAP deinit"); 01280 eap_sm_abort(sm); 01281 tls_deinit(sm->ssl_ctx); 01282 os_free(sm); 01283 } 01284 01285 01295 int eap_peer_sm_step(struct eap_sm *sm) 01296 { 01297 int res = 0; 01298 do { 01299 sm->changed = FALSE; 01300 SM_STEP_RUN(EAP); 01301 if (sm->changed) 01302 res = 1; 01303 } while (sm->changed); 01304 return res; 01305 } 01306 01307 01315 void eap_sm_abort(struct eap_sm *sm) 01316 { 01317 wpabuf_free(sm->lastRespData); 01318 sm->lastRespData = NULL; 01319 wpabuf_free(sm->eapRespData); 01320 sm->eapRespData = NULL; 01321 os_free(sm->eapKeyData); 01322 sm->eapKeyData = NULL; 01323 01324 /* This is not clearly specified in the EAP statemachines draft, but 01325 * it seems necessary to make sure that some of the EAPOL variables get 01326 * cleared for the next authentication. */ 01327 eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); 01328 } 01329 01330 01331 #ifdef CONFIG_CTRL_IFACE 01332 static const char * eap_sm_state_txt(int state) 01333 { 01334 switch (state) { 01335 case EAP_INITIALIZE: 01336 return "INITIALIZE"; 01337 case EAP_DISABLED: 01338 return "DISABLED"; 01339 case EAP_IDLE: 01340 return "IDLE"; 01341 case EAP_RECEIVED: 01342 return "RECEIVED"; 01343 case EAP_GET_METHOD: 01344 return "GET_METHOD"; 01345 case EAP_METHOD: 01346 return "METHOD"; 01347 case EAP_SEND_RESPONSE: 01348 return "SEND_RESPONSE"; 01349 case EAP_DISCARD: 01350 return "DISCARD"; 01351 case EAP_IDENTITY: 01352 return "IDENTITY"; 01353 case EAP_NOTIFICATION: 01354 return "NOTIFICATION"; 01355 case EAP_RETRANSMIT: 01356 return "RETRANSMIT"; 01357 case EAP_SUCCESS: 01358 return "SUCCESS"; 01359 case EAP_FAILURE: 01360 return "FAILURE"; 01361 default: 01362 return "UNKNOWN"; 01363 } 01364 } 01365 #endif /* CONFIG_CTRL_IFACE */ 01366 01367 01368 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 01369 static const char * eap_sm_method_state_txt(EapMethodState state) 01370 { 01371 switch (state) { 01372 case METHOD_NONE: 01373 return "NONE"; 01374 case METHOD_INIT: 01375 return "INIT"; 01376 case METHOD_CONT: 01377 return "CONT"; 01378 case METHOD_MAY_CONT: 01379 return "MAY_CONT"; 01380 case METHOD_DONE: 01381 return "DONE"; 01382 default: 01383 return "UNKNOWN"; 01384 } 01385 } 01386 01387 01388 static const char * eap_sm_decision_txt(EapDecision decision) 01389 { 01390 switch (decision) { 01391 case DECISION_FAIL: 01392 return "FAIL"; 01393 case DECISION_COND_SUCC: 01394 return "COND_SUCC"; 01395 case DECISION_UNCOND_SUCC: 01396 return "UNCOND_SUCC"; 01397 default: 01398 return "UNKNOWN"; 01399 } 01400 } 01401 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 01402 01403 01404 #ifdef CONFIG_CTRL_IFACE 01405 01419 int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose) 01420 { 01421 int len, ret; 01422 01423 if (sm == NULL) 01424 return 0; 01425 01426 len = os_snprintf(buf, buflen, 01427 "EAP state=%s\n", 01428 eap_sm_state_txt(sm->EAP_state)); 01429 if (len < 0 || (size_t) len >= buflen) 01430 return 0; 01431 01432 if (sm->selectedMethod != EAP_TYPE_NONE) { 01433 const char *name; 01434 if (sm->m) { 01435 name = sm->m->name; 01436 } else { 01437 const struct eap_method *m = 01438 eap_peer_get_eap_method(EAP_VENDOR_IETF, 01439 sm->selectedMethod); 01440 if (m) 01441 name = m->name; 01442 else 01443 name = "?"; 01444 } 01445 ret = os_snprintf(buf + len, buflen - len, 01446 "selectedMethod=%d (EAP-%s)\n", 01447 sm->selectedMethod, name); 01448 if (ret < 0 || (size_t) ret >= buflen - len) 01449 return len; 01450 len += ret; 01451 01452 if (sm->m && sm->m->get_status) { 01453 len += sm->m->get_status(sm, sm->eap_method_priv, 01454 buf + len, buflen - len, 01455 verbose); 01456 } 01457 } 01458 01459 if (verbose) { 01460 ret = os_snprintf(buf + len, buflen - len, 01461 "reqMethod=%d\n" 01462 "methodState=%s\n" 01463 "decision=%s\n" 01464 "ClientTimeout=%d\n", 01465 sm->reqMethod, 01466 eap_sm_method_state_txt(sm->methodState), 01467 eap_sm_decision_txt(sm->decision), 01468 sm->ClientTimeout); 01469 if (ret < 0 || (size_t) ret >= buflen - len) 01470 return len; 01471 len += ret; 01472 } 01473 01474 return len; 01475 } 01476 #endif /* CONFIG_CTRL_IFACE */ 01477 01478 01479 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 01480 typedef enum { 01481 TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD, 01482 TYPE_PASSPHRASE 01483 } eap_ctrl_req_type; 01484 01485 static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type, 01486 const char *msg, size_t msglen) 01487 { 01488 struct eap_peer_config *config; 01489 char *field, *txt, *tmp; 01490 01491 if (sm == NULL) 01492 return; 01493 config = eap_get_config(sm); 01494 if (config == NULL) 01495 return; 01496 01497 switch (type) { 01498 case TYPE_IDENTITY: 01499 field = "IDENTITY"; 01500 txt = "Identity"; 01501 config->pending_req_identity++; 01502 break; 01503 case TYPE_PASSWORD: 01504 field = "PASSWORD"; 01505 txt = "Password"; 01506 config->pending_req_password++; 01507 break; 01508 case TYPE_NEW_PASSWORD: 01509 field = "NEW_PASSWORD"; 01510 txt = "New Password"; 01511 config->pending_req_new_password++; 01512 break; 01513 case TYPE_PIN: 01514 field = "PIN"; 01515 txt = "PIN"; 01516 config->pending_req_pin++; 01517 break; 01518 case TYPE_OTP: 01519 field = "OTP"; 01520 if (msg) { 01521 tmp = os_malloc(msglen + 3); 01522 if (tmp == NULL) 01523 return; 01524 tmp[0] = '['; 01525 os_memcpy(tmp + 1, msg, msglen); 01526 tmp[msglen + 1] = ']'; 01527 tmp[msglen + 2] = '\0'; 01528 txt = tmp; 01529 os_free(config->pending_req_otp); 01530 config->pending_req_otp = tmp; 01531 config->pending_req_otp_len = msglen + 3; 01532 } else { 01533 if (config->pending_req_otp == NULL) 01534 return; 01535 txt = config->pending_req_otp; 01536 } 01537 break; 01538 case TYPE_PASSPHRASE: 01539 field = "PASSPHRASE"; 01540 txt = "Private key passphrase"; 01541 config->pending_req_passphrase++; 01542 break; 01543 default: 01544 return; 01545 } 01546 01547 if (sm->eapol_cb->eap_param_needed) 01548 sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt); 01549 } 01550 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 01551 #define eap_sm_request(sm, type, msg, msglen) do { } while (0) 01552 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 01553 01554 01564 void eap_sm_request_identity(struct eap_sm *sm) 01565 { 01566 eap_sm_request(sm, TYPE_IDENTITY, NULL, 0); 01567 } 01568 01569 01579 void eap_sm_request_password(struct eap_sm *sm) 01580 { 01581 eap_sm_request(sm, TYPE_PASSWORD, NULL, 0); 01582 } 01583 01584 01594 void eap_sm_request_new_password(struct eap_sm *sm) 01595 { 01596 eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0); 01597 } 01598 01599 01609 void eap_sm_request_pin(struct eap_sm *sm) 01610 { 01611 eap_sm_request(sm, TYPE_PIN, NULL, 0); 01612 } 01613 01614 01625 void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len) 01626 { 01627 eap_sm_request(sm, TYPE_OTP, msg, msg_len); 01628 } 01629 01630 01640 void eap_sm_request_passphrase(struct eap_sm *sm) 01641 { 01642 eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0); 01643 } 01644 01645 01653 void eap_sm_notify_ctrl_attached(struct eap_sm *sm) 01654 { 01655 struct eap_peer_config *config = eap_get_config(sm); 01656 01657 if (config == NULL) 01658 return; 01659 01660 /* Re-send any pending requests for user data since a new control 01661 * interface was added. This handles cases where the EAP authentication 01662 * starts immediately after system startup when the user interface is 01663 * not yet running. */ 01664 if (config->pending_req_identity) 01665 eap_sm_request_identity(sm); 01666 if (config->pending_req_password) 01667 eap_sm_request_password(sm); 01668 if (config->pending_req_new_password) 01669 eap_sm_request_new_password(sm); 01670 if (config->pending_req_otp) 01671 eap_sm_request_otp(sm, NULL, 0); 01672 if (config->pending_req_pin) 01673 eap_sm_request_pin(sm); 01674 if (config->pending_req_passphrase) 01675 eap_sm_request_passphrase(sm); 01676 } 01677 01678 01679 static int eap_allowed_phase2_type(int vendor, int type) 01680 { 01681 if (vendor != EAP_VENDOR_IETF) 01682 return 0; 01683 return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS && 01684 type != EAP_TYPE_FAST; 01685 } 01686 01687 01698 u32 eap_get_phase2_type(const char *name, int *vendor) 01699 { 01700 int v; 01701 u8 type = eap_peer_get_type(name, &v); 01702 if (eap_allowed_phase2_type(v, type)) { 01703 *vendor = v; 01704 return type; 01705 } 01706 *vendor = EAP_VENDOR_IETF; 01707 return EAP_TYPE_NONE; 01708 } 01709 01710 01720 struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, 01721 size_t *count) 01722 { 01723 struct eap_method_type *buf; 01724 u32 method; 01725 int vendor; 01726 size_t mcount; 01727 const struct eap_method *methods, *m; 01728 01729 methods = eap_peer_get_methods(&mcount); 01730 if (methods == NULL) 01731 return NULL; 01732 *count = 0; 01733 buf = os_malloc(mcount * sizeof(struct eap_method_type)); 01734 if (buf == NULL) 01735 return NULL; 01736 01737 for (m = methods; m; m = m->next) { 01738 vendor = m->vendor; 01739 method = m->method; 01740 if (eap_allowed_phase2_type(vendor, method)) { 01741 if (vendor == EAP_VENDOR_IETF && 01742 method == EAP_TYPE_TLS && config && 01743 config->private_key2 == NULL) 01744 continue; 01745 buf[*count].vendor = vendor; 01746 buf[*count].method = method; 01747 (*count)++; 01748 } 01749 } 01750 01751 return buf; 01752 } 01753 01754 01760 void eap_set_fast_reauth(struct eap_sm *sm, int enabled) 01761 { 01762 sm->fast_reauth = enabled; 01763 } 01764 01765 01771 void eap_set_workaround(struct eap_sm *sm, unsigned int workaround) 01772 { 01773 sm->workaround = workaround; 01774 } 01775 01776 01787 struct eap_peer_config * eap_get_config(struct eap_sm *sm) 01788 { 01789 return sm->eapol_cb->get_config(sm->eapol_ctx); 01790 } 01791 01792 01799 const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) 01800 { 01801 struct eap_peer_config *config = eap_get_config(sm); 01802 if (config == NULL) 01803 return NULL; 01804 *len = config->identity_len; 01805 return config->identity; 01806 } 01807 01808 01815 const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len) 01816 { 01817 struct eap_peer_config *config = eap_get_config(sm); 01818 if (config == NULL) 01819 return NULL; 01820 *len = config->password_len; 01821 return config->password; 01822 } 01823 01824 01834 const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash) 01835 { 01836 struct eap_peer_config *config = eap_get_config(sm); 01837 if (config == NULL) 01838 return NULL; 01839 *len = config->password_len; 01840 if (hash) 01841 *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); 01842 return config->password; 01843 } 01844 01845 01852 const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len) 01853 { 01854 struct eap_peer_config *config = eap_get_config(sm); 01855 if (config == NULL) 01856 return NULL; 01857 *len = config->new_password_len; 01858 return config->new_password; 01859 } 01860 01861 01868 const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len) 01869 { 01870 struct eap_peer_config *config = eap_get_config(sm); 01871 if (config == NULL) 01872 return NULL; 01873 *len = config->otp_len; 01874 return config->otp; 01875 } 01876 01877 01886 void eap_clear_config_otp(struct eap_sm *sm) 01887 { 01888 struct eap_peer_config *config = eap_get_config(sm); 01889 if (config == NULL) 01890 return; 01891 os_memset(config->otp, 0, config->otp_len); 01892 os_free(config->otp); 01893 config->otp = NULL; 01894 config->otp_len = 0; 01895 } 01896 01897 01903 const char * eap_get_config_phase1(struct eap_sm *sm) 01904 { 01905 struct eap_peer_config *config = eap_get_config(sm); 01906 if (config == NULL) 01907 return NULL; 01908 return config->phase1; 01909 } 01910 01911 01917 const char * eap_get_config_phase2(struct eap_sm *sm) 01918 { 01919 struct eap_peer_config *config = eap_get_config(sm); 01920 if (config == NULL) 01921 return NULL; 01922 return config->phase2; 01923 } 01924 01925 01931 int eap_key_available(struct eap_sm *sm) 01932 { 01933 return sm ? sm->eapKeyAvailable : 0; 01934 } 01935 01936 01946 void eap_notify_success(struct eap_sm *sm) 01947 { 01948 if (sm) { 01949 sm->decision = DECISION_COND_SUCC; 01950 sm->EAP_state = EAP_SUCCESS; 01951 } 01952 } 01953 01954 01962 void eap_notify_lower_layer_success(struct eap_sm *sm) 01963 { 01964 if (sm == NULL) 01965 return; 01966 01967 if (eapol_get_bool(sm, EAPOL_eapSuccess) || 01968 sm->decision == DECISION_FAIL || 01969 (sm->methodState != METHOD_MAY_CONT && 01970 sm->methodState != METHOD_DONE)) 01971 return; 01972 01973 if (sm->eapKeyData != NULL) 01974 sm->eapKeyAvailable = TRUE; 01975 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); 01976 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS 01977 "EAP authentication completed successfully (based on lower " 01978 "layer success)"); 01979 } 01980 01981 01993 const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len) 01994 { 01995 if (sm == NULL || sm->eapKeyData == NULL) { 01996 *len = 0; 01997 return NULL; 01998 } 01999 02000 *len = sm->eapKeyDataLen; 02001 return sm->eapKeyData; 02002 } 02003 02004 02015 struct wpabuf * eap_get_eapRespData(struct eap_sm *sm) 02016 { 02017 struct wpabuf *resp; 02018 02019 if (sm == NULL || sm->eapRespData == NULL) 02020 return NULL; 02021 02022 resp = sm->eapRespData; 02023 sm->eapRespData = NULL; 02024 02025 return resp; 02026 } 02027 02028 02037 void eap_register_scard_ctx(struct eap_sm *sm, void *ctx) 02038 { 02039 if (sm) 02040 sm->scard_ctx = ctx; 02041 } 02042 02043 02052 void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob) 02053 { 02054 #ifndef CONFIG_NO_CONFIG_BLOBS 02055 sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob); 02056 #endif /* CONFIG_NO_CONFIG_BLOBS */ 02057 } 02058 02059 02066 const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, 02067 const char *name) 02068 { 02069 #ifndef CONFIG_NO_CONFIG_BLOBS 02070 return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name); 02071 #else /* CONFIG_NO_CONFIG_BLOBS */ 02072 return NULL; 02073 #endif /* CONFIG_NO_CONFIG_BLOBS */ 02074 } 02075 02076 02085 void eap_set_force_disabled(struct eap_sm *sm, int disabled) 02086 { 02087 sm->force_disabled = disabled; 02088 } 02089 02090 02100 void eap_notify_pending(struct eap_sm *sm) 02101 { 02102 sm->eapol_cb->notify_pending(sm->eapol_ctx); 02103 } 02104 02105 02110 void eap_invalidate_cached_session(struct eap_sm *sm) 02111 { 02112 if (sm) 02113 eap_deinit_prev_method(sm, "invalidate"); 02114 } 02115 02116 02117 int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf) 02118 { 02119 if (conf->identity_len != WSC_ID_ENROLLEE_LEN || 02120 os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)) 02121 return 0; /* Not a WPS Enrollee */ 02122 02123 if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL) 02124 return 0; /* Not using PBC */ 02125 02126 return 1; 02127 } 02128 02129 02130 int eap_is_wps_pin_enrollee(struct eap_peer_config *conf) 02131 { 02132 if (conf->identity_len != WSC_ID_ENROLLEE_LEN || 02133 os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)) 02134 return 0; /* Not a WPS Enrollee */ 02135 02136 if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL) 02137 return 0; /* Not using PIN */ 02138 02139 return 1; 02140 }