Hi Team,
We are working on migration of nsldap C sdk to OpenLDAP C sdk for our application client code.
We are using OpenLDAP 2.6.7.
As part of this migration, we are facing one issue with a search filter that we are using to get content from LDAP servers.
search filter: (| (uid=user1) (| (mail=user1@test.com) (! (mail= user100@test.com) ) ) )
We are using this search filter for user lookup from LDAP servers in our application for one of our cases. We are using OpenLDAP C API: ldap_search_ext_s (and/or ldap_search_ext) in our application. When we make a search call from our application to LDAP server using the above search filter, we are getting "Bad search filter (-7)" error instead of the users list. Due to this, our migration is blocked. Tried using the same search filter with *ldapsearch *utility provided by OpenLDAP, but getting the same error message. Below is the snippet of error with search filter.
*>ldapsearch.exe -H ldap://ldapserver1.com:389 http://ldapserver1.com:389 -D "cn=admin,o=test.com http://test.com" -b o=test.com http://test.com "(| (uid=user1) (| (mail=user1@test.com user1@test.com) (! (mail=user100@test.com user100@test.com) ) ) )"# extended LDIF## LDAPv3# base <o=test.com http://test.com> with scope subtree# filter: (| (uid=user1) (| (mail=user1@test.com user1@test.com) (! (mail=user2@test.com user2@test.com) ) ) )# requesting: ALL#ldap_search_ext: Bad search filter (-7)*
But the same search filter is working fine with our existing nsldap provider. We are able to get the users list from the LDAP server using the same search filter without any changes. To maintain backward compatibility in our application, we should be able to get the content from the LDAP server using the same search filter.
Could you please look into this problem and provide a solution for this?
Le 17/10/2025 à 13:24, venugopal chinnakotla a écrit :
search filter: (| (uid=user1) (| (mail=user1@test.com) (! (mail= user100@test.com) ) ) )
Hi
Looks that spaces are the problem ? Didn't know that.
I can search with filter
(|(uid=user1)(|(mail=user1@test.com)(!(mail=user100@test.com))))
Hi Grégory Rocher,
Yes, if we remove spaces from search filter, it is working. But the problem here is: Same search filter with spaces is working fine with Mozilla nsldap APIs, where we are getting results from LDAP server without any errors. We are getting "Bad search filter (-7)" error with OpenLDAP APIs. In our application, we must maintain backward compatibility, which means our application with OpenLDAP APIs should give results from LDAP server for search filter with spaces.
Can you provide solution in OpenLDAP APIs to fix this problem?
Thank you
On 17Oct25 13:48+0200, Gregory Rocher wrote:
Looks that spaces are the problem ? Didn't know that.
The space seems to be an issue at only one location. At the trailing space at `^` in the expression `(!(attr=val)^)`
Using slapd 2.6.9:
Working filter examples: '(!(uid=u1))' '( !(uid=u1))' '( ! (uid=u1))' '( ! ( uid=u1))' '( ! ( uid=u1 ))'
As soon as there is a trailing space after the `)` of the `not filter` expression, then a `Bad search filter (-7)` is returned. E.g.: '(!(uid=u1) )'
I cannot tell from [1] if this might be a bug in the parser or works as designed.
1: https://www.rfc-editor.org/rfc/rfc4515#section-3
On 21.10.25. 10:58, Bastian Tweddell wrote:
The space seems to be an issue at only one location. At the trailing space at `^` in the expression `(!(attr=val)^)`
[...]
I cannot tell from [1] if this might be a bug in the parser or works as designed.
The RFC 4515 grammar only permits spaces in assertion values, so a strictly conforming parser wouldn't even work with the examples you've given.
Ivan Nejgebauer wrote:
On 21.10.25. 10:58, Bastian Tweddell wrote:
The space seems to be an issue at only one location. At the trailing space at `^` in the expression `(!(attr=val)^)`
[...]
I cannot tell from [1] if this might be a bug in the parser or works as designed.
The RFC 4515 grammar only permits spaces in assertion values, so a strictly conforming parser wouldn't even work with the examples you've given.
The git history shows that the parser has always accepted and ignored leading spaces ' (foo=bar)', that behavior has been present since 1998 (initial commit, 42e0d83cb3a1a1c5b25183f1ab74ce7edbe25de7, libldap/search.c) It doesn't appear to have ever done anything special with trailing spaces.
A change was made in 2001 (commit 4e79e82972c0d5815608e139c1a3db0c6d2f7704) to require NOT filters to contain only a single component. This is the change that is rejecting the trailing space, and it only affects NOT filters. I think the behavior regarding trailing spaces was simply ignored.
Yes @Howard Chu.
The code in the file libraries/libldap/filter.c file: In function put_filter_list:
if( tag == LDAP_FILTER_NOT && ( next == NULL || *str )) { return -1; } This code is only for NOT filters. If there is a trailing space, *str will be true, and the function will incorrectly return an error (-1). To handle trailing spaces for NOT filters, we should add some code to check/skip for tailing spaces performing the final check for a NOT filter.
//New code - start if( tag == LDAP_FILTER_NOT && next != NULL ) { while ( *str && LDAP_SPACE( (unsigned char) *str ) ) { str++; } } //New code - end
if( tag == LDAP_FILTER_NOT && ( next == NULL || *str )) { return -1; }
The above new code ensures that filters with spaces between components are parsed correctly for NOT filters.
Share your thoughts on these code changes.
Thank you.
c.venugopal521@gmail.com wrote:
Yes @Howard Chu.
The code in the file libraries/libldap/filter.c file: In function put_filter_list:
if( tag == LDAP_FILTER_NOT && ( next == NULL || *str )) { return -1; } This code is only for NOT filters. If there is a trailing space, *str will be true, and the function will incorrectly return an error (-1). To handle trailing spaces for NOT filters, we should add some code to check/skip for tailing spaces performing the final check for a NOT filter.
//New code - start if( tag == LDAP_FILTER_NOT && next != NULL ) { while ( *str && LDAP_SPACE( (unsigned char) *str ) ) { str++; } } //New code - end
if( tag == LDAP_FILTER_NOT && ( next == NULL || *str )) { return -1; }
The above new code ensures that filters with spaces between components are parsed correctly for NOT filters.
Share your thoughts on these code changes.
It would be better to fix the apps to stop generating invalid filters, rather than add special cases to the library. Adding special cases is how bloat grows over time.
On 2025/10/23 06:25, Howard Chu wrote:
Adding special cases is how bloat grows over time.
"... bloat grows unmanageable"...
That said, unless conditions prohibit it, I believe in trimming spaces at either end of extracted substrings as a matter of course. My assumptions is that leading and trailing spaces are usually invisible and unintended and are frequent enough as a result to not be considered "a special case". Just my two cents.
Lucio.
openldap-technical@openldap.org