A couple of other points about LDAP-Group. (1) I tried adding the following for debugging inside a policy module (invoked after the LDAP lookup has taken place): update control { Tmp-String-0 := "%{request:LDAP-Group}" Tmp-String-1 := "%{control:LDAP-Group}" Tmp-String-2 := "%{reply:LDAP-Group}" Tmp-String-3 := "%{request:LDAP-Group[*]}" Tmp-String-4 := "%{control:LDAP-Group[*]}" Tmp-String-5 := "%{reply:LDAP-Group[*]}" } All six variations expand to empty: rlm_ldap (ldap): Bind successful (0) [ldap] = updated (0) policy group_authorization { (0) update control { (0) EXPAND %{request:LDAP-Group} (0) --> (0) Tmp-String-0 := (0) EXPAND %{control:LDAP-Group} (0) --> (0) Tmp-String-1 := (0) EXPAND %{reply:LDAP-Group} (0) --> (0) Tmp-String-2 := (0) EXPAND %{request:LDAP-Group[*]} (0) --> (0) Tmp-String-3 := (0) EXPAND %{control:LDAP-Group[*]} (0) --> (0) Tmp-String-4 := (0) EXPAND %{reply:LDAP-Group[*]} (0) --> (0) Tmp-String-5 := (0) } # update control = noop Changing %{...} to %{&...} didn't make any difference either. Is this expected behaviour? If the LDAP-Group pseudo-attribute is not valid in string expansions, perhaps it should at least generate a warning? (2) I found another fragility issue with LDAP-Group: if you are comparing this attribute but miss the leading &, it silently fails, without even so much as a warning. Here is a snippet from a working policy: if (&Huntgroup-Name == "wifi") { if (&Called-Station-Id =~ /:Admin$/ && ( &LDAP-Group[*] == "server_guru" || &LDAP-Group[*] == "network_guru")) { return } Debug is happy: (0) if (&Huntgroup-Name == "wifi") { (0) if (&Huntgroup-Name == "wifi") -> TRUE (0) if (&Huntgroup-Name == "wifi") { (0) if (&Called-Station-Id =~ /:Admin$/ && ( &LDAP-Group[*] == "server_guru" || &LDAP-Group[*] == "network_guru")) { (0) Searching for user in group "server_guru" rlm_ldap (ldap): Reserved connection (1) (0) Using user DN from request "uid=bcandler,cn=users,cn=accounts,dc=ipa,dc=example,dc=com" (0) Checking user object's memberOf attributes ... snip (0) User found in group "server_guru". Comparison between membership: name (resolved from DN "cn=server_guru,cn=groups,cn=accounts,dc=ipa,dc=example,dc=com"), check: name rlm_ldap (ldap): Released connection (1) (0) if (&Called-Station-Id =~ /:example Admin$/ && ( &LDAP-Group[*] == "server_guru" || &LDAP-Group[*] == "network_guru")) -> TRUE However in the first iteration of writing this policy, I had accidentally missed out one of the & signs. To reproduce the issue, I have changed it to this: if (&Huntgroup-Name == "wifi") { if (&Called-Station-Id =~ /:Admin$/ && ( LDAP-Group[*] == "server_guru" || LDAP-Group[*] == "network_guru")) { return } The only difference is dropping & before the two instances of LDAP-Group[*] The debug output now looks like this: (0) if (&Huntgroup-Name == "wifi") { (0) if (&Called-Station-Id =~ /:example Admin$/ && ( LDAP-Group[*] == "server_guru" || LDAP-Group[*] == "network_guru")) { (0) if (&Called-Station-Id =~ /:example Admin$/ && ( LDAP-Group[*] == "server_guru" || LDAP-Group[*] == "network_guru")) -> FALSE That's it. The whole expression fails, and there's no other indication that I did something wrong. This, I think, could lead to some difficult-to-find bugs in policy. And the unlang documentation does say that the & is optional for attributes on the left-hand side of a comparison operator: " Where the left-hand side is an attribute, the "&" can be omitted." Regards, Brian.