📄 eap.c
字号:
(unsigned long) plen); return; } sm->respVendor = WPA_GET_BE24(pos); pos += 3; sm->respVendorMethod = WPA_GET_BE32(pos); } } wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d " "respMethod=%u respVendor=%u respVendorMethod=%u", sm->rxResp, sm->respId, sm->respMethod, sm->respVendor, sm->respVendorMethod);}static int eap_sm_getId(const struct wpabuf *data){ const struct eap_hdr *hdr; if (data == NULL || wpabuf_len(data) < sizeof(*hdr)) return -1; hdr = wpabuf_head(data); wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier); return hdr->identifier;}static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id){ struct wpabuf *msg; struct eap_hdr *resp; wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); msg = wpabuf_alloc(sizeof(*resp)); if (msg == NULL) return NULL; resp = wpabuf_put(msg, sizeof(*resp)); resp->code = EAP_CODE_SUCCESS; resp->identifier = id; resp->length = host_to_be16(sizeof(*resp)); return msg;}static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id){ struct wpabuf *msg; struct eap_hdr *resp; wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); msg = wpabuf_alloc(sizeof(*resp)); if (msg == NULL) return NULL; resp = wpabuf_put(msg, sizeof(*resp)); resp->code = EAP_CODE_FAILURE; resp->identifier = id; resp->length = host_to_be16(sizeof(*resp)); return msg;}static int eap_sm_nextId(struct eap_sm *sm, int id){ if (id < 0) { /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a * random number */ id = rand() & 0xff; if (id != sm->lastId) return id; } return (id + 1) & 0xff;}/** * eap_sm_process_nak - Process EAP-Response/Nak * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * @nak_list: Nak list (allowed methods) from the supplicant * @len: Length of nak_list in bytes * * This function is called when EAP-Response/Nak is received from the * supplicant. This can happen for both phase 1 and phase 2 authentications. */void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len){ int i; size_t j; if (sm->user == NULL) return; wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " "index %d)", sm->user_eap_method_index); wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", (u8 *) sm->user->methods, EAP_MAX_METHODS * sizeof(sm->user->methods[0])); 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].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_NONE)) { if (sm->user->methods[i].vendor != EAP_VENDOR_IETF) goto not_found; for (j = 0; j < len; j++) { if (nak_list[j] == sm->user->methods[i].method) { break; } } if (j < len) { /* found */ i++; continue; } not_found: /* not found - remove from the list */ os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1], (EAP_MAX_METHODS - i - 1) * sizeof(sm->user->methods[0])); sm->user->methods[EAP_MAX_METHODS - 1].vendor = EAP_VENDOR_IETF; sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE; } wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", (u8 *) sm->user->methods, EAP_MAX_METHODS * sizeof(sm->user->methods[0]));}static void eap_sm_Policy_update(struct eap_sm *sm, const 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, int *vendor){ EapType next; int idx = sm->user_eap_method_index; /* 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) { *vendor = EAP_VENDOR_IETF; next = EAP_TYPE_IDENTITY; sm->update_user = TRUE; } else if (sm->user && idx < EAP_MAX_METHODS && (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || sm->user->methods[idx].method != EAP_TYPE_NONE)) { *vendor = sm->user->methods[idx].vendor; next = sm->user->methods[idx].method; sm->user_eap_method_index++; } else { *vendor = EAP_VENDOR_IETF; next = EAP_TYPE_NONE; } wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d", *vendor, next); return next;}static int eap_sm_Policy_getDecision(struct eap_sm *sm){ if (!sm->eap_server && sm->identity) { wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH"); return DECISION_PASSTHROUGH; } 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].vendor != EAP_VENDOR_IETF || sm->user->methods[sm->user_eap_method_index].method != 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;}/** * eap_server_sm_step - Step EAP server state machine * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * Returns: 1 if EAP state was changed or 0 if not * * This function advances EAP state machine to a new state to match with the * current variables. This should be called whenever variables used by the EAP * state machine have changed. */int eap_server_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;}static void eap_user_free(struct eap_user *user){ if (user == NULL) return; os_free(user->password); user->password = NULL; os_free(user);}/** * eap_server_sm_init - Allocate and initialize EAP server state machine * @eapol_ctx: Context data to be used with eapol_cb calls * @eapol_cb: Pointer to EAPOL callback functions * @conf: EAP configuration * Returns: Pointer to the allocated EAP state machine or %NULL on failure * * This function allocates and initializes an EAP state machine. */struct eap_sm * eap_server_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, struct eap_config *conf){ struct eap_sm *sm; sm = os_zalloc(sizeof(*sm)); if (sm == NULL) return NULL; sm->eapol_ctx = eapol_ctx; sm->eapol_cb = eapol_cb; sm->MaxRetrans = 10; sm->ssl_ctx = conf->ssl_ctx; sm->eap_sim_db_priv = conf->eap_sim_db_priv; sm->backend_auth = conf->backend_auth; sm->eap_server = conf->eap_server; if (conf->pac_opaque_encr_key) { sm->pac_opaque_encr_key = os_malloc(16); if (sm->pac_opaque_encr_key) { os_memcpy(sm->pac_opaque_encr_key, conf->pac_opaque_encr_key, 16); } } if (conf->eap_fast_a_id) sm->eap_fast_a_id = os_strdup(conf->eap_fast_a_id); sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; sm->tnc = conf->tnc; wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); return sm;}/** * eap_server_sm_deinit - Deinitialize and free an EAP server state machine * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * * This function deinitializes EAP state machine and frees all allocated * resources. */void eap_server_sm_deinit(struct eap_sm *sm){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAP: Server state machine removed"); if (sm->m && sm->eap_method_priv) sm->m->reset(sm, sm->eap_method_priv); wpabuf_free(sm->eap_if.eapReqData); os_free(sm->eap_if.eapKeyData); os_free(sm->lastReqData); wpabuf_free(sm->eap_if.eapRespData); os_free(sm->identity); os_free(sm->pac_opaque_encr_key); os_free(sm->eap_fast_a_id); wpabuf_free(sm->eap_if.aaaEapReqData); wpabuf_free(sm->eap_if.aaaEapRespData); os_free(sm->eap_if.aaaEapKeyData); eap_user_free(sm->user); os_free(sm);}/** * eap_sm_notify_cached - Notify EAP state machine of cached PMK * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * * This function is called when PMKSA caching is used to skip EAP * authentication. */void eap_sm_notify_cached(struct eap_sm *sm){ if (sm == NULL) return; sm->EAP_state = EAP_SUCCESS;}/** * eap_sm_pending_cb - EAP state machine callback for a pending EAP request * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * * This function is called when data for a pending EAP-Request is received. */void eap_sm_pending_cb(struct eap_sm *sm){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received"); if (sm->method_pending == METHOD_PENDING_WAIT) sm->method_pending = METHOD_PENDING_CONT;}/** * eap_sm_method_pending - Query whether EAP method is waiting for pending data * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * Returns: 1 if method is waiting for pending data or 0 if not */int eap_sm_method_pending(struct eap_sm *sm){ if (sm == NULL) return 0; return sm->method_pending == METHOD_PENDING_WAIT;}/** * eap_get_identity - Get the user identity (from EAP-Response/Identity) * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * @len: Buffer for returning identity length * Returns: Pointer to the user identity or %NULL if not available */const u8 * eap_get_identity(struct eap_sm *sm, size_t *len){ *len = sm->identity_len; return sm->identity;}/** * eap_get_interface - Get pointer to EAP-EAPOL interface data * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * Returns: Pointer to the EAP-EAPOL interface data */struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm){ return &sm->eap_if;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -