Hi, I've just noticed that there is a little difference in functionality between FR 2.x and 3.21. The config I have, worked fine in v2 but now in v3 it is not doing what I intend. I'm using an Openldap backend which consists of users and groups and I would like to restrict access based on the user-group association in ldap. eg. any user belonging to the Guest group should only be given authenticated access to guest areas (currently restricted to Wifi) while 'normal' users should get standard Wifi access but not access to NAS config shells etc; admin group gets all access with no restrictions My current FR config takes the Huntgroup name and looks at the 'l' values in ldap for a match. This is the tail end of my Authorize file: *I've used <> to indicate comments and it is not part of the config file* DEFAULT Huntgroup-Name == Huntgroup1, Ldap-Group == "<PPP Dialin group>" Service-Type = "Framed-User" DEFAULT Huntgroup-Name == Huntgroup2 <this is the Guest group>, Ldap-Group == "<Guest ldap group>" NAS-Port-Type = "Wireless-802.11", Airespace-QOS-Level = 3 DEFAULT Huntgroup-Name == Huntgroup3, Ldap-Group == "<Regular Wifi group>" NAS-Port-Type = "Wireless-802.11" DEFAULT Huntgroup-Name == Huntgroup4, Ldap-Group == "<Full Admin group>" Service-Type = "NAS-Prompt-User", Idle-Timeout = 600, Cisco-AVPair = "shell:priv-lvl=15" DEFAULT Huntgroup-Name == Huntgroup4, Ldap-Group == "<Net Admin group>" Service-Type = "NAS-Prompt-User", Idle-Timeout = 600, Cisco-AVPair = "shell:priv-lvl=15" DEFAULT Huntgroup-Name == Huntgroup5, Ldap-Group == "<Net Admin group>" Service-Type = "NAS-Prompt-User", Idle-Timeout = 600, STI-Access-Level = 1, APC-Service-Type = 1 DEFAULT Huntgroup-Name == Huntgroup6, Ldap-Group == "<Net Admin group>" Service-Type = "Administrative-User", Idle-Timeout = 600, Cisco-AVPair = "shell:priv-lvl=15" DEFAULT Auth-Type := Reject The Outer-tunnel (default) file contains the following under the Authorize section: authorize { update request { Huntgroup-Name ="%{ldap:ldap:///<ldap path 1>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name +="%{ldap:ldap:///<ldap path 2>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name +="%{ldap:ldap:///<ldap path 3>l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name +="%{ldap:ldap:///<ldap path 4>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name +="%{ldap:ldap:///<ldap path 5>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name +="%{ldap:ldap:///<ldap path 6>?l?sub?cn=%{Packet-Src-IP-Address}}" } # # Take a User-Name, and perform some checks on it, for spaces and other # invalid characters. If the User-Name appears invalid, reject the # request. # # See policy.d/filter for the definition of the filter_username policy. # filter_username ... The Inner-tunnel file contains this, it's slightly different from the 'Outer' tunnel due to various matching issues I found when there are multiple 'l' values attached to the NAS lookup in ldap - To clarify what I mean is that example:- a Wireless Controller has Huntgroup2, Huntgroup3 and Huntgroup4 set in the 'l' value under different ldap paths, so if it matches <ldap path 3> then look the user up and authenticate - if the huntgroup does not match then try a different path using attributes based on the unlang operators: authorize { update request { Huntgroup-Name ="%{ldap:ldap:///<ldap path 1>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name ="%{ldap:ldap:///<ldap path 2>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name ="%{ldap:ldap:///<ldap path 3>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name :="%{ldap:ldap:///<ldap path 4>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name ="%{ldap:ldap:///<ldap path 5>?l?sub?cn=%{Packet-Src-IP-Address}}" Huntgroup-Name :="%{ldap:ldap:///<ldap path 6>?l?sub?cn=%{Packet-Src-IP-Address}}" } # # Take a User-Name, and perform some checks on it, for spaces and other # invalid characters. If the User-Name appears invalid, reject the # request. # # See policy.d/filter for the definition of the filter_username policy. # filter_username ... This is a partial output from radiusd -X - the user is not found in any of the administrative ldap paths and then hits line 314 which is the line "DEFAULT Auth-Type := Reject" in the authorize file, but then it proceeds to the ldap module and is granted access: (946) auth_log: EXPAND %t (946) auth_log: --> Wed Nov 25 02:26:21 2020 (946) [auth_log] = ok (946) [chap] = noop (946) [mschap] = noop (946) [digest] = noop (946) suffix: Checking for suffix after "@" (946) suffix: No '@' in User-Name = "<guest user>", looking up realm NULL (946) suffix: No such realm "NULL" (946) [suffix] = noop (946) eap: No EAP-Message, not doing EAP (946) [eap] = noop (946) files: Searching for user in group "<Full Admin group>" rlm_ldap (ldap): Reserved connection (204) (946) files: EXPAND (uid=%{%{Stripped-User-Name}:-%{User-Name}}) (946) files: --> (uid=<guest user>) (946) files: Performing search in "<Base DN>" with filter "(uid=<guest user>)", scope "sub" (946) files: Waiting for search result... (946) files: User object found at DN "uid=<guest user>,<Guest user path>" (946) files: Checking user object's memberOf attributes (946) files: Performing unfiltered search in "uid=<guest user>,<Guest user path>", scope "base" (946) files: Waiting for search result... (946) files: Processing memberOf value "<Guest ldap group>" as a DN rlm_ldap (ldap): Released connection (204) (946) files: User is not a member of "<Full Admin group>" (946) files: Searching for user in group "<Net Admin group>" rlm_ldap (ldap): Reserved connection (202) (946) files: Using user DN from request "uid=<guest user>,<Guest user path>" (946) files: Checking user object's memberOf attributes (946) files: Performing unfiltered search in "uid=<guest user>,<Guest user path>", scope "base" (946) files: Waiting for search result... (946) files: Processing memberOf value "<Guest ldap group>" as a DN rlm_ldap (ldap): Released connection (202) (946) files: User is not a member of "<Net Admin group>" (946) files: users: Matched entry DEFAULT at line 314 (946) [files] = ok rlm_ldap (ldap): Reserved connection (203) (946) ldap: EXPAND (uid=%{%{Stripped-User-Name}:-%{User-Name}}) (946) ldap: --> (uid=<guest user>) (946) ldap: Performing search in "<Base DN>" with filter "(uid=<guest user>)", scope "sub" (946) ldap: Waiting for search result... (946) ldap: User object found at DN "uid=<guest user>,<Guest user path>" (946) ldap: Processing user attributes (946) ldap: control:Password-With-Header += 'Wifi<guest user>' rlm_ldap (ldap): Released connection (203) (946) [ldap] = updated (946) [expiration] = noop (946) [logintime] = noop (946) pap: No {...} in Password-With-Header, re-writing to Cleartext-Password (946) pap: Removing &control:Password-With-Header (946) pap: WARNING: Auth-Type already set. Not setting to PAP (946) [pap] = noop (946) if (User-Password) { (946) if (User-Password) -> TRUE (946) if (User-Password) { (946) update control { (946) Auth-Type := ldap (946) } # update control = noop (946) } # if (User-Password) = noop (946) } # authorize = updated (946) Found Auth-Type = ldap (946) # Executing group from file /usr/local/etc/raddb/sites-enabled/default (946) authenticate { rlm_ldap (ldap): Reserved connection (204) (946) ldap: Login attempt by "<guest user>" (946) ldap: Using user DN from request "uid=<guest user>,<Guest user path>" (946) ldap: Waiting for bind result... (946) ldap: Bind successful What needs to be done in order for FR to make a decision based on the evaluation of the authorize file and 'accept' or 'reject' accordingly? Currently I'm going through the 'unlang' and 'SQL-Huntgroup-Howto' in the FR Wiki but I'm unable to work this one out. Perhaps a 'Post-auth' statement is necessary? - currently this is in the 'inner-tunnel' file: # # Access-Reject packets are sent through the REJECT sub-section of the # post-auth section. # # Add the ldap module name (or instance) if you have set # 'edir_account_policy_check = yes' in the ldap module configuration # Post-Auth-Type REJECT { # log failed authentications in SQL, too. -sql attr_filter.access_reject # # Let the outer session know which module failed, and why. # update outer.session-state { &Module-Failure-Message := &request:Module-Failure-Message } } } and this is in the 'default' file: Post-Auth-Type REJECT { # log failed authentications in SQL, too. -sql attr_filter.access_reject # Insert EAP-Failure message if the request was # rejected by policy instead of because of an # authentication failure eap # Remove reply message if the response contains an EAP-Message remove_reply_message_if_eap } Would anyone be able to give me some advice? Many Thanks! Kaya