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:
Jouni Malinen 2023-09-21 11:00:04 +03:00 committed by Jouni Malinen
parent 40af6560ba
commit c6268e103f
4 changed files with 61 additions and 6 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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 &&

View file

@ -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;