From c573c20bc8c5a16e4dce84b7d7692e1b8e98c347 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 18 Nov 2013 16:04:03 -0600 Subject: [PATCH] Don't disconnect when PMKSA cache gets too large (rh #1016707) --- ...OKC-based-PMKSA-cache-entry-clearing.patch | 150 ++++++++++++++++++ wpa_supplicant.spec | 9 +- 2 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 0001-Fix-OKC-based-PMKSA-cache-entry-clearing.patch diff --git a/0001-Fix-OKC-based-PMKSA-cache-entry-clearing.patch b/0001-Fix-OKC-based-PMKSA-cache-entry-clearing.patch new file mode 100644 index 0000000..91fdc12 --- /dev/null +++ b/0001-Fix-OKC-based-PMKSA-cache-entry-clearing.patch @@ -0,0 +1,150 @@ +From 4033935dd9098938838d6d7934ceb65f92a1fa3c Mon Sep 17 00:00:00 2001 +From: Jouni Malinen +Date: Wed, 22 May 2013 13:24:30 +0300 +Subject: [PATCH] Fix OKC-based PMKSA cache entry clearing + +Commit c3fea272747f738f5723fc577371fe03711d988f added a call to clear +all other PMKSA cache entries for the same network if the PMKSA cache +entry of the current AP changed. This was needed to fix OKC cases since +the other APs would likely use the new PMK in the future. However, this +ended up clearing entries in cases where that is not desired and this +resulted in needing additional full EAP authentication with networks +that did not support OKC if wpa_supplicant was configured to try to use +it. + +Make PMKSA cache entry flushing more limited so that the other entries +are removed only if they used the old PMK that was replaced for the +current AP and only if that PMK had previously been used successfully +(i.e., opportunistic flag was already cleared back to 0 in +wpa_supplicant_key_neg_complete()). This is still enough to fix the +issue described in that older commit while not causing problems for +standard PMKSA caching operations even if OKC is enabled in +wpa_supplicant configuration. + +Signed-hostap: Jouni Malinen +--- + src/rsn_supp/pmksa_cache.c | 27 ++++++++++++++++++++------- + src/rsn_supp/pmksa_cache.h | 3 ++- + src/rsn_supp/wpa.c | 2 +- + 3 files changed, 23 insertions(+), 9 deletions(-) + +diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c +index df67583..93056ea 100644 +--- a/src/rsn_supp/pmksa_cache.c ++++ b/src/rsn_supp/pmksa_cache.c +@@ -160,25 +160,31 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, + os_free(entry); + return pos; + } + if (prev == NULL) + pmksa->pmksa = pos->next; + else + prev->next = pos->next; +- wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " +- "the current AP"); +- pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); + + /* + * If OKC is used, there may be other PMKSA cache + * entries based on the same PMK. These needs to be + * flushed so that a new entry can be created based on +- * the new PMK. ++ * the new PMK. Only clear other entries if they have a ++ * matching PMK and this PMK has been used successfully ++ * with the current AP, i.e., if opportunistic flag has ++ * been cleared in wpa_supplicant_key_neg_complete(). + */ +- pmksa_cache_flush(pmksa, network_ctx); ++ wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " ++ "the current AP and any PMKSA cache entry " ++ "that was based on the old PMK"); ++ if (!pos->opportunistic) ++ pmksa_cache_flush(pmksa, network_ctx, pos->pmk, ++ pos->pmk_len); ++ pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); + break; + } + prev = pos; + pos = pos->next; + } + + if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { +@@ -231,23 +237,30 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, + } + + + /** + * pmksa_cache_flush - Flush PMKSA cache entries for a specific network + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() + * @network_ctx: Network configuration context or %NULL to flush all entries ++ * @pmk: PMK to match for or %NYLL to match all PMKs ++ * @pmk_len: PMK length + */ +-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx) ++void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, ++ const u8 *pmk, size_t pmk_len) + { + struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp; + int removed = 0; + + entry = pmksa->pmksa; + while (entry) { +- if (entry->network_ctx == network_ctx || network_ctx == NULL) { ++ if ((entry->network_ctx == network_ctx || ++ network_ctx == NULL) && ++ (pmk == NULL || ++ (pmk_len == entry->pmk_len && ++ os_memcmp(pmk, entry->pmk, pmk_len) == 0))) { + wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry " + "for " MACSTR, MAC2STR(entry->aa)); + if (prev) + prev->next = entry->next; + else + pmksa->pmksa = entry->next; + tmp = entry; +diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h +index 6f3dfb3..d5aa229 100644 +--- a/src/rsn_supp/pmksa_cache.h ++++ b/src/rsn_supp/pmksa_cache.h +@@ -62,15 +62,16 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); + void pmksa_cache_clear_current(struct wpa_sm *sm); + int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, + const u8 *bssid, void *network_ctx, + int try_opportunistic); + struct rsn_pmksa_cache_entry * + pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, + void *network_ctx, const u8 *aa); +-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx); ++void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, ++ const u8 *pmk, size_t pmk_len); + + #else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ + + static inline struct rsn_pmksa_cache * + pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx, int reason), + void *ctx, struct wpa_sm *sm) +diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c +index e50404c..365a710 100644 +--- a/src/rsn_supp/wpa.c ++++ b/src/rsn_supp/wpa.c +@@ -2618,15 +2618,15 @@ void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr) + os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN); + } + + + void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx) + { + #ifndef CONFIG_NO_WPA2 +- pmksa_cache_flush(sm->pmksa, network_ctx); ++ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0); + #endif /* CONFIG_NO_WPA2 */ + } + + + #ifdef CONFIG_WNM + int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) + { +-- +1.8.3.1 + diff --git a/wpa_supplicant.spec b/wpa_supplicant.spec index 9d3b81a..1df49c8 100644 --- a/wpa_supplicant.spec +++ b/wpa_supplicant.spec @@ -7,7 +7,7 @@ Summary: WPA/WPA2/IEEE 802.1X Supplicant Name: wpa_supplicant Epoch: 1 Version: 2.0 -Release: 7%{?dist} +Release: 8%{?dist} License: BSD Group: System Environment/Base Source0: http://w1.fi/releases/%{name}-%{version}%{rcver}%{snapshot}.tar.gz @@ -42,6 +42,9 @@ Patch6: wpa_supplicant-gui-qt4.patch Patch7: libnl3-includes.patch # Less aggressive roaming; signal strength is wildly variable Patch8: rh837402-less-aggressive-roaming.patch +# Don't evict current AP from PMKSA cache when it's large +Patch9: 0001-Fix-OKC-based-PMKSA-cache-entry-clearing.patch + %if %{build_libeap} # Dirty hack for WiMAX # http://linuxwimax.org/Download?action=AttachFile&do=get&target=wpa-1.5-README.txt @@ -110,6 +113,7 @@ Don't use this unless you know what you're doing. %patch6 -p1 -b .qt4 %patch7 -p1 -b .libnl3 %patch8 -p1 -b .rh837402-less-aggressive-roaming +%patch9 -p1 -b .okc-current-fix %build pushd wpa_supplicant @@ -253,6 +257,9 @@ fi %endif %changelog +* Mon Nov 18 2013 Dan Williams - 1:2.0-8 +- Don't disconnect when PMKSA cache gets too large (rh #1016707) + * Sun Aug 04 2013 Fedora Release Engineering - 1:2.0-7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild