diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index 9783e7c4a..df675834c 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -25,7 +25,7 @@ struct rsn_pmksa_cache { struct wpa_sm *sm; /* TODO: get rid of this reference(?) */ void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx, - int replace); + enum pmksa_free_reason reason); void *ctx; }; @@ -41,11 +41,11 @@ static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, struct rsn_pmksa_cache_entry *entry, - int replace) + enum pmksa_free_reason reason) { wpa_sm_remove_pmkid(pmksa->sm, entry->aa, entry->pmkid); pmksa->pmksa_count--; - pmksa->free_cb(entry, pmksa->ctx, replace); + pmksa->free_cb(entry, pmksa->ctx, reason); _pmksa_cache_free_entry(entry); } @@ -61,7 +61,7 @@ static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) pmksa->pmksa = entry->next; wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " MACSTR, MAC2STR(entry->aa)); - pmksa_cache_free_entry(pmksa, entry, 0); + pmksa_cache_free_entry(pmksa, entry, PMKSA_EXPIRE); } pmksa_cache_set_expiration(pmksa); @@ -164,22 +164,9 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, pmksa->pmksa = pos->next; else prev->next = pos->next; - if (pos == pmksa->sm->cur_pmksa) { - /* We are about to replace the current PMKSA - * cache entry. This happens when the PMKSA - * caching attempt fails, so we don't want to - * force pmksa_cache_free_entry() to disconnect - * at this point. Let's just make sure the old - * PMKSA cache entry will not be used in the - * future. - */ - wpa_printf(MSG_DEBUG, "RSN: replacing current " - "PMKSA entry"); - pmksa->sm->cur_pmksa = NULL; - } wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " "the current AP"); - pmksa_cache_free_entry(pmksa, pos, 1); + pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); /* * If OKC is used, there may be other PMKSA cache @@ -214,7 +201,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, "PMKSA cache entry (for " MACSTR ") to " "make room for new one", MAC2STR(pos->aa)); - pmksa_cache_free_entry(pmksa, pos, 0); + pmksa_cache_free_entry(pmksa, pos, PMKSA_FREE); } } @@ -265,7 +252,7 @@ void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx) pmksa->pmksa = entry->next; tmp = entry; entry = entry->next; - pmksa_cache_free_entry(pmksa, tmp, 0); + pmksa_cache_free_entry(pmksa, tmp, PMKSA_FREE); removed++; } else { prev = entry; @@ -507,7 +494,7 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) */ struct rsn_pmksa_cache * pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), + void *ctx, enum pmksa_free_reason reason), void *ctx, struct wpa_sm *sm) { struct rsn_pmksa_cache *pmksa; diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h index 9245aab53..f318c52fa 100644 --- a/src/rsn_supp/pmksa_cache.h +++ b/src/rsn_supp/pmksa_cache.h @@ -38,11 +38,17 @@ struct rsn_pmksa_cache_entry { struct rsn_pmksa_cache; +enum pmksa_free_reason { + PMKSA_FREE, + PMKSA_REPLACE, + PMKSA_EXPIRE, +}; + #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) struct rsn_pmksa_cache * pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), + void *ctx, enum pmksa_free_reason reason), void *ctx, struct wpa_sm *sm); void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, @@ -66,7 +72,7 @@ void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx); static inline struct rsn_pmksa_cache * pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), + void *ctx, int reason), void *ctx, struct wpa_sm *sm) { return (void *) -1; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index eb1b1d95e..c825ec7b6 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1935,25 +1935,40 @@ int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace) + void *ctx, enum pmksa_free_reason reason) { struct wpa_sm *sm = ctx; + int deauth = 0; - if (sm->cur_pmksa == entry || + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: " + MACSTR " reason=%d", MAC2STR(entry->aa), reason); + + if (sm->cur_pmksa == entry) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: %s current PMKSA entry", + reason == PMKSA_REPLACE ? "replaced" : "removed"); + pmksa_cache_clear_current(sm); + + /* + * If an entry is simply being replaced, there's no need to + * deauthenticate because it will be immediately re-added. + * This happens when EAP authentication is completed again + * (reauth or failed PMKSA caching attempt). + */ + if (reason != PMKSA_REPLACE) + deauth = 1; + } + + if (reason == PMKSA_EXPIRE && (sm->pmk_len == entry->pmk_len && os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: removed current PMKSA entry"); - sm->cur_pmksa = NULL; - - if (replace) { - /* A new entry is being added, so no need to - * deauthenticate in this case. This happens when EAP - * authentication is completed again (reauth or failed - * PMKSA caching attempt). */ - return; - } + "RSN: deauthenticating due to expired PMK"); + pmksa_cache_clear_current(sm); + deauth = 1; + } + if (deauth) { os_memset(sm->pmk, 0, sizeof(sm->pmk)); wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); }