Lists of access directives are evaluated in the order they appear in
slapd.conf. When a <what> clause matches the datum whose access is
being evaluated, its <who> clause list is checked. When a <who> clause
matches the accessor's properties, its <access> and <control> clauses
are evaluated. Access control checking stops at the first match of the
<what> and <who> clause, unless otherwise dictated by the <control>
clause.
First matching <what>
and <who>
for attempt to change password is:
access to *
by users read
If you move 'access to *' clause at end of list it should work fine. Or just swap order of "by users read" and "by self write".
ACLs is most tricky part of OpenLDAP configuration, so read slapd.access(5)
carefully, and be sure that you completely understood how ACLs work before writing some non-trivial.
The error no global superior knowledge
means that slapd
doesn't know where to put your new entry. This typically means that you have not defined an appropriate database. With newer systems (ones using cn=config
instead of slapd.conf
), you would typically first add a new database or modify an existing database entry using ldapadd
or ldapmodify
. For example, on my Fedora 17 system, the default install sets up a database like this for hosting dc=my-domain,dc=com
:
dn: olcDatabase={2}hdb
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
structuralObjectClass: olcHdbConfig
creatorsName: cn=config
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
To host your organization (o=myorganization, c=fr
), I would need to create the following LDIF file:
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: o=myorganization, c=fr
-
replace: olcRootDN
olcRootDN: cn=Manager,o=myorganization,c=fr
-
replace: olcAccess
olcAccess: {0}to *
by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
by dn.base="cn=Manager,o=myorganization,c=fr" write
by * none
And I would then load these modifications like this:
ldapmodify -Y EXTERNAL -H ldapi:/// -f mychanges.ldif
This works because of the following olcAccess
lines already present in the configuration:
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to *
by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
by * none
This grants root
, contacting slapd
over the ldapi:///
socket, password-free access to the cn=config
tree.
I would then load in my top-level entry:
dn: o=myorganization, c=fr
objectclass: organization
o: myorganization
By running:
ldapadd -Y EXTERNAL -H ldapi:/// -f myobject.ldif
This works because I've added a similar ACL to this database. Note that I didn't need to start with c=fr
here, because the database is defined to hold o=myorganization,c=fr
Best Answer
It's amazing how the little things can bite you so hard. Since this was in a script, I indented the command section to keep with coding conventions. Apparently, ldapmodify interpreted the white space as part of the commands/data and got confused. I reformatted it to look like this, and now it works: