Bug 56060 - Support MAC auth with computer objects and VLAN-ID assignment
Support MAC auth with computer objects and VLAN-ID assignment
Status: CLOSED FIXED
Product: UCS
Classification: Unclassified
Component: Radius
UCS 5.0
Other All
: P5 normal (vote)
: UCS 5.0-6-errata
Assigned To: Iván.Delgado
Florian Best
https://git.knut.univention.de/univen...
:
Depends on:
Blocks: 57069
  Show dependency treegraph
 
Reported: 2023-05-12 16:58 CEST by Ingo Jürgensmann
Modified: 2024-02-19 16:40 CET (History)
6 users (show)

See Also:
What kind of report is it?: Feature Request
What type of bug is this?: ---
Who will be affected by this bug?: ---
How will those affected feel about the bug?: ---
User Pain:
Enterprise Customer affected?:
School Customer affected?:
ISV affected?:
Waiting Support:
Flags outvoted (downgraded) after PO Review:
Ticket number:
Bug group (optional):
Max CVSS v3 score:
juergensmann: Patch_Available+


Attachments
patch-alike file for sites-available/default - will not work out of the box (3.49 KB, patch)
2023-05-12 16:58 CEST, Ingo Jürgensmann
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ingo Jürgensmann univentionstaff 2023-05-12 16:58:40 CEST
Created attachment 11064 [details]
patch-alike file for sites-available/default - will not work out of the box

Currently UCS RADIUS supports the authentication and VLAN-assignment for user objects. So, if someone wants to do such things as MAC Authentication Bypass (MAB) with a computer object and assign a VLAN-ID on this, the current approach will not work - unless another user object is being created with the MAC address as username/uid. 

This will lead to double data in many cases: one time for the computer object and another time for the user object. Maintaining this will be difficult if it is not automated. 

However, changing the RADIUS config in such way that a MAC address can be used (and therefor a computer object) will solve the issue. 
To just authenticate a MAC address a simple addition to the filter in mods-available/ldap should be sufficient: 

----------------------------------------------------------------------
 #              filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
-               filter = "(uid=%{mschap:User-Name:-%{User-Name}})"
-
+#              filter = "(uid=%{mschap:User-Name:-%{User-Name}})"
+                filter = "(|(uid=%{mschap:User-Name:-%{User-Name}})(macAddress=%{mschap:User-Name:-%{User-Name}}))"

                #  Filter to find group objects a user is a member of.
                #  That is, group objects with attributes that
                #  identify members (the inverse of membership_attribute).
-#              membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
+               membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
----------------------------------------------------------------------

The issue is that assigning a VLAN-ID is more challenging. The current config uses the uid and memberUid attributed to match the groups containing the VLAN-IDs with the requesting user. 
With a MAC another step is necessary, because the memberUid of the group lists the machine name ("<uid>$"), but the provided "user" is the MAC address. So, another lookup must be done to get the uid from the provided MAC address and use this for looking up the group and VLAN-ID: 

----------------------------------------------------------------------
--- default     2023-05-12 16:17:27.040000000 +0200
+++ ../server-available_default 2023-05-12 16:15:54.616000000 +0200
@@ -761,18 +761,45 @@
			 User-Name := "%{1}$"    # The uid attribute in the ldap object is filled with the host name and a trailing dollar sign.
		 }
	 }
+
+    if ("%{ldap:ldap:///dc=domain,dc=net?uid?sub?(macAddress=%{User-Name})}") {
+        # For known users as well for known machines we take the vlan-id from the group the user/machine is member of.
+        # In case there are assignments for several groups the first vlan-id is automatically taken.
+        update request {
+            User-Name := "%{ldap:ldap:///dc=domain,dc=net?uid?sub?(macAddress=%{User-Name})}"    # The uid attribute in the ldap object is filled with the host name and a trailing dollar sign.
+        }
+        if ("%{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(macAddress=%{User-Name})(univentionObjectType=groups/group)(univentionVlanId=*))}") {
+            update reply {
+                Reply-Message := "DEBUG: Assigning VLAN-ID from user / computer object"
+                Tunnel-Type := VLAN
+                Tunnel-Medium-Type := IEEE-802
+                Tunnel-Private-Group-Id := "%{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(|(memberUid=%{User-Name})(macAddress=%{User-Name}))(univentionObjectType=groups/group)(univentionVlanId=*))}"
+            }
+        }
+        # If we can't find a matching VLAN ID for the user or machine client in LDAP, we return the default VLAN ID, if configured.
+        # If no default vlan-id is configured in ucr we do not return any vlan information
+        elsif ("1") {
+            update reply {
+                Reply-Message := "DEBUG: Not found, assigning default VLAN-ID"
+                Tunnel-Type := VLAN
+                Tunnel-Medium-Type := IEEE-802
+                Tunnel-Private-Group-Id := "1"
+            }
+        }
+    }
+
	 # Check if the user or machine exists and do post-auth actions
	 # else do nothing in post-auth
	 # This way we also make sure that we do not change the VLAN ID again if the non-EAP-auth (MAC address auth) succeeded before (see above)
-    if ("%{ldap:ldap:///dc=domain,dc=net?uid?sub?(uid=%{User-Name})}") {
+    if ("%{ldap:ldap:///dc=domain,dc=net?uid?sub?(|(uid=%{User-Name})(macAddress=%{User-Name}))}") {
		 # For known users as well for known machines we take the vlan-id from the group the user/machine is member of.
		 # In case there are assignments for several groups the first vlan-id is automatically taken.
-        if ("%{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(memberUid=%{User-Name})(univentionObjectType=groups/group)(univentionVlanId=*))}") {
+        if ("%{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(|(memberUid=%{User-Name})(macAddress=%{User-Name}))(univentionObjectType=groups/group)(univentionVlanId=*))}") {
			 update reply {
				 Reply-Message := "DEBUG: Assigning VLAN-ID from user / computer object"
				 Tunnel-Type := VLAN
				 Tunnel-Medium-Type := IEEE-802
-                Tunnel-Private-Group-Id := "%{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(memberUid=%{User-Name})(univentionObjectType=groups/group)(univentionVlanId=*))}"
+                Tunnel-Private-Group-Id := "%{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(|(memberUid=%{User-Name})(memberUid=%{1}))(univentionObjectType=groups/group)(univentionVlanId=*))}"
			 }
		 }
		 # If we can't find a matching VLAN ID for the user or machine client in LDAP, we return the default VLAN ID, if configured.
----------------------------------------------------------------------
 
Please note that the above is a diff from /etc/freeradius/3.0/sites-available/default and NOT from the template!
Anyway, it shows what maybe needs to be done/changed. I'd recommend to use a more elaborated approach with nested if/elif or case statements inside of the RADIUS config. 

Please also note that this works when the MAC address is transmitted from the client in a certain format (":" as separator). On a Cisco 2690 switch with IOS 15.x this can be achieved by configuring "mab request format attribute 1 groupsize 2 separator :". 

Using MAB and VLAN-IDs are sometimes requested in customer projects. One customer already did chose another solution because UCS couldn't provide a simple solution for this task. In another project the customer asked, if this is possible. 


PS: 
The resulting RADIUS debug is like this: 

(0)           Reply-Message := "DEBUG: Assigning VLAN-ID from user / computer object"
(0)           Tunnel-Type := VLAN
(0)           Tunnel-Medium-Type := IEEE-802
rlm_ldap (ldap): Reserved connection (6)
(0)           Performing search in "dc=domain,dc=net" with filter "(&(|(memberUid=arrakis$)(memberUid=))(univentionObjectType=groups/group)(univentionVlanId=*))", scope "sub"
(0)           Waiting for search result...
rlm_ldap (ldap): Released connection (6)
(0)           EXPAND %{ldap:ldap:///dc=domain,dc=net?univentionVlanId?sub?(&(|(memberUid=%{User-Name})(memberUid=%{1}))(univentionObjectType=groups/group)(univentionVlanId=*))}
(0)              --> 300
(0)           Tunnel-Private-Group-Id := 300

Or as transmitted to the client/switch: 

(0) Login OK: [arrakis$] (from client c2960 port 50001 cli 28-CD-4C-FF-FD-BD)
(0) Sent Access-Accept Id 10 from 192.168.254.5:1812 to 172.19.21.10:1645 length 0
(0)   Reply-Message := "DEBUG: Assigning VLAN-ID from user / computer object"
(0)   Tunnel-Type := VLAN
(0)   Tunnel-Medium-Type := IEEE-802
(0)   Tunnel-Private-Group-Id := "300"
Comment 1 Robert Heyer univentionstaff 2023-11-17 10:57:39 CET
Customer 0006 LKF would also like to have this.
Comment 3 Iván.Delgado univentionstaff 2023-12-21 08:50:00 CET
The UCR variable `freeradius/conf/allow-mac-address-authentication`
has been added to to allow authentication via MAC address and
VLAN-assignment for computer objects. By default, this feature is
disabled.

univention-radius.yaml
09821641c8c4 | Bug #56060: UCS Radius support Mac auth bypass

univention-radius (7.0.6-1)
ebf56df4601f | Bug #56060: implement networkaccess configuration for computers.
09821641c8c4 | Bug #56060: UCS Radius support Mac auth bypass

ucs-test (10.0.20-10)
d3d5d09e1e1b | Bug #56060: implement new radius test for mac auth support.
Comment 4 Iván.Delgado univentionstaff 2023-12-21 08:50:33 CET
Successful build
Package: univention-radius
Version: 7.0.6-1
Branch: ucs_5.0-0
Scope: errata5.0-6
Comment 5 Florian Best univentionstaff 2024-01-02 12:26:49 CET
OK: authentication via MAC address
OK: Code review: matches whished implementation
OK: Jenkins tests pass since 7 runs (https://univention-dist-jenkins.k8s.knut.univention.de/job/UCS-5.0/job/UCS-5.0-6/job/AutotestJoin/lastCompletedBuild/SambaVersion=s4,Systemrolle=master/testReport/45_radius/16_mac/)
OK: YAML
OK~: ldap base is not urlencoded but other previously existing code doesn't do it as well
OK: disabled by default
OK~: nothing has been added to the manual but there is a UCRv description
Comment 8 Nico Gulden univentionstaff 2024-01-15 13:49:55 CET
Documentation added:
e310821624 | doc(manual): Add Sphinx Inline Tabs extension
fe9bc39280 | doc(manual): Add section about MAC Authentication Bypass
55de9eba89 | doc(manual): Add German translation about MAC Authentication Bypass

Published at https://docs.software-univention.de/manual/5.0/en/ip-config/radius.html#mac-authentication-bypass-with-computer-objects