| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Codecov Report
@@ Coverage Diff @@
## master #272 +/- ##
==========================================
+ Coverage 71.30% 71.72% +0.41%
==========================================
Files 50 49 -1
Lines 4796 5033 +237
Branches 802 894 +92
==========================================
+ Hits 3420 3610 +190
- Misses 1045 1067 +22
- Partials 331 356 +25
Continue to review full report at Codecov.
|
Sorry, something went wrong.
There was a problem hiding this comment.
I'm -1 on this approach.
It seems rather wasteful and slow to create a LDAP connection object to verify that a string is a valid filter. The call will also connect to the default ldap server from /etc/openldap/ldap.conf on success. This will spam the error log of the default LDAP server.
ldap_pvt_put_filter might work, but the function is not exposed in ldap.h.
Sorry, something went wrong.
|
@tiran Would it create a ldap connection if I had a /etc/openldap/ldap.conf? Then I will see if I can find a way to prevent this. |
Sorry, something went wrong.
|
If there is no connection involved, why catch SERVER_DOWN? |
Sorry, something went wrong.
|
If the ldap object is uninitialized and unconnected it raises ldap.SERVER_DOWN without any connection attempt. What I can see is that it reads my "/etc/ldap/ldap.conf" and tries to read ~/.ldaprc. |
Sorry, something went wrong.
|
The main problem is that, however you connect, on SERVER_DOWN, all filters would be considered valid – the function would return a wrong result with no indication of failure. |
Sorry, something went wrong.
Suggested in python-ldap#272
|
I don't want to merge code that can silently hide a failure, so I'll reject this approach. It might be suitable for a library that builds on top of python-ldap, rather than for python-ldap itself. |
Sorry, something went wrong.
|
There is no REOPEN button. |
Sorry, something went wrong.
|
If you set LDAPNOINIT the client libraries will bypass reading ldap.conf/.ldaprc. This is what the OpenLDAP test suite does to ensure that local client configurations don't interfere. |
Sorry, something went wrong.
|
In my opinion the patch is not a clean solution but a hack. I don't like to add such hacks to python-ldap. You can easily ship the short function in your application. I wouldn't mind to add this feature iff OpenLDAP adds a public API to perform the check. |
Sorry, something went wrong.
Apologies, I had wrong assumptions of the GitHub UI. My main objection is that is_filter returns different results based on whether the server is reachable or not. |
Sorry, something went wrong.
Yes, that would be the best. You already mentioned the not exposed function ldap_pvt_put_filter.
The ldap connection there is not connected and will never be. At least I could not get any connection attempt with that code. ldap.SERVER_DOWN therefore does only indicate that the filter is valid, no matter if there is a server which can be connected to or not. The filter validity is checked before any connection attempts, it there are any at all. If that code really does a connection, how would I set this up to reproduce this? We are using the above code since years and it works. We have a /etc/openldap/ldap.conf and a /etc/ldap/ldap.conf with valid entries. I don't see where it's evaluated. and we did not set LDAPNOINIT. |
Sorry, something went wrong.
|
I took the name is_filter() for consistency, because there is also a is_dn() already. |
Sorry, something went wrong.
|
I see. I misunderstood the code. Still, this does rely on undocumented behavior, so @tiran's comment holds:
IOW, if this is the easiest way to check filter validity using OpenLDAP, it's an issue in OpenLDAP. python-ldap is the wrong place for a workaround. |
Sorry, something went wrong.
|
Did you raise the issue with OpenLDAP upstream to request a filter validation function? I'm hesitant to use an internal, private function ldap_pvt_put_filter to validate filters. |
Sorry, something went wrong.
|
Sorry, I did not see your latest answer. I created a feature request at openldap: https://bugs.openldap.org/show_bug.cgi?id=9393 I also updated the pull request, made it more clear that ldap.SERVER_DOWN is expected to be raised and raise a RuntimeError (which can't happen) in all other cases. Maybe you are fine with this implementation and could provide it as fallback until there is something available in Open-LDAP? The function has detailed tests. |
Sorry, something went wrong.
|
They aren't replying at all. |
Sorry, something went wrong.
What you filed is a feature request. The earliest it would be done is OpenLDAP 2.7. |
Sorry, something went wrong.
|
Meanwhile openldap exposed ldap_pvt_put_filter: https://git.openldap.org/openldap/openldap/-/merge_requests/730/diffs Target Milestone of the bug says OpenLDAP 2.7, it's not released yet (no git tag, just in branch master). But I wrote my own Filter parsing library which should be identical to the OpenLDAP one. I have over 500 test cases and hope to have catched all possible combinations. OpenLDAP isn't strictly following the RFC, especially regarding whitespace. https://docs.freeiam.org/en/latest/examples/ldap_filter.html |
Sorry, something went wrong.
Yes, I guess we could do what we used to do with ldap_init_fd, expect it to be available by defining it ourselves under a version check (and for platforms that don't have it, use this fallback implementation instead?)
I really like the interface in this! What exactly are the differences between libldap's parsing and the RFC? I think I knew it was slightly more lenient on extra whitespace in a position or two, anything else? Was there a python parsing library that could work at build-time? I think there were people who wanted to keep the dependencies of python-ldap to a minimum. Only gripe is that attr == '' for a presence filter looks wrong, but in some ways so would attr != None. And the typo comparision -> comparison (and while ldap uses the term 'assertion' I'd use something like 'predicate') |
Sorry, something went wrong.
I don't remember exactly every case anymore but:
(! ( a= b )) ^ ^ ^ ^·
I don't understand the question?
You mean value == ''? Because attr is correctly set: >>> x = freeiam.ldap.filter.Filter('foo=*')
>>> x.root.comparisons[0].attr
'foo'
>>> x.root.comparisons[0].value
''
In theory a presence filter has no attribute value, but it's inherited from the base class and easier for composing the string again.
Thanks, I fixed it, will be released soon. I stored it wrong in my brain, not the first time for this word.
You mean attribute not assertion, which I use. |
Sorry, something went wrong.
Sorry for nerd sniping both of us I guess. I wrapped ldap_pvt_put_filter to do a bunch of tests to check. My expectation was that libldap might accept (some) whitespace but only when it's clearly not a valid filter otherwise. Sort of seems like things work that way already:
That's consistent with the above, maybe not great for a test_filter() function, sure.
As expected this is equal to (!(a= b )) as in NOT(a equals \20b\20).
They actually behave exactly according to the RFC (as substring filters)?
Yes, again for good reason (noone would use the command line tools otherwise) but not ideal for test_filter()
That one encodes correctly (preserving everything), what you're probably seeing is matching rule processing on the server (e.g. caseIgnoreMatch normalising the assertion to foo bar by stripping leading/trailing/consecutive whitespace)?
True, the project never had a way to test these library level things. There is a start on a Python test suite which would be able to now, but also a limit on people's attention so writing a test suite for something that is probably working fine is not high on people's list... It's a shame when someone wants to write a parallel implementation, sure.
I thought you were suggesting we adopt something similar here.
No, what I mean is that if you set attr = Filter.attr('attr') these are different filters
Which is why I'm saying that using something like attr != None is a slightly better way of expressing a presence filter.
Exactly
Yeah, it was bikeshedding and I apologise. |
Sorry, something went wrong.
I only need to validate whether the filter will be accepted by OpenLDAP - so the function should also just accept it and shouldn't be stricter than what is actually possible.
Okay, nice that the matching rule is responsible for it. I didn't had a look yet, whether those spaces were transmitted along with on protocol level.
Well no, as I wrote it for myself I have something - purely python.
Ah, now I understand :-) |
Sorry, something went wrong.
In here then, you could do what I suggested, use ldap_pvt_put_fitler if available, the ldap_search hack otherwise?
Do they provide command-line tools (that don't use libldap) or other interfaces that process string representations? Because over the wire, the filter structure is completely unambiguous and value-agnostic.
I checked the output of ldap_pvt_put_fitler which is how things get embedded in the search request. That was enough to sate my curiosity, might not be enough for you :)
Given I'm planning on providing much more pythonic APIs, a filter abstraction (creation only, so an algebraic structure) has always been on the list that would be useful and I think you hit the nail on the head in terms of a desirable shape for one. Sure, that means we probably don't need to parse string representations. And that would be definitely be a whole new PR, targeting 4.0+.
Saw those updates, nice. Just a note, very few attributes allow an empty value, so that's probably why you wrote what you wrote originally, but they exist. |
Sorry, something went wrong.
done. |
Sorry, something went wrong.
|
btw does pvt in ldap_pvt_put_filter stands for private? |
Sorry, something went wrong.
691bb4ff.1f8ee5cd 0x7fee8600f6c0 ldap_read: want=34, got=34 691bb4ff.1f8efd36 0x7fee8600f6c0 0000: 00 0a 01 02 0a 01 00 02 01 00 02 01 00 01 01 00 ................ 691bb4ff.1f8f1563 0x7fee8600f6c0 0010: a3 0e 04 02 63 6e 04 08 66 6f 6f 20 20 62 61 72 ....cn..foo bar 691bb4ff.1f8f273d 0x7fee8600f6c0 0020: 30 00 0. → the two spaces are transmitted correctly: 66 6f 6f 20 20 62 61 72 691bb4ff.1f935137 0x7fee8600f6c0 conn=1011 op=4 SRCH base="" scope=2 deref=0 filter="(cn=foo bar)" → and then the filter is normalized inside of slapd. |
Sorry, something went wrong.
Yes, it was originally a private API, normally private APIs are only available to other code in the project, but the project decided to expose it as is. |
Sorry, something went wrong.
|
I'm ok with this. @tiran you put this on hold, what do you think of this version? |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Add a utility functions ldap.filter.is_filter which can be used to check if the ldap filter has valid syntax.
This uses an unbound ldap connection, so the values are ensured to be correct via the C library.
I added test cases for the function.