Hi,
my experimental overlay intercepts search requests and modifies the filter-expressions (e.g. removes/expand AND|OR). Therefore the overlay modifies "struct Filter op->ors_filter" on the fly, handles memory (op->o_tmpmemctx/filter_free) and so on. It works fine, currently no memleaks (valgrind) etc and I would like contribute it (once it's finished... ;-) )
To get the maximum flexibility out of the current prototyp I'm looking after a solution to have my overlay intercept the following "search", too:
access to filter=(description=editMe) by self write by * none
The ACL's filter seems not to "fire" a search request because in acl.c lines 704 to 709 "test_filter(NULL, e, a->acl_filter)" get's called directly. This results in bypassing the overlay's search callback. Was this for performance reasons?
Are there any chances to replace "test_filter()" by some kind of slapd_internal_search() in a way to enable overlay stack processing, for this internal search? Any sort of advice is very welcome - I just want to experiment with this, but currently I'm lost, regarding the right approach.
I think I've seen some kind of internal search regarding sasl-regexp expansion. When using a filter-expressions in a sasl-regexp some sort of internal search gets triggered, because my overlay reacts correctly on it: slapd/saslauthz.c lines 1805 - 1835. Possibly something similar could be done in acl.c, too? What's your opinion?
Thanks a lot! Daniel P.S.: slapd version: OpenLDAP-CVS
Daniel wrote:
Hi,
my experimental overlay intercepts search requests and modifies the filter-expressions (e.g. removes/expand AND|OR). Therefore the overlay modifies "struct Filter op->ors_filter" on the fly, handles memory (op->o_tmpmemctx/filter_free) and so on. It works fine, currently no memleaks (valgrind) etc and I would like contribute it (once it's finished... ;-) )
To get the maximum flexibility out of the current prototyp I'm looking after a solution to have my overlay intercept the following "search", too:
access to filter=(description=editMe) by self write by * none
The ACL's filter seems not to "fire" a search request because in acl.c lines 704 to 709 "test_filter(NULL, e, a->acl_filter)" get's called directly. This results in bypassing the overlay's search callback. Was this for performance reasons?
Are there any chances to replace "test_filter()" by some kind of slapd_internal_search() in a way to enable overlay stack processing, for this internal search?
No.
Any sort of advice is very welcome - I just want to experiment with this, but currently I'm lost, regarding the right approach.
Try intercepting bi_access_allowed().
Howard Chu wrote:
Daniel wrote:
Hi,
my experimental overlay intercepts search requests and modifies the filter-expressions (e.g. removes/expand AND|OR). Therefore the overlay modifies "struct Filter op->ors_filter" on the fly, handles memory (op->o_tmpmemctx/filter_free) and so on. It works fine, currently no memleaks (valgrind) etc and I would like contribute it (once it's finished... ;-) )
To get the maximum flexibility out of the current prototyp I'm looking after a solution to have my overlay intercept the following "search", too:
access to filter=(description=editMe) by self write by * none
The ACL's filter seems not to "fire" a search request because in acl.c lines 704 to 709 "test_filter(NULL, e, a->acl_filter)" get's called directly. This results in bypassing the overlay's search callback. Was this for performance reasons?
Are there any chances to replace "test_filter()" by some kind of slapd_internal_search() in a way to enable overlay stack processing, for this internal search?
No.
To clarify - there is no search operation at all here. It is simply comparing the ACL terms to the target entry for which access is being checked. The target entry may be the target of a Modify, Compare, etc., not necessarily a Search request. And there is no reason to perform an internal search, since the target entry is already in hand, being evaluated.
Whatever your overlay is doing, it seems silly to invoke it here. If you want a different filter, just write the desired filter into the ACL. Rewriting a static configuration item every time it's evaluated is rather wasteful.
Howard Chu wrote:
Howard Chu wrote:
Daniel wrote:
Hi,
my experimental overlay intercepts search requests and modifies the filter-expressions (e.g. removes/expand AND|OR). Therefore the overlay modifies "struct Filter op->ors_filter" on the fly, handles memory (op->o_tmpmemctx/filter_free) and so on. It works fine, currently no memleaks (valgrind) etc and I would like contribute it (once it's finished... ;-) )
To get the maximum flexibility out of the current prototyp I'm looking after a solution to have my overlay intercept the following "search", too:
access to filter=(description=editMe) by self write by * none
The ACL's filter seems not to "fire" a search request because in acl.c lines 704 to 709 "test_filter(NULL, e, a->acl_filter)" get's called directly. This results in bypassing the overlay's search callback. Was this for performance reasons?
Are there any chances to replace "test_filter()" by some kind of slapd_internal_search() in a way to enable overlay stack processing, for this internal search?
No.
Thanks a lot for your second reply. I think I need to explain this stupid thing in more detail:
To clarify - there is no search operation at all here.
Yes, that's what I've already (not) found out before. And it was the reason for my initial question. Why is test_filter() called directly here instead of an internal search (my assumption: probably because fo performance)?
It is simply comparing the ACL terms to the target entry for which access is being checked. The target entry may be the target of a Modify, Compare, etc., not necessarily a Search request. And there is no reason to perform an internal search, since the target entry is already in hand, being evaluated.
Ok, this answers why test_filter() is called directly - thanks. But how can an overlay possibly intercept this or what has to be change that an overlay can intercept this? My thought was: maybe by doing a "internal_search(scope base on entry e with filter a->acl_filter)" (how about performance?).
Whatever your overlay is doing, it seems silly to invoke it here. If you want a different filter, just write the desired filter into the ACL. Rewriting a static configuration item every time it's evaluated is rather wasteful.
These were exactly my doubts too, please see: http://www.openldap.org/lists/openldap-technical/200907/msg00144.html
Background-Information:
I've been searching after some kind of new LDAP feature (currently aka protocol-violation ;-) ) - mostly comparable to SQL's "select * from * where timestamp=now()". Translated into LDAP this would perhaps mean something like: "ldapsearch ... -H ... '(validnow=*)'"
Violating the LDAP-protocol by highjacking a "search-filter-expression" seems not to be the most elegant ldap-way (in regard to protocol extensions and the use of new extend controls etc), but: This functionality should be a server-side-controlled&enforced feature (customizable for different subtrees etc. pp.). The Server is able to detect the above "special" PRESENT-filter and replace it on-the-fly into: '(&(validNotBefore<=op's time)(validNotAfter>=op's time))'.
Additionally the server (overlay) enforces this kind of filtering transparently below distinct subtrees. This means: an incoming ldapsearch '(objectclass=*)' gets extended to (&(objectClass=*)(validnow=*)) and "validnow=*" itself explodes into "(&(vNB...)(vNA...))".
EQUALITY-Filters are handle the way that any incoming filter that contains: "validnow=19700101000000Z" get transformed into '(&(vNB<=1970...Z)(vNA>=1970...Z))'. Only in case the req_ndn is allowed to bypass or the resulting objects are allowed to be ignored.
Although this feature could be completly integrated into an catch-all-overlay I've split it into two parts: a slapd-internal validnow-core-part (very rare changes to filter.c only three additional functions, no changes to existing code) to fulfill the above (simple) feature. And an validnow-ctrl-part to handle subtree-configuration, exceptions, etc. The validnow-ctrl uses a fine grained configuration matrix to allow distinct entries and rdn-subtrees to bypass the server side enforcement under special circumstances (globally and/or locally configurable).
All this works fine: under enforced subtrees only valid objects are returned and only valid objects are allowed to authenticate, exceptions are handled correctly etc. I've successfully tested the behavior regarding bind-operation (simple & sasl) and various search request-scenarios. If the server respond (with an enforced/limited reply) extended control's are added to the reply, to inform validnow-capable clients (already tested). Currently the compare, add and modify is work in progress.
Now I want to come back to the original question: It would be nice to let validnow also take effect on slapd's ACL processing, e.g.
access to filter=(validnow=*) by users search by * none
I've already tried to "modify/replace" the a->acl_filter struct (quick&dirty hardcoded within in acl.c). It has worked fine for the first request but during the second request slapd segfaults away ;-). I think the overlay traversal [sh|w]ould work better...
In my opinion the above partially described feature (possibly not this solution) would be a very interessting LDAP feature especially in regard to authorization, provisioning and de-provisioning, data privacy and so on...
What kind of alternative solutions exist or do you see?
Cheers Daniel
To clarify - there is no search operation at all here.
Yes, that's what I've already (not) found out before. And it was the reason for my initial question. Why is test_filter() called directly here instead of an internal search (my assumption: probably because fo performance)?
No. Just because it's silly to perform a search when you already have the result available. The purpose of the "filter" ACL clause is to check whether an *already available* entry matches a filter, not to search for it. Performing an internal search would result in something possibly different, and definitely not in what this ACL clause is meant to.
It is simply comparing the ACL terms to the target entry for which access is being checked. The target entry may be the target of a Modify, Compare, etc., not necessarily a Search request. And there is no reason to perform an internal search, since the target entry is already in hand, being evaluated.
Ok, this answers why test_filter() is called directly - thanks. But how can an overlay possibly intercept this or what has to be change that an overlay can intercept this? My thought was: maybe by doing a "internal_search(scope base on entry e with filter a->acl_filter)" (how about performance?).
Whatever your overlay is doing, it seems silly to invoke it here. If you want a different filter, just write the desired filter into the ACL. Rewriting a static configuration item every time it's evaluated is rather wasteful.
These were exactly my doubts too, please see: http://www.openldap.org/lists/openldap-technical/200907/msg00144.html
Background-Information:
I've been searching after some kind of new LDAP feature (currently aka protocol-violation ;-) ) - mostly comparable to SQL's "select * from * where timestamp=now()". Translated into LDAP this would perhaps mean something like: "ldapsearch ... -H ... '(validnow=*)'"
Violating the LDAP-protocol by highjacking a "search-filter-expression" seems not to be the most elegant ldap-way (in regard to protocol extensions and the use of new extend controls etc), but: This functionality should be a server-side-controlled&enforced feature (customizable for different subtrees etc. pp.). The Server is able to detect the above "special" PRESENT-filter and replace it on-the-fly into: '(&(validNotBefore<=op's time)(validNotAfter>=op's time))'.
Additionally the server (overlay) enforces this kind of filtering transparently below distinct subtrees. This means: an incoming ldapsearch '(objectclass=*)' gets extended to (&(objectClass=*)(validnow=*)) and "validnow=*" itself explodes into "(&(vNB...)(vNA...))".
EQUALITY-Filters are handle the way that any incoming filter that contains: "validnow=19700101000000Z" get transformed into '(&(vNB<=1970...Z)(vNA>=1970...Z))'. Only in case the req_ndn is allowed to bypass or the resulting objects are allowed to be ignored.
Although this feature could be completly integrated into an catch-all-overlay I've split it into two parts: a slapd-internal validnow-core-part (very rare changes to filter.c only three additional functions, no changes to existing code) to fulfill the above (simple) feature. And an validnow-ctrl-part to handle subtree-configuration, exceptions, etc. The validnow-ctrl uses a fine grained configuration matrix to allow distinct entries and rdn-subtrees to bypass the server side enforcement under special circumstances (globally and/or locally configurable).
All this works fine: under enforced subtrees only valid objects are returned and only valid objects are allowed to authenticate, exceptions are handled correctly etc. I've successfully tested the behavior regarding bind-operation (simple & sasl) and various search request-scenarios. If the server respond (with an enforced/limited reply) extended control's are added to the reply, to inform validnow-capable clients (already tested). Currently the compare, add and modify is work in progress.
Now I want to come back to the original question: It would be nice to let validnow also take effect on slapd's ACL processing, e.g.
access to filter=(validnow=*) by users search by * none
I've already tried to "modify/replace" the a->acl_filter struct (quick&dirty hardcoded within in acl.c). It has worked fine for the first request but during the second request slapd segfaults away ;-). I think the overlay traversal [sh|w]ould work better...
In my opinion the above partially described feature (possibly not this solution) would be a very interessting LDAP feature especially in regard to authorization, provisioning and de-provisioning, data privacy and so on...
What kind of alternative solutions exist or do you see?
I'd rather define a new ordering matching rule for time-valued attrs that checks how a given value compares with "now"; something like "greaterThanNow" and "lessThanNow". This would allow to do something like
access to attrs=validnow val/greaterThanNow=19700101000000Z
or
access to filter=(validnow:greaterThanNow:=19700101000000Z)
where 19700101000000Z (the epoch) is used as a placeholder for the asserted value, which would be ignored.
Or, I'd write a dynacl module that does the same. I actually wrote one some time ago, and never found it useful. It's here ftp://ftp.openldap.org/incoming/pierangelo-masarati-2009-08-05.1.c
p.
masarati@aero.polimi.it schrieb:
What kind of alternative solutions exist or do you see?
I'd rather define a new ordering matching rule for time-valued attrs that checks how a given value compares with "now"; something like "greaterThanNow" and "lessThanNow". This would allow to do something like
access to attrs=validnow val/greaterThanNow=19700101000000Z
or
access to filter=(validnow:greaterThanNow:=19700101000000Z)
where 19700101000000Z (the epoch) is used as a placeholder for the asserted value, which would be ignored.
The attr "validnow" does not really exist. It's used for "detection" purposes only (that's the kind of protocol violation I've talked about).
The effective (exploded) filter contains the entries validity period's dead-ends (both generalizedTime Syntax): "validNotBefore" and "validNotAfter" which might be exist in an entry.
Nevertheless, I think I've understood your suggestion. I'll investigate into the direction of two additional MRs and try to implement them:
earlierThanNow and laterThanNow
This would result in a filter statement like this: (&(validNotBefore:earlierThanNow:=epoch)(validNotAfter:laterThanNow:=epoch))
Sounds this correct?
Thanks a lot!
Or, I'd write a dynacl module that does the same. I actually wrote one some time ago, and never found it useful. It's here ftp://ftp.openldap.org/incoming/pierangelo-masarati-2009-08-05.1.c
I have already had a look into contrib/slapd-modules/acl and decided: dynacl in general is not what I think I'll need or want. The ACL-processing would have been only a "nice to have". The core functionality is the server side transparent enforcment in combination with the bypass-exception. I have understood the dynacl contrib code the way, that only "by" clauses could be handled...