RADIUS DAS: Allow PMKSA cache entry to be removed without association
This extends Disconnect-Request processing to check against PMKSA cache entries if no active session (STA association) match the request. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
e94a3f626d
commit
cbc210de09
5 changed files with 99 additions and 0 deletions
|
@ -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
|
static enum radius_das_res
|
||||||
hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
|
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");
|
"RADIUS DAS: Multiple sessions match - not supported");
|
||||||
return RADIUS_DAS_MULTI_SESSION_MATCH;
|
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");
|
wpa_printf(MSG_DEBUG, "RADIUS DAS: No matching session found");
|
||||||
return RADIUS_DAS_SESSION_NOT_FOUND;
|
return RADIUS_DAS_SESSION_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "utils/eloop.h"
|
#include "utils/eloop.h"
|
||||||
#include "eapol_auth/eapol_auth_sm.h"
|
#include "eapol_auth/eapol_auth_sm.h"
|
||||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||||
|
#include "radius/radius_das.h"
|
||||||
#include "sta_info.h"
|
#include "sta_info.h"
|
||||||
#include "ap_config.h"
|
#include "ap_config.h"
|
||||||
#include "pmksa_cache_auth.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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -61,5 +61,7 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||||
struct eapol_state_machine *eapol);
|
struct eapol_state_machine *eapol);
|
||||||
void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
|
void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
|
||||||
struct rsn_pmksa_cache_entry *entry);
|
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 */
|
#endif /* PMKSA_CACHE_H */
|
||||||
|
|
|
@ -3340,3 +3340,10 @@ int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
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 */
|
#endif /* WPA_AUTH_H */
|
||||||
|
|
Loading…
Reference in a new issue