]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP-AKA server: Skip AKA/Identity exchange if EAP identity recognized
authorJouni Malinen <j@w1.fi>
Sun, 2 Sep 2012 08:27:39 +0000 (11:27 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 2 Sep 2012 08:27:39 +0000 (11:27 +0300)
If EAP-Response/Identity includes a known pseudonym or re-auth username,
skip the AKA/Identity exchange since we already know the permanent
username of the peer.

Signed-hostap: Jouni Malinen <j@w1.fi>

src/eap_server/eap_server_aka.c
src/eap_server/eap_sim_db.c

index 628b0c87c1906f53402f6c488014ad7b05a5c310..a965cac49070d0c3f32517678228ce43471ceded 100644 (file)
@@ -54,6 +54,9 @@ struct eap_aka_data {
 };
 
 
+static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
+
+
 static const char * eap_aka_state_txt(int state)
 {
        switch (state) {
@@ -84,6 +87,96 @@ static void eap_aka_state(struct eap_aka_data *data, int state)
 }
 
 
+static int eap_aka_check_identity_reauth(struct eap_sm *sm,
+                                        struct eap_aka_data *data,
+                                        const char *username)
+{
+       if (data->eap_method == EAP_TYPE_AKA_PRIME &&
+           username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX)
+               return 0;
+       if (data->eap_method == EAP_TYPE_AKA &&
+           username[0] != EAP_AKA_REAUTH_ID_PREFIX)
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
+       data->reauth = eap_sim_db_get_reauth_entry(sm->eap_sim_db_priv,
+                                                  username);
+       if (data->reauth == NULL) {
+               wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
+                          "request full auth identity");
+               /* Remain in IDENTITY state for another round */
+               return 0;
+       }
+
+       wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
+       os_strlcpy(data->permanent, data->reauth->permanent,
+                  sizeof(data->permanent));
+       data->counter = data->reauth->counter;
+       if (data->eap_method == EAP_TYPE_AKA_PRIME) {
+               os_memcpy(data->k_encr, data->reauth->k_encr,
+                         EAP_SIM_K_ENCR_LEN);
+               os_memcpy(data->k_aut, data->reauth->k_aut,
+                         EAP_AKA_PRIME_K_AUT_LEN);
+               os_memcpy(data->k_re, data->reauth->k_re,
+                         EAP_AKA_PRIME_K_RE_LEN);
+       } else {
+               os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
+       }
+
+       eap_aka_state(data, REAUTH);
+       return 1;
+}
+
+
+static void eap_aka_check_identity(struct eap_sm *sm,
+                                  struct eap_aka_data *data)
+{
+       char *username;
+
+       /* Check if we already know the identity from EAP-Response/Identity */
+
+       username = sim_get_username(sm->identity, sm->identity_len);
+       if (username == NULL)
+               return;
+
+       if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
+               os_free(username);
+               /*
+                * Since re-auth username was recognized, skip AKA/Identity
+                * exchange.
+                */
+               return;
+       }
+
+       if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+            username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
+           (data->eap_method == EAP_TYPE_AKA &&
+            username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
+               const char *permanent;
+               wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
+                          username);
+               permanent = eap_sim_db_get_permanent(
+                       sm->eap_sim_db_priv, username);
+               if (permanent == NULL) {
+                       os_free(username);
+                       wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
+                                  "identity - request permanent identity");
+                       /* Remain in IDENTITY state for another round */
+                       return;
+               }
+               os_strlcpy(data->permanent, permanent,
+                          sizeof(data->permanent));
+               /*
+                * Since pseudonym username was recognized, skip AKA/Identity
+                * exchange.
+                */
+               eap_aka_fullauth(sm, data);
+       }
+
+       os_free(username);
+}
+
+
 static void * eap_aka_init(struct eap_sm *sm)
 {
        struct eap_aka_data *data;
@@ -101,6 +194,7 @@ static void * eap_aka_init(struct eap_sm *sm)
 
        data->state = IDENTITY;
        data->pending_id = -1;
+       eap_aka_check_identity(sm, data);
 
        return data;
 }
@@ -133,6 +227,7 @@ static void * eap_aka_prime_init(struct eap_sm *sm)
 
        data->state = IDENTITY;
        data->pending_id = -1;
+       eap_aka_check_identity(sm, data);
 
        return data;
 }
@@ -615,8 +710,6 @@ static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
 }
 
 
-static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
-
 static void eap_aka_determine_identity(struct eap_sm *sm,
                                       struct eap_aka_data *data)
 {
@@ -632,36 +725,8 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
                return;
        }
 
-       if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
-            username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
-           (data->eap_method == EAP_TYPE_AKA &&
-            username[0] == EAP_AKA_REAUTH_ID_PREFIX)) {
-               wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'",
-                          username);
-               data->reauth = eap_sim_db_get_reauth_entry(
-                       sm->eap_sim_db_priv, username);
+       if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
                os_free(username);
-               if (data->reauth == NULL) {
-                       wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth "
-                                  "identity - request full auth identity");
-                       /* Remain in IDENTITY state for another round */
-                       return;
-               }
-               wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
-               os_strlcpy(data->permanent, data->reauth->permanent,
-                          sizeof(data->permanent));
-               data->counter = data->reauth->counter;
-               if (data->eap_method == EAP_TYPE_AKA_PRIME) {
-                       os_memcpy(data->k_encr, data->reauth->k_encr,
-                                 EAP_SIM_K_ENCR_LEN);
-                       os_memcpy(data->k_aut, data->reauth->k_aut,
-                                 EAP_AKA_PRIME_K_AUT_LEN);
-                       os_memcpy(data->k_re, data->reauth->k_re,
-                                 EAP_AKA_PRIME_K_RE_LEN);
-               } else {
-                       os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
-               }
-               eap_aka_state(data, REAUTH);
                return;
        }
 
index 823a4d38e5bc8a1c9f3948aaa99bf964c527e5a1..e41c99fd47eb9840a9622294bcaa0e4a353bac9d 100644 (file)
@@ -1493,6 +1493,9 @@ char * sim_get_username(const u8 *identity, size_t identity_len)
        char *username;
        size_t pos;
 
+       if (identity == NULL)
+               return NULL;
+
        for (pos = 0; pos < identity_len; pos++) {
                if (identity[pos] == '@' || identity[pos] == '\0')
                        break;