LDAP group query optimisation

Brian Candler b.candler at pobox.com
Thu Oct 13 16:14:48 CEST 2016


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.


More information about the Freeradius-Users mailing list