Reputation: 1038
I am using python library ldap3 to send requests to the servers to query user objects that are not disabled and have a display name or email that contains the user input:
query = "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(displayName={0}*)(mail={0}*))".format(value)
I followed what I think the documentation says about forming LDAP filters, but I am getting an incorrect LDAP filter error message:
LDAPInvalidFilterError: malformed filter
I played around with it and this works:
query = "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(displayName={0}*))".format(value)
I haven't been able to construct a filter using |
yet. How should the query be constructed?
Upvotes: 1
Views: 1807
Reputation: 26
not sure if this is a bug in ldap3 or if the strict adherence to RFC 4515, but I had this same issue and managed to resolve it partly due to this post, so hopefully this helps someone else.
https://ldap3.readthedocs.io/en/latest/searches.html https://www.rfc-editor.org/rfc/rfc4515
I was testing the following query which worked perfectly fine using ldp.exe:
(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(|(userprincipalname={0})(samaccountname={0})(distinguishedname={0})))
I tried a couple of different variations and like yourself, just changing the OR (pipe) to AND (ampersand) allowed the query to run without error.
In the end, I resolved it by adding brackets to my NOT assertion, based on an example in the ldap3 documentation link above.
This query works for me without the "malformed filter" error:
(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(userprincipalname={0})(samaccountname={0})(distinguishedname={0})))
Upvotes: 1
Reputation: 338228
You cannot simply .format()
any value into a filter.
You need to escape certain characters before you interpolate them into the string.
* -> \2a ( -> \28 ) -> \29 \ -> \5c NUL -> \00 / -> \2f
Just like with URLs, you're free to escape any character you like using the above scheme, but the ones above are the minimum.
I haven't been able to construct a filter using | yet. How should the query be constructed?
That being said, you had a nesting error. You'll see it when you format your query:
(& (objectClass=user) (!(userAccountControl:1.2.840.113556.1.4.803:=2)) (| (displayName={0}*) (mail={0}*) )
You still need to escape the value
, but since the LDAP server does not care, keep the query formatting:
value = ldap3.utils.conv.escape_filter_chars(user_input)
query = f"""
(&
(objectClass=user)
(!(userAccountControl:1.2.840.113556.1.4.803:=2))
(|
(displayName={value}*)
(mail={value}*)
)
)
"""
Upvotes: 3