HS 2.0R2 AP: Use Subscr Remediation request from RADIUS server
If the RADIUS server includes the WFA RADIUS VSA in Access-Accept to indicate need for subscription remediation, copy the server URL from the message and send it to the station after successfully completed 4-way handshake (i.e., after PTK is set to allow PMF to work) in a WNM-Notification. AP must not allow PMKSA caching to be used after subscription remediation association, so do not add the PMKSA cache entry whenever the authentication server is indicating need for subscription remediation. This allows station reassociation to use EAP authentication to move to non-remediation connection. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
7bc9c25d1f
commit
6ca0853d18
3 changed files with 92 additions and 2 deletions
|
@ -30,6 +30,7 @@
|
|||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "hs20.h"
|
||||
#include "ieee802_1x.h"
|
||||
|
||||
|
||||
|
@ -1238,6 +1239,74 @@ static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
|
||||
static void ieee802_1x_hs20_sub_rem(struct sta_info *sta, u8 *pos, size_t len)
|
||||
{
|
||||
sta->remediation = 1;
|
||||
os_free(sta->remediation_url);
|
||||
if (len > 2) {
|
||||
sta->remediation_url = os_malloc(len);
|
||||
if (!sta->remediation_url)
|
||||
return;
|
||||
sta->remediation_method = pos[0];
|
||||
os_memcpy(sta->remediation_url, pos + 1, len - 1);
|
||||
sta->remediation_url[len - 1] = '\0';
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed "
|
||||
"for " MACSTR " - server method %u URL %s",
|
||||
MAC2STR(sta->addr), sta->remediation_method,
|
||||
sta->remediation_url);
|
||||
} else {
|
||||
sta->remediation_url = NULL;
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed "
|
||||
"for " MACSTR, MAC2STR(sta->addr));
|
||||
}
|
||||
/* TODO: assign the STA into remediation VLAN or add filtering */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
|
||||
static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
#ifdef CONFIG_HS20
|
||||
u8 *buf, *pos, *end, type, sublen;
|
||||
size_t len;
|
||||
|
||||
buf = NULL;
|
||||
sta->remediation = 0;
|
||||
for (;;) {
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
|
||||
&buf, &len, buf) < 0)
|
||||
break;
|
||||
if (len < 6)
|
||||
continue;
|
||||
pos = buf;
|
||||
end = buf + len;
|
||||
if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA)
|
||||
continue;
|
||||
pos += 4;
|
||||
|
||||
type = *pos++;
|
||||
sublen = *pos++;
|
||||
if (sublen < 2)
|
||||
continue; /* invalid length */
|
||||
sublen -= 2; /* skip header */
|
||||
if (pos + sublen > end)
|
||||
continue; /* invalid WFA VSA */
|
||||
|
||||
switch (type) {
|
||||
case RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION:
|
||||
ieee802_1x_hs20_sub_rem(sta, pos, sublen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
}
|
||||
|
||||
|
||||
struct sta_id_search {
|
||||
u8 identifier;
|
||||
struct eapol_state_machine *sm;
|
||||
|
@ -1396,7 +1465,8 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||
ieee802_1x_store_radius_class(hapd, sta, msg);
|
||||
ieee802_1x_update_sta_identity(hapd, sta, msg);
|
||||
ieee802_1x_update_sta_cui(hapd, sta, msg);
|
||||
if (sm->eap_if->eapKeyAvailable &&
|
||||
ieee802_1x_check_hs20(hapd, sta, msg);
|
||||
if (sm->eap_if->eapKeyAvailable && !sta->remediation &&
|
||||
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
|
||||
session_timeout_set ?
|
||||
(int) session_timeout : -1, sm) == 0) {
|
||||
|
@ -2150,8 +2220,24 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
|
|||
/* TODO: get PMKLifetime from WPA parameters */
|
||||
static const int dot11RSNAConfigPMKLifetime = 43200;
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
if (success) {
|
||||
if (sta->remediation) {
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification "
|
||||
"to " MACSTR " to indicate Subscription "
|
||||
"Remediation",
|
||||
MAC2STR(sta->addr));
|
||||
hs20_send_wnm_notification(hapd, sta->addr,
|
||||
sta->remediation_method,
|
||||
sta->remediation_url);
|
||||
os_free(sta->remediation_url);
|
||||
sta->remediation_url = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
key = ieee802_1x_get_key(sta->eapol_sm, &len);
|
||||
if (success && key && len >= PMK_LEN &&
|
||||
if (success && key && len >= PMK_LEN && !sta->remediation &&
|
||||
wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime,
|
||||
sta->eapol_sm) == 0) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
|
||||
|
|
|
@ -265,6 +265,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
hostapd_free_psk_list(sta->psk);
|
||||
os_free(sta->identity);
|
||||
os_free(sta->radius_cui);
|
||||
os_free(sta->remediation_url);
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
sae_clear_data(sta->sae);
|
||||
|
|
|
@ -57,6 +57,7 @@ struct sta_info {
|
|||
unsigned int ht_20mhz_set:1;
|
||||
unsigned int no_p2p_set:1;
|
||||
unsigned int qos_map_enabled:1;
|
||||
unsigned int remediation:1;
|
||||
|
||||
u16 auth_alg;
|
||||
u8 previous_ap[6];
|
||||
|
@ -125,6 +126,8 @@ struct sta_info {
|
|||
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
||||
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
|
||||
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
|
||||
u8 remediation_method;
|
||||
char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
|
||||
|
||||
struct os_reltime connected_time;
|
||||
|
||||
|
|
Loading…
Reference in a new issue