diff options
author | Hai Shalom <haishalom@google.com> | 2019-08-02 15:56:26 -0700 |
---|---|---|
committer | Hai Shalom <haishalom@google.com> | 2019-08-13 16:49:04 +0000 |
commit | ef6ae566f2444bff52e4b3f009f8d0be4976019d (patch) | |
tree | a5f8a0c451fbcdb75c0e15007e5f18f18d08a2ed | |
parent | 43b5a299f9d6cfb161342030cdca2ae37cf5e65f (diff) | |
download | wpa_supplicant_8-ef6ae566f2444bff52e4b3f009f8d0be4976019d.tar.gz |
Do not clear anonymous id when anonymous@<realm> is used
If the EAP-SIM/AKA server does not provide a new pseudonym and the
locally configured "pseudonym" in anonymous_identity is actually
an anonymous identity instead of a real EAP-SIM/AKA pseudonym, do
not clear the anonymous_identity network profile parameter.
This is needed to avoid forgetting the anonymous identity when
going through EAP-SIM/AKA authentication and then reverting back
to using IMSI-based (e.g., encrypted) identity.
Bug: 138610772
Test: Associate to <carrier> AP, get out of range, reassociate
Test: Associate to <carrier> AP, pop SIM, reinsert, reassociate
Change-Id: I41819a22005848d37d5247ebf6543bb66ea78fce
(cherry picked from commit afd394b5a79e48be55dd82fcaf6782e7ed6cc77a)
-rw-r--r-- | src/eap_common/eap_sim_common.c | 16 | ||||
-rw-r--r-- | src/eap_common/eap_sim_common.h | 1 | ||||
-rw-r--r-- | src/eap_peer/eap_aka.c | 28 | ||||
-rw-r--r-- | src/eap_peer/eap_sim.c | 30 |
4 files changed, 44 insertions, 31 deletions
diff --git a/src/eap_common/eap_sim_common.c b/src/eap_common/eap_sim_common.c index 6290c35f..cfdd1bf4 100644 --- a/src/eap_common/eap_sim_common.c +++ b/src/eap_common/eap_sim_common.c @@ -1203,3 +1203,19 @@ void eap_sim_report_notification(void *msg_ctx, int notification, int aka) } } } + + +int eap_sim_anonymous_username(const u8 *id, size_t id_len) +{ + static const char *anonymous_id_prefix = "anonymous@"; + size_t anonymous_id_len = os_strlen(anonymous_id_prefix); + + if (id_len > anonymous_id_len && + os_memcmp(id, anonymous_id_prefix, anonymous_id_len) == 0) + return 1; /* 'anonymous@realm' */ + + if (id_len > 1 && id[0] == '@') + return 1; /* '@realm' */ + + return 0; +} diff --git a/src/eap_common/eap_sim_common.h b/src/eap_common/eap_sim_common.h index daeb0e2d..7142b94c 100644 --- a/src/eap_common/eap_sim_common.h +++ b/src/eap_common/eap_sim_common.h @@ -226,5 +226,6 @@ int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad); void eap_sim_report_notification(void *msg_ctx, int notification, int aka); +int eap_sim_anonymous_username(const u8 *id, size_t id_len); #endif /* EAP_SIM_COMMON_H */ diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index a96a39f4..ff88cf8a 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -57,7 +57,6 @@ struct eap_aka_data { u16 last_kdf_attrs[EAP_AKA_PRIME_KDF_MAX]; size_t last_kdf_count; int error_code; - int anonymous_flag; }; @@ -94,7 +93,6 @@ static void * eap_aka_init(struct eap_sm *sm) struct eap_aka_data *data; const char *phase1 = eap_get_config_phase1(sm); struct eap_peer_config *config = eap_get_config(sm); - static const char *anonymous_id_prefix = "anonymous@"; data = os_zalloc(sizeof(*data)); if (data == NULL) @@ -109,7 +107,6 @@ static void * eap_aka_init(struct eap_sm *sm) data->prev_id = -1; data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL; - data->anonymous_flag = 0; data->use_pseudonym = !sm->init_phase2; if (config && config->anonymous_identity && data->use_pseudonym) { @@ -118,13 +115,6 @@ static void * eap_aka_init(struct eap_sm *sm) os_memcpy(data->pseudonym, config->anonymous_identity, config->anonymous_identity_len); data->pseudonym_len = config->anonymous_identity_len; - if (data->pseudonym_len > os_strlen(anonymous_id_prefix) && - !os_memcmp(data->pseudonym, anonymous_id_prefix, - os_strlen(anonymous_id_prefix))) { - data->anonymous_flag = 1; - wpa_printf(MSG_DEBUG, - "EAP-AKA: Setting anonymous@realm flag"); - } } } @@ -427,7 +417,6 @@ static int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data, if (data->use_pseudonym) eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len); - data->anonymous_flag = 0; } if (attr->next_reauth_id) { @@ -633,15 +622,22 @@ static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm, identity_len = data->reauth_id_len; data->reauth = 1; } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym && !data->anonymous_flag) { + data->pseudonym && + !eap_sim_anonymous_username(data->pseudonym, + data->pseudonym_len)) { identity = data->pseudonym; identity_len = data->pseudonym_len; eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID); } else if (id_req != NO_ID_REQ) { identity = eap_get_config_identity(sm, &identity_len); if (identity) { - eap_aka_clear_identities(sm, data, CLEAR_PSEUDONYM | - CLEAR_REAUTH_ID); + int ids = CLEAR_PSEUDONYM | CLEAR_REAUTH_ID; + + if (data->pseudonym && + eap_sim_anonymous_username(data->pseudonym, + data->pseudonym_len)) + ids &= ~CLEAR_PSEUDONYM; + eap_aka_clear_identities(sm, data, ids); } } if (id_req != NO_ID_REQ) @@ -1037,7 +1033,9 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, if (data->last_eap_identity) { identity = data->last_eap_identity; identity_len = data->last_eap_identity_len; - } else if (data->pseudonym && !data->anonymous_flag) { + } else if (data->pseudonym && + !eap_sim_anonymous_username(data->pseudonym, + data->pseudonym_len)) { identity = data->pseudonym; identity_len = data->pseudonym_len; } else { diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index 6989aa88..b5811a8a 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -48,7 +48,6 @@ struct eap_sim_data { int result_ind, use_result_ind; int use_pseudonym; int error_code; - int anonymous_flag; }; @@ -84,7 +83,6 @@ static void * eap_sim_init(struct eap_sm *sm) { struct eap_sim_data *data; struct eap_peer_config *config = eap_get_config(sm); - static const char *anonymous_id_prefix = "anonymous@"; data = os_zalloc(sizeof(*data)); if (data == NULL) @@ -99,7 +97,7 @@ static void * eap_sim_init(struct eap_sm *sm) /* Zero is a valid error code, so we need to initialize */ data->error_code = NO_EAP_METHOD_ERROR; - data->anonymous_flag = 0; + data->min_num_chal = 2; if (config && config->phase1) { char *pos = os_strstr(config->phase1, "sim_min_num_chal="); @@ -129,14 +127,6 @@ static void * eap_sim_init(struct eap_sm *sm) os_memcpy(data->pseudonym, config->anonymous_identity, config->anonymous_identity_len); data->pseudonym_len = config->anonymous_identity_len; - if (data->pseudonym_len > os_strlen(anonymous_id_prefix) && - !os_memcmp(data->pseudonym, anonymous_id_prefix, - os_strlen(anonymous_id_prefix))) { - data->anonymous_flag = 1; - wpa_printf(MSG_DEBUG, - "EAP-SIM: Setting anonymous@realm flag"); - } - } } @@ -447,7 +437,6 @@ static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data, if (data->use_pseudonym) eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len); - data->anonymous_flag = 0; } if (attr->next_reauth_id) { @@ -503,15 +492,22 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, identity_len = data->reauth_id_len; data->reauth = 1; } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym && !data->anonymous_flag) { + data->pseudonym && + !eap_sim_anonymous_username(data->pseudonym, + data->pseudonym_len)) { identity = data->pseudonym; identity_len = data->pseudonym_len; eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID); } else if (id_req != NO_ID_REQ) { identity = eap_get_config_identity(sm, &identity_len); if (identity) { - eap_sim_clear_identities(sm, data, CLEAR_PSEUDONYM | - CLEAR_REAUTH_ID); + int ids = CLEAR_PSEUDONYM | CLEAR_REAUTH_ID; + + if (data->pseudonym && + eap_sim_anonymous_username(data->pseudonym, + data->pseudonym_len)) + ids &= ~CLEAR_PSEUDONYM; + eap_sim_clear_identities(sm, data, ids); } } if (id_req != NO_ID_REQ) @@ -779,7 +775,9 @@ static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm, if (data->last_eap_identity) { identity = data->last_eap_identity; identity_len = data->last_eap_identity_len; - } else if (data->pseudonym && !data->anonymous_flag) { + } else if (data->pseudonym && + !eap_sim_anonymous_username(data->pseudonym, + data->pseudonym_len)) { identity = data->pseudonym; identity_len = data->pseudonym_len; } else { |