From c5390c53bb7315f38b73697ea81a6854354fb697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jurek=20Ko=C5=82osowski?= Date: Fri, 8 May 2026 20:13:29 +0200 Subject: [PATCH] freeradius: add configurable LDAP group membership mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `group_membership_mode` to the LDAP settings (model, form, template): - `attribute` (default): `membership_attribute = 'memberOf'` — existing behaviour, compatible with POSIX groups and flat LDAP structures. - `filter`: `membership_filter` with LDAP_MATCHING_RULE_IN_CHAIN OID (1.2.840.113556.1.4.1941) — resolves nested group membership against Active Directory and Samba 4 AD DC in a single LDAP query. The `memberOf` attribute reflects only direct memberships, breaking `Ldap-Group ==` checks (e.g. VLAN assignment) when groups are nested. The OID-based filter traverses the full membership chain server-side. Default is `attribute`; existing configurations are unaffected. Tested with Samba 4.24 AD DC and FreeRADIUS 3.2 (os-freeradius plugin). --- .../app/controllers/OPNsense/Freeradius/forms/ldap.xml | 6 ++++++ .../mvc/app/models/OPNsense/Freeradius/Ldap.xml | 10 +++++++++- .../templates/OPNsense/Freeradius/mods-enabled-ldap | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/net/freeradius/src/opnsense/mvc/app/controllers/OPNsense/Freeradius/forms/ldap.xml b/net/freeradius/src/opnsense/mvc/app/controllers/OPNsense/Freeradius/forms/ldap.xml index be7d1affd1..eb488f57d5 100644 --- a/net/freeradius/src/opnsense/mvc/app/controllers/OPNsense/Freeradius/forms/ldap.xml +++ b/net/freeradius/src/opnsense/mvc/app/controllers/OPNsense/Freeradius/forms/ldap.xml @@ -65,4 +65,10 @@ text Filter for group objects, should match all available group objects a user might be a member of. + + ldap.group_membership_mode + + dropdown + How FreeRADIUS checks LDAP group membership. Use "member filter" for Active Directory or Samba 4 with nested groups (uses LDAP_MATCHING_RULE_IN_CHAIN OID for transitive lookup). + diff --git a/net/freeradius/src/opnsense/mvc/app/models/OPNsense/Freeradius/Ldap.xml b/net/freeradius/src/opnsense/mvc/app/models/OPNsense/Freeradius/Ldap.xml index 67cffa256e..90c3a12c27 100644 --- a/net/freeradius/src/opnsense/mvc/app/models/OPNsense/Freeradius/Ldap.xml +++ b/net/freeradius/src/opnsense/mvc/app/models/OPNsense/Freeradius/Ldap.xml @@ -1,7 +1,7 @@ //OPNsense/freeradius/ldap LDAP configuration - 1.0.1 + 1.0.2 0 @@ -47,5 +47,13 @@ (objectClass=posixGroup) N + + attribute + Y + + memberOf attribute (POSIX / flat groups) + member filter (Active Directory / Samba 4 nested groups) + + diff --git a/net/freeradius/src/opnsense/service/templates/OPNsense/Freeradius/mods-enabled-ldap b/net/freeradius/src/opnsense/service/templates/OPNsense/Freeradius/mods-enabled-ldap index f45a9d389d..7cf7543473 100644 --- a/net/freeradius/src/opnsense/service/templates/OPNsense/Freeradius/mods-enabled-ldap +++ b/net/freeradius/src/opnsense/service/templates/OPNsense/Freeradius/mods-enabled-ldap @@ -85,7 +85,11 @@ ldap { {% if helpers.exists('OPNsense.freeradius.ldap.group_filter') and OPNsense.freeradius.ldap.group_filter != '' %} filter = "{{ OPNsense.freeradius.ldap.group_filter }}" {% endif %} +{% if helpers.exists('OPNsense.freeradius.ldap.group_membership_mode') and OPNsense.freeradius.ldap.group_membership_mode == 'filter' %} + membership_filter = "(member:1.2.840.113556.1.4.1941:=%{control:Ldap-UserDn})" +{% else %} membership_attribute = 'memberOf' +{% endif %} } profile { }