[PATCH 15/44] FT-over-DS: use macaddr_acl

michael-dev at fami-braun.de michael-dev at fami-braun.de
Wed Feb 24 03:53:21 PST 2016


From: Michael Braun <michael-dev at fami-braun.de>

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 | 78 ++++++++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 154 insertions(+), 18 deletions(-)

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index d318b53..7bf6d2e 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -936,11 +936,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)
@@ -2037,7 +2039,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));
@@ -2053,7 +2056,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,
@@ -2756,6 +2759,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 60058e4..e5976f9 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -368,7 +368,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) {
@@ -535,6 +535,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 08e795e..abb207c 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -40,6 +40,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). */
@@ -63,7 +64,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 400828f..1a2ff92 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -235,7 +235,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 ft_vlan *vlan);
 	int (*get_vlan)(void *ctx, const u8 *sta_addr, struct ft_vlan *vlan);
 	int (*send_ft_action)(void *ctx, const u8 *dst,
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 4007764..9fef8f2 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,
@@ -51,12 +54,19 @@ static int wpa_ft_action_send(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);
 }
 
 
@@ -1339,21 +1349,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 ec82080..f72ac7f 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -18,6 +18,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"
@@ -536,9 +538,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)
@@ -563,6 +564,77 @@ 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;
+}
+
+
 /* sanity check for vlan definitions */
 #if FT_MAX_NUM_TAGGED_VLAN != MAX_NUM_TAGGED_VLAN
 #error FT_MAX_NUM_TAGGED_VLAN and MAX_NUM_TAGGED_VLAN differ
@@ -734,7 +806,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;
-- 
1.9.1




More information about the Hostap mailing list