Full_Name: Michael Str��der Version: 2.4.25 OS: openSUSE Linux URL: Submission from: (NULL) (195.145.144.134) If an assertion control is sent along with a modify request slapo-unique returns operation error with diagnostic message "unique_search failed" instead of returning constraint violation.
Further observations show that... 1. processing add requests seems to behave like expected. 2. it depends on the assertion filter sent in the control value: $ ldapmodify -H ldap://localhost -D "uid=Mstroeder,dc=stroeder,dc=de" -W -f uidnumber_clash.ldif -e 'assert=(cn=*)' modifying entry "uid=ttester,dc=stroeder,dc=de" ldap_modify: Operations error (1) additional info: unique_search failed $ ldapmodify -H ldap://localhost -D "uid=Mstroeder,dc=stroeder,dc=de" -W -f uidnumber_clash.ldif -e 'assert=(objectClass=*)' modifying entry "uid=ttester,dc=stroeder,dc=de" ldap_modify: Constraint violation (19) additional info: some attributes not unique
Note that with assertion control always Operations error: "unique_search failed" is returned even if the attribute values are unique. I'd really like to get this solved. web2ldap makes use of the assertion control to ensure that an entry has not been changed since being edited by the user. Otherwise I have to implement another vendor-specific hack switching off this feature when OpenLDAP is used as server. :-( Ciao, Michael. michael@stroeder.com wrote: > Further observations show that... > > 1. processing add requests seems to behave like expected. > > 2. it depends on the assertion filter sent in the control value: > > $ ldapmodify -H ldap://localhost -D "uid=Mstroeder,dc=stroeder,dc=de" -W -f > uidnumber_clash.ldif -e 'assert=(cn=*)' > modifying entry "uid=ttester,dc=stroeder,dc=de" > ldap_modify: Operations error (1) > additional info: unique_search failed > > $ ldapmodify -H ldap://localhost -D "uid=Mstroeder,dc=stroeder,dc=de" -W -f > uidnumber_clash.ldif -e 'assert=(objectClass=*)' > modifying entry "uid=ttester,dc=stroeder,dc=de" > ldap_modify: Constraint violation (19) > additional info: some attributes not unique
michael@stroeder.com wrote: > Note that with assertion control always > Operations error: "unique_search failed" > is returned even if the attribute values are unique. > > I'd really like to get this solved. web2ldap makes use of the assertion > control to ensure that an entry has not been changed since being edited by the > user. Otherwise I have to implement another vendor-specific hack switching off > this feature when OpenLDAP is used as server. :-( First step toward a solution would be providing slapd -d output for the problem. Probably a sample config would help too. > Ciao, Michael. > > michael@stroeder.com wrote: >> Further observations show that... >> >> 1. processing add requests seems to behave like expected. >> >> 2. it depends on the assertion filter sent in the control value: >> >> $ ldapmodify -H ldap://localhost -D "uid=Mstroeder,dc=stroeder,dc=de" -W -f >> uidnumber_clash.ldif -e 'assert=(cn=*)' >> modifying entry "uid=ttester,dc=stroeder,dc=de" >> ldap_modify: Operations error (1) >> additional info: unique_search failed >> >> $ ldapmodify -H ldap://localhost -D "uid=Mstroeder,dc=stroeder,dc=de" -W -f >> uidnumber_clash.ldif -e 'assert=(objectClass=*)' >> modifying entry "uid=ttester,dc=stroeder,dc=de" >> ldap_modify: Constraint violation (19) >> additional info: some attributes not unique > > > -- -- Howard Chu CTO, Symas Corp. http://www.symas.com Director, Highland Sun http://highlandsun.com/hyc/ Chief Architect, OpenLDAP http://www.openldap.org/project/
Howard Chu wrote: > michael@stroeder.com wrote: >> Note that with assertion control always >> Operations error: "unique_search failed" >> is returned even if the attribute values are unique. >> >> I'd really like to get this solved. web2ldap makes use of the assertion >> control to ensure that an entry has not been changed since being >> edited by the >> user. Otherwise I have to implement another vendor-specific hack >> switching off >> this feature when OpenLDAP is used as server. :-( > > First step toward a solution would be providing slapd -d output for the > problem. Probably a sample config would help too. (Sigh! Did anybody actually read through my report?) Take any slapd.conf with database hdb and add these lines (no other overlays configured): overlay unique unique_attributes uid uidNumber employeeNumber Or any other LDAP-URL-based unique constraint... Then apply a LDIF change record (example below) which contains any of the attributes defined as unique (no matter whether unique constraint is violated or not). ------------------------------- snip ------------------------------- dn: cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local changetype: modify replace: employeeNumber employeeNumber: 456 - ------------------------------- snip ------------------------------- Try these commands (bind-DN is the rootdn here): Without assertion control it works: $ ldapmodify -H ldap://localhost:2071 -D "uid=diradm,ou=schulung,dc=stroeder,dc=local" -w testsecret -f unique.ldif modifying entry "cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local" Assertion control just contains objectClass filter: $ ldapmodify -H ldap://localhost:2071 -D "uid=diradm,ou=schulung,dc=stroeder,dc=local" -w testsecret -f unique.ldif -e 'assert=(objectClass=*)' modifying entry "cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local" This fails: $ ldapmodify -H ldap://localhost:2071 -D "uid=diradm,ou=schulung,dc=stroeder,dc=local" -w testsecret -f unique.ldif -e 'assert=(cn=*)'modifying entry "cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local" ldap_modify: Operations error (1) additional info: unique_search failed Output of slapd -d config,stats,stats2,acl,args,trace,sync: ------------------------------- snip ------------------------------- [..] conn=1000 op=1 modifications: replace: employeeNumber one value, length 3 conn=1000 op=1 MOD dn="cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local" conn=1000 op=1 MOD attr=employeeNumber bdb_dn2entry("cn=anna blume,ou=users,ou=schulung,dc=stroeder,dc=local") => hdb_dn2id("ou=users,ou=schulung,dc=stroeder,dc=local") <= hdb_dn2id: got id=0x6 => hdb_dn2id("cn=anna blume,ou=users,ou=schulung,dc=stroeder,dc=local") <= hdb_dn2id: got id=0xd entry_decode: "" <= entry_decode() ==> unique_modify <cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local> ==> unique_search (|(employeeNumber=456)) put_filter: "(|(employeeNumber=456))" put_filter: OR put_filter_list "(employeeNumber=456)" put_filter: "(employeeNumber=456)" put_filter: simple put_simple_filter: "employeeNumber=456" ber_scanf fmt ({mm}) ber: => hdb_search bdb_dn2entry("ou=schulung,dc=stroeder,dc=local") => access_allowed: search access to "ou=schulung,dc=stroeder,dc=local" "entry" requested <= root access granted => access_allowed: search access granted by manage(=mwrscxd) => access_allowed: search access to "ou=schulung,dc=stroeder,dc=local" "cn" requested <= root access granted => access_allowed: search access granted by manage(=mwrscxd) send_ldap_result: conn=1000 op=1 p=3 send_ldap_result: err=122 matched="" text="" send_ldap_result: conn=1000 op=1 p=3 send_ldap_result: err=1 matched="" text="unique_search failed" send_ldap_response: msgid=2 tag=103 err=1 ber_flush2: 34 bytes to sd 16 conn=1000 op=1 RESULT tag=103 err=1 text=unique_search failed connection_get(16) connection_get(16): got connid=1000 connection_read(16): checking for input on id=1000 ber_get_next ber_get_next: tag 0x30 len 5 contents: op tag 0x42, time 1304069972 ber_get_next ber_get_next on fd 16 failed errno=0 (Success) conn=1000 op=2 do_unbind conn=1000 op=2 UNBIND connection_close: conn=1000 sd=16 conn=1000 fd=16 closed ------------------------------- snip -------------------------------
Sad enough I had to turn off using the assertion control in upcoming web2ldap release as yet another vendor-specific workaround - this time for OpenLDAP... It works with OpenDS and OpenDJ and web2ldap uses it with these servers.
The problem seems to be that unique_modify() calls unique_search() passing it an Operation that contains the assertion, which fails within the search. The failure is propagated back to the modification. The assertion control should not apply to internal operations performed by the unique overlay. The solution to me is not straightforward, apart from explicitly removing the assert control when calling unique_search(). I understand this solution is by no means general; similar problems may surface in other overlays and with other controls. p.
changed notes moved from Incoming to Software Bugs
internal ops should not use assertion control
A workaround is to extend the assertion filter to match all other entries except the one to be modified: (|(cn=*)(!(entryDN=cn=Anna Blume,ou=Users,ou=schulung,dc=stroeder,dc=local))) -- Mit freundlichem Gruß Im Auftrag Johannes Kanefendt Kommunales Rechenzentrum Niederrhein Der Verbandsvorsteher Abteilung 2.3.2 - Schulen Online Friedrich-Heinrich-Allee 130 47475 Kamp-Lintfort -Germany- Telefon: +49 (0)2842 90 70 125 Web: www.krzn.de Email: Johannes.Kanefendt@krzn.de
Johannes.Kanefendt@krzn.de wrote: > A workaround is to extend the assertion filter to match all other entries > except the one to be modified: > > (|(cn=*)(!(entryDN=cn=Anna\20Blume,ou=Users,ou=schulung,dc=stroeder,dc=local))) The whole purpose of using the Assertion Control is that it should match the modified entry. When I construct a filter deliberately not matching the entry I can simply omit the Assertion Control completely. Maybe I didn't get your idea though. The use-case: My web2ldap sends Assertion Control along with a modify request with a filter constructed from all attributes considered to be not modified by another user: (&(entryCSN=20160112183104\2e449732Z\23000000\23000\23000000)(creatorsName=cn=michael\20str\c3\b6der\2bmail=michael@stroeder\2ecom\2cou=private\2cdc=stroeder\2cdc=de)(entryUUID=1c66859e\2d3441\2d1034\2d93db\2d751297a711ee)(modifiersName=cn=michael\20str\c3\b6der\2bmail=michael@stroeder\2ecom\2cou=private\2cdc=stroeder\2cdc=de)(createTimestamp=20150119160811Z)(entryDN=ou=test\2cou=Testing\2cdc=stroeder\2cdc=de)(modifyTimestamp=20160112183104Z)) This is done to really ensure that the entry was *not* changed after being read into the input form the user edits. Ciao, Michael.
Michael Ströder <michael@stroeder.com> schrieb am 12.01.2016 20:13:15: > The whole purpose of using the Assertion Control is that it should match the > modified entry. When I construct a filter deliberately not matching > the entry I > can simply omit the Assertion Control completely. The logical outcome of the assertion doesn't change as the actual assertion filter is or-ed with a rule that will never match the targeted entry. However, when (wrongly) passed to unique_search, it will prevent a failure as all other entries than the target match. > > Maybe I didn't get your idea though. > > The use-case: My web2ldap sends Assertion Control along with a modify request > with a filter constructed from all attributes considered to be not modified by > another user: > > (&(entryCSN=20160112183104\2e449732Z\23000000\23000\23000000) > (creatorsName=cn=michael\20str\c3\b6der\2bmail=michael@stroeder > \2ecom\2cou=private\2cdc=stroeder\2cdc=de)(entryUUID=1c66859e\2d3441 > \2d1034\2d93db\2d751297a711ee)(modifiersName=cn=michael\20str\c3 > \b6der\2bmail=michael@stroeder\2ecom\2cou=private\2cdc=stroeder > \2cdc=de)(createTimestamp=20150119160811Z)(entryDN=ou=test > \2cou=Testing\2cdc=stroeder\2cdc=de)(modifyTimestamp=20160112183104Z)) > Try to enclose the assertion by (|(...)(!(entryDN=ou=test,ou=Testing,dc=stroeder,dc=de))) or (|(...)(!(entryUUID=1c66859e-34411034-93db-751297a711ee)))
fixed in master
Commits: • 4bd6a6d4 by Howard Chu at 2021-07-20T17:54:26+01:00 ITS#6916 unique: internal ops shouldn't have user's controls