Hi there,
I'm trying to enforce that the 'uid' attribute is globally unique in my tree using the unique overlay. For a collection of mostly-uninteresting reasons, the LDAP server is publicly connectable but not publicly searchable (details below). It appears that the unique overlay uses the *worst possible* combination of credentials to perform the searches it uses to guarantee uniqueness.
All of the following information was obtained from ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config -- it's really what slapd thinks it's seeing.
My unique configuration:
dn: olcOverlay={0}unique,olcDatabase={1}hdb,cn=config objectClass: olcUniqueConfig olcOverlay: {0}unique olcUniqueURI: ldap:///dc=unreasonent,dc=com?uid?sub?
My database configuration (indexes and hdb configuration elided):
dn: olcDatabase={1}hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: {1}hdb olcDbDirectory: /var/lib/ldap/unreasonent.com olcSuffix: dc=unreasonent,dc=com olcAccess: {0}to attrs=userPassword by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by group="cn=Directory Administrator,ou=Roles,dc=internal,dc=unreasonent,dc=com" manage by anonymous auth by self write by * none olcAccess: {1}to attrs=shadowLastChange by self write by * break olcAccess: {2}to dn.base="" by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by group="cn=Directory Administrator,ou=Roles,dc=internal,dc=unreasonent,dc=com" manage by * break olcAccess: {3}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by group="cn=Directory Administrator,ou=Roles,dc=internal,dc=unreasonent,dc=com" manage by users read by peername.regex="IP=10.27.70.6:\d+" read by * none
(The peername.regex ACL entry is shrapnel from my attempts to make this work on my own, but it came in handy. The IP address there is the IP address of my LDAP server.)
As you can see anonymous users are allowed to do one thing: authenticate. My tree contains the following user already:
dn: uid=owen,ou=People,dc=internal,dc=unreasonent,dc=com
When I log in with the user above (who is in the group cn=Directory Administrator,ou=Roles,dc=internal,dc=unreasonent,dc=com) and add the following test user
dn: uid=owen,ou=test,ou=People,dc=unreasonent,dc=com changetype: add objectClass: inetOrgPerson uid: owen sn: Test cn: Test
the add succeeds (which should not happen, as the UID is already in use). A little digging with slapd -d -1 reveals that the unique overlay is doing a search of its own:
==> unique_add <uid=owen,ou=test,ou=People,dc=unreasonent,dc=com> ==> unique_search (|(uid=owen)) str2filter "(|(uid=owen))" put_filter: "(|(uid=owen))" put_filter: OR put_filter_list "(uid=owen)" put_filter: "(uid=owen)" put_filter: simple put_simple_filter: "uid=owen" begin get_filter OR begin get_filter_list begin get_filter EQUALITY ber_scanf fmt ({mm}) ber: ber_dump: buf=0xb5dd5438 ptr=0xb5dd543a end=0xb5dd5447 len=13 0000: a3 0b 04 03 75 69 64 04 04 6f 77 65 6e ....uid..owen end get_filter 0 end get_filter_list end get_filter 0 => hdb_search bdb_dn2entry("dc=unreasonent,dc=com") => access_allowed: search access to "dc=unreasonent,dc=com" "entry" requested => dn: [3] => acl_get: [4] attr entry => acl_mask: access to entry "dc=unreasonent,dc=com", attr "entry" requested => acl_mask: to all values by "", (=0) <= check a_dn_pat: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth <= check a_dn_pat: users <= check a_peername_path: IP=10.27.70.6:\d+ => acl_string_expand: pattern: IP=10.27.70.6:\d+ => acl_string_expand: expanded: IP=10.27.70.6:\d+ => regex_matches: string: IP=10.27.70.210:46908 => regex_matches: rc: 1 no matches <= check a_dn_pat: * <= acl_mask: [5] applying none(=0) (stop) <= acl_mask: [5] mask: none(=0) => slap_access_allowed: search access denied by none(=0) => access_allowed: no more rules send_ldap_result: conn=1029 op=33 p=3 send_ldap_result: err=32 matched="" text="" => unique_search found 0 records
As you can see, (a) the IP address the search "comes from" is not the IP address of the LDAP server nor is it the LDAP server's ldapi:// socket (it's actually my client machine's IP address) and (b) the authenticated DN used in the search is empty. Combined, these two facts lead to slapd deciding the search is not permitted by the ACL, which in turn causes the unique overlay to decide no other entries with the same uid exist. This seems wrong: the connection from that IP and port has already authenticated as a user (which would've permitted the search).
Assuming for the moment that allowing the world at large to search my LDAP server is not an option, how can I allow the unique overlay to enforce my constraint?
-o
Owen Jacobson wrote:
Hi there,
I'm trying to enforce that the 'uid' attribute is globally unique in my tree
using the unique overlay. For a collection of mostly-uninteresting reasons, the LDAP server is publicly connectable but not publicly searchable (details below). It appears that the unique overlay uses the *worst possible* combination of credentials to perform the searches it uses to guarantee uniqueness.
All of the following information was obtained from ldapsearch -Y EXTERNAL -H
ldapi:/// -b cn=config -- it's really what slapd thinks it's seeing.
As you can see, (a) the IP address the search "comes from" is not the IP
address of the LDAP server nor is it the LDAP server's ldapi:// socket (it's actually my client machine's IP address) and (b) the authenticated DN used in the search is empty. Combined, these two facts lead to slapd deciding the search is not permitted by the ACL, which in turn causes the unique overlay to decide no other entries with the same uid exist. This seems wrong: the connection from that IP and port has already authenticated as a user (which would've permitted the search).
Assuming for the moment that allowing the world at large to search my LDAP
server is not an option, how can I allow the unique overlay to enforce my constraint?
Re-read the slapo-unique(5) manpage. Specifically the 3rd paragraph.
On 2010-10-07, at 9:03 PM, Howard Chu wrote:
Owen Jacobson wrote:
Hi there,
I'm trying to enforce that the 'uid' attribute is globally unique in my tree using the unique overlay. For a collection of mostly-uninteresting reasons,
the LDAP server is publicly connectable but not publicly searchable (details below). It appears that the unique overlay uses the *worst possible* combination of credentials to perform the searches it uses to guarantee uniqueness.
All of the following information was obtained from ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config -- it's really what slapd thinks it's seeing.
As you can see, (a) the IP address the search "comes from" is not the IP address of the LDAP server nor is it the LDAP server's ldapi:// socket (it's actually my client machine's IP address) and (b) the authenticated DN used in the search is empty. Combined, these two facts lead to slapd deciding the search is not permitted by the ACL, which in turn causes the unique overlay to decide no other entries with the same uid exist. This seems wrong: the connection from that IP and port has already authenticated as a user (which would've permitted the search).
Assuming for the moment that allowing the world at large to search my LDAP server is not an option, how can I allow the unique overlay to enforce my constraint?
Re-read the slapo-unique(5) manpage. Specifically the 3rd paragraph.
Thanks.
I originally read the man page on my Mac, which is missing the relevant paragraph. (It's present on the Ubuntu version of the same man page.) In the future, you may want to include the paragraph, just in case. In case anyone else has the same problem:
The search is performed using the rootdn of the database, to avoid issues with ACLs preventing the overlay from seeing all of the relevant data. As such, the database must have a rootdn configured.
Cheers, -o
On Friday, 8 October 2010 02:46:58 Owen Jacobson wrote:
I originally read the man page on my Mac, which is missing the relevant
paragraph. (It's present on the Ubuntu version of the same man page.) In the future, you may want to include the paragraph, just in case.
Your Mac probably has an older version. This paragraph was added between the release of 2.4.16 and 2.4.17 ...
In future, you may want to read the *current* documentation, just in case it has bugfixes (ITS #6108 in this case).
Regards, Buchan
openldap-technical@openldap.org