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:
Jouni Malinen 2015-01-16 15:55:39 +02:00 committed by Jouni Malinen
parent e94a3f626d
commit cbc210de09
5 changed files with 99 additions and 0 deletions

View file

@ -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;
} }

View file

@ -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;
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 */