Lines Matching refs:sm
39 static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
41 static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id);
42 static void eap_sm_processIdentity(struct eap_sm *sm,
44 static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req);
46 static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
51 static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
56 static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
58 return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
62 static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
65 sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
69 static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
71 return sm->eapol_cb->get_int(sm->eapol_ctx, var);
75 static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
78 sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
82 static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
84 return sm->eapol_cb->get_eapReqData(sm->eapol_ctx);
88 static void eap_notify_status(struct eap_sm *sm, const char *status,
93 if (sm->eapol_cb->notify_status)
94 sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
98 static void eap_report_error(struct eap_sm *sm, int error_code)
101 if (sm->eapol_cb->notify_eap_error)
102 sm->eapol_cb->notify_eap_error(sm->eapol_ctx, error_code);
106 static void eap_sm_free_key(struct eap_sm *sm)
108 if (sm->eapKeyData) {
109 bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
110 sm->eapKeyData = NULL;
115 static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
117 ext_password_free(sm->ext_pw_buf);
118 sm->ext_pw_buf = NULL;
120 if (sm->m == NULL || sm->eap_method_priv == NULL)
124 "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
125 sm->m->deinit(sm, sm->eap_method_priv);
126 sm->eap_method_priv = NULL;
127 sm->m = NULL;
133 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
139 static int eap_config_allowed_method(struct eap_sm *sm,
161 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
166 int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
168 return eap_config_allowed_method(sm, eap_get_config(sm), vendor,
174 static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
218 if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
219 sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
220 !sm->prev_failure &&
221 sm->last_config == eap_get_config(sm)) {
224 sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
226 sm->last_config = eap_get_config(sm);
227 eap_deinit_prev_method(sm, "INITIALIZE");
229 sm->selectedMethod = EAP_TYPE_NONE;
230 sm->methodState = METHOD_NONE;
231 sm->allowNotifications = TRUE;
232 sm->decision = DECISION_FAIL;
233 sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
234 eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
235 eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
236 eapol_set_bool(sm, EAPOL_eapFail, FALSE);
237 eap_sm_free_key(sm);
238 os_free(sm->eapSessionId);
239 sm->eapSessionId = NULL;
240 sm->eapKeyAvailable = FALSE;
241 eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
242 sm->lastId = -1; /* new session - make sure this does not match with
252 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
253 eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
261 sm->ignore = 0;
262 sm->num_rounds = 0;
263 sm->prev_failure = 0;
264 sm->expected_failure = 0;
265 sm->reauthInit = FALSE;
266 sm->erp_seq = (u32) -1;
278 sm->num_rounds = 0;
284 eapol_set_int(sm, EAPOL_idleWhile, 0);
308 eapReqData = eapol_get_eapReqData(sm);
310 eap_sm_parseEapReq(sm, eapReqData);
311 sm->num_rounds++;
327 if (sm->reqMethod == EAP_TYPE_EXPANDED)
328 method = sm->reqVendorMethod;
330 method = sm->reqMethod;
332 eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
334 if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
336 sm->reqVendor, method);
337 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
339 sm->reqVendor, method);
340 eap_notify_status(sm, "refuse proposed method",
345 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
346 "vendor=%u method=%u", sm->reqVendor, method);
348 eap_notify_status(sm, "accept proposed method",
358 if (sm->fast_reauth &&
359 sm->m && sm->m->vendor == sm->reqVendor &&
360 sm->m->method == method &&
361 sm->m->has_reauth_data &&
362 sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
367 eap_deinit_prev_method(sm, "GET_METHOD");
371 sm->selectedMethod = sm->reqMethod;
372 if (sm->m == NULL)
373 sm->m = eap_method;
374 if (!sm->m) {
377 sm->reqVendor, method);
381 sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
385 sm->reqVendor, method, sm->m->name);
387 sm->eap_method_priv = sm->m->init_for_reauth(
388 sm, sm->eap_method_priv);
390 sm->waiting_ext_cert_check = 0;
391 sm->ext_cert_check = 0;
392 sm->eap_method_priv = sm->m->init(sm);
395 if (sm->eap_method_priv == NULL) {
396 struct eap_peer_config *config = eap_get_config(sm);
397 wpa_msg(sm->msg_ctx, MSG_INFO,
400 sm->reqVendor, method, sm->m->name);
401 sm->m = NULL;
402 sm->methodState = METHOD_NONE;
403 sm->selectedMethod = EAP_TYPE_NONE;
404 if (sm->reqMethod == EAP_TYPE_TLS && config &&
420 sm->methodState = METHOD_INIT;
421 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
423 sm->reqVendor, method, sm->m->name);
427 wpabuf_free(sm->eapRespData);
428 sm->eapRespData = NULL;
429 sm->eapRespData = eap_sm_buildNak(sm, sm->reqId);
435 static char * eap_get_realm(struct eap_sm *sm, struct eap_peer_config *config)
481 sm->eapol_cb->get_imsi &&
482 (eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
484 eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
486 eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
493 mnc_len = sm->eapol_cb->get_imsi(sm->eapol_ctx, config->sim_num,
499 if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
518 static char * eap_home_realm(struct eap_sm *sm)
520 return eap_get_realm(sm, eap_get_config(sm));
525 eap_erp_get_key(struct eap_sm *sm, const char *realm)
529 dl_list_for_each(erp, &sm->erp_keys, struct eap_erp_key, list) {
545 eap_erp_get_key_nai(struct eap_sm *sm, const char *nai)
549 dl_list_for_each(erp, &sm->erp_keys, struct eap_erp_key, list) {
565 static void eap_erp_remove_keys_realm(struct eap_sm *sm, const char *realm)
569 while ((erp = eap_erp_get_key(sm, realm)) != NULL) {
577 int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 next_seq_num)
582 home_realm = eap_home_realm(sm);
588 erp = eap_erp_get_key(sm, home_realm);
611 int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config,
622 home_realm = eap_get_realm(sm, config);
624 home_realm = eap_home_realm(sm);
630 erp = eap_erp_get_key(sm, home_realm);
662 void eap_peer_erp_free_keys(struct eap_sm *sm)
667 dl_list_for_each_safe(erp, tmp, &sm->erp_keys, struct eap_erp_key, list)
676 void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id,
692 realm = eap_home_realm(sm);
697 eap_erp_remove_keys_realm(sm, realm);
718 emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
733 session_id = sm->eapSessionId;
734 session_id_len = sm->eapSessionIdLen;
778 dl_list_add(&sm->erp_keys, &erp->list);
793 struct wpabuf * eap_peer_build_erp_reauth_start(struct eap_sm *sm, u8 eap_id)
800 realm = eap_home_realm(sm);
804 erp = eap_erp_get_key(sm, realm);
840 sm->erp_seq = erp->next_seq;
849 static int eap_peer_erp_reauth_start(struct eap_sm *sm, u8 eap_id)
853 msg = eap_peer_build_erp_reauth_start(sm, eap_id);
858 wpabuf_free(sm->eapRespData);
859 sm->eapRespData = msg;
860 sm->reauthInit = TRUE;
877 if (sm->m == NULL) {
882 eapReqData = eapol_get_eapReqData(sm);
883 if (sm->m->vendor == EAP_VENDOR_IETF && sm->m->method == EAP_TYPE_LEAP)
903 ret.ignore = sm->ignore;
904 ret.methodState = sm->methodState;
905 ret.decision = sm->decision;
906 ret.allowNotifications = sm->allowNotifications;
907 wpabuf_free(sm->eapRespData);
908 sm->eapRespData = NULL;
909 sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
916 sm->eapRespData);
918 sm->ignore = ret.ignore;
919 if (sm->ignore)
921 sm->methodState = ret.methodState;
922 sm->decision = ret.decision;
923 sm->allowNotifications = ret.allowNotifications;
925 if (sm->m->isKeyAvailable && sm->m->getKey &&
926 sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
927 eap_sm_free_key(sm);
928 sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
929 &sm->eapKeyDataLen);
930 os_free(sm->eapSessionId);
931 sm->eapSessionId = NULL;
932 if (sm->m->getSessionId) {
933 sm->eapSessionId = sm->m->getSessionId(
934 sm, sm->eap_method_priv,
935 &sm->eapSessionIdLen);
937 sm->eapSessionId, sm->eapSessionIdLen);
950 wpabuf_free(sm->lastRespData);
951 if (sm->eapRespData) {
952 if (sm->workaround)
953 os_memcpy(sm->last_sha1, sm->req_sha1, 20);
954 sm->lastId = sm->reqId;
955 sm->lastRespData = wpabuf_dup(sm->eapRespData);
956 eapol_set_bool(sm, EAPOL_eapResp, TRUE);
959 sm->lastRespData = NULL;
961 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
962 eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
963 sm->reauthInit = FALSE;
974 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
975 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
987 eapReqData = eapol_get_eapReqData(sm);
990 eap_sm_processIdentity(sm, eapReqData);
991 wpabuf_free(sm->eapRespData);
992 sm->eapRespData = NULL;
993 sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0);
1005 eapReqData = eapol_get_eapReqData(sm);
1008 eap_sm_processNotify(sm, eapReqData);
1009 wpabuf_free(sm->eapRespData);
1010 sm->eapRespData = NULL;
1011 sm->eapRespData = eap_sm_buildNotify(sm->reqId);
1021 wpabuf_free(sm->eapRespData);
1022 if (sm->lastRespData)
1023 sm->eapRespData = wpabuf_dup(sm->lastRespData);
1025 sm->eapRespData = NULL;
1036 struct eap_peer_config *config = eap_get_config(sm);
1039 if (sm->eapKeyData != NULL)
1040 sm->eapKeyAvailable = TRUE;
1041 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
1048 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
1056 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
1058 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
1061 if (config->erp && sm->m->get_emsk && sm->eapSessionId &&
1062 sm->m->isKeyAvailable &&
1063 sm->m->isKeyAvailable(sm, sm->eap_method_priv))
1064 eap_peer_erp_init(sm, NULL, 0, NULL, 0);
1075 eapol_set_bool(sm, EAPOL_eapFail, TRUE);
1082 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
1089 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
1091 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
1094 sm->prev_failure = 1;
1098 static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
1110 if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
1128 static void eap_peer_sm_step_idle(struct eap_sm *sm)
1135 if (eapol_get_bool(sm, EAPOL_eapReq))
1137 else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
1138 sm->decision != DECISION_FAIL) ||
1139 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
1140 sm->decision == DECISION_UNCOND_SUCC))
1142 else if (eapol_get_bool(sm, EAPOL_altReject) ||
1143 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
1144 sm->decision != DECISION_UNCOND_SUCC) ||
1145 (eapol_get_bool(sm, EAPOL_altAccept) &&
1146 sm->methodState != METHOD_CONT &&
1147 sm->decision == DECISION_FAIL))
1149 else if (sm->selectedMethod == EAP_TYPE_LEAP &&
1150 sm->leap_done && sm->decision != DECISION_FAIL &&
1151 sm->methodState == METHOD_DONE)
1153 else if (sm->selectedMethod == EAP_TYPE_PEAP &&
1154 sm->peap_done && sm->decision != DECISION_FAIL &&
1155 sm->methodState == METHOD_DONE)
1160 static int eap_peer_req_is_duplicate(struct eap_sm *sm)
1164 duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
1165 if (sm->workaround && duplicate &&
1166 os_memcmp(sm->req_sha1, sm->last_sha1, 20) != 0) {
1186 static int eap_peer_sm_allow_canned(struct eap_sm *sm)
1188 struct eap_peer_config *config = eap_get_config(sm);
1195 static void eap_peer_sm_step_received(struct eap_sm *sm)
1197 int duplicate = eap_peer_req_is_duplicate(sm);
1204 if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
1205 (sm->reqId == sm->lastId ||
1206 eap_success_workaround(sm, sm->reqId, sm->lastId)))
1208 else if (sm->workaround && sm->lastId == -1 && sm->rxSuccess &&
1209 !sm->rxFailure && !sm->rxReq && eap_peer_sm_allow_canned(sm))
1211 else if (sm->workaround && sm->lastId == -1 && sm->rxFailure &&
1212 !sm->rxReq && sm->methodState != METHOD_CONT &&
1213 eap_peer_sm_allow_canned(sm))
1215 else if (sm->workaround && sm->rxSuccess && !sm->rxFailure &&
1216 !sm->rxReq && sm->methodState != METHOD_CONT &&
1217 eap_peer_sm_allow_canned(sm))
1219 else if (sm->methodState != METHOD_CONT &&
1220 ((sm->rxFailure &&
1221 sm->decision != DECISION_UNCOND_SUCC) ||
1222 (sm->rxSuccess && sm->decision == DECISION_FAIL &&
1223 (sm->selectedMethod != EAP_TYPE_LEAP ||
1224 sm->methodState != METHOD_MAY_CONT))) &&
1225 (sm->reqId == sm->lastId ||
1226 eap_success_workaround(sm, sm->reqId, sm->lastId)))
1228 else if (sm->rxReq && duplicate)
1230 else if (sm->rxReq && !duplicate &&
1231 sm->reqMethod == EAP_TYPE_NOTIFICATION &&
1232 sm->allowNotifications)
1234 else if (sm->rxReq && !duplicate &&
1235 sm->selectedMethod == EAP_TYPE_NONE &&
1236 sm->reqMethod == EAP_TYPE_IDENTITY)
1238 else if (sm->rxReq && !duplicate &&
1239 sm->selectedMethod == EAP_TYPE_NONE &&
1240 sm->reqMethod != EAP_TYPE_IDENTITY &&
1241 sm->reqMethod != EAP_TYPE_NOTIFICATION)
1243 else if (sm->rxReq && !duplicate &&
1244 sm->reqMethod == sm->selectedMethod &&
1245 sm->methodState != METHOD_DONE)
1247 else if (sm->selectedMethod == EAP_TYPE_LEAP &&
1248 (sm->rxSuccess || sm->rxResp))
1250 else if (sm->reauthInit)
1257 static void eap_peer_sm_step_local(struct eap_sm *sm)
1259 switch (sm->EAP_state) {
1264 if (eapol_get_bool(sm, EAPOL_portEnabled) &&
1265 !sm->force_disabled)
1269 eap_peer_sm_step_idle(sm);
1272 eap_peer_sm_step_received(sm);
1275 if (sm->selectedMethod == sm->reqMethod)
1289 if (sm->ignore)
1291 else if (sm->methodState == METHOD_DONE &&
1292 sm->decision == DECISION_FAIL && !sm->eapRespData)
1323 if (eapol_get_bool(sm, EAPOL_eapRestart) &&
1324 eapol_get_bool(sm, EAPOL_portEnabled))
1326 else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
1328 else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
1337 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
1338 wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
1341 sm->num_rounds++;
1346 eap_peer_sm_step_local(sm);
1351 static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
1354 if (!eap_allowed_method(sm, vendor, method)) {
1368 struct eap_sm *sm, int id, const struct eap_method *methods,
1387 if (sm->reqVendor == m->vendor &&
1388 sm->reqVendorMethod == m->method)
1390 if (eap_allowed_method(sm, m->vendor, m->method)) {
1414 static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id)
1423 "vendor=%u method=%u not allowed)", sm->reqMethod,
1424 sm->reqVendor, sm->reqVendorMethod);
1428 if (sm->reqMethod == EAP_TYPE_EXPANDED)
1429 return eap_sm_build_expanded_nak(sm, id, methods, count);
1440 if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
1442 if (eap_allowed_method(sm, m->vendor, m->method)) {
1463 static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
1468 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
1470 eap_notify_status(sm, "started", "");
1515 static int eap_sm_imsi_identity(struct eap_sm *sm,
1525 if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
1538 mnc_len = scard_get_mnc_len(sm->scard_ctx);
1547 if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
1595 static int eap_sm_set_scard_pin(struct eap_sm *sm,
1598 if (scard_set_pin(sm->scard_ctx, conf->pin)) {
1607 eap_sm_request_pin(sm);
1614 static int eap_sm_get_scard_identity(struct eap_sm *sm,
1617 if (eap_sm_set_scard_pin(sm, conf))
1620 return eap_sm_imsi_identity(sm, conf);
1628 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1637 struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
1639 struct eap_peer_config *config = eap_get_config(sm);
1650 if (sm->m && sm->m->get_identity &&
1651 (identity = sm->m->get_identity(sm, sm->eap_method_priv,
1670 if (eap_sm_get_scard_identity(sm, config) < 0)
1677 } else if (eap_sm_set_scard_pin(sm, config) < 0) {
1686 eap_sm_request_identity(sm);
1701 static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
1720 wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
1734 static void eap_peer_initiate(struct eap_sm *sm, const struct eap_hdr *hdr,
1774 if (eap_peer_erp_reauth_start(sm, hdr->identifier) == 0)
1781 eapol_set_bool(sm, EAPOL_eapTriggerStart, TRUE);
1785 void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, size_t len)
1825 if (seq != sm->erp_seq) {
1856 erp = eap_erp_get_key_nai(sm, nai);
1905 eapol_set_bool(sm, EAPOL_eapFail, TRUE);
1906 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
1907 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
1908 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
1910 sm->prev_failure = 1;
1917 eap_sm_free_key(sm);
1918 sm->eapKeyDataLen = 0;
1919 sm->eapKeyData = os_malloc(erp->rRK_len);
1920 if (!sm->eapKeyData)
1922 sm->eapKeyDataLen = erp->rRK_len;
1929 sm->eapKeyData, erp->rRK_len) < 0) {
1931 eap_sm_free_key(sm);
1935 sm->eapKeyData, sm->eapKeyDataLen);
1936 sm->eapKeyAvailable = TRUE;
1937 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
1938 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
1939 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
1940 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
1946 static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
1952 sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
1953 sm->reqId = 0;
1954 sm->reqMethod = EAP_TYPE_NONE;
1955 sm->reqVendor = EAP_VENDOR_IETF;
1956 sm->reqVendorMethod = EAP_TYPE_NONE;
1971 sm->reqId = hdr->identifier;
1973 if (sm->workaround) {
1976 sha1_vector(1, addr, &plen, sm->req_sha1);
1986 sm->rxReq = TRUE;
1988 sm->reqMethod = *pos++;
1989 if (sm->reqMethod == EAP_TYPE_EXPANDED) {
1996 sm->reqVendor = WPA_GET_BE24(pos);
1998 sm->reqVendorMethod = WPA_GET_BE32(pos);
2002 sm->reqId, sm->reqMethod, sm->reqVendor,
2003 sm->reqVendorMethod);
2006 if (sm->selectedMethod == EAP_TYPE_LEAP) {
2017 sm->rxResp = TRUE;
2019 sm->reqMethod = *pos;
2022 sm->reqMethod, sm->reqId);
2029 eap_notify_status(sm, "completion", "success");
2030 sm->rxSuccess = TRUE;
2034 eap_notify_status(sm, "completion", "failure");
2037 if (sm->m && sm->m->get_error_code) {
2040 error_code = sm->m->get_error_code(sm->eap_method_priv);
2042 eap_report_error(sm, error_code);
2044 sm->rxFailure = TRUE;
2047 eap_peer_initiate(sm, hdr, plen);
2050 eap_peer_finish(sm, hdr, plen);
2063 struct eap_sm *sm = ctx;
2068 eap_notify_status(sm, "remote certificate verification",
2070 if (sm->ext_cert_check) {
2071 sm->waiting_ext_cert_check = 1;
2072 eap_sm_request(sm, WPA_CTRL_REQ_EXT_CERT_CHECK,
2077 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
2083 eap_notify_status(sm, "remote certificate verification",
2087 if (!sm->eapol_cb->notify_cert)
2100 sm->eapol_cb->notify_cert(sm->eapol_ctx,
2109 eap_notify_status(sm, "local TLS alert",
2112 eap_notify_status(sm, "remote TLS alert",
2139 struct eap_sm *sm;
2142 sm = os_zalloc(sizeof(*sm));
2143 if (sm == NULL)
2145 sm->eapol_ctx = eapol_ctx;
2146 sm->eapol_cb = eapol_cb;
2147 sm->msg_ctx = msg_ctx;
2148 sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
2149 sm->wps = conf->wps;
2150 dl_list_init(&sm->erp_keys);
2161 tlsconf.cb_ctx = sm;
2163 sm->ssl_ctx = tls_init(&tlsconf);
2164 if (sm->ssl_ctx == NULL) {
2167 os_free(sm);
2171 sm->ssl_ctx2 = tls_init(&tlsconf);
2172 if (sm->ssl_ctx2 == NULL) {
2178 return sm;
2184 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2189 void eap_peer_sm_deinit(struct eap_sm *sm)
2191 if (sm == NULL)
2193 eap_deinit_prev_method(sm, "EAP deinit");
2194 eap_sm_abort(sm);
2195 if (sm->ssl_ctx2)
2196 tls_deinit(sm->ssl_ctx2);
2197 tls_deinit(sm->ssl_ctx);
2198 eap_peer_erp_free_keys(sm);
2199 os_free(sm);
2205 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2212 int eap_peer_sm_step(struct eap_sm *sm)
2216 sm->changed = FALSE;
2218 if (sm->changed)
2220 } while (sm->changed);
2227 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2232 void eap_sm_abort(struct eap_sm *sm)
2234 wpabuf_free(sm->lastRespData);
2235 sm->lastRespData = NULL;
2236 wpabuf_free(sm->eapRespData);
2237 sm->eapRespData = NULL;
2238 eap_sm_free_key(sm);
2239 os_free(sm->eapSessionId);
2240 sm->eapSessionId = NULL;
2245 eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
2326 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2337 int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
2341 if (sm == NULL)
2346 eap_sm_state_txt(sm->EAP_state));
2350 if (sm->selectedMethod != EAP_TYPE_NONE) {
2352 if (sm->m) {
2353 name = sm->m->name;
2357 sm->selectedMethod);
2365 sm->selectedMethod, name);
2370 if (sm->m && sm->m->get_status) {
2371 len += sm->m->get_status(sm, sm->eap_method_priv,
2383 sm->reqMethod,
2384 eap_sm_method_state_txt(sm->methodState),
2385 eap_sm_decision_txt(sm->decision),
2386 sm->ClientTimeout);
2397 static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
2405 if (sm == NULL)
2407 config = eap_get_config(sm);
2456 if (sm->eapol_cb->eap_param_needed)
2457 sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
2462 const char * eap_sm_get_method_name(struct eap_sm *sm)
2464 if (sm->m == NULL)
2466 return sm->m->name;
2472 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2479 void eap_sm_request_identity(struct eap_sm *sm)
2481 eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
2487 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2494 void eap_sm_request_password(struct eap_sm *sm)
2496 eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
2502 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2509 void eap_sm_request_new_password(struct eap_sm *sm)
2511 eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
2517 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2524 void eap_sm_request_pin(struct eap_sm *sm)
2526 eap_sm_request(sm, WPA_CTRL_REQ_EAP_PIN, NULL, 0);
2532 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2540 void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
2542 eap_sm_request(sm, WPA_CTRL_REQ_EAP_OTP, msg, msg_len);
2548 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2555 void eap_sm_request_passphrase(struct eap_sm *sm)
2557 eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSPHRASE, NULL, 0);
2563 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2566 void eap_sm_request_sim(struct eap_sm *sm, const char *req)
2568 eap_sm_request(sm, WPA_CTRL_REQ_SIM, req, os_strlen(req));
2574 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2579 void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
2581 struct eap_peer_config *config = eap_get_config(sm);
2591 eap_sm_request_identity(sm);
2593 eap_sm_request_password(sm);
2595 eap_sm_request_new_password(sm);
2597 eap_sm_request_otp(sm, NULL, 0);
2599 eap_sm_request_pin(sm);
2601 eap_sm_request_passphrase(sm);
2683 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2686 void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
2688 sm->fast_reauth = enabled;
2694 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2697 void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
2699 sm->workaround = workaround;
2705 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2713 struct eap_peer_config * eap_get_config(struct eap_sm *sm)
2715 return sm->eapol_cb->get_config(sm->eapol_ctx);
2721 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2725 const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
2727 struct eap_peer_config *config = eap_get_config(sm);
2735 static int eap_get_ext_password(struct eap_sm *sm,
2748 ext_password_free(sm->ext_pw_buf);
2749 sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
2752 return sm->ext_pw_buf == NULL ? -1 : 0;
2758 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2762 const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
2764 struct eap_peer_config *config = eap_get_config(sm);
2769 if (eap_get_ext_password(sm, config) < 0)
2771 *len = wpabuf_len(sm->ext_pw_buf);
2772 return wpabuf_head(sm->ext_pw_buf);
2782 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2789 const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
2791 struct eap_peer_config *config = eap_get_config(sm);
2796 if (eap_get_ext_password(sm, config) < 0)
2800 *len = wpabuf_len(sm->ext_pw_buf);
2801 return wpabuf_head(sm->ext_pw_buf);
2813 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2817 const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
2819 struct eap_peer_config *config = eap_get_config(sm);
2829 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2833 const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
2835 struct eap_peer_config *config = eap_get_config(sm);
2845 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2851 void eap_clear_config_otp(struct eap_sm *sm)
2853 struct eap_peer_config *config = eap_get_config(sm);
2865 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2868 const char * eap_get_config_phase1(struct eap_sm *sm)
2870 struct eap_peer_config *config = eap_get_config(sm);
2879 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2882 const char * eap_get_config_phase2(struct eap_sm *sm)
2884 struct eap_peer_config *config = eap_get_config(sm);
2891 int eap_get_config_fragment_size(struct eap_sm *sm)
2893 struct eap_peer_config *config = eap_get_config(sm);
2902 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2905 int eap_key_available(struct eap_sm *sm)
2907 return sm ? sm->eapKeyAvailable : 0;
2913 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2920 void eap_notify_success(struct eap_sm *sm)
2922 if (sm) {
2923 sm->decision = DECISION_COND_SUCC;
2924 sm->EAP_state = EAP_SUCCESS;
2931 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2936 void eap_notify_lower_layer_success(struct eap_sm *sm)
2938 if (sm == NULL)
2941 if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
2942 sm->decision == DECISION_FAIL ||
2943 (sm->methodState != METHOD_MAY_CONT &&
2944 sm->methodState != METHOD_DONE))
2947 if (sm->eapKeyData != NULL)
2948 sm->eapKeyAvailable = TRUE;
2949 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
2950 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
2958 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2966 const u8 * eap_get_eapSessionId(struct eap_sm *sm, size_t *len)
2968 if (sm == NULL || sm->eapSessionId == NULL) {
2973 *len = sm->eapSessionIdLen;
2974 return sm->eapSessionId;
2980 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2989 const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
2991 if (sm == NULL || sm->eapKeyData == NULL) {
2996 *len = sm->eapKeyDataLen;
2997 return sm->eapKeyData;
3003 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3011 struct wpabuf * eap_get_eapRespData(struct eap_sm *sm)
3015 if (sm == NULL || sm->eapRespData == NULL)
3018 resp = sm->eapRespData;
3019 sm->eapRespData = NULL;
3027 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3033 void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
3035 if (sm)
3036 sm->scard_ctx = ctx;
3042 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3048 void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
3051 sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
3058 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3062 const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
3066 return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
3075 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3081 void eap_set_force_disabled(struct eap_sm *sm, int disabled)
3083 sm->force_disabled = disabled;
3089 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3092 void eap_set_external_sim(struct eap_sm *sm, int external_sim)
3094 sm->external_sim = external_sim;
3100 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3107 void eap_notify_pending(struct eap_sm *sm)
3109 sm->eapol_cb->notify_pending(sm->eapol_ctx);
3115 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3117 void eap_invalidate_cached_session(struct eap_sm *sm)
3119 if (sm)
3120 eap_deinit_prev_method(sm, "invalidate");
3150 void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext)
3152 ext_password_free(sm->ext_pw_buf);
3153 sm->ext_pw_buf = NULL;
3154 sm->ext_pw = ext;
3160 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
3164 void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len)
3166 if (sm->eapol_cb->set_anon_id)
3167 sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
3171 int eap_peer_was_failure_expected(struct eap_sm *sm)
3173 return sm->expected_failure;