diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 81e9b2b15..b641503c7 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -794,6 +794,15 @@ static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd, } +static int hostapd_das_disconnect_pmksa(struct hostapd_data *hapd, + struct radius_das_attrs *attr) +{ + if (!hapd->wpa_auth) + return -1; + return wpa_auth_radius_das_disconnect_pmksa(hapd->wpa_auth, attr); +} + + static enum radius_das_res hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr) { @@ -811,6 +820,11 @@ hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr) "RADIUS DAS: Multiple sessions match - not supported"); return RADIUS_DAS_MULTI_SESSION_MATCH; } + if (hostapd_das_disconnect_pmksa(hapd, attr) == 0) { + wpa_printf(MSG_DEBUG, + "RADIUS DAS: PMKSA cache entry matched"); + return RADIUS_DAS_SUCCESS; + } wpa_printf(MSG_DEBUG, "RADIUS DAS: No matching session found"); return RADIUS_DAS_SESSION_NOT_FOUND; } diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index 427038217..650e9a81d 100644 --- a/src/ap/pmksa_cache_auth.c +++ b/src/ap/pmksa_cache_auth.c @@ -12,6 +12,7 @@ #include "utils/eloop.h" #include "eapol_auth/eapol_auth_sm.h" #include "eapol_auth/eapol_auth_sm_i.h" +#include "radius/radius_das.h" #include "sta_info.h" #include "ap_config.h" #include "pmksa_cache_auth.h" @@ -452,3 +453,74 @@ pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, return pmksa; } + + +static int das_attr_match(struct rsn_pmksa_cache_entry *entry, + struct radius_das_attrs *attr) +{ + int match = 0; + + if (attr->sta_addr) { + if (os_memcmp(attr->sta_addr, entry->spa, ETH_ALEN) != 0) + return 0; + match++; + } + + if (attr->acct_multi_session_id) { + char buf[20]; + + if (attr->acct_multi_session_id_len != 17) + return 0; + os_snprintf(buf, sizeof(buf), "%08X+%08X", + entry->acct_multi_session_id_hi, + entry->acct_multi_session_id_lo); + if (os_memcmp(attr->acct_multi_session_id, buf, 17) != 0) + return 0; + match++; + } + + if (attr->cui) { + if (!entry->cui || + attr->cui_len != wpabuf_len(entry->cui) || + os_memcmp(attr->cui, wpabuf_head(entry->cui), + attr->cui_len) != 0) + return 0; + match++; + } + + if (attr->user_name) { + if (!entry->identity || + attr->user_name_len != entry->identity_len || + os_memcmp(attr->user_name, entry->identity, + attr->user_name_len) != 0) + return 0; + match++; + } + + return match; +} + + +int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, + struct radius_das_attrs *attr) +{ + int found = 0; + struct rsn_pmksa_cache_entry *entry, *prev; + + if (attr->acct_session_id) + return -1; + + entry = pmksa->pmksa; + while (entry) { + if (das_attr_match(entry, attr)) { + found++; + prev = entry; + entry = entry->next; + pmksa_cache_free_entry(pmksa, prev); + continue; + } + entry = entry->next; + } + + return found ? 0 : -1; +} diff --git a/src/ap/pmksa_cache_auth.h b/src/ap/pmksa_cache_auth.h index 519555f8a..8b7be1291 100644 --- a/src/ap/pmksa_cache_auth.h +++ b/src/ap/pmksa_cache_auth.h @@ -61,5 +61,7 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, struct eapol_state_machine *eapol); void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, struct rsn_pmksa_cache_entry *entry); +int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, + struct radius_das_attrs *attr); #endif /* PMKSA_CACHE_H */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 059b8848d..f71b02857 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3340,3 +3340,10 @@ int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) return 0; } #endif /* CONFIG_P2P */ + + +int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, + struct radius_das_attrs *attr) +{ + return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr); +} diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 757e49e44..b34b84dd6 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -315,4 +315,8 @@ int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm); int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr); +struct radius_das_attrs; +int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, + struct radius_das_attrs *attr); + #endif /* WPA_AUTH_H */