This is needed to avoid trying the subsequent connections with the old
PMKID that the AP claims not to hold and continues connection failures.
This was already handled for the SME-in-the-driver case in commit commit
50b77f50e80f ("DPP: Flush PMKSA if an assoc reject without timeout is
received"), but the wpa_supplicant SME case did not have matching
processing.
Add the needed check to avoid recover from cases where the AP has
dropped its PMKSA cache entry. Do this only based on the specific status
code value (53 = invalid PMKID) and only for the PMKSA entry that
triggered this failure to minimize actions taken based on an unprotected
(Re)Association Response frame.
Signed-off-by: Jouni Malinen <j@w1.fi>
}
+void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ struct rsn_pmksa_cache_entry *e;
+
+ e = pmksa->pmksa;
+ while (e) {
+ if (e == entry) {
+ pmksa->pmksa = entry->next;
+ break;
+ }
+ if (e->next == entry) {
+ e->next = entry->next;
+ break;
+ }
+ }
+
+ if (!e) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: Could not remove PMKSA cache entry %p since it is not in the list",
+ entry);
+ return;
+ }
+
+ pmksa_cache_free_entry(pmksa, entry, PMKSA_FREE);
+}
+
+
static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
{
struct rsn_pmksa_cache *pmksa = eloop_ctx;
void *network_ctx, const u8 *aa, int akmp);
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
const u8 *pmk, size_t pmk_len, bool external_only);
+void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry);
void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa);
#else /* IEEE8021X_EAPOL */
{
}
+static inline void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry)
+{
+}
+
static inline void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa)
{
}
}
+void wpa_sm_pmksa_cache_remove(struct wpa_sm *sm,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ if (sm && sm->pmksa)
+ pmksa_cache_remove(sm->pmksa, entry);
+}
+
+
void wpa_sm_drop_sa(struct wpa_sm *sm)
{
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
const u8 *pmkid,
const void *network_ctx,
int akmp);
+void wpa_sm_pmksa_cache_remove(struct wpa_sm *sm,
+ struct rsn_pmksa_cache_entry *entry);
bool wpa_sm_has_ft_keys(struct wpa_sm *sm, const u8 *md);
int wpa_sm_has_ptk_installed(struct wpa_sm *sm);
}
#endif /* CONFIG_SAE */
+#ifdef CONFIG_DPP
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
+ !data->assoc_reject.timed_out &&
+ data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ pmksa = pmksa_cache_get_current(wpa_s->wpa);
+ if (pmksa) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
+ wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
+ }
+ wpa_sm_aborted_cached(wpa_s->wpa);
+ if (wpa_s->current_bss) {
+ struct wpa_bss *bss = wpa_s->current_bss;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "DPP: Try network introduction again");
+ wpas_connect_work_done(wpa_s);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_supplicant_connect(wpa_s, bss, ssid);
+ return;
+ }
+ }
+#endif /* CONFIG_DPP */
+
/*
* For now, unconditionally terminate the previous authentication. In
* theory, this should not be needed, but mac80211 gets quite confused