static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_aka_data *data = priv; const struct eap_hdr *req; u8 subtype, id; struct wpabuf *res; const u8 *pos; struct eap_sim_attrs attr; size_t len; wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); eap_sm_request_identity(sm); ret->ignore = TRUE; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, &len); if (pos == NULL || len < 1) { ret->ignore = TRUE; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = TRUE; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); pos += 2; /* Reserved */ if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 0)) { res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); goto done; } switch (subtype) { case EAP_AKA_SUBTYPE_IDENTITY: res = eap_aka_process_identity(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_CHALLENGE: res = eap_aka_process_challenge(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_NOTIFICATION: res = eap_aka_process_notification(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_REAUTHENTICATION: res = eap_aka_process_reauthentication(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_CLIENT_ERROR: wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); break; default: wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); break; } done: if (data->state == FAILURE) { ret->decision = DECISION_FAIL; ret->methodState = METHOD_DONE; } else if (data->state == SUCCESS) { ret->decision = data->use_result_ind ? DECISION_UNCOND_SUCC : DECISION_COND_SUCC; /* * It is possible for the server to reply with AKA * Notification, so we must allow the method to continue and * not only accept EAP-Success at this point. */ ret->methodState = data->use_result_ind ? METHOD_DONE : METHOD_MAY_CONT; } else if (data->state == RESULT_FAILURE) ret->methodState = METHOD_CONT; else if (data->state == RESULT_SUCCESS) ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } return res; }
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, data->eap_method, 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, data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 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; } }