From 5ee56c4e1930b007d36704f62e614e0dbb88f1f8 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Sun, 25 Nov 2012 17:49:25 +0200 Subject: [PATCH] Keep and use list of PSKs per station for RADIUS-based PSK This adds support for multiple PSKs per station when using a RADIUS authentication server to fetch the PSKs during MAC address authentication step. This can be useful if multiple users share a device but each user has his or her own private passphrase. Signed-hostap: Michael Braun --- src/ap/ieee802_11.c | 14 ++++++++------ src/ap/sta_info.c | 6 +++++- src/ap/sta_info.h | 3 ++- src/ap/wpa_auth_glue.c | 14 +++++++++++--- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 3bc7059db..9e87b8096 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -570,13 +570,15 @@ static void handle_auth(struct hostapd_data *hapd, HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); } - if (psk && hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) { - os_free(sta->psk); - sta->psk = os_malloc(PMK_LEN); - if (sta->psk) - os_memcpy(sta->psk, psk->psk, PMK_LEN); + while (sta->psk) { + struct hostapd_sta_wpa_psk_short *prev = sta->psk; + sta->psk = sta->psk->next; + os_free(prev); + } + if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) { + sta->psk = psk; + psk = NULL; } else { - os_free(sta->psk); sta->psk = NULL; } diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 4f57af5dc..ef1aab891 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -235,7 +235,11 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) wpabuf_free(sta->hs20_ie); os_free(sta->ht_capabilities); - os_free(sta->psk); + while (sta->psk) { + struct hostapd_sta_wpa_psk_short *prev = sta->psk; + sta->psk = sta->psk->next; + os_free(prev); + } os_free(sta->identity); os_free(sta->radius_cui); diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 132830f99..d5e92faa7 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -95,7 +95,8 @@ struct sta_info { struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */ int vlan_id; - u8 *psk; /* PSK from RADIUS authentication server */ + /* PSKs from RADIUS authentication server */ + struct hostapd_sta_wpa_psk_short *psk; char *identity; /* User-Name from RADIUS */ char *radius_cui; /* Chargeable-User-Identity from RADIUS */ diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 68fe59653..76c61ea18 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -188,10 +188,18 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, /* * This is about to iterate over all psks, prev_psk gives the last * returned psk which should not be returned again. - * logic list (all hostapd_get_psk; sta->psk) + * logic list (all hostapd_get_psk; all sta->psk) */ - if (sta && sta->psk && !psk && sta->psk != prev_psk) - psk = sta->psk; + if (sta && sta->psk && !psk) { + struct hostapd_sta_wpa_psk_short *pos; + psk = sta->psk->psk; + for (pos = sta->psk; pos; pos = pos->next) { + if (pos->psk == prev_psk) { + psk = pos->next ? pos->next->psk : NULL; + break; + } + } + } return psk; }