}
+/**
+ * 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
+ */
+void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx)
+{
+ 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) {
+ 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;
+ entry = entry->next;
+ wpa_sm_remove_pmkid(pmksa->sm, tmp->aa, tmp->pmkid);
+ pmksa_cache_free_entry(pmksa, tmp, 0);
+ removed++;
+ } else {
+ prev = entry;
+ entry = entry->next;
+ }
+ }
+ if (removed)
+ pmksa_cache_set_expiration(pmksa);
+}
+
+
/**
* pmksa_cache_deinit - Free all entries in PMKSA cache
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
}
-/**
- * pmksa_cache_notify_reconfig - Reconfiguration notification for PMKSA cache
- * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
- *
- * Clear references to old data structures when wpa_supplicant is reconfigured.
- */
-void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa)
-{
- struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
- while (entry) {
- entry->network_ctx = NULL;
- entry = entry->next;
- }
-}
-
-
static struct rsn_pmksa_cache_entry *
pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
const struct rsn_pmksa_cache_entry *old_entry,
struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
-void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa);
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,
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);
#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
return NULL;
}
-static inline void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa)
-{
-}
-
static inline void pmksa_cache_clear_current(struct wpa_sm *sm)
{
}
return -1;
}
+static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
+ void *network_ctx)
+{
+}
+
#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
#endif /* PMKSA_CACHE_H */
sm->ssid_len = 0;
sm->wpa_ptk_rekey = 0;
}
- if (config == NULL || config->network_ctx != sm->network_ctx)
- pmksa_cache_notify_reconfig(sm->pmksa);
}
{
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);
+#endif /* CONFIG_NO_WPA2 */
+}
void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr);
+void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx);
+
#else /* CONFIG_NO_WPA */
static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
{
}
+static inline void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm,
+ void *network_ctx)
+{
+}
+
#endif /* CONFIG_NO_WPA */
#ifdef CONFIG_PEERKEY
wpas_notify_network_removed(wpa_s, remove_ssid);
wpa_config_remove_network(wpa_s->conf, id);
}
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
if (wpa_s->current_ssid) {
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_supplicant_disassociate(wpa_s,
return -1;
}
- if (ssid == wpa_s->current_ssid) {
+ if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
/*
- * Invalidate the EAP session cache if the current network is
- * removed.
+ * Invalidate the EAP session cache if the current or
+ * previously used network is removed.
*/
eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
+
+ if (ssid == wpa_s->current_ssid) {
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
return -1;
}
- if (wpa_s->current_ssid == ssid) {
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+
+ if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
/*
* Invalidate the EAP session cache if anything in the current
- * configuration changes.
+ * or previously used configuration changes.
*/
eapol_sm_invalidate_cached_session(wpa_s->eapol);
}
#include "dbus/dbus_common.h"
#include "dbus/dbus_old.h"
#include "dbus/dbus_new.h"
+#include "rsn_supp/wpa.h"
#include "driver_i.h"
#include "scan.h"
#include "p2p_supplicant.h"
void wpas_notify_network_removed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
if (wpa_s->global->p2p_group_formation != wpa_s)
wpas_dbus_unregister_network(wpa_s, ssid->id);
}
}
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_sm_set_config(wpa_s->wpa, NULL);
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
rsn_preauth_deinit(wpa_s->wpa);