[PATCH] Allow remote RADIUS authentication with local VLAN management

Nils Nieuwejaar nils.nieuwejaar at gmail.com
Wed Apr 18 15:12:46 PDT 2018


If dynamic_vlan=0 (disabled), then vlan assignments will be managed
using the local accept_mac_file ACL file, even if a RADIUS server is
being used for user authentication.  This allows us to manage users
and devices independently.

—

diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 220625651..7f13b147d 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1104,7 +1104,7 @@ own_ip_addr=127.0.0.1
 # Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value
 # VLANID as a string). Optionally, the local MAC ACL list (accept_mac_file) can
 # be used to set static client MAC address to VLAN ID mapping.
-# 0 = disabled (default)
+# 0 = disabled (default); only VLAN IDs from accept_mac_file will be used
 # 1 = option; use default interface if RADIUS server does not include VLAN ID
 # 2 = required; reject authentication if RADIUS server does not include VLAN ID
 #dynamic_vlan=0
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 5cb7fb145..b2ea12c3a 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -289,6 +289,9 @@ int hostapd_allowed_address(struct hostapd_data
*hapd, const u8 *addr,
 			return HOSTAPD_ACL_ACCEPT;
 		};

+		if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
+			vlan_id = NULL;
+
 		/* 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,
@@ -574,12 +577,14 @@ hostapd_acl_recv_radius(struct radius_msg *msg,
struct radius_msg *req,
 			cache->acct_interim_interval = 0;
 		}

-		notempty = &cache->vlan_id.notempty;
-		untagged = &cache->vlan_id.untagged;
-		tagged = cache->vlan_id.tagged;
-		*notempty = !!radius_msg_get_vlanid(msg, untagged,
-						    MAX_NUM_TAGGED_VLAN,
-						    tagged);
+		if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED) {
+			notempty = &cache->vlan_id.notempty;
+			untagged = &cache->vlan_id.untagged;
+			tagged = cache->vlan_id.tagged;
+			*notempty = !!radius_msg_get_vlanid(msg, untagged,
+							    MAX_NUM_TAGGED_VLAN,
+							    tagged);
+		}

 		decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
 					msg, req, cache);
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 4fcccce72..ffff58d55 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1683,6 +1683,49 @@ ieee802_1x_search_radius_identifier(struct
hostapd_data *hapd, u8 identifier)
 }


+#ifndef CONFIG_NO_VLAN
+static int
+ieee802_1x_update_vlan(struct radius_msg *msg,
+		       struct hostapd_data *hapd,
+		       struct sta_info *sta)
+{
+	struct vlan_description vlan_desc;
+	int *untagged, *tagged, *notempty;
+
+	os_memset(&vlan_desc, 0, sizeof(vlan_desc));
+	notempty = &vlan_desc.notempty;
+	untagged = &vlan_desc.untagged;
+	tagged = vlan_desc.tagged;
+	*notempty = !!radius_msg_get_vlanid(msg, untagged, MAX_NUM_TAGGED_VLAN,
+					    tagged);
+
+	if (vlan_desc.notempty &&
+	    !hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
+		sta->eapol_sm->authFail = TRUE;
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+			       HOSTAPD_LEVEL_INFO,
+			       "Invalid VLAN %d%s received from RADIUS server",
+			       vlan_desc.untagged,
+			       vlan_desc.tagged[0] ? "+" : "");
+		os_memset(&vlan_desc, 0, sizeof(vlan_desc));
+		ap_sta_set_vlan(hapd, sta, &vlan_desc);
+		return -1;
+	}
+
+	if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
+	    !vlan_desc.notempty) {
+		sta->eapol_sm->authFail = TRUE;
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
+			       HOSTAPD_LEVEL_INFO, "authentication server did "
+			       "not include required VLAN ID in Access-Accept");
+		return -1;
+	}
+
+	return (ap_sta_set_vlan(hapd, sta, &vlan_desc));
+}
+#endif /* CONFIG_NO_VLAN */
+
+
 /**
  * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server
  * @msg: RADIUS response message
@@ -1705,12 +1748,6 @@ ieee802_1x_receive_auth(struct radius_msg *msg,
struct radius_msg *req,
 	struct eapol_state_machine *sm;
 	int override_eapReq = 0;
 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
-	struct vlan_description vlan_desc;
-#ifndef CONFIG_NO_VLAN
-	int *untagged, *tagged, *notempty;
-#endif /* CONFIG_NO_VLAN */
-
-	os_memset(&vlan_desc, 0, sizeof(vlan_desc));

 	sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier);
 	if (sm == NULL) {
@@ -1775,56 +1812,21 @@ ieee802_1x_receive_auth(struct radius_msg
*msg, struct radius_msg *req,
 	switch (hdr->code) {
 	case RADIUS_CODE_ACCESS_ACCEPT:
 #ifndef CONFIG_NO_VLAN
-		if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED) {
-			notempty = &vlan_desc.notempty;
-			untagged = &vlan_desc.untagged;
-			tagged = vlan_desc.tagged;
-			*notempty = !!radius_msg_get_vlanid(msg, untagged,
-							    MAX_NUM_TAGGED_VLAN,
-							    tagged);
-		}
-
-		if (vlan_desc.notempty &&
-		    !hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
-			sta->eapol_sm->authFail = TRUE;
-			hostapd_logger(hapd, sta->addr,
-				       HOSTAPD_MODULE_RADIUS,
-				       HOSTAPD_LEVEL_INFO,
-				       "Invalid VLAN %d%s received from RADIUS server",
-				       vlan_desc.untagged,
-				       vlan_desc.tagged[0] ? "+" : "");
-			os_memset(&vlan_desc, 0, sizeof(vlan_desc));
-			ap_sta_set_vlan(hapd, sta, &vlan_desc);
-			break;
-		}
-
-		if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
-		    !vlan_desc.notempty) {
-			sta->eapol_sm->authFail = TRUE;
-			hostapd_logger(hapd, sta->addr,
-				       HOSTAPD_MODULE_IEEE8021X,
-				       HOSTAPD_LEVEL_INFO, "authentication "
-				       "server did not include required VLAN "
-				       "ID in Access-Accept");
-			break;
-		}
-#endif /* CONFIG_NO_VLAN */
-
-		if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0)
+		if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
+		    ieee802_1x_update_vlan(msg, hapd, sta) < 0)
 			break;

-#ifndef CONFIG_NO_VLAN
 		if (sta->vlan_id > 0) {
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_RADIUS,
 				       HOSTAPD_LEVEL_INFO,
 				       "VLAN ID %d", sta->vlan_id);
 		}
-#endif /* CONFIG_NO_VLAN */

 		if ((sta->flags & WLAN_STA_ASSOC) &&
 		    ap_sta_bind_vlan(hapd, sta) < 0)
 			break;
+#endif /* CONFIG_NO_VLAN */

 		sta->session_timeout_set = !!session_timeout_set;
 		os_get_reltime(&sta->session_timeout);
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index cb9be2832..94833ee1e 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -893,9 +893,6 @@ int ap_sta_set_vlan(struct hostapd_data *hapd,
struct sta_info *sta,
 	struct hostapd_vlan *vlan = NULL, *wildcard_vlan = NULL;
 	int old_vlan_id, vlan_id = 0, ret = 0;

-	if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
-		vlan_desc = NULL;
-
 	/* Check if there is something to do */
 	if (hapd->conf->ssid.per_sta_vif && !sta->vlan_id) {
 		/* This sta is lacking its own vif */



More information about the Hostap mailing list