EAP-SIM/AKA server: Allow method specific identity exchange to be skipped
While the EAP-SIM/AKA RFCs recommend against doing this, some deployed authentication servers use the identity from the EAP-Response/Identity directly without using an EAP method specific indication (AT_IDENTITY). Having a capability to configure hostapd EAP server to behave in this manner helps in increasing testing coverage for the EAP peer implementation. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
40af6560ba
commit
c6268e103f
4 changed files with 61 additions and 6 deletions
|
@ -1465,6 +1465,14 @@ eap_server=0
|
||||||
# 1 = use pseudonyms, but not fast reauthentication
|
# 1 = use pseudonyms, but not fast reauthentication
|
||||||
# 2 = do not use pseudonyms, but use fast reauthentication
|
# 2 = do not use pseudonyms, but use fast reauthentication
|
||||||
# 3 = use pseudonyms and use fast reauthentication (default)
|
# 3 = use pseudonyms and use fast reauthentication (default)
|
||||||
|
# 4 = do not use pseudonyms or fast reauthentication and allow
|
||||||
|
# EAP-Response/Identity to be used without method specific identity exchange
|
||||||
|
# 5 = use pseudonyms, but not fast reauthentication and allow
|
||||||
|
# EAP-Response/Identity to be used without method specific identity exchange
|
||||||
|
# 6 = do not use pseudonyms, but use fast reauthentication and allow
|
||||||
|
# EAP-Response/Identity to be used without method specific identity exchange
|
||||||
|
# 7 = use pseudonyms and use fast reauthentication and allow
|
||||||
|
# EAP-Response/Identity to be used without method specific identity exchange
|
||||||
#eap_sim_id=3
|
#eap_sim_id=3
|
||||||
|
|
||||||
# IMSI privacy key (PEM encoded RSA 2048-bit private key) for decrypting
|
# IMSI privacy key (PEM encoded RSA 2048-bit private key) for decrypting
|
||||||
|
|
|
@ -160,6 +160,7 @@ struct eap_sm {
|
||||||
size_t identity_len;
|
size_t identity_len;
|
||||||
char *serial_num;
|
char *serial_num;
|
||||||
char imsi[20];
|
char imsi[20];
|
||||||
|
char sim_aka_permanent[20];
|
||||||
/* Whether Phase 2 method should validate identity match */
|
/* Whether Phase 2 method should validate identity match */
|
||||||
int require_identity_match;
|
int require_identity_match;
|
||||||
int lastId; /* Identifier used in the last EAP-Packet */
|
int lastId; /* Identifier used in the last EAP-Packet */
|
||||||
|
|
|
@ -134,10 +134,17 @@ static void eap_aka_check_identity(struct eap_sm *sm,
|
||||||
struct eap_aka_data *data)
|
struct eap_aka_data *data)
|
||||||
{
|
{
|
||||||
char *username;
|
char *username;
|
||||||
|
const u8 *identity = sm->identity;
|
||||||
|
size_t identity_len = sm->identity_len;
|
||||||
|
|
||||||
|
if (sm->sim_aka_permanent[0]) {
|
||||||
|
identity = (const u8 *) sm->sim_aka_permanent;
|
||||||
|
identity_len = os_strlen(sm->sim_aka_permanent);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if we already know the identity from EAP-Response/Identity */
|
/* Check if we already know the identity from EAP-Response/Identity */
|
||||||
|
|
||||||
username = sim_get_username(sm->identity, sm->identity_len);
|
username = sim_get_username(identity, identity_len);
|
||||||
if (username == NULL)
|
if (username == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -150,6 +157,16 @@ static void eap_aka_check_identity(struct eap_sm *sm,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sm->sim_aka_permanent[0] && data->state == IDENTITY) {
|
||||||
|
/* Skip AKA/Identity exchange since the permanent identity
|
||||||
|
* was recognized. */
|
||||||
|
os_free(username);
|
||||||
|
os_strlcpy(data->permanent, sm->sim_aka_permanent,
|
||||||
|
sizeof(data->permanent));
|
||||||
|
eap_aka_fullauth(sm, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
|
if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
|
||||||
username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
|
username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
|
||||||
(data->eap_method == EAP_TYPE_AKA &&
|
(data->eap_method == EAP_TYPE_AKA &&
|
||||||
|
|
|
@ -106,12 +106,28 @@ static struct wpabuf * eap_sim_build_start(struct eap_sm *sm,
|
||||||
{
|
{
|
||||||
struct eap_sim_msg *msg;
|
struct eap_sim_msg *msg;
|
||||||
u8 ver[2];
|
u8 ver[2];
|
||||||
|
bool id_req = true;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start");
|
wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start");
|
||||||
msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
|
msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
|
||||||
EAP_SIM_SUBTYPE_START);
|
EAP_SIM_SUBTYPE_START);
|
||||||
data->start_round++;
|
data->start_round++;
|
||||||
if (data->start_round == 1) {
|
|
||||||
|
if (data->start_round == 1 && (sm->cfg->eap_sim_id & 0x04)) {
|
||||||
|
char *username;
|
||||||
|
|
||||||
|
username = sim_get_username(sm->identity, sm->identity_len);
|
||||||
|
if (username && username[0] == EAP_SIM_REAUTH_ID_PREFIX &&
|
||||||
|
eap_sim_db_get_reauth_entry(sm->cfg->eap_sim_db_priv,
|
||||||
|
username))
|
||||||
|
id_req = false;
|
||||||
|
|
||||||
|
os_free(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!id_req) {
|
||||||
|
wpa_printf(MSG_DEBUG, " No identity request");
|
||||||
|
} else if (data->start_round == 1) {
|
||||||
/*
|
/*
|
||||||
* RFC 4186, Chap. 4.2.4 recommends that identity from EAP is
|
* RFC 4186, Chap. 4.2.4 recommends that identity from EAP is
|
||||||
* ignored and the SIM/Start is used to request the identity.
|
* ignored and the SIM/Start is used to request the identity.
|
||||||
|
@ -434,6 +450,7 @@ static void eap_sim_process_start(struct eap_sm *sm,
|
||||||
struct wpabuf *respData,
|
struct wpabuf *respData,
|
||||||
struct eap_sim_attrs *attr)
|
struct eap_sim_attrs *attr)
|
||||||
{
|
{
|
||||||
|
const u8 *identity;
|
||||||
size_t identity_len;
|
size_t identity_len;
|
||||||
u8 ver_list[2];
|
u8 ver_list[2];
|
||||||
u8 *new_identity;
|
u8 *new_identity;
|
||||||
|
@ -449,9 +466,13 @@ static void eap_sim_process_start(struct eap_sm *sm,
|
||||||
goto skip_id_update;
|
goto skip_id_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((sm->cfg->eap_sim_id & 0x04) &&
|
||||||
|
(!attr->identity || attr->identity_len == 0))
|
||||||
|
goto skip_id_attr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We always request identity in SIM/Start, so the peer is required to
|
* Unless explicitly configured otherwise, we always request identity
|
||||||
* have replied with one.
|
* in SIM/Start, so the peer is required to have replied with one.
|
||||||
*/
|
*/
|
||||||
if (!attr->identity || attr->identity_len == 0) {
|
if (!attr->identity || attr->identity_len == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-SIM: Peer did not provide any "
|
wpa_printf(MSG_DEBUG, "EAP-SIM: Peer did not provide any "
|
||||||
|
@ -467,9 +488,17 @@ static void eap_sim_process_start(struct eap_sm *sm,
|
||||||
os_memcpy(sm->identity, attr->identity, attr->identity_len);
|
os_memcpy(sm->identity, attr->identity, attr->identity_len);
|
||||||
sm->identity_len = attr->identity_len;
|
sm->identity_len = attr->identity_len;
|
||||||
|
|
||||||
|
skip_id_attr:
|
||||||
|
if (sm->sim_aka_permanent[0]) {
|
||||||
|
identity = (const u8 *) sm->sim_aka_permanent;
|
||||||
|
identity_len = os_strlen(sm->sim_aka_permanent);
|
||||||
|
} else {
|
||||||
|
identity = sm->identity;
|
||||||
|
identity_len = sm->identity_len;
|
||||||
|
}
|
||||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
|
wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
|
||||||
sm->identity, sm->identity_len);
|
identity, identity_len);
|
||||||
username = sim_get_username(sm->identity, sm->identity_len);
|
username = sim_get_username(identity, identity_len);
|
||||||
if (username == NULL)
|
if (username == NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue