"that was based on the old PMK");
if (!pos->opportunistic)
pmksa_cache_flush(pmksa, entry->network_ctx,
- pos->pmk, pos->pmk_len);
+ pos->pmk, pos->pmk_len,
+ false);
pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
break;
}
* @network_ctx: Network configuration context or %NULL to flush all entries
* @pmk: PMK to match for or %NULL to match all PMKs
* @pmk_len: PMK length
+ * @external_only: Flush only PMKSA cache entries configured by external
+ * applications
*/
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
- const u8 *pmk, size_t pmk_len)
+ const u8 *pmk, size_t pmk_len, bool external_only)
{
struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
int removed = 0;
network_ctx == NULL) &&
(pmk == NULL ||
(pmk_len == entry->pmk_len &&
- os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
+ os_memcmp(pmk, entry->pmk, pmk_len) == 0)) &&
+ (!external_only || entry->external)) {
wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
"for " MACSTR, MAC2STR(entry->aa));
if (prev)
*/
void *network_ctx;
int opportunistic;
+ bool external;
};
struct rsn_pmksa_cache;
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
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);
+ const u8 *pmk, size_t pmk_len, bool external_only);
#else /* IEEE8021X_EAPOL */
static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
void *network_ctx,
- const u8 *pmk, size_t pmk_len)
+ const u8 *pmk, size_t pmk_len,
+ bool external_only)
{
}
}
+void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
+{
+ if (sm && sm->cur_pmksa && sm->cur_pmksa->external) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Cancelling external PMKSA caching attempt");
+ sm->cur_pmksa = NULL;
+ }
+}
+
+
static void wpa_eapol_key_dump(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
unsigned int key_data_len,
void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
{
- pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
+ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, false);
+}
+
+
+void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
+{
+ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, true);
}
struct wpa_ie_data *data);
void wpa_sm_aborted_cached(struct wpa_sm *sm);
+void wpa_sm_aborted_external_cached(struct wpa_sm *sm);
int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len);
int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
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);
+void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx);
int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf);
{
}
+static inline void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
+{
+}
+
static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
{
}
+static inline void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm,
+ void *network_ctx)
+{
+}
+
static inline void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm,
void *network_ctx)
{
entry->network_ctx = ssid;
+ entry->external = true;
+
wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
entry = NULL;
ret = 0;
* Check for ERP keys existing to limit when this can be done since
* the rejection response is not protected and such triggers should
* really not allow internal state to be modified unless required to
- * avoid significant issues in functionality. In this case, this is
- * needed to allow recovery from cases where the AP or authentication
- * server has dropped PMKSAs and ERP keys. */
- if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
- eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
+ * avoid significant issues in functionality. In addition, drop
+ * externally configure PMKSA entries even without ERP keys since it
+ * is possible for an external component to add PMKSA entries for FILS
+ * authentication without restoring previously generated ERP keys.
+ *
+ * In this case, this is needed to allow recovery from cases where the
+ * AP or authentication server has dropped PMKSAs and ERP keys. */
+ if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
+ return;
+
+ if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
&username, &username_len,
&realm, &realm_len, &next_seq_num,
&rrk, &rrk_len) != 0 ||
- !realm)
+ !realm) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "FILS: Drop external PMKSA cache entry");
+ wpa_sm_aborted_external_cached(wpa_s->wpa);
+ wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
return;
+ }
wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
wpa_sm_aborted_cached(wpa_s->wpa);