From 0603bcb7fe8babf183362518238c142afe8e2036 Mon Sep 17 00:00:00 2001 From: Anton Nayshtut Date: Thu, 22 Oct 2015 19:48:04 +0300 Subject: [PATCH] hostapd: Process MAC ACLs on a station association event (SME in driver) Now hostapd will use station MAC-based permissions according to the macaddr_acl policy also for drivers which use AP SME offload, but do not support NL80211_CMD_SET_MAC_ACL for offloading MAC ACL processing. It should be noted that in this type of case the association goes through and the station gets disconnected immediately after that. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 9 ++++++++ src/ap/ieee802_11_auth.c | 50 +++++++++++++++++++++++++++------------- src/ap/ieee802_11_auth.h | 1 + 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 37537b3c6..fd0720156 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -22,6 +22,7 @@ #include "wnm_ap.h" #include "hostapd.h" #include "ieee802_11.h" +#include "ieee802_11_auth.h" #include "sta_info.h" #include "accounting.h" #include "tkip_countermeasures.h" @@ -114,6 +115,14 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, } sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); + res = hostapd_check_acl(hapd, addr, NULL); + if (res != HOSTAPD_ACL_ACCEPT) { + wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect", + MAC2STR(addr)); + reason = WLAN_REASON_UNSPECIFIED; + goto fail; + } + #ifdef CONFIG_P2P if (elems.p2p) { wpabuf_free(sta->p2p_ie); diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c index 531a67da4..b7e7ce357 100644 --- a/src/ap/ieee802_11_auth.c +++ b/src/ap/ieee802_11_auth.c @@ -212,6 +212,32 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, #endif /* CONFIG_NO_RADIUS */ +/** + * hostapd_check_acl - Check a specified STA against accept/deny ACLs + * @hapd: hostapd BSS data + * @addr: MAC address of the STA + * @vlan_id: Buffer for returning VLAN ID + * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING + */ + int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, int *vlan_id) +{ + if (hostapd_maclist_found(hapd->conf->accept_mac, + hapd->conf->num_accept_mac, addr, vlan_id)) + return HOSTAPD_ACL_ACCEPT; + + if (hostapd_maclist_found(hapd->conf->deny_mac, + hapd->conf->num_deny_mac, addr, vlan_id)) + return HOSTAPD_ACL_REJECT; + + if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) + return HOSTAPD_ACL_ACCEPT; + if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) + return HOSTAPD_ACL_REJECT; + + return HOSTAPD_ACL_PENDING; +} + + /** * hostapd_allowed_address - Check whether a specified STA can be authenticated * @hapd: hostapd BSS data @@ -235,6 +261,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, struct hostapd_sta_wpa_psk_short **psk, char **identity, char **radius_cui) { + int res; + if (session_timeout) *session_timeout = 0; if (acct_interim_interval) @@ -248,18 +276,9 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, if (radius_cui) *radius_cui = NULL; - if (hostapd_maclist_found(hapd->conf->accept_mac, - hapd->conf->num_accept_mac, addr, vlan_id)) - return HOSTAPD_ACL_ACCEPT; - - if (hostapd_maclist_found(hapd->conf->deny_mac, - hapd->conf->num_deny_mac, addr, vlan_id)) - return HOSTAPD_ACL_REJECT; - - if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) - return HOSTAPD_ACL_ACCEPT; - if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) - return HOSTAPD_ACL_REJECT; + res = hostapd_check_acl(hapd, addr, vlan_id); + if (res != HOSTAPD_ACL_PENDING) + return res; if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { #ifdef CONFIG_NO_RADIUS @@ -268,10 +287,9 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, struct hostapd_acl_query_data *query; /* Check whether ACL cache has an entry for this station */ - int res = hostapd_acl_cache_get(hapd, addr, session_timeout, - acct_interim_interval, - vlan_id, psk, - identity, radius_cui); + res = hostapd_acl_cache_get(hapd, addr, session_timeout, + acct_interim_interval, vlan_id, psk, + identity, radius_cui); if (res == HOSTAPD_ACL_ACCEPT || res == HOSTAPD_ACL_ACCEPT_TIMEOUT) return res; diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h index b66f244b3..da81c146d 100644 --- a/src/ap/ieee802_11_auth.h +++ b/src/ap/ieee802_11_auth.h @@ -16,6 +16,7 @@ enum { HOSTAPD_ACL_ACCEPT_TIMEOUT = 3 }; +int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, int *vlan_id); int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, const u8 *msg, size_t len, u32 *session_timeout, u32 *acct_interim_interval, int *vlan_id,