Check for own address (SPA) match when finding PMKSA entries
This prevents attempts of trying to use PMKSA caching when the existing entry was created using a different MAC address than the one that is currently being used. This avoids exposing the longer term PMKID value when using random MAC addresses for connections. In practice, similar restriction was already done by flushing the PMKSA cache entries whenever wpas_update_random_addr() changed the local address or when the interface was marked down (e.g., for an external operation to change the MAC address). Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
9f04a9c8dd
commit
9ff778fa4b
8 changed files with 28 additions and 19 deletions
|
@ -553,7 +553,7 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct pasn_data *pasn,
|
||||||
struct rsn_pmksa_cache_entry *pmksa;
|
struct rsn_pmksa_cache_entry *pmksa;
|
||||||
|
|
||||||
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr,
|
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr,
|
||||||
NULL, NULL, pasn->akmp);
|
pasn->own_addr, NULL, NULL, pasn->akmp);
|
||||||
if (pmksa && pasn->custom_pmkid_valid)
|
if (pmksa && pasn->custom_pmkid_valid)
|
||||||
pmkid = pasn->custom_pmkid;
|
pmkid = pasn->custom_pmkid;
|
||||||
else if (pmksa)
|
else if (pmksa)
|
||||||
|
@ -795,6 +795,7 @@ static int wpas_pasn_set_pmk(struct pasn_data *pasn,
|
||||||
}
|
}
|
||||||
|
|
||||||
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr,
|
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr,
|
||||||
|
pasn->own_addr,
|
||||||
pmkid, NULL, pasn->akmp);
|
pmkid, NULL, pasn->akmp);
|
||||||
if (pmksa) {
|
if (pmksa) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Using PMKSA");
|
wpa_printf(MSG_DEBUG, "PASN: Using PMKSA");
|
||||||
|
|
|
@ -148,7 +148,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
|
entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
|
||||||
pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 0);
|
pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, NULL, 0);
|
||||||
if (entry && !wpa_key_mgmt_sae(entry->akmp)) {
|
if (entry && !wpa_key_mgmt_sae(entry->akmp)) {
|
||||||
sec = pmksa->pmksa->reauth_time - now.sec;
|
sec = pmksa->pmksa->reauth_time - now.sec;
|
||||||
if (sec < 0)
|
if (sec < 0)
|
||||||
|
@ -419,13 +419,15 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
|
||||||
* Returns: Pointer to PMKSA cache entry or %NULL if no match was found
|
* Returns: Pointer to PMKSA cache entry or %NULL if no match was found
|
||||||
*/
|
*/
|
||||||
struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
||||||
const u8 *aa, const u8 *pmkid,
|
const u8 *aa, const u8 *spa,
|
||||||
|
const u8 *pmkid,
|
||||||
const void *network_ctx,
|
const void *network_ctx,
|
||||||
int akmp)
|
int akmp)
|
||||||
{
|
{
|
||||||
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
|
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
|
if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
|
||||||
|
(!spa || os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
|
||||||
(pmkid == NULL ||
|
(pmkid == NULL ||
|
||||||
os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
|
os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
|
||||||
(!akmp || akmp == entry->akmp) &&
|
(!akmp || akmp == entry->akmp) &&
|
||||||
|
@ -601,11 +603,11 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
|
||||||
|
|
||||||
sm->cur_pmksa = NULL;
|
sm->cur_pmksa = NULL;
|
||||||
if (pmkid)
|
if (pmkid)
|
||||||
sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
|
sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, sm->own_addr,
|
||||||
network_ctx, akmp);
|
pmkid, network_ctx, akmp);
|
||||||
if (sm->cur_pmksa == NULL && bssid)
|
if (sm->cur_pmksa == NULL && bssid)
|
||||||
sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
|
sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, sm->own_addr,
|
||||||
network_ctx, akmp);
|
NULL, network_ctx, akmp);
|
||||||
if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
|
if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
|
||||||
sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
|
sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
|
||||||
network_ctx,
|
network_ctx,
|
||||||
|
|
|
@ -65,7 +65,8 @@ pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
|
||||||
void *ctx, struct wpa_sm *sm);
|
void *ctx, struct wpa_sm *sm);
|
||||||
void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
|
void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
|
||||||
struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
||||||
const u8 *aa, const u8 *pmkid,
|
const u8 *aa, const u8 *spa,
|
||||||
|
const u8 *pmkid,
|
||||||
const void *network_ctx,
|
const void *network_ctx,
|
||||||
int akmp);
|
int akmp);
|
||||||
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
|
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
|
||||||
|
|
|
@ -330,7 +330,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
|
||||||
dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
|
dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
|
||||||
struct rsn_pmksa_candidate, list) {
|
struct rsn_pmksa_candidate, list) {
|
||||||
struct rsn_pmksa_cache_entry *p = NULL;
|
struct rsn_pmksa_cache_entry *p = NULL;
|
||||||
p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL, 0);
|
p = pmksa_cache_get(sm->pmksa, candidate->bssid, sm->own_addr,
|
||||||
|
NULL, NULL, 0);
|
||||||
if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
|
if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
|
||||||
(p == NULL || p->opportunistic)) {
|
(p == NULL || p->opportunistic)) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
|
wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
|
||||||
|
@ -491,7 +492,7 @@ void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
|
||||||
if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
|
if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL, 0);
|
pmksa = pmksa_cache_get(sm->pmksa, bssid, sm->own_addr, NULL, NULL, 0);
|
||||||
if (pmksa && (!pmksa->opportunistic ||
|
if (pmksa && (!pmksa->opportunistic ||
|
||||||
!(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
|
!(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -318,7 +318,8 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
||||||
* not have enough time to get the association information
|
* not have enough time to get the association information
|
||||||
* event before receiving this 1/4 message, so try to find a
|
* event before receiving this 1/4 message, so try to find a
|
||||||
* matching PMKSA cache entry here. */
|
* matching PMKSA cache entry here. */
|
||||||
sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
|
sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr,
|
||||||
|
sm->own_addr, pmkid,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
if (sm->cur_pmksa) {
|
if (sm->cur_pmksa) {
|
||||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
@ -434,8 +435,8 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
||||||
fils_cache_id);
|
fils_cache_id);
|
||||||
}
|
}
|
||||||
if (!sm->cur_pmksa && pmkid &&
|
if (!sm->cur_pmksa && pmkid &&
|
||||||
pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL,
|
pmksa_cache_get(sm->pmksa, src_addr, sm->own_addr,
|
||||||
0)) {
|
pmkid, NULL, 0)) {
|
||||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
"RSN: the new PMK matches with the "
|
"RSN: the new PMK matches with the "
|
||||||
"PMKID");
|
"PMKID");
|
||||||
|
@ -4731,10 +4732,11 @@ void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
|
int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, const u8 *own_addr,
|
||||||
const void *network_ctx)
|
const void *network_ctx)
|
||||||
{
|
{
|
||||||
return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL;
|
return pmksa_cache_get(sm->pmksa, bssid, own_addr, NULL, network_ctx,
|
||||||
|
0) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4744,7 +4746,8 @@ struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
|
||||||
const void *network_ctx,
|
const void *network_ctx,
|
||||||
int akmp)
|
int akmp)
|
||||||
{
|
{
|
||||||
return pmksa_cache_get(sm->pmksa, aa, pmkid, network_ctx, akmp);
|
return pmksa_cache_get(sm->pmksa, aa, sm->own_addr, pmkid, network_ctx,
|
||||||
|
akmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
|
||||||
void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
|
void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
|
||||||
const u8 *pmkid, const u8 *bssid,
|
const u8 *pmkid, const u8 *bssid,
|
||||||
const u8 *fils_cache_id);
|
const u8 *fils_cache_id);
|
||||||
int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
|
int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, const u8 *own_addr,
|
||||||
const void *network_ctx);
|
const void *network_ctx);
|
||||||
void wpa_sm_drop_sa(struct wpa_sm *sm);
|
void wpa_sm_drop_sa(struct wpa_sm *sm);
|
||||||
struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
|
struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
|
||||||
|
|
|
@ -4358,7 +4358,7 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||||
if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
|
if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
|
||||||
!(ied.key_mgmt & WPA_KEY_MGMT_DPP))
|
!(ied.key_mgmt & WPA_KEY_MGMT_DPP))
|
||||||
return 0; /* AP does not support DPP AKM - continue */
|
return 0; /* AP does not support DPP AKM - continue */
|
||||||
if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
|
if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
|
||||||
return 0; /* PMKSA exists for DPP AKM - continue */
|
return 0; /* PMKSA exists for DPP AKM - continue */
|
||||||
|
|
||||||
if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
|
if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
|
||||||
|
|
|
@ -1515,7 +1515,8 @@ skip_assoc_disallow:
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
|
if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
|
||||||
!wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) &&
|
!wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr,
|
||||||
|
ssid) &&
|
||||||
(!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
|
(!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
|
||||||
!ssid->dpp_csign)) {
|
!ssid->dpp_csign)) {
|
||||||
if (debug_print)
|
if (debug_print)
|
||||||
|
|
Loading…
Reference in a new issue