diff mbox series

Allow remote RADIUS authentication with local VLAN management

Message ID CAEcV5Pq9kypzwFewfbGtNcLhLvVyJ=mmZLxnzGkOSie26dYMAA@mail.gmail.com
State Changes Requested
Headers show
Series Allow remote RADIUS authentication with local VLAN management | expand

Commit Message

Nils Nieuwejaar April 18, 2018, 10:12 p.m. UTC
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.

—

 		/* This sta is lacking its own vif */

Comments

Jouni Malinen April 19, 2018, 10:21 p.m. UTC | #1
On Wed, Apr 18, 2018 at 03:12:46PM -0700, Nils Nieuwejaar wrote:
> 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.
> 
> —

Please read the top level CONTRIBUTIONS and send this again with the
Signed-off-by: tag added to the commit message for me to be able to
consider applying the changes. In addition, the inline patch had some
whitespace issues that prevent it from being applied. For example here:

> 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,

That line got split in the middle..

Please use a mailer that does not modify whitespace and/or send the
patch also as an attachment so that I don't need to try to apply this
manually.
diff mbox series

Patch

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) {