[PATCH v2 15/33] 802.11 Factor out authentication code for reuse with FT-over-DS

Michael Braun michael-dev at fami-braun.de
Sat Sep 24 13:53:56 PDT 2016


Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
 src/ap/ieee802_11.c      | 143 ++++++++++++++++++++++++++++-------------------
 src/ap/ieee802_11.h      |   4 ++
 src/ap/ieee802_11_auth.c | 110 ++++++++++++++++++------------------
 src/ap/ieee802_11_auth.h |  24 ++++++--
 4 files changed, 166 insertions(+), 115 deletions(-)

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index f1c396b..caa05ad 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -980,6 +980,76 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
 #endif /* CONFIG_SAE */
 
 
+void handle_auth_restart_cb(struct hostapd_data *hapd, const u8 *buf,
+			    size_t len, const u8 *mac, int accepted,
+			    u32 session_timeout)
+{
+#ifdef CONFIG_DRIVER_RADIUS_ACL
+	hostapd_drv_set_radius_acl_auth(hapd, mac, accepted, session_timeout);
+#else /* CONFIG_DRIVER_RADIUS_ACL */
+#ifdef NEED_AP_MLME
+	/* Re-send original authentication frame for 802.11 processing */
+	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
+		   "successful RADIUS ACL query");
+	ieee802_11_mgmt(hapd, buf, len, NULL);
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_DRIVER_RADIUS_ACL */
+}
+
+
+int handle_auth_cfg_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			int res, struct hostapd_allowed_address_info *info,
+			u16 *resp)
+{
+	if (info->vlan_id.notempty &&
+	    !hostapd_vlan_valid(hapd->conf->vlan, &info->vlan_id)) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+			       HOSTAPD_LEVEL_INFO,
+			       "Invalid VLAN %d%s received from RADIUS server",
+			       info->vlan_id.untagged,
+			       info->vlan_id.tagged[0] ? "+" : "");
+		*resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+		return -1;
+	}
+	if (ap_sta_set_vlan(hapd, sta, &info->vlan_id) < 0) {
+		*resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+		return -1;
+	}
+	if (sta->vlan_id)
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+			       HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
+
+	hostapd_free_psk_list(sta->psk);
+	if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED)
+		hostapd_copy_psk_list(&sta->psk, info->psk);
+	else
+		sta->psk = NULL;
+
+	os_free(sta->identity);
+	if (info->identity)
+		sta->identity = os_strdup(info->identity);
+	else
+		sta->identity = NULL;
+
+	os_free(sta->radius_cui);
+	if (info->radius_cui)
+		sta->radius_cui = os_strdup(info->radius_cui);
+	else
+		sta->radius_cui = NULL;
+
+	if (hapd->conf->acct_interim_interval == 0 &&
+	    info->acct_interim_interval)
+		sta->acct_interim_interval = info->acct_interim_interval;
+
+	if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
+		ap_sta_session_timeout(hapd, sta, info->session_timeout);
+	else
+		ap_sta_no_session_timeout(hapd, sta);
+
+	return 0;
+}
+
+
 static void handle_auth(struct hostapd_data *hapd,
 			const struct ieee80211_mgmt *mgmt, size_t len)
 {
@@ -989,16 +1059,10 @@ static void handle_auth(struct hostapd_data *hapd,
 	int res, reply_res;
 	u16 fc;
 	const u8 *challenge = NULL;
-	u32 session_timeout, acct_interim_interval;
-	struct vlan_description vlan_id;
-	struct hostapd_sta_wpa_psk_short *psk = NULL;
 	u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
 	size_t resp_ies_len = 0;
-	char *identity = NULL;
-	char *radius_cui = NULL;
 	u16 seq_ctrl;
-
-	os_memset(&vlan_id, 0, sizeof(vlan_id));
+	struct hostapd_allowed_address_info details;
 
 	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
 		wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
@@ -1016,6 +1080,8 @@ static void handle_auth(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
+	hostapd_allowed_address_init(&details);
+
 	auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
 	auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
 	status_code = le_to_host16(mgmt->u.auth.status_code);
@@ -1140,9 +1206,8 @@ static void handle_auth(struct hostapd_data *hapd,
 	}
 
 	res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
-				      &session_timeout,
-				      &acct_interim_interval, &vlan_id,
-				      &psk, &identity, &radius_cui);
+				      &handle_auth_restart_cb,
+				      &details);
 
 	if (res == HOSTAPD_ACL_REJECT) {
 		wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
@@ -1157,7 +1222,7 @@ static void handle_auth(struct hostapd_data *hapd,
 		/* Authentication code will re-send the authentication frame
 		 * after it has received (and cached) information from the
 		 * external source. */
-		return;
+		goto out;
 	}
 
 	sta = ap_get_sta(hapd, mgmt->sa);
@@ -1171,7 +1236,7 @@ static void handle_auth(struct hostapd_data *hapd,
 				       HOSTAPD_LEVEL_DEBUG,
 				       "Drop repeated authentication frame seq_ctrl=0x%x",
 				       seq_ctrl);
-			return;
+			goto out;
 		}
 #ifdef CONFIG_MESH
 		if ((hapd->conf->mesh & MESH_ENABLED) &&
@@ -1179,7 +1244,7 @@ static void handle_auth(struct hostapd_data *hapd,
 			wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
 				   " is blocked - drop Authentication frame",
 				   MAC2STR(mgmt->sa));
-			return;
+			goto out;
 		}
 #endif /* CONFIG_MESH */
 	} else {
@@ -1197,7 +1262,7 @@ static void handle_auth(struct hostapd_data *hapd,
 			wpabuf_free(hapd->mesh_pending_auth);
 			hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
 			os_get_reltime(&hapd->mesh_pending_auth_time);
-			return;
+			goto out;
 		}
 #endif /* CONFIG_MESH */
 
@@ -1210,47 +1275,12 @@ static void handle_auth(struct hostapd_data *hapd,
 	sta->last_seq_ctrl = seq_ctrl;
 	sta->last_subtype = WLAN_FC_STYPE_AUTH;
 
-	if (vlan_id.notempty &&
-	    !hostapd_vlan_valid(hapd->conf->vlan, &vlan_id)) {
-		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
-			       HOSTAPD_LEVEL_INFO,
-			       "Invalid VLAN %d%s received from RADIUS server",
-			       vlan_id.untagged,
-			       vlan_id.tagged[0] ? "+" : "");
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-		goto fail;
-	}
-	if (ap_sta_set_vlan(hapd, sta, &vlan_id) < 0) {
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	if (handle_auth_cfg_sta(hapd, sta, res, &details, &resp) < 0)
 		goto fail;
-	}
-	if (sta->vlan_id)
-		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
-			       HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
-
-	hostapd_free_psk_list(sta->psk);
-	if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
-		sta->psk = psk;
-		psk = NULL;
-	} else {
-		sta->psk = NULL;
-	}
-
-	sta->identity = identity;
-	identity = NULL;
-	sta->radius_cui = radius_cui;
-	radius_cui = NULL;
 
 	sta->flags &= ~WLAN_STA_PREAUTH;
 	ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
 
-	if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
-		sta->acct_interim_interval = acct_interim_interval;
-	if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
-		ap_sta_session_timeout(hapd, sta, session_timeout);
-	else
-		ap_sta_no_session_timeout(hapd, sta);
-
 	/*
 	 * If the driver supports full AP client state, add a station to the
 	 * driver before sending authentication reply to make sure the driver
@@ -1334,7 +1364,7 @@ static void handle_auth(struct hostapd_data *hapd,
 				    sizeof(mgmt->u.auth),
 				    handle_auth_ft_finish, hapd);
 		/* handle_auth_ft_finish() callback will complete auth. */
-		return;
+		goto out;
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_SAE
 	case WLAN_AUTH_SAE:
@@ -1355,15 +1385,11 @@ static void handle_auth(struct hostapd_data *hapd,
 #endif /* CONFIG_MESH */
 		handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
 				status_code);
-		return;
+		goto out;
 #endif /* CONFIG_SAE */
 	}
 
- fail:
-	os_free(identity);
-	os_free(radius_cui);
-	hostapd_free_psk_list(psk);
-
+fail:
 	reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
 				    auth_transaction + 1, resp, resp_ies,
 				    resp_ies_len);
@@ -1373,6 +1399,9 @@ static void handle_auth(struct hostapd_data *hapd,
 		hostapd_drv_sta_remove(hapd, sta->addr);
 		sta->added_unassoc = 0;
 	}
+
+out:
+	hostapd_allowed_address_free(&details);
 }
 
 
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 0327dec..7ce33cb 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -16,6 +16,7 @@ struct hostapd_frame_info;
 struct ieee80211_ht_capabilities;
 struct ieee80211_vht_capabilities;
 struct ieee80211_mgmt;
+struct hostapd_allowed_address_info;
 
 int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
 		    struct hostapd_frame_info *fi);
@@ -109,6 +110,9 @@ static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
 {
 }
 #endif /* CONFIG_SAE */
+int handle_auth_cfg_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			int res, struct hostapd_allowed_address_info *info,
+			u16 *resp);
 
 #ifdef CONFIG_MBO
 
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index b890537..d3d4145 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -47,10 +47,25 @@ struct hostapd_acl_query_data {
 	macaddr addr;
 	u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
 	size_t auth_msg_len;
+	void (*cb)(struct hostapd_data *hapd, const u8 *buf, size_t len,
+		   const u8 *mac, int accepted, u32 session_timeout);
 	struct hostapd_acl_query_data *next;
 };
 
 
+void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
+			   struct hostapd_sta_wpa_psk_short *src)
+{
+	if (!psk)
+		return;
+
+	if (src)
+		src->ref++;
+
+	*psk = src;
+}
+
+
 #ifndef CONFIG_NO_RADIUS
 static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
 {
@@ -73,19 +88,6 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
 }
 
 
-static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
-			  struct hostapd_sta_wpa_psk_short *src)
-{
-	if (!psk)
-		return;
-
-	if (src)
-		src->ref++;
-
-	*psk = src;
-}
-
-
 static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
 				 u32 *session_timeout,
 				 u32 *acct_interim_interval,
@@ -113,7 +115,7 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
 				entry->acct_interim_interval;
 		if (vlan_id)
 			*vlan_id = entry->vlan_id;
-		copy_psk_list(psk, entry->psk);
+		hostapd_copy_psk_list(psk, entry->psk);
 		if (identity) {
 			if (entry->identity)
 				*identity = os_strdup(entry->identity);
@@ -205,6 +207,23 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
 #endif /* CONFIG_NO_RADIUS */
 
 
+void hostapd_allowed_address_init(struct hostapd_allowed_address_info *info)
+{
+	os_memset(info, 0, sizeof(*info));
+}
+
+
+void hostapd_allowed_address_free(struct hostapd_allowed_address_info *info)
+{
+	os_free(info->identity);
+	info->identity = NULL;
+	os_free(info->radius_cui);
+	info->radius_cui = NULL;
+	hostapd_free_psk_list(info->psk);
+	info->psk = NULL;
+}
+
+
 /**
  * hostapd_check_acl - Check a specified STA against accept/deny ACLs
  * @hapd: hostapd BSS data
@@ -250,28 +269,16 @@ int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
  * values with os_free().
  */
 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
-			    const u8 *msg, size_t len, u32 *session_timeout,
-			    u32 *acct_interim_interval,
-			    struct vlan_description *vlan_id,
-			    struct hostapd_sta_wpa_psk_short **psk,
-			    char **identity, char **radius_cui)
+			    const u8 *msg, size_t len,
+			    void (*cb)(struct hostapd_data *hapd,
+				       const u8 *buf, size_t len,
+				       const u8 *mac, int accepted,
+				       u32 session_timeout),
+			    struct hostapd_allowed_address_info *info)
 {
 	int res;
 
-	if (session_timeout)
-		*session_timeout = 0;
-	if (acct_interim_interval)
-		*acct_interim_interval = 0;
-	if (vlan_id)
-		os_memset(vlan_id, 0, sizeof(*vlan_id));
-	if (psk)
-		*psk = NULL;
-	if (identity)
-		*identity = NULL;
-	if (radius_cui)
-		*radius_cui = NULL;
-
-	res = hostapd_check_acl(hapd, addr, vlan_id);
+	res = hostapd_check_acl(hapd, addr, &info->vlan_id);
 	if (res != HOSTAPD_ACL_PENDING)
 		return res;
 
@@ -282,9 +289,12 @@ 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 */
-		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,
+						&info->session_timeout,
+						&info->acct_interim_interval,
+						&info->vlan_id, &info->psk,
+						&info->identity,
+						&info->radius_cui);
 		if (res == HOSTAPD_ACL_ACCEPT ||
 		    res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
 			return res;
@@ -296,13 +306,13 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 			if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
 				/* pending query in RADIUS retransmit queue;
 				 * do not generate a new one */
-				if (identity) {
-					os_free(*identity);
-					*identity = NULL;
+				if (info->identity) {
+					os_free(info->identity);
+					info->identity = NULL;
 				}
-				if (radius_cui) {
-					os_free(*radius_cui);
-					*radius_cui = NULL;
+				if (info->radius_cui) {
+					os_free(info->radius_cui);
+					info->radius_cui = NULL;
 				}
 				return HOSTAPD_ACL_PENDING;
 			}
@@ -336,6 +346,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 		}
 		os_memcpy(query->auth_msg, msg, len);
 		query->auth_msg_len = len;
+		query->cb = cb;
 		query->next = hapd->acl_queries;
 		hapd->acl_queries = query;
 
@@ -613,17 +624,10 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 	cache->next = hapd->acl_cache;
 	hapd->acl_cache = cache;
 
-#ifdef CONFIG_DRIVER_RADIUS_ACL
-	hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
-					cache->session_timeout);
-#else /* CONFIG_DRIVER_RADIUS_ACL */
-#ifdef NEED_AP_MLME
-	/* Re-send original authentication frame for 802.11 processing */
-	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
-		   "successful RADIUS ACL query");
-	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
-#endif /* NEED_AP_MLME */
-#endif /* CONFIG_DRIVER_RADIUS_ACL */
+	if (query->cb)
+		query->cb(hapd, query->auth_msg, query->auth_msg_len,
+			  query->addr, cache->accepted,
+			  cache->session_timeout);
 
  done:
 	if (prev == NULL)
diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h
index 71f53b9..dea889c 100644
--- a/src/ap/ieee802_11_auth.h
+++ b/src/ap/ieee802_11_auth.h
@@ -16,16 +16,30 @@ enum {
 	HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
 };
 
+struct hostapd_allowed_address_info {
+	u32 session_timeout;
+	u32 acct_interim_interval;
+	struct vlan_description vlan_id;
+	struct hostapd_sta_wpa_psk_short *psk;
+	char *identity;
+	char *radius_cui;
+};
+
+void hostapd_allowed_address_init(struct hostapd_allowed_address_info *info);
+void hostapd_allowed_address_free(struct hostapd_allowed_address_info *info);
 int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
 		      struct vlan_description *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,
-			    struct vlan_description *vlan_id,
-			    struct hostapd_sta_wpa_psk_short **psk,
-			    char **identity, char **radius_cui);
+			    const u8 *msg, size_t len,
+			    void (*cb)(struct hostapd_data *hapd,
+				       const u8 *buf, size_t len,
+				       const u8 *mac, int accepted,
+				       u32 session_timeout),
+			    struct hostapd_allowed_address_info *info);
 int hostapd_acl_init(struct hostapd_data *hapd);
 void hostapd_acl_deinit(struct hostapd_data *hapd);
+void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
+			   struct hostapd_sta_wpa_psk_short *src);
 void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
 void hostapd_acl_expire(struct hostapd_data *hapd);
 
-- 
2.1.4




More information about the Hostap mailing list