Understanding Wildcard in LDAP Search
Asterisk (*
) is wildly used as a wildcard card in regular express (regexp)
matching and file name matching. So it is not a suprise at all that many expect
it works the same way when put into a LDAP search filter. However, it may give
surprising search results at times. More specifically, sometimes the filter does
not match any entries while it should. This blog is to help you understand the
reason of it and use *
in LDAP searches correctly.
Firstly, please note that the filter attribute=*
(say member=*
) is different
from attribute=a_string_contains_*_etc
(member=test*
, member=*test
and
member=*test*
for example). The former filter means "present", i.e. so long as
the attribute exists, corresponding LDAP entry is considered a match. This type
of filters does not really incur many confusions. It is the later that sometimes
does not work as one may have expected. To be accurate, this filter is not a
regexp but a "substring filter". I'll be focusing on substring filters from now
on. (Please refer to String Search Filter Definition for more information)
One key point to understand "LDAP search regexp issues" is: attributes can have
a different LDAP substring filter matching rules. So, while *
in LDAP
substring filters normally work the same way as Linux shell file name
matching, it is ignored if the targeted attribute does not have substring
matching rules. To better understand this, let's have a look at the following
test:
Reviewing the schemas of description and member (shown below), we can see that
description
has a substring matching rule (SUBSTR caseIgnoreSubstringsMatch
) butmember
does not.attributetype ( 2.5.4.13 NAME 'description' DESC 'RFC2256: descriptive information' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
olcAttributeTypes: {27}( 2.5.4.31 NAME 'member' DESC 'RFC2256: member of a g roup' SUP distinguishedName )
Add an LDAP entry which has both attributes set to the same value:
dn: cn=guests,ou=OmRoles,dc=mongo,dc=com objectClass: groupOfNames cn: guests member: uid=guest@mongodb.com,ou=OmUsers,dc=mongo,dc=com description: uid=guest@mongodb.com,ou=OmUsers,dc=mongo,dc=com
- Apply the same substring filter to
member
anddescription
respectively.The search based on
description
returns the LDAP entry as expected.$ ldapsearch -LLL -H ldap://localhost:389 -D cn=Manager,dc=mongo,dc=com -w password -b ou=OmRoles,dc=mongo,dc=com -s sub 'description=*guest*' dn: cn=guests,ou=OmRoles,dc=mongo,dc=com objectClass: groupOfNames cn: guests member: uid=guest@mongodb.com,ou=OmUsers,dc=mongo,dc=com description: uid=guest@mongodb.com,ou=OmUsers,dc=mongo,dc=com $
The search against
member
returns nothing. This is actually desired behaviour because, as mentioned above, the filter is ignored sincemember
does not define substring matching rule.$ ldapsearch -LLL -H ldap://localhost:389 -D cn=Manager,dc=mongo,dc=com -w password -b ou=OmRoles,dc=mongo,dc=com -s sub 'member=*guest*' $
As you might have noted, since the substring matching rule for
description
is "caseIngore…", the filter is case insensitive: I get the same result usingGUEST
instead ofguest
.$ ldapsearch -LLL -H ldap://localhost:389 -D cn=Manager,dc=mongo,dc=com -w password -b ou=OmRoles,dc=mongo,dc=com -s sub 'description=*GUEST*' dn: cn=guests,ou=OmRoles,dc=mongo,dc=com objectClass: groupOfNames cn: guests member: uid=guest@mongodb.com,ou=OmUsers,dc=mongo,dc=com description: uid=guest@mongodb.com,ou=OmUsers,dc=mongo,dc=com
blog comments powered by Disqus