📄 eap_aka.c
字号:
sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) { identity = sm->identity; identity_len = sm->identity_len; } else { identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, sm->identity_len, &identity_len); if (identity == NULL) { data->reauth = eap_sim_db_get_reauth_entry( sm->eap_sim_db_priv, sm->identity, sm->identity_len); if (data->reauth) { wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast " "re-authentication"); identity = data->reauth->identity; identity_len = data->reauth->identity_len; data->counter = data->reauth->counter; os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN); } } } if (identity == NULL || eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, sm->identity_len) < 0) { if (before_identity) { wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name " "not known - send AKA-Identity request"); eap_aka_state(data, IDENTITY); return; } else { wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the " "permanent user name is known; try to use " "it"); /* eap_sim_db_get_aka_auth() will report failure, if * this identity is not known. */ } } wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity", identity, identity_len); if (!after_reauth && data->reauth) { eap_aka_state(data, REAUTH); return; } res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity, identity_len, data->rand, data->autn, data->ik, data->ck, data->res, &data->res_len, sm); if (res == EAP_SIM_DB_PENDING) { wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " "not yet available - pending request"); sm->method_pending = METHOD_PENDING_WAIT; return; } data->reauth = NULL; data->counter = 0; /* reset re-auth counter since this is full auth */ if (res != 0) { wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA " "authentication data for the peer"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (sm->method_pending == METHOD_PENDING_WAIT) { wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " "available - abort pending wait"); sm->method_pending = METHOD_PENDING_NONE; } identity_len = sm->identity_len; while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " "character from identity"); identity_len--; } wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", sm->identity, identity_len); eap_aka_derive_mk(sm->identity, identity_len, data->ik, data->ck, data->mk); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, data->emsk); eap_aka_state(data, CHALLENGE);}static void eap_aka_process_identity(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); if (attr->mac || attr->iv || attr->encr_data) { wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " "received in EAP-Response/AKA-Identity"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (attr->identity) { os_free(sm->identity); sm->identity = os_malloc(attr->identity_len); if (sm->identity) { os_memcpy(sm->identity, attr->identity, attr->identity_len); sm->identity_len = attr->identity_len; } } eap_aka_determine_identity(sm, data, 0, 0); if (eap_get_id(respData) == data->pending_id) { data->pending_id = -1; eap_aka_add_id_msg(data, respData); }}static void eap_aka_process_challenge(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ const u8 *identity; size_t identity_len; wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); if (attr->checkcode && eap_aka_verify_checkcode(data, attr->checkcode, attr->checkcode_len)) { wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " "message"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (attr->mac == NULL || eap_sim_verify_mac(data->k_aut, respData, attr->mac, NULL, 0)) { wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " "did not include valid AT_MAC"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (attr->res == NULL || attr->res_len != data->res_len || os_memcmp(attr->res, data->res, data->res_len) != 0) { wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " "include valid AT_RES"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the " "correct AT_MAC"); if (sm->eap_sim_aka_result_ind && attr->result_ind) { data->use_result_ind = 1; data->notification = EAP_SIM_SUCCESS; eap_aka_state(data, NOTIFICATION); } else eap_aka_state(data, SUCCESS); identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, sm->identity_len, &identity_len); if (identity == NULL) { identity = sm->identity; identity_len = sm->identity_len; } if (data->next_pseudonym) { eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, identity_len, data->next_pseudonym); data->next_pseudonym = NULL; } if (data->next_reauth_id) { eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, identity_len, data->next_reauth_id, data->counter + 1, data->mk); data->next_reauth_id = NULL; }}static void eap_aka_process_sync_failure(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); if (attr->auts == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " "message did not include valid AT_AUTS"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } /* Avoid re-reporting AUTS when processing pending EAP packet by * maintaining a local flag stating whether this AUTS has already been * reported. */ if (!data->auts_reported && eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity, sm->identity_len, attr->auts, data->rand)) { wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } data->auts_reported = 1; /* Try again after resynchronization */ eap_aka_determine_identity(sm, data, 0, 0);}static void eap_aka_process_reauth(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ struct eap_sim_attrs eattr; u8 *decrypted = NULL; const u8 *identity, *id2; size_t identity_len, id2_len; wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); if (attr->mac == NULL || eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, EAP_SIM_NONCE_S_LEN)) { wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " "did not include valid AT_MAC"); goto fail; } if (attr->encr_data == NULL || attr->iv == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " "message did not include encrypted data"); goto fail; } decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, attr->encr_data_len, attr->iv, &eattr, 0); if (decrypted == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " "data from reauthentication message"); goto fail; } if (eattr.counter != data->counter) { wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " "used incorrect counter %u, expected %u", eattr.counter, data->counter); goto fail; } os_free(decrypted); decrypted = NULL; wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " "the correct AT_MAC"); if (eattr.counter_too_small) { wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " "included AT_COUNTER_TOO_SMALL - starting full " "authentication"); eap_aka_determine_identity(sm, data, 0, 1); return; } if (sm->eap_sim_aka_result_ind && attr->result_ind) { data->use_result_ind = 1; data->notification = EAP_SIM_SUCCESS; eap_aka_state(data, NOTIFICATION); } else eap_aka_state(data, SUCCESS); if (data->reauth) { identity = data->reauth->identity; identity_len = data->reauth->identity_len; } else { identity = sm->identity; identity_len = sm->identity_len; } id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, identity_len, &id2_len); if (id2) { identity = id2; identity_len = id2_len; } if (data->next_pseudonym) { eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, identity_len, data->next_pseudonym); data->next_pseudonym = NULL; } if (data->next_reauth_id) { eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, identity_len, data->next_reauth_id, data->counter + 1, data->mk); data->next_reauth_id = NULL; } else { eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); data->reauth = NULL; } return;fail: data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); data->reauth = NULL; os_free(decrypted);}static void eap_aka_process_client_error(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", attr->client_error_code); if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) eap_aka_state(data, SUCCESS); else eap_aka_state(data, FAILURE);}static void eap_aka_process_authentication_reject( struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication"); eap_aka_state(data, FAILURE);}static void eap_aka_process_notification(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) eap_aka_state(data, SUCCESS); else eap_aka_state(data, FAILURE);}static void eap_aka_process(struct eap_sm *sm, void *priv, struct wpabuf *respData){ struct eap_aka_data *data = priv; const u8 *pos, *end; u8 subtype; size_t len; struct eap_sim_attrs attr; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_AKA, respData, &len); if (pos == NULL || len < 3) return; end = pos + len; subtype = *pos; pos += 3; if (eap_aka_subtype_ok(data, subtype)) { wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " "EAP-AKA Subtype in EAP Response"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (eap_sim_parse_attr(pos, end, &attr, 1, 0)) { wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { eap_aka_process_client_error(sm, data, respData, &attr); return; } if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { eap_aka_process_authentication_reject(sm, data, respData, &attr); return; } switch (data->state) { case IDENTITY: eap_aka_process_identity(sm, data, respData, &attr); break; case CHALLENGE: if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { eap_aka_process_sync_failure(sm, data, respData, &attr); } else { eap_aka_process_challenge(sm, data, respData, &attr); } break; case REAUTH: eap_aka_process_reauth(sm, data, respData, &attr); break; case NOTIFICATION: eap_aka_process_notification(sm, data, respData, &attr); break; default: wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " "process", data->state); break; }}static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv){ struct eap_aka_data *data = priv; return data->state == SUCCESS || data->state == FAILURE;}static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len){ struct eap_aka_data *data = priv; u8 *key; if (data->state != SUCCESS) return NULL; key = os_malloc(EAP_SIM_KEYING_DATA_LEN); if (key == NULL) return NULL; os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); *len = EAP_SIM_KEYING_DATA_LEN; return key;}static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len){ struct eap_aka_data *data = priv; u8 *key; if (data->state != SUCCESS) return NULL; key = os_malloc(EAP_EMSK_LEN); if (key == NULL) return NULL; os_memcpy(key, data->emsk, EAP_EMSK_LEN); *len = EAP_EMSK_LEN; return key;}static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv){ struct eap_aka_data *data = priv; return data->state == SUCCESS;}int eap_server_aka_register(void){ struct eap_method *eap; int ret; eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); if (eap == NULL) return -1; eap->init = eap_aka_init; eap->reset = eap_aka_reset; eap->buildReq = eap_aka_buildReq; eap->check = eap_aka_check; eap->process = eap_aka_process; eap->isDone = eap_aka_isDone; eap->getKey = eap_aka_getKey; eap->isSuccess = eap_aka_isSuccess; eap->get_emsk = eap_aka_get_emsk; ret = eap_server_method_register(eap); if (ret) eap_server_method_free(eap); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -