HS 2.0R2 AP: Add support for deauthentication request
If the RADIUS server includes deauthentication request in Access-Accept, send a WNM-Notification frame to the station after 4-way handshake and disconnect the station after configurable timeout. A new control interface command, WNM_DEAUTH_REQ, is added for testing purposes to allow the notification frame to sent based on local request. This case does not disconnect the station automatically, i.e., a separate control interface command would be needed for that. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
a14896e8bb
commit
8e1146d9da
11 changed files with 167 additions and 0 deletions
|
@ -2814,6 +2814,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->osen = atoi(pos);
|
||||
} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
|
||||
bss->anqp_domain_id = atoi(pos);
|
||||
} else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
|
||||
bss->hs20_deauth_req_timeout = atoi(pos);
|
||||
} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
|
||||
if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
|
||||
errors++;
|
||||
|
|
|
@ -642,6 +642,56 @@ static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
|
|||
return hs20_send_wnm_notification(hapd, addr, 1, url);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
|
||||
const char *cmd)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
int code, reauth_delay, ret;
|
||||
const char *pos;
|
||||
size_t url_len;
|
||||
struct wpabuf *req;
|
||||
|
||||
/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
|
||||
if (hwaddr_aton(cmd, addr))
|
||||
return -1;
|
||||
|
||||
pos = os_strchr(cmd, ' ');
|
||||
if (pos == NULL)
|
||||
return -1;
|
||||
pos++;
|
||||
code = atoi(pos);
|
||||
|
||||
pos = os_strchr(pos, ' ');
|
||||
if (pos == NULL)
|
||||
return -1;
|
||||
pos++;
|
||||
reauth_delay = atoi(pos);
|
||||
|
||||
url_len = 0;
|
||||
pos = os_strchr(pos, ' ');
|
||||
if (pos) {
|
||||
pos++;
|
||||
url_len = os_strlen(pos);
|
||||
}
|
||||
|
||||
req = wpabuf_alloc(4 + url_len);
|
||||
if (req == NULL)
|
||||
return -1;
|
||||
wpabuf_put_u8(req, code);
|
||||
wpabuf_put_le16(req, reauth_delay);
|
||||
wpabuf_put_u8(req, url_len);
|
||||
if (pos)
|
||||
wpabuf_put_data(req, pos, url_len);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
|
||||
" to indicate imminent deauthentication (code=%d "
|
||||
"reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
|
||||
ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
|
||||
wpabuf_free(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
|
||||
|
@ -1379,6 +1429,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||
} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
|
||||
if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
|
||||
if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
|
||||
reply_len = -1;
|
||||
#endif /* CONFIG_HS20 */
|
||||
#ifdef CONFIG_WNM
|
||||
} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
|
||||
|
|
|
@ -1590,6 +1590,13 @@ own_ip_addr=127.0.0.1
|
|||
# information. 0 = Some of the ANQP information is unique to this AP (default).
|
||||
#anqp_domain_id=1234
|
||||
|
||||
# Deauthentication request timeout
|
||||
# If the RADIUS server indicates that the station is not allowed to connect to
|
||||
# the BSS/ESS, the AP can allow the station some time to download a
|
||||
# notification page (URL included in the message). This parameter sets that
|
||||
# timeout in seconds.
|
||||
#hs20_deauth_req_timeout=60
|
||||
|
||||
# Operator Friendly Name
|
||||
# This parameter can be used to configure one or more Operator Friendly Name
|
||||
# Duples. Each entry has a two or three character language code (ISO-639)
|
||||
|
|
|
@ -763,6 +763,31 @@ static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 3)
|
||||
res = os_snprintf(buf, sizeof(buf),
|
||||
"HS20_DEAUTH_REQ %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
else
|
||||
res = os_snprintf(buf, sizeof(buf),
|
||||
"HS20_DEAUTH_REQ %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
hostapd_cli_quit = 1;
|
||||
|
@ -962,6 +987,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
|
||||
{ "chan_switch", hostapd_cli_cmd_chan_switch },
|
||||
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
|
||||
{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -465,6 +465,7 @@ struct hostapd_bss_config {
|
|||
size_t hs20_connection_capability_len;
|
||||
u8 *hs20_operating_class;
|
||||
u8 hs20_operating_class_len;
|
||||
unsigned int hs20_deauth_req_timeout;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
|
||||
|
|
|
@ -140,3 +140,38 @@ int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
|
||||
const u8 *addr,
|
||||
const struct wpabuf *payload)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
int ret;
|
||||
|
||||
/* TODO: should refuse to send notification if the STA is not associated
|
||||
* or if the STA did not indicate support for WNM-Notification */
|
||||
|
||||
buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload));
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_ACTION_WNM);
|
||||
wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
|
||||
wpabuf_put_u8(buf, 1); /* Dialog token */
|
||||
wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
|
||||
|
||||
/* Deauthentication Imminent Notice subelement */
|
||||
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
|
||||
wpabuf_put_u8(buf, 4 + wpabuf_len(payload));
|
||||
wpabuf_put_be24(buf, OUI_WFA);
|
||||
wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE);
|
||||
wpabuf_put_buf(buf, payload);
|
||||
|
||||
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
||||
wpabuf_head(buf), wpabuf_len(buf));
|
||||
|
||||
wpabuf_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -15,5 +15,8 @@ u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid);
|
|||
u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid);
|
||||
int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 osu_method, const char *url);
|
||||
int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
|
||||
const u8 *addr,
|
||||
const struct wpabuf *payload);
|
||||
|
||||
#endif /* HS20_H */
|
||||
|
|
|
@ -1265,6 +1265,27 @@ static void ieee802_1x_hs20_sub_rem(struct sta_info *sta, u8 *pos, size_t len)
|
|||
/* TODO: assign the STA into remediation VLAN or add filtering */
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_hs20_deauth_req(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u8 *pos,
|
||||
size_t len)
|
||||
{
|
||||
if (len < 3)
|
||||
return; /* Malformed information */
|
||||
sta->hs20_deauth_requested = 1;
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: Deauthentication request - Code %u "
|
||||
"Re-auth Delay %u",
|
||||
*pos, WPA_GET_LE16(pos + 1));
|
||||
wpabuf_free(sta->hs20_deauth_req);
|
||||
sta->hs20_deauth_req = wpabuf_alloc(len + 1);
|
||||
if (sta->hs20_deauth_req) {
|
||||
wpabuf_put_data(sta->hs20_deauth_req, pos, 3);
|
||||
wpabuf_put_u8(sta->hs20_deauth_req, len - 3);
|
||||
wpabuf_put_data(sta->hs20_deauth_req, pos + 3, len - 3);
|
||||
}
|
||||
ap_sta_session_timeout(hapd, sta, hapd->conf->hs20_deauth_req_timeout);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
|
||||
|
@ -1278,6 +1299,8 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
|
|||
|
||||
buf = NULL;
|
||||
sta->remediation = 0;
|
||||
sta->hs20_deauth_requested = 0;
|
||||
|
||||
for (;;) {
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
|
||||
&buf, &len, buf) < 0)
|
||||
|
@ -1302,6 +1325,9 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
|
|||
case RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION:
|
||||
ieee802_1x_hs20_sub_rem(sta, pos, sublen);
|
||||
break;
|
||||
case RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ:
|
||||
ieee802_1x_hs20_deauth_req(hapd, sta, pos, sublen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
@ -1468,6 +1494,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||
ieee802_1x_update_sta_cui(hapd, sta, msg);
|
||||
ieee802_1x_check_hs20(hapd, sta, msg);
|
||||
if (sm->eap_if->eapKeyAvailable && !sta->remediation &&
|
||||
!sta->hs20_deauth_requested &&
|
||||
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
|
||||
session_timeout_set ?
|
||||
(int) session_timeout : -1, sm) == 0) {
|
||||
|
@ -2234,11 +2261,20 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
|
|||
os_free(sta->remediation_url);
|
||||
sta->remediation_url = NULL;
|
||||
}
|
||||
|
||||
if (sta->hs20_deauth_req) {
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification "
|
||||
"to " MACSTR " to indicate imminent "
|
||||
"deauthentication", MAC2STR(sta->addr));
|
||||
hs20_send_wnm_notification_deauth_req(
|
||||
hapd, sta->addr, sta->hs20_deauth_req);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
key = ieee802_1x_get_key(sta->eapol_sm, &len);
|
||||
if (success && key && len >= PMK_LEN && !sta->remediation &&
|
||||
!sta->hs20_deauth_requested &&
|
||||
wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime,
|
||||
sta->eapol_sm) == 0) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
|
||||
|
|
|
@ -266,6 +266,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
os_free(sta->identity);
|
||||
os_free(sta->radius_cui);
|
||||
os_free(sta->remediation_url);
|
||||
wpabuf_free(sta->hs20_deauth_req);
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
sae_clear_data(sta->sae);
|
||||
|
|
|
@ -58,6 +58,7 @@ struct sta_info {
|
|||
unsigned int no_p2p_set:1;
|
||||
unsigned int qos_map_enabled:1;
|
||||
unsigned int remediation:1;
|
||||
unsigned int hs20_deauth_requested:1;
|
||||
|
||||
u16 auth_alg;
|
||||
u8 previous_ap[6];
|
||||
|
@ -128,6 +129,7 @@ struct sta_info {
|
|||
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 wpabuf *hs20_deauth_req;
|
||||
|
||||
struct os_reltime connected_time;
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ enum {
|
|||
RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION = 1,
|
||||
RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION = 2,
|
||||
RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION = 3,
|
||||
RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ = 4,
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
Loading…
Reference in a new issue