station: network: rework ERP/FILS code path

This refactors some code to eliminate getting the ERP entry twice
by simply returning it from network_has_erp_identity (now renamed
to network_get_erp_cache). In addition this code was moved into
station_build_handshake_rsn and properly cleaned up in case there
was an error or if a FILS AKM was not chosen.
This commit is contained in:
James Prestwood 2021-08-03 14:40:43 -07:00 committed by Denis Kenzior
parent 236bb27cdd
commit 630c2c2a08
3 changed files with 30 additions and 22 deletions

View File

@ -1056,7 +1056,7 @@ static bool match_bss(const void *a, const void *b)
return a == b; return a == b;
} }
bool network_has_erp_identity(struct network *network) struct erp_cache_entry *network_get_erp_cache(struct network *network)
{ {
struct erp_cache_entry *cache; struct erp_cache_entry *cache;
struct l_settings *settings; struct l_settings *settings;
@ -1066,16 +1066,16 @@ bool network_has_erp_identity(struct network *network)
settings = network_get_settings(network); settings = network_get_settings(network);
if (!settings) if (!settings)
return false; return NULL;
check_id = l_settings_get_string(settings, "Security", "EAP-Identity"); check_id = l_settings_get_string(settings, "Security", "EAP-Identity");
if (!check_id) if (!check_id)
return false; return NULL;
cache = erp_cache_get(network_get_ssid(network)); cache = erp_cache_get(network_get_ssid(network));
if (!cache) { if (!cache) {
l_free(check_id); l_free(check_id);
return false; return NULL;
} }
identity = erp_cache_entry_get_identity(cache); identity = erp_cache_entry_get_identity(cache);
@ -1083,17 +1083,19 @@ bool network_has_erp_identity(struct network *network)
ret = strcmp(check_id, identity) == 0; ret = strcmp(check_id, identity) == 0;
l_free(check_id); l_free(check_id);
erp_cache_put(cache);
/* /*
* The settings file must have change out from under us. In this * The settings file must have change out from under us. In this
* case we want to remove the ERP entry because it is no longer * case we want to remove the ERP entry because it is no longer
* valid. * valid.
*/ */
if (!ret) if (!ret) {
erp_cache_put(cache);
erp_cache_remove(identity); erp_cache_remove(identity);
return NULL;
}
return ret; return cache;
} }
const struct l_queue_entry *network_bss_list_get_entries( const struct l_queue_entry *network_bss_list_get_entries(

View File

@ -29,6 +29,7 @@ struct station;
struct network; struct network;
struct scan_bss; struct scan_bss;
struct handshake_state; struct handshake_state;
struct erp_cache_entry;
void network_connected(struct network *network); void network_connected(struct network *network);
void network_disconnected(struct network *network); void network_disconnected(struct network *network);
@ -87,7 +88,7 @@ void network_blacklist_add(struct network *network, struct scan_bss *bss);
const struct iovec *network_get_extra_ies(struct network *network, const struct iovec *network_get_extra_ies(struct network *network,
size_t *num_elems); size_t *num_elems);
bool network_has_erp_identity(struct network *network); struct erp_cache_entry *network_get_erp_cache(struct network *network);
const struct l_queue_entry *network_bss_list_get_entries( const struct l_queue_entry *network_bss_list_get_entries(
struct network *network); struct network *network);

View File

@ -743,7 +743,7 @@ static int station_build_handshake_rsn(struct handshake_state *hs,
{ {
enum security security = network_get_security(network); enum security security = network_get_security(network);
bool add_mde = false; bool add_mde = false;
bool fils_hint = false; struct erp_cache_entry *erp_cache = NULL;
struct ie_rsn_info bss_info; struct ie_rsn_info bss_info;
uint8_t rsne_buf[256]; uint8_t rsne_buf[256];
@ -764,10 +764,10 @@ static int station_build_handshake_rsn(struct handshake_state *hs,
* wiphy may select FILS if supported by the AP. * wiphy may select FILS if supported by the AP.
*/ */
if (security == SECURITY_8021X && hs->support_fils) if (security == SECURITY_8021X && hs->support_fils)
fils_hint = network_has_erp_identity(network); erp_cache = network_get_erp_cache(network);
info.akm_suites = wiphy_select_akm(wiphy, bss, security, info.akm_suites = wiphy_select_akm(wiphy, bss, security,
&bss_info, fils_hint); &bss_info, erp_cache != NULL);
/* /*
* Special case for OWE. With OWE we still need to build up the * Special case for OWE. With OWE we still need to build up the
@ -848,6 +848,19 @@ build_ie:
if (IE_AKM_IS_FT(info.akm_suites)) if (IE_AKM_IS_FT(info.akm_suites))
add_mde = true; add_mde = true;
/*
* If FILS was chosen, the ERP cache has been verified to exist. Take
* a reference now so it remains valid (in case of expiration) until
* FILS starts.
*/
if (hs->akm_suite & (IE_RSN_AKM_SUITE_FILS_SHA256 |
IE_RSN_AKM_SUITE_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384))
hs->erp_cache = erp_cache;
else if (erp_cache)
erp_cache_put(erp_cache);
open_network: open_network:
if (security == SECURITY_NONE) if (security == SECURITY_NONE)
/* Perform FT association if available */ /* Perform FT association if available */
@ -867,6 +880,9 @@ open_network:
return 0; return 0;
not_supported: not_supported:
if (erp_cache)
erp_cache_put(erp_cache);
return -ENOTSUP; return -ENOTSUP;
} }
@ -889,17 +905,6 @@ static struct handshake_state *station_handshake_setup(struct station *station,
if (network_handshake_setup(network, hs) < 0) if (network_handshake_setup(network, hs) < 0)
goto not_supported; goto not_supported;
/*
* If FILS was chosen, the ERP cache has been verified to exist. We
* wait to get it until here because at this point so there are no
* failure paths before fils_sm_new
*/
if (hs->akm_suite & (IE_RSN_AKM_SUITE_FILS_SHA256 |
IE_RSN_AKM_SUITE_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384))
hs->erp_cache = erp_cache_get(network_get_ssid(network));
return hs; return hs;
not_supported: not_supported: