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