📄 eap.c
字号:
sm->eapReqData = eap_sm_buildFailure(sm, sm->currentId, &sm->eapReqDataLen); if (sm->eapReqData) { eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen); free(sm->eapReqData); sm->eapReqData = NULL; sm->eapReqDataLen = 0; } free(sm->lastReqData); sm->lastReqData = NULL; sm->lastReqDataLen = 0; eapol_set_bool(sm, EAPOL_eapFail, TRUE);}SM_STATE(EAP, SUCCESS){ SM_ENTRY(EAP, SUCCESS); free(sm->eapReqData); sm->eapReqData = eap_sm_buildSuccess(sm, sm->currentId, &sm->eapReqDataLen); if (sm->eapReqData) { eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen); free(sm->eapReqData); sm->eapReqData = NULL; sm->eapReqDataLen = 0; } free(sm->lastReqData); sm->lastReqData = NULL; sm->lastReqDataLen = 0; if (sm->eapKeyData) { eapol_set_eapKeyData(sm, sm->eapKeyData, sm->eapKeyDataLen); } eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);}SM_STEP(EAP){ if (eapol_get_bool(sm, EAPOL_eapRestart) && eapol_get_bool(sm, EAPOL_portEnabled)) SM_ENTER_GLOBAL(EAP, INITIALIZE); else if (!eapol_get_bool(sm, EAPOL_portEnabled)) SM_ENTER_GLOBAL(EAP, DISABLED); else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { wpa_printf(MSG_DEBUG, "EAP: more than %d " "authentication rounds - abort", EAP_MAX_AUTH_ROUNDS); sm->num_rounds++; SM_ENTER_GLOBAL(EAP, FAILURE); } } else switch (sm->EAP_state) { case EAP_INITIALIZE: if (sm->backend_auth) { if (!sm->rxResp) SM_ENTER(EAP, SELECT_ACTION); else if (sm->rxResp && (sm->respMethod == EAP_TYPE_NAK || sm->respMethod == EAP_TYPE_EXPANDED_NAK)) SM_ENTER(EAP, NAK); else SM_ENTER(EAP, PICK_UP_METHOD); } else { SM_ENTER(EAP, SELECT_ACTION); } break; case EAP_PICK_UP_METHOD: if (sm->currentMethod == EAP_TYPE_NONE) { SM_ENTER(EAP, SELECT_ACTION); } else { SM_ENTER(EAP, METHOD_RESPONSE); } break; case EAP_DISABLED: if (eapol_get_bool(sm, EAPOL_portEnabled)) SM_ENTER(EAP, INITIALIZE); break; case EAP_IDLE: if (sm->retransWhile == 0) SM_ENTER(EAP, RETRANSMIT); else if (eapol_get_bool(sm, EAPOL_eapResp)) SM_ENTER(EAP, RECEIVED); break; case EAP_RETRANSMIT: if (sm->retransCount > sm->MaxRetrans) SM_ENTER(EAP, TIMEOUT_FAILURE); else SM_ENTER(EAP, IDLE); break; case EAP_RECEIVED: if (sm->rxResp && (sm->respId == sm->currentId) && (sm->respMethod == EAP_TYPE_NAK || sm->respMethod == EAP_TYPE_EXPANDED_NAK) && (sm->methodState == METHOD_PROPOSED)) SM_ENTER(EAP, NAK); else if (sm->rxResp && (sm->respId == sm->currentId) && (sm->respMethod == sm->currentMethod)) SM_ENTER(EAP, INTEGRITY_CHECK); else SM_ENTER(EAP, DISCARD); break; case EAP_DISCARD: SM_ENTER(EAP, IDLE); break; case EAP_SEND_REQUEST: SM_ENTER(EAP, IDLE); break; case EAP_INTEGRITY_CHECK: if (sm->ignore) SM_ENTER(EAP, DISCARD); else SM_ENTER(EAP, METHOD_RESPONSE); break; case EAP_METHOD_REQUEST: SM_ENTER(EAP, SEND_REQUEST); break; case EAP_METHOD_RESPONSE: if (sm->methodState == METHOD_END) SM_ENTER(EAP, SELECT_ACTION); else SM_ENTER(EAP, METHOD_REQUEST); break; case EAP_PROPOSE_METHOD: SM_ENTER(EAP, METHOD_REQUEST); break; case EAP_NAK: SM_ENTER(EAP, SELECT_ACTION); break; case EAP_SELECT_ACTION: if (sm->decision == DECISION_FAILURE) SM_ENTER(EAP, FAILURE); else if (sm->decision == DECISION_SUCCESS) SM_ENTER(EAP, SUCCESS); else SM_ENTER(EAP, PROPOSE_METHOD); break; case EAP_TIMEOUT_FAILURE: break; case EAP_FAILURE: break; case EAP_SUCCESS: break; }}static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, int eapSRTT, int eapRTTVAR, int methodTimeout){ /* For now, retransmission is done in EAPOL state machines, so make * sure EAP state machine does not end up trying to retransmit packets. */ return 1;}static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len){ struct eap_hdr *hdr; size_t plen; /* parse rxResp, respId, respMethod */ sm->rxResp = FALSE; sm->respId = -1; sm->respMethod = EAP_TYPE_NONE; if (resp == NULL || len < sizeof(*hdr)) return; hdr = (struct eap_hdr *) resp; plen = ntohs(hdr->length); if (plen > len) { wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " "(len=%lu plen=%lu)", (unsigned long) len, (unsigned long) plen); return; } sm->respId = hdr->identifier; if (hdr->code == EAP_CODE_RESPONSE) sm->rxResp = TRUE; if (len > sizeof(*hdr)) sm->respMethod = *((u8 *) (hdr + 1)); wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d " "respMethod=%d", sm->rxResp, sm->respId, sm->respMethod);}static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len){ struct eap_hdr *resp; wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); *len = sizeof(*resp); resp = malloc(*len); if (resp == NULL) return NULL; resp->code = EAP_CODE_SUCCESS; resp->identifier = id; resp->length = htons(*len); return (u8 *) resp;}static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len){ struct eap_hdr *resp; wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); *len = sizeof(*resp); resp = malloc(*len); if (resp == NULL) return NULL; resp->code = EAP_CODE_FAILURE; resp->identifier = id; resp->length = htons(*len); return (u8 *) resp;}static int eap_sm_nextId(struct eap_sm *sm, int id){ if (id < 0) { /* RFC 3748 Ch 4.1: recommended to initalize Identifier with a * random number */ id = rand() & 0xff; if (id != sm->lastId) return id; } return (id + 1) & 0xff;}void eap_sm_process_nak(struct eap_sm *sm, u8 *nak_list, size_t len){ int i, j; wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " "index %d)", sm->user_eap_method_index); wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", sm->user->methods, EAP_MAX_METHODS); wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer", nak_list, len); i = sm->user_eap_method_index; while (i < EAP_MAX_METHODS && sm->user->methods[i] != EAP_TYPE_NONE) { for (j = 0; j < len; j++) { if (nak_list[j] == sm->user->methods[i]) { break; } } if (j < len) { /* found */ i++; continue; } /* not found - remove from the list */ memmove(&sm->user->methods[i], &sm->user->methods[i + 1], EAP_MAX_METHODS - i - 1); sm->user->methods[EAP_MAX_METHODS - 1] = EAP_TYPE_NONE; } wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", sm->user->methods, EAP_MAX_METHODS);}static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len){ if (nak_list == NULL || sm == NULL || sm->user == NULL) return; if (sm->user->phase2) { wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user" " info was selected - reject"); sm->decision = DECISION_FAILURE; return; } eap_sm_process_nak(sm, nak_list, len);}static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm){ EapType next; /* In theory, there should be no problems with starting * re-authentication with something else than EAP-Request/Identity and * this does indeed work with wpa_supplicant. However, at least Funk * Supplicant seemed to ignore re-auth if it skipped * EAP-Request/Identity. * Re-auth sets currentId == -1, so that can be used here to select * whether Identity needs to be requested again. */ if (sm->identity == NULL || sm->currentId == -1) { next = EAP_TYPE_IDENTITY; sm->update_user = TRUE; } else if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && sm->user->methods[sm->user_eap_method_index] != EAP_TYPE_NONE) { next = sm->user->methods[sm->user_eap_method_index++]; } else { next = EAP_TYPE_NONE; } wpa_printf(MSG_DEBUG, "EAP: getNextMethod: type %d", next); return next;}static int eap_sm_Policy_getDecision(struct eap_sm *sm){ if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY && sm->m->isSuccess(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " "SUCCESS"); sm->update_user = TRUE; return DECISION_SUCCESS; } if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) && !sm->m->isSuccess(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " "FAILURE"); sm->update_user = TRUE; return DECISION_FAILURE; } if ((sm->user == NULL || sm->update_user) && sm->identity) { if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) { wpa_printf(MSG_DEBUG, "EAP: getDecision: user not " "found from database -> FAILURE"); return DECISION_FAILURE; } sm->update_user = FALSE; } if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && sm->user->methods[sm->user_eap_method_index] != EAP_TYPE_NONE) { wpa_printf(MSG_DEBUG, "EAP: getDecision: another method " "available -> CONTINUE"); return DECISION_CONTINUE; } if (sm->identity == NULL || sm->currentId == -1) { wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known " "yet -> CONTINUE"); return DECISION_CONTINUE; } wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> " "FAILURE"); return DECISION_FAILURE;}static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method){ return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;}int eap_sm_step(struct eap_sm *sm){ int res = 0; do { sm->changed = FALSE; SM_STEP_RUN(EAP); if (sm->changed) res = 1; } while (sm->changed); return res;}u8 eap_get_type(const char *name){ int i; for (i = 0; i < NUM_EAP_METHODS; i++) { if (strcmp(eap_methods[i]->name, name) == 0) return eap_methods[i]->method; } return EAP_TYPE_NONE;}void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData, size_t eapRespDataLen){ if (sm == NULL) return; free(sm->eapRespData); sm->eapRespData = malloc(eapRespDataLen); if (sm->eapRespData == NULL) return; memcpy(sm->eapRespData, eapRespData, eapRespDataLen); sm->eapRespDataLen = eapRespDataLen; wpa_hexdump(MSG_MSGDUMP, "EAP: EAP-Response received", eapRespData, eapRespDataLen);}static void eap_user_free(struct eap_user *user){ if (user == NULL) return; free(user->password); user->password = NULL; free(user);}struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, struct eap_config *eap_conf){ struct eap_sm *sm; sm = malloc(sizeof(*sm)); if (sm == NULL) return NULL; memset(sm, 0, sizeof(*sm)); sm->eapol_ctx = eapol_ctx; sm->eapol_cb = eapol_cb; sm->MaxRetrans = 10; sm->ssl_ctx = eap_conf->ssl_ctx; sm->eap_sim_db_priv = eap_conf->eap_sim_db_priv; sm->backend_auth = eap_conf->backend_auth; wpa_printf(MSG_DEBUG, "EAP: State machine created"); return sm;}void eap_sm_deinit(struct eap_sm *sm){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAP: State machine removed"); if (sm->m && sm->eap_method_priv) sm->m->reset(sm, sm->eap_method_priv); free(sm->eapReqData); free(sm->eapKeyData); free(sm->lastReqData); free(sm->eapRespData); free(sm->identity); eap_user_free(sm->user); free(sm);}void eap_sm_notify_cached(struct eap_sm *sm){ if (sm == NULL) return; sm->EAP_state = EAP_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -