[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