|
|
147a26 |
From 4033935dd9098938838d6d7934ceb65f92a1fa3c Mon Sep 17 00:00:00 2001
|
|
|
147a26 |
From: Jouni Malinen <jouni@qca.qualcomm.com>
|
|
|
147a26 |
Date: Wed, 22 May 2013 13:24:30 +0300
|
|
|
147a26 |
Subject: [PATCH] Fix OKC-based PMKSA cache entry clearing
|
|
|
147a26 |
|
|
|
147a26 |
Commit c3fea272747f738f5723fc577371fe03711d988f added a call to clear
|
|
|
147a26 |
all other PMKSA cache entries for the same network if the PMKSA cache
|
|
|
147a26 |
entry of the current AP changed. This was needed to fix OKC cases since
|
|
|
147a26 |
the other APs would likely use the new PMK in the future. However, this
|
|
|
147a26 |
ended up clearing entries in cases where that is not desired and this
|
|
|
147a26 |
resulted in needing additional full EAP authentication with networks
|
|
|
147a26 |
that did not support OKC if wpa_supplicant was configured to try to use
|
|
|
147a26 |
it.
|
|
|
147a26 |
|
|
|
147a26 |
Make PMKSA cache entry flushing more limited so that the other entries
|
|
|
147a26 |
are removed only if they used the old PMK that was replaced for the
|
|
|
147a26 |
current AP and only if that PMK had previously been used successfully
|
|
|
147a26 |
(i.e., opportunistic flag was already cleared back to 0 in
|
|
|
147a26 |
wpa_supplicant_key_neg_complete()). This is still enough to fix the
|
|
|
147a26 |
issue described in that older commit while not causing problems for
|
|
|
147a26 |
standard PMKSA caching operations even if OKC is enabled in
|
|
|
147a26 |
wpa_supplicant configuration.
|
|
|
147a26 |
|
|
|
147a26 |
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
|
|
|
147a26 |
---
|
|
|
147a26 |
src/rsn_supp/pmksa_cache.c | 27 ++++++++++++++++++++-------
|
|
|
147a26 |
src/rsn_supp/pmksa_cache.h | 3 ++-
|
|
|
147a26 |
src/rsn_supp/wpa.c | 2 +-
|
|
|
147a26 |
3 files changed, 23 insertions(+), 9 deletions(-)
|
|
|
147a26 |
|
|
|
147a26 |
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
|
|
|
147a26 |
index df67583..93056ea 100644
|
|
|
147a26 |
--- a/src/rsn_supp/pmksa_cache.c
|
|
|
147a26 |
+++ b/src/rsn_supp/pmksa_cache.c
|
|
|
147a26 |
@@ -160,25 +160,31 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|
|
147a26 |
os_free(entry);
|
|
|
147a26 |
return pos;
|
|
|
147a26 |
}
|
|
|
147a26 |
if (prev == NULL)
|
|
|
147a26 |
pmksa->pmksa = pos->next;
|
|
|
147a26 |
else
|
|
|
147a26 |
prev->next = pos->next;
|
|
|
147a26 |
- wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
|
|
|
147a26 |
- "the current AP");
|
|
|
147a26 |
- pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
|
|
|
147a26 |
|
|
|
147a26 |
/*
|
|
|
147a26 |
* If OKC is used, there may be other PMKSA cache
|
|
|
147a26 |
* entries based on the same PMK. These needs to be
|
|
|
147a26 |
* flushed so that a new entry can be created based on
|
|
|
147a26 |
- * the new PMK.
|
|
|
147a26 |
+ * the new PMK. Only clear other entries if they have a
|
|
|
147a26 |
+ * matching PMK and this PMK has been used successfully
|
|
|
147a26 |
+ * with the current AP, i.e., if opportunistic flag has
|
|
|
147a26 |
+ * been cleared in wpa_supplicant_key_neg_complete().
|
|
|
147a26 |
*/
|
|
|
147a26 |
- pmksa_cache_flush(pmksa, network_ctx);
|
|
|
147a26 |
+ wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
|
|
|
147a26 |
+ "the current AP and any PMKSA cache entry "
|
|
|
147a26 |
+ "that was based on the old PMK");
|
|
|
147a26 |
+ if (!pos->opportunistic)
|
|
|
147a26 |
+ pmksa_cache_flush(pmksa, network_ctx, pos->pmk,
|
|
|
147a26 |
+ pos->pmk_len);
|
|
|
147a26 |
+ pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
|
|
|
147a26 |
break;
|
|
|
147a26 |
}
|
|
|
147a26 |
prev = pos;
|
|
|
147a26 |
pos = pos->next;
|
|
|
147a26 |
}
|
|
|
147a26 |
|
|
|
147a26 |
if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
|
|
|
147a26 |
@@ -231,23 +237,30 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|
|
147a26 |
}
|
|
|
147a26 |
|
|
|
147a26 |
|
|
|
147a26 |
/**
|
|
|
147a26 |
* pmksa_cache_flush - Flush PMKSA cache entries for a specific network
|
|
|
147a26 |
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
|
|
|
147a26 |
* @network_ctx: Network configuration context or %NULL to flush all entries
|
|
|
147a26 |
+ * @pmk: PMK to match for or %NYLL to match all PMKs
|
|
|
147a26 |
+ * @pmk_len: PMK length
|
|
|
147a26 |
*/
|
|
|
147a26 |
-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx)
|
|
|
147a26 |
+void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
|
|
|
147a26 |
+ const u8 *pmk, size_t pmk_len)
|
|
|
147a26 |
{
|
|
|
147a26 |
struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
|
|
|
147a26 |
int removed = 0;
|
|
|
147a26 |
|
|
|
147a26 |
entry = pmksa->pmksa;
|
|
|
147a26 |
while (entry) {
|
|
|
147a26 |
- if (entry->network_ctx == network_ctx || network_ctx == NULL) {
|
|
|
147a26 |
+ if ((entry->network_ctx == network_ctx ||
|
|
|
147a26 |
+ network_ctx == NULL) &&
|
|
|
147a26 |
+ (pmk == NULL ||
|
|
|
147a26 |
+ (pmk_len == entry->pmk_len &&
|
|
|
147a26 |
+ os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
|
|
|
147a26 |
wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
|
|
|
147a26 |
"for " MACSTR, MAC2STR(entry->aa));
|
|
|
147a26 |
if (prev)
|
|
|
147a26 |
prev->next = entry->next;
|
|
|
147a26 |
else
|
|
|
147a26 |
pmksa->pmksa = entry->next;
|
|
|
147a26 |
tmp = entry;
|
|
|
147a26 |
diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h
|
|
|
147a26 |
index 6f3dfb3..d5aa229 100644
|
|
|
147a26 |
--- a/src/rsn_supp/pmksa_cache.h
|
|
|
147a26 |
+++ b/src/rsn_supp/pmksa_cache.h
|
|
|
147a26 |
@@ -62,15 +62,16 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
|
|
|
147a26 |
void pmksa_cache_clear_current(struct wpa_sm *sm);
|
|
|
147a26 |
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
|
|
|
147a26 |
const u8 *bssid, void *network_ctx,
|
|
|
147a26 |
int try_opportunistic);
|
|
|
147a26 |
struct rsn_pmksa_cache_entry *
|
|
|
147a26 |
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
|
|
|
147a26 |
void *network_ctx, const u8 *aa);
|
|
|
147a26 |
-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx);
|
|
|
147a26 |
+void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
|
|
|
147a26 |
+ const u8 *pmk, size_t pmk_len);
|
|
|
147a26 |
|
|
|
147a26 |
#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
|
|
|
147a26 |
|
|
|
147a26 |
static inline struct rsn_pmksa_cache *
|
|
|
147a26 |
pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
|
|
|
147a26 |
void *ctx, int reason),
|
|
|
147a26 |
void *ctx, struct wpa_sm *sm)
|
|
|
147a26 |
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
|
|
|
147a26 |
index e50404c..365a710 100644
|
|
|
147a26 |
--- a/src/rsn_supp/wpa.c
|
|
|
147a26 |
+++ b/src/rsn_supp/wpa.c
|
|
|
147a26 |
@@ -2618,15 +2618,15 @@ void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
|
|
|
147a26 |
os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
|
|
|
147a26 |
}
|
|
|
147a26 |
|
|
|
147a26 |
|
|
|
147a26 |
void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
|
|
|
147a26 |
{
|
|
|
147a26 |
#ifndef CONFIG_NO_WPA2
|
|
|
147a26 |
- pmksa_cache_flush(sm->pmksa, network_ctx);
|
|
|
147a26 |
+ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
|
|
|
147a26 |
#endif /* CONFIG_NO_WPA2 */
|
|
|
147a26 |
}
|
|
|
147a26 |
|
|
|
147a26 |
|
|
|
147a26 |
#ifdef CONFIG_WNM
|
|
|
147a26 |
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
|
|
|
147a26 |
{
|
|
|
147a26 |
--
|
|
|
147a26 |
1.8.3.1
|
|
|
147a26 |
|