[R] Using LDAP search filter to query attributes without value

Reading Time: 2 minutes

When it comes to searching for an object in the LDAP directory (like Active Directory) most of us will use a LDAP filter to display the objects we are looking for. An LDAP filter is a quick and easy way to construct queries that will be excecuted against the target directory service. Most of the queries are built to query objects of specified class or category for some attributes with additional conditions to narrow the query results, eg:

(&(objectCategory=person)(cn=John Smith))

And interesting situation I came across was when I wanted to perform a query with additional conditions based on some attribute of an object, using a wildcard '*' as an condition in my query I can expect that in a result I will get all the objects regardless of this attribute value. This is only partial true, because such query will not return for us an objects in which this attribute will not have any value (will not be set even for null value). The original problem which pushed me to write this short article was a question from the user how to find all the Active Directory users with Exchange mailboxes and OWA access enabled. Finding all users with mailboxes is pretty easy, but the problem started when it comes to query against enabled protocols. Enabled Exchange protocols configuration is stored in protocolSettings AD attribute. This attribute has no value set if an use has default protocols enabled (which includes OWA because by default all Exchange protocols are enabled for all users). If uses has not default settings for some protocol this attribute has an value which contains modification to the defaults. These modifications are stored in the string format as a value of protocolSettings attribute, for example string valu for HTTP access will look like this "http'1'1'". So first approach which we can use to find all the users with OWA enabled is to user LDAP query as stated below:

(&(objectCategory=person)(protocolSettings=*http'1'1'*))

But in fact we will fail because this will give us only these users who has not default settings for HTTP access to the OWA. Using wildcard for this query:

(&(objectCategory=person)( protocolSettings=*))

Will also not give us expected results because this filter will only give us users with *some* value in the protocolSettings attribute, and as I stated earlier users with default settings are not having any value for this attribute (not null but ). So to get all the users with default settings (which is OWA enabled) and those who has not default settings of the protocols but OWA also is enabled for them we have to use combination of the attributes with a little trick:

(&(&(objectcategory=Person)(homeMDB=*)(|(!(protocolSettings=*))(protocolSetting=*http'1'1')))

As You can see we are using negation of the wildcard to get all of the objects without any value in the protocolSettings attribute. Sometimes such approach can be useful and will require some additional logic in our script or application – because if we want to get all the users from the directory with query based on some attribute we can expect that there can be an object without any value in this attribute – so we have to query twice or construct our LDAP filter in the way showed above.

4 thoughts on “[R] Using LDAP search filter to query attributes without value”

  1. Hi Tomek. Just wanted to comment on this a little further. First, on this item: "And interesting situation I came across was when I wanted to perform a query with additional conditions based on some attribute of an object, using a wildcard '*' as an condition in my query I can expect that in a result I will get all the objects regardless of this attribute value. This is only partial true, because such query will not return for us an objects in which this attribute will not have any value (will not be set even for null value)." I would point out, we didn't mandate this. πŸ™‚ Rather, LDAP standards did. The wildcard operator signifies "presence", so we respected this. Else, we'd be the odd kid on the block. See RFC 2254 for more details on this: http://www.ietf.org/rfc/rfc2254.txt Second, on performance. I would note that not statements (!) in LDAP queries sometimes result in poor performance. The reason is fairly simple….we often times don't have an index we can leverage to service them. So in a large dataset scenario, a not statement on a term may result in us scanning a large % of the database in scope of the query. This may not be desireable if your dataset is large. πŸ™‚ So the short of it is….if you can avoid not statements, it's in your best interest to do so. Also, you have a medial substring search in one of your filters (This one: (protocolSettings=*http'1'1'*))). This also can't be optimized well unless you have medial substring indexes enabled for this attribute (sometimes called tuple indexes in some circles/documentation). So this too may be slow unless planned for. πŸ™‚ Since medial substring indexes are quite large, I would not enable them unless required. There is an update performance cost. Hope that helps. If you have any followup questions please do holler. ~Eric

  2. Hi Eric, Thank You for the valuable input for this entry. Regarding queries using wildcards operators – I wasn't my intention to point this as an issue or bug, my fault – I haven't take a look how it is defined in the LDAP RFC. This post was a result of work performed on-line with few users who tried to find a way to perfrom such queries. And I didn't checked perforrmance of such queries but I can image that they can be "fat", becouse this was a solution to perform one time queries for some atributes not very regular or massive. But Your input on this topic is also very valuable.

Comments are closed.