[PATCH v2 16/33] FT-over-DS: use macaddr_acl
Michael Braun
michael-dev at fami-braun.de
Sat Sep 24 13:53:57 PDT 2016
With FT-over-air, the station sends an authentication request which is
subject to macaddr_acl (RADIUS) in src/ieee802_11.c.
But with FT-over-DS, the authentication request is replaced by an
FT-action frame and FT inter-AP messages, which are not subject to any
macaddr_acl logic.
This patch fixes this by adopting macaddr_acl processing for FT over DS.
This ensures session_timeout, radius accounting configuration and alike.
In order to correctly handle this, a new sta flag is introduced.
Therefore, sta->flags is converted to u64. Though, the BIT marcro only
works for <32bit (https://gcc.gnu.org/ml/gcc/1999-09n/msg00860.html).
Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
src/ap/ieee802_11.c | 12 +++++---
src/ap/sta_info.c | 5 +++-
src/ap/sta_info.h | 3 +-
src/ap/wpa_auth.h | 7 ++++-
src/ap/wpa_auth_ft.c | 67 +++++++++++++++++++++++++++++++++++++------
src/ap/wpa_auth_glue.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++--
6 files changed, 153 insertions(+), 18 deletions(-)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index caa05ad..d0a7029 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1008,11 +1008,13 @@ int handle_auth_cfg_sta(struct hostapd_data *hapd, struct sta_info *sta,
"Invalid VLAN %d%s received from RADIUS server",
info->vlan_id.untagged,
info->vlan_id.tagged[0] ? "+" : "");
- *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ if (resp)
+ *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
return -1;
}
if (ap_sta_set_vlan(hapd, sta, &info->vlan_id) < 0) {
- *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ if (resp)
+ *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
return -1;
}
if (sta->vlan_id)
@@ -2148,7 +2150,8 @@ static void handle_assoc(struct hostapd_data *hapd,
sta = ap_get_sta(hapd, mgmt->sa);
#ifdef CONFIG_IEEE80211R
if (sta && sta->auth_alg == WLAN_AUTH_FT &&
- (sta->flags & WLAN_STA_AUTH) == 0) {
+ (sta->flags & WLAN_STA_AUTH) == 0 &&
+ (sta->flags & WLAN_STA_PREAUTH_FT_OVER_DS)) {
wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
"prior to authentication since it is using "
"over-the-DS FT", MAC2STR(mgmt->sa));
@@ -2164,7 +2167,7 @@ static void handle_assoc(struct hostapd_data *hapd,
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "Station tried to "
"associate before authentication "
- "(aid=%d flags=0x%x)",
+ "(aid=%d flags=0x%lx)",
sta ? sta->aid : -1,
sta ? sta->flags : 0);
send_deauth(hapd, mgmt->sa,
@@ -2875,6 +2878,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
new_assoc = 0;
sta->flags |= WLAN_STA_ASSOC;
sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
+ sta->flags &= ~WLAN_STA_PREAUTH_FT_OVER_DS;
if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) ||
sta->auth_alg == WLAN_AUTH_FT) {
/*
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index f12d408..b508afb 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -376,7 +376,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
unsigned long next_time = 0;
int reason;
- wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%x timeout_next=%d",
+ wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%lx timeout_next=%d",
hapd->conf->iface, __func__, MAC2STR(sta->addr), sta->flags,
sta->timeout_next);
if (sta->timeout_next == STA_REMOVE) {
@@ -543,6 +543,9 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
+
+ sta->flags &= ~WLAN_STA_PREAUTH_FT_OVER_DS;
+
if (!(sta->flags & WLAN_STA_AUTH)) {
if (sta->flags & WLAN_STA_GAS) {
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index d0e43be..29043a6 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -41,6 +41,7 @@
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
+#define WLAN_STA_PREAUTH_FT_OVER_DS (((u64) 1) << 32)
/* Maximum number of supported rates (from both Supported Rates and Extended
* Supported Rates IEs). */
@@ -69,7 +70,7 @@ struct sta_info {
be32 ipaddr;
struct dl_list ip6addr; /* list head for struct ip6addr */
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
- u32 flags; /* Bitfield of WLAN_STA_* */
+ u64 flags; /* Bitfield of WLAN_STA_* */
u16 capability;
u16 listen_interval; /* or beacon_int for APs */
u8 supported_rates[WLAN_SUPP_RATES_MAX];
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 3c454ce..127ae60 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -223,7 +223,12 @@ struct wpa_auth_callbacks {
int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data,
size_t data_len);
#ifdef CONFIG_IEEE80211R
- struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
+ int (*add_sta)(void *ctx, const u8 *sta_addr,
+ struct wpa_state_machine **sm,
+ void (*cb)(void *ctx, const u8 *buf, size_t len,
+ const u8 *mac, int accepted,
+ u32 session_timeout),
+ void *cb_ctx, int cb_ctx_len);
int (*set_vlan)(void *ctx, const u8 *sta_addr,
struct vlan_description *vlan);
int (*get_vlan)(void *ctx, const u8 *sta_addr,
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 86e6a27..7530196 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -24,6 +24,9 @@
#ifdef CONFIG_IEEE80211R
+static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
+ const u8 *current_ap, const u8 *sta_addr,
+ const u8 *body, size_t len);
static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
const u8 *current_ap, const u8 *sta_addr,
u16 status, const u8 *resp_ies,
@@ -457,12 +460,19 @@ static inline const u8 * wpa_ft_get_psk(struct wpa_authenticator *wpa_auth,
}
-static struct wpa_state_machine *
-wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
+static int
+wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ struct wpa_state_machine **sm,
+ void (*cb)(void *hapd, const u8 *buf, size_t len,
+ const u8 *mac, int accepted, u32 session_timeout),
+ void *cb_ctx, int cb_ctx_len)
{
- if (wpa_auth->cb.add_sta == NULL)
- return NULL;
- return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr);
+ if (wpa_auth->cb.add_sta == NULL) {
+ *sm = NULL;
+ return 0;
+ }
+ return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr, sm, cb, cb_ctx,
+ cb_ctx_len);
}
@@ -2032,21 +2042,62 @@ static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR,
MAC2STR(sm->addr));
wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr,
- WLAN_STATUS_SUCCESS, ies, ies_len);
+ resp, ies, ies_len);
}
+struct wpa_ft_rrb_rx_request_restart_ctx {
+ struct wpa_authenticator *wpa_auth;
+ u8 current_ap[ETH_ALEN];
+ u8 sta_addr[ETH_ALEN];
+ u8 buf[];
+};
+
+
+static void
+wpa_ft_rrb_rx_request_restart_cb(void *hapd, const u8 *buf,
+ size_t len, const u8 *mac, int accepted,
+ u32 session_timeout)
+{
+ struct wpa_ft_rrb_rx_request_restart_ctx *ctx;
+
+ ctx = (struct wpa_ft_rrb_rx_request_restart_ctx *) buf;
+ wpa_ft_rrb_rx_request(ctx->wpa_auth, ctx->current_ap, ctx->sta_addr,
+ ctx->buf, len - sizeof(*ctx));
+}
+
static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
const u8 *current_ap, const u8 *sta_addr,
const u8 *body, size_t len)
{
- struct wpa_state_machine *sm;
+ struct wpa_state_machine *sm = NULL;
u16 status;
u8 *resp_ies;
size_t resp_ies_len;
int res;
+ struct wpa_ft_rrb_rx_request_restart_ctx *cb_ctx;
+
+ cb_ctx = os_zalloc(sizeof(*cb_ctx) + len);
+ if (cb_ctx == NULL) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to allocate "
+ "wpa_ft_rrb_rx_request_restart_ctx");
+ return -1;
+ }
+
+ cb_ctx->wpa_auth = wpa_auth;
+ os_memcpy(cb_ctx->current_ap, current_ap, ETH_ALEN);
+ os_memcpy(cb_ctx->sta_addr, sta_addr, ETH_ALEN);
+ os_memcpy(cb_ctx->buf, body, len);
- sm = wpa_ft_add_sta(wpa_auth, sta_addr);
+ res = wpa_ft_add_sta(wpa_auth, sta_addr, &sm,
+ &wpa_ft_rrb_rx_request_restart_cb, cb_ctx,
+ sizeof(*cb_ctx) + len);
+ os_free(cb_ctx); cb_ctx = NULL;
+ if (res < 0) {
+ wpa_printf(MSG_DEBUG, "FT: No immediate response available - "
+ "wait for macaddr_acl response");
+ return 0;
+ }
if (sm == NULL) {
wpa_printf(MSG_DEBUG, "FT: Failed to add new STA based on "
"RRB Request");
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index c29086a..fd1c4aa 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -19,6 +19,8 @@
#include "l2_packet/l2_packet.h"
#include "hostapd.h"
#include "ieee802_1x.h"
+#include "ieee802_11_auth.h"
+#include "ieee802_11.h"
#include "preauth_auth.h"
#include "sta_info.h"
#include "tkip_countermeasures.h"
@@ -547,9 +549,8 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
static struct wpa_state_machine *
-hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
+hostapd_wpa_auth_add_sta(struct hostapd_data *hapd, const u8 *sta_addr)
{
- struct hostapd_data *hapd = ctx;
struct sta_info *sta;
if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0)
@@ -574,6 +575,76 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
}
+static int
+hostapd_wpa_auth_add_sta_auth(void *ctx, const u8 *sta_addr,
+ struct wpa_state_machine **sm,
+ void (*cb)(void *hapd, const u8 *buf, size_t len,
+ const u8 *mac, int accepted,
+ u32 session_timeout),
+ void *cb_ctx, int cb_ctx_len)
+{
+ struct hostapd_data *hapd = ctx;
+ struct sta_info *sta = NULL;
+ int res = 0;
+ void (*cb2)(struct hostapd_data *hapd, const u8 *buf, size_t len,
+ const u8 *mac, int accepted, u32 session_timeout);
+ struct hostapd_allowed_address_info info;
+
+ hostapd_allowed_address_init(&info);
+ cb2 = (void (*) (struct hostapd_data *hapd, const u8 *buf, size_t len,
+ const u8 *mac, int accepted, u32 session_timeout)) cb;
+
+ if (os_memcmp(sta_addr, hapd->own_addr, ETH_ALEN) == 0) {
+ wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to "
+ "authenticate", MAC2STR(sta_addr));
+ *sm = NULL;
+ return 0;
+ }
+
+ *sm = hostapd_wpa_auth_add_sta(hapd, sta_addr);
+ if (!*sm)
+ return 0;
+
+ res = hostapd_allowed_address(hapd, sta_addr, (u8 *) cb_ctx,
+ cb_ctx_len, cb2, &info);
+
+ if (res == HOSTAPD_ACL_REJECT) {
+ wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to "
+ "authenticate", MAC2STR(sta_addr));
+ goto fail;
+ }
+ if (res == HOSTAPD_ACL_PENDING) {
+ wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
+ " waiting for an external authentication",
+ MAC2STR(sta_addr));
+ /* Authentication code will re-send the authentication frame
+ * after it has received (and cached) information from the
+ * external source.
+ */
+ res = -1;
+ goto fail;
+ }
+
+ sta = ap_get_sta(hapd, sta_addr);
+ if (!sta)
+ goto fail;
+
+ if (handle_auth_cfg_sta(hapd, sta, res, &info, NULL) < 0)
+ goto fail;
+
+ sta->flags &= ~WLAN_STA_PREAUTH;
+ sta->flags |= WLAN_STA_PREAUTH_FT_OVER_DS;
+
+ ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
+
+ return 0;
+fail:
+ hostapd_allowed_address_free(&info);
+ *sm = NULL;
+
+ return res;
+}
+
static int hostapd_wpa_auth_set_vlan(void *ctx, const u8 *sta_addr,
struct vlan_description *vlan)
@@ -691,7 +762,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
cb.send_ether = hostapd_wpa_auth_send_ether;
#ifdef CONFIG_IEEE80211R
cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
- cb.add_sta = hostapd_wpa_auth_add_sta;
+ cb.add_sta = hostapd_wpa_auth_add_sta_auth;
cb.set_vlan = hostapd_wpa_auth_set_vlan;
cb.get_vlan = hostapd_wpa_auth_get_vlan;
cb.add_tspec = hostapd_wpa_auth_add_tspec;
--
2.1.4
More information about the Hostap
mailing list