]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP-SIM/AKA server: Allow method specific identity exchange to be skipped
authorJouni Malinen <quic_jouni@quicinc.com>
Thu, 21 Sep 2023 08:00:04 +0000 (11:00 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 21 Sep 2023 08:55:49 +0000 (11:55 +0300)
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>
hostapd/hostapd.conf
src/eap_server/eap_i.h
src/eap_server/eap_server_aka.c
src/eap_server/eap_server_sim.c

index bafc9232b3b295c71e6183dacdc70d027400955d..b8d27112be92b9a55f7cbdfaa86223ffd5783fc4 100644 (file)
@@ -1465,6 +1465,14 @@ eap_server=0
 # 1 = use pseudonyms, but not fast reauthentication
 # 2 = do not use pseudonyms, but use fast reauthentication
 # 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
 
 # IMSI privacy key (PEM encoded RSA 2048-bit private key) for decrypting
index 1c59bb0cc62b03bccff41ef694632c3dd07c7077..10affa431c0e0e685fd7cbb0c0228d9f281570c2 100644 (file)
@@ -160,6 +160,7 @@ struct eap_sm {
        size_t identity_len;
        char *serial_num;
        char imsi[20];
+       char sim_aka_permanent[20];
        /* Whether Phase 2 method should validate identity match */
        int require_identity_match;
        int lastId; /* Identifier used in the last EAP-Packet */
index 5fb19e976a7138d5353a4d872c881d22131c96bc..c154d7f6e8fd9ed8b83f28c4604bd07bdeb97f94 100644 (file)
@@ -134,10 +134,17 @@ static void eap_aka_check_identity(struct eap_sm *sm,
                                   struct eap_aka_data *data)
 {
        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 */
 
-       username = sim_get_username(sm->identity, sm->identity_len);
+       username = sim_get_username(identity, identity_len);
        if (username == NULL)
                return;
 
@@ -150,6 +157,16 @@ static void eap_aka_check_identity(struct eap_sm *sm,
                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 &&
             username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
            (data->eap_method == EAP_TYPE_AKA &&
index 1bcf26c467ca32aa6e7ac28a0610adb9c54790e7..51faca95f198d1e6a8beb4c79db12ac22e49a41e 100644 (file)
@@ -106,12 +106,28 @@ static struct wpabuf * eap_sim_build_start(struct eap_sm *sm,
 {
        struct eap_sim_msg *msg;
        u8 ver[2];
+       bool id_req = true;
 
        wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start");
        msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
                               EAP_SIM_SUBTYPE_START);
        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
                 * 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 eap_sim_attrs *attr)
 {
+       const u8 *identity;
        size_t identity_len;
        u8 ver_list[2];
        u8 *new_identity;
@@ -449,9 +466,13 @@ static void eap_sim_process_start(struct eap_sm *sm,
                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
-        * have replied with one.
+        * Unless explicitly configured otherwise, we always request identity
+        * in SIM/Start, so the peer is required to have replied with one.
         */
        if (!attr->identity || attr->identity_len == 0) {
                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);
        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",
-                         sm->identity, sm->identity_len);
-       username = sim_get_username(sm->identity, sm->identity_len);
+                         identity, identity_len);
+       username = sim_get_username(identity, identity_len);
        if (username == NULL)
                goto failed;