0

I have a user directory in an openldap server under the base DN ou=users,dc=mydomain. The user entries are uid=user1,ou=users,dc=mydomain

My current ACLs are:

{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none {4}to dn.subtree="ou=users,dc=mydomain" by self read {3}to dn.exact="dc=mydomain" attrs=entry by users search by * none {2}to dn.base="" by * read {1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none

Those allow a user to query and find his own entry. But if the authentictated user user1 searches for the base DN with the filter (uid=user1) set, no entries are found. In other words: ldapsearch -H ldap://myserver -b "ou=users,dc=mydomain" -D "uid=user1,ou=users,dc=mydomain" -x -W return nothing while ldapsearch -H ldap://myserver -b "uid=user1,ou=users,dc=mydomain" -D "uid=user1,ou=users,dc=mydomain" -x -W returns the entry for user1.

How do I need to tweak the ACLs so that the user can find his own entry (and only his own) with a filtered search on the base DN?

2 Answers 2

1

Defining OpenLDAP ACLs is tricky.

Most times ACL issues are caused by processing order of ACLs themselves and their who-clauses (by ...) and that ACLs implicitly end with by * none stopping the control flow.

You're using dynamic configuration with cn=config and this uses X-ORDERED extension in the schema to preserve order of some attribute values like olcAccess.

So the order in which your ACLs are processed is:

{0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by  dn="cn=admin,dc=mydomain" write by * none
{1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read
{2}to dn.base="" by * read
{3}to dn.exact="dc=mydomain" attrs=entry by users search by * none
{4}to dn.subtree="ou=users,dc=mydomain" by self read
{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none

So let's look at your ACLs in detail:

{0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none

This is an rule probably taken from some default configuration. It's ok to begin with it but I'd suggest some re-factoring:

  1. Omit attribute shadowLastChange since LDAP shadow is broken concept. And if you do use shadow maps, this ACL would allow the user to circumvent shadow password expiry.
  2. Change the order of who-clauses. In general follow the rule to mention the "higher" privileges first.
  3. If cn=admin,dc=mydomain is already the rootdn of this database you don't need that who-clause.
  4. Better grant password admin rights to a group.
  5. Do not grant read privilege at all by inclusive write access, use write-only privilege =w instead.

Better use:

{0}to attrs=userPassword by group="cn=admins,ou=groups,dc=mydomain" =w by self =w by anonymous auth by * none

{1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read

If dc=mydomain is your database suffix this ACL does not make much sense to me in the context of your question. Maybe a left-over from some tests?

{2}to dn.base="" by * read

This is not effective if placed in your database config entry. This must be added to front-end config entry cn=config (formerly in static config slapd.conf before any database section).

{3}to dn.exact="dc=mydomain" attrs=entry by users search by * none

I'd place an ACL like this at the end of the ACL list so it won't stop access to entry at this point. And if you want to use arbitrary search bases like ou=users,dc=mydomain you would have to grant this search right to the whole sub-tree.

So place this at the end of your ACLs and remove {3} or...

{6}to dn.subtree="dc=mydomain" attrs=entry by users search by * none

...move this rule:

{4}to dn.subtree="ou=users,dc=mydomain" by self read

Should probably be last ACL and replace {3}. See comment for {5}.

{5}to * by self write by dn="cn=admin,dc=mydomain" write by * none

Issues here:

  1. The by self write will never be reach because of the by self read in {4}.
  2. This ACL is not reached at all because of the implicit by * none in {4}.
  3. again: granting access to rootdn is not necessary
  4. again: better grant admin access to a group
  5. use better order of who-clauses
  6. reconsider if you really want to grant write access to all attributes to the user himself

Better:

{5}to * by group="cn=admins,ou=groups,dc=mydomain" write by self write by * none

One of the most important debugging option is to start slapd with logging its ACL processing:

/usr/sbin/slapd … -d config,stats,stats2,acl

So these hints should get you a started to work on your ACLs solving your problems yourself. Always think twice. It seems to me you have little bit of contradictive assumptions in your rules.

But there's obviously no way around deep-diving into the docs:

If you want to understand the ACLs in detail you should consult various on-line documentation:

2
  • I updated my question with more details.
    – mat
    Jul 20, 2018 at 12:58
  • 1
    I've did several edits to my answer. Please read carefully. Jul 20, 2018 at 14:28
0

This answer gace me the deciding clue. The only thing I had to alter was the suggested search acl from the top dn (dc=mydomain) to the user dn (ou=users,dc=mydomain)

Changing the ACLs to this does the trick: {5}to * by self write by dn="cn=admin,dc=mydomain" write by * none {4}to dn.subtree="ou=users,dc=mydomain" by self read {3}to dn.exact="ou=users,dc=mydomain" attrs=entry by users search by * none {2}to dn.base="" by * read {1}to dn.subtree="dc=something,dc=mydomain" by dn="uid=someone,ou=users,dc=mydomain" write by * read {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=mydomain" write by * none

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .