Blame SOURCES/rh1032758-fix-pmksa-cache-entry-clearing.patch

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