?? eap_sim.c
字號:
/* * hostapd / EAP-SIM (RFC 4186) * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "eap_server/eap_i.h"#include "eap_common/eap_sim_common.h"#include "eap_server/eap_sim_db.h"struct eap_sim_data { u8 mk[EAP_SIM_MK_LEN]; u8 nonce_mt[EAP_SIM_NONCE_MT_LEN]; u8 nonce_s[EAP_SIM_NONCE_S_LEN]; u8 k_aut[EAP_SIM_K_AUT_LEN]; u8 k_encr[EAP_SIM_K_ENCR_LEN]; u8 msk[EAP_SIM_KEYING_DATA_LEN]; u8 emsk[EAP_EMSK_LEN]; u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; int num_chal; enum { START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE } state; char *next_pseudonym; char *next_reauth_id; u16 counter; struct eap_sim_reauth *reauth; u16 notification; int use_result_ind;};static const char * eap_sim_state_txt(int state){ switch (state) { case START: return "START"; case CHALLENGE: return "CHALLENGE"; case REAUTH: return "REAUTH"; case SUCCESS: return "SUCCESS"; case FAILURE: return "FAILURE"; case NOTIFICATION: return "NOTIFICATION"; default: return "Unknown?!"; }}static void eap_sim_state(struct eap_sim_data *data, int state){ wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", eap_sim_state_txt(data->state), eap_sim_state_txt(state)); data->state = state;}static void * eap_sim_init(struct eap_sm *sm){ struct eap_sim_data *data; if (sm->eap_sim_db_priv == NULL) { wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = START; return data;}static void eap_sim_reset(struct eap_sm *sm, void *priv){ struct eap_sim_data *data = priv; os_free(data->next_pseudonym); os_free(data->next_reauth_id); os_free(data);}static struct wpabuf * eap_sim_build_start(struct eap_sm *sm, struct eap_sim_data *data, u8 id){ struct eap_sim_msg *msg; u8 ver[2]; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, sm->identity_len)) { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); } else { /* * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is * ignored and the SIM/Start is used to request the identity. */ wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); ver[0] = 0; ver[1] = EAP_SIM_VERSION; eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), ver, sizeof(ver)); return eap_sim_msg_finish(msg, NULL, NULL, 0);}static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, struct eap_sim_msg *msg, u16 counter, const u8 *nonce_s){ os_free(data->next_pseudonym); data->next_pseudonym = eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); os_free(data->next_reauth_id); if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { data->next_reauth_id = eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0); } else { wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " "count exceeded - force full authentication"); data->next_reauth_id = NULL; } if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && counter == 0 && nonce_s == NULL) return 0; wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); if (counter > 0) { wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); } if (nonce_s) { wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, EAP_SIM_NONCE_S_LEN); } if (data->next_pseudonym) { wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", data->next_pseudonym); eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, os_strlen(data->next_pseudonym), (u8 *) data->next_pseudonym, os_strlen(data->next_pseudonym)); } if (data->next_reauth_id) { wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", data->next_reauth_id); eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, os_strlen(data->next_reauth_id), (u8 *) data->next_reauth_id, os_strlen(data->next_reauth_id)); } if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " "AT_ENCR_DATA"); return -1; } return 0;}static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, struct eap_sim_data *data, u8 id){ struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_RAND"); eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, data->num_chal * GSM_RAND_LEN); if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { eap_sim_msg_free(msg); return NULL; } if (sm->eap_sim_aka_result_ind) { wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, EAP_SIM_NONCE_MT_LEN);}static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, struct eap_sim_data *data, u8 id){ struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN)) return NULL; wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", data->nonce_s, EAP_SIM_NONCE_S_LEN); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, data->emsk); eap_sim_derive_keys_reauth(data->counter, sm->identity, sm->identity_len, data->nonce_s, data->mk, data->msk, data->emsk); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION); if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { eap_sim_msg_free(msg); return NULL; } if (sm->eap_sim_aka_result_ind) { wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);}static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, struct eap_sim_data *data, u8 id){ struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, NULL, 0); if (data->use_result_ind) { if (data->reauth) { wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", data->counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, NULL, 0); if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " "encrypt AT_ENCR_DATA"); eap_sim_msg_free(msg); return NULL; } } wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); } return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);}static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id){ struct eap_sim_data *data = priv; switch (data->state) { case START: return eap_sim_build_start(sm, data, id); case CHALLENGE: return eap_sim_build_challenge(sm, data, id); case REAUTH: return eap_sim_build_reauth(sm, data, id); case NOTIFICATION: return eap_sim_build_notification(sm, data, id); default: wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " "buildReq", data->state); break; } return NULL;}static Boolean eap_sim_check(struct eap_sm *sm, void *priv, struct wpabuf *respData){ struct eap_sim_data *data = priv; const u8 *pos; size_t len; u8 subtype; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); return TRUE; } subtype = *pos; if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) return FALSE; switch (data->state) { case START: if (subtype != EAP_SIM_SUBTYPE_START) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); return TRUE; } break; case CHALLENGE: if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); return TRUE; } break; case REAUTH: if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); return TRUE; } break; case NOTIFICATION: if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); return TRUE; } break; default: wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " "processing a response", data->state); return TRUE; } return FALSE;}static int eap_sim_supported_ver(struct eap_sim_data *data, int version){ return version == EAP_SIM_VERSION;}static void eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr){ const u8 *identity; size_t identity_len; u8 ver_list[2]; wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -