Hi Brian, Thank you for the pushing to the right direction - I reshaped the ldap group section including filters and it worked like a charm. For the record in mods-available/ldap: ldap { server = 'abc.abc' identity = 'CN=ServiceAccount,DC=Users,DC=abc,DC=abc' password = '123456789' base_dn = 'DC=abc,DC=abc' user { base_dn = "${..base_dn}" filter = "(&(objectClass=user)(sAMAccountName=%{&User-Name}))" scope = 'sub' uid_attribute = "sAMAccountName" attribute { memberOf := "session-state:LDAP-Group" } } group { base_dn = "${..base_dn}" filter = '(objectClass=group)' name_attribute = cn # use magic AD search to get all groups membership_filter = "(member:1.2.840.113556.1.4.1941:=%{control:Ldap-UserDN})" membership_attribute = 'memberOf' # enable cache module cacheable_dn = 'yes' cache_attribute = "${..:instance}-LDAP-Group" } options { chase_referrals = no rebind = yes ldap_debug = 2147483647 timeout = 10 timelimit = 3 net_timeout = 1 idle = 60 } tls { start_tls = no } } The LDAP queries are happening in the authorize section after the proxy call (sites-available/default) and will yield a list of groups in the control:ldap-LDAP-Group attribute: authorize { preprocess auth_log chap # suffix if (&request:User-Name) { update session-state { Persisted-User-Name := "%{request:User-Name}" } } update control { Proxy-To-Realm := "radius_server" } ldap } So, when you will be getting it in the post-auth section, you can go over it with the foreach loop: foreach &control:ldap-LDAP-Group { if ("%{Foreach-Variable-0}" == "CN=Radius_ReadOnly_Group,DC=Groups,DC=abc,DC=abc") { update reply { Reply-Message := "Authorized as RO user" } update control { Auth-Type := Accept } } if ("%{Foreach-Variable-0}" == "CN=Radius_ReadWrite_Group,DC=Groups,DC=abc,DC=abc") { update reply { Reply-Message := "Authorized as RW user" } update control { Auth-Type := Accept } } if ("%{Foreach-Variable-0}" == "CN=Radius_Admin_Group,DC=Groups,DC=abc,DC=abc") { update reply { Reply-Message := "Authorized as Admin" } update control { Auth-Type := Accept } } } The problem I still have is how to send the Reject back if the loop conditions are not met, because before I go into it, I set Reject explicitly: update { reply:Reply-Message := "Unauthorized - No group found" control:Auth-Type := "Reject" } but it is still returning accept: (0) # Executing section post-auth from file /etc/freeradius/3.0/sites-enabled/default (0) post-auth { (0) update { (0) reply:Reply-Message := "Unauthorized - No group found" (0) control:Auth-Type := Reject (0) } # update = noop (0) foreach &control:ldap-LDAP-Group { (0) } # foreach &control:ldap-LDAP-Group = noop (0) } # post-auth = noop (0) Login OK: [generic-ms-user] (from client localhost port 1) (0) Sent Access-Accept Id 116 from 127.0.0.1:1825 to 127.0.0.1:50310 length 0 (0) Reply-Message := "Unauthorized - No group found" (0) Finished request The strange thing is that the message is being set, but the update still says "noop". Does anyone have a clue? Best regards Matvey Teplov +31 62 705 12 73 ________________________________ From: Freeradius-Users <freeradius-users-bounces+matvey.teplov=nomios.nl@lists.freeradius.org> on behalf of Matvey Teplov via Freeradius-Users <freeradius-users@lists.freeradius.org> Sent: 15 May 2025 15:23 To: Brian Julin <BJulin@clarku.edu>; freeradius-users@lists.freeradius.org <freeradius-users@lists.freeradius.org> Cc: Matvey Teplov <matvey.teplov@nomios.nl> Subject: Re: [EXT] Fetching memberOf attribute Hi Brian, How do you define ldap_ad-LDAP-Group? Best regards Matvey Teplov +31 62 705 12 73 ________________________________ From: Brian Julin <BJulin@clarku.edu> Sent: 15 May 2025 15:02 To: freeradius-users@lists.freeradius.org <freeradius-users@lists.freeradius.org> Cc: Matvey Teplov <matvey.teplov@nomios.nl> Subject: Re: [EXT] Fetching memberOf attribute [You don't often get email from bjulin@clarku.edu. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] Matvey Teplov via Freeradius-Users <freeradius-users@lists.freeradius.org> wrote:
Hi Guys,
I cannot get the ldap module to fetch a memberOf attribute from AD - it is not putting it as a filter parameter in the LDAP search packet. I need this list later to search through for port-authentication phase through the groups in session-state:LDAP-Group[*]'s to identify which ones are present and return a proper VSA. The LDAP configuration is as follows:
We use this, because it searches the group membership hierarchy so nested groups work: user { ... filter = "(&(objectClass=user)(sAMAccountName=%{Stripped-User-Name}))" scope = 'sub' } group { ... scope = 'sub' filter = '(objectCategory=group)' membership_filter = "(member:1.2.840.113556.1.4.1941:=%{&control:Ldap-UserDN})" ... } You can thank Microsoft for the ugly OID, as far as I know it has no textual alias. then: if (&ldap_ad-LDAP-Group[*] == "whatever") ...that statement will be true if any one of the users groups, including groups inherited from other groups, is "whatever", no need for a for loop unless you need to do something fancy. Do note that if you have a lot of groups in the OU the search will not be especially efficient, it will even rummage through your printers and whatnot. We made a new OU for the top level RADIUS groups and then could put groups from our other OUs inside those groups to reduce the scope of the search to just users. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html