Edit: I have discovered the cause of the failures, which is a bug in my customized smbk5passwd module. Line 278 has a faulty #ifdef, causing the operation not to be marked as an internal modification. OpenLDAP assumes the worst and requires manage access for the operation. However, part of my question remains — what does manage access really mean?
I have a password-changing operation on an OpenLDAP 2.3 server that sometimes succeeds and sometimes fails.
When if fails, this is what the user sees:
ldapclient:~# passwd twohund Enter new password: Re-type new password: LDAP password information update failed: Insufficient access passwd: Permission denied passwd: password unchanged
I have debug traces from slapd -d 233 from unsuccessful and successful attempts below. As you can see, in the first case, slapd wants manage-level access to an attribute, and in the other it just wants to delete and write the attribute. In slapd.conf, I have configured the attribute such that the user has write access.
My question has two parts:
- What does
manage-level access mean? The slapd.conf(5) man page says that "managegrants all access including administrative access", but doesn't explain further what administrative access means, when it would be applicable, how it differs fromwriteaccess, or what kind of damage a rogue user withmanage-level access can do. The OpenLDAP manual does not elaborate any further. I have not been able to find any examples of OpenLDAP configurations that have amanage-level access control entry. Optional Bonus: Why wouldslapdrandomly need different access levels for the same operation? It seems like a bug to me. I'm using a customized version of the smbk2passwd module to make the LDAP server internally modifysmbPasswdMustChangeand other timestamps on an EXOP password change.
Here is a slapd debug trace from the failure:
do_extended
ber_scanf fmt ({m) ber:
ber_scanf fmt (m) ber:
ber_scanf fmt ({) ber:
ber_scanf fmt (m) ber:ber_scanf fmt (m) ber:
>>> dnPrettyNormal:
,
bdb_dn2entry("uid=twohund,ou=people,dc=my,dc=org")
=> bdb_dn2id("ou=people,dc=my,dc=org")
bdb_dn2id("uid=twohund,ou=people,dc=my,dc=org")
bdb_entry_get: found entry: "uid=twohund,ou=people,dc=my,dc=org"
bdb_entry_get: rc=0
bdb_dn2entry("uid=twohund,ou=people,dc=my,dc=org")
=> bdb_entry_get: found entry: "uid=twohund,ou=people,dc=my,dc=org"
bdb_entry_get: rc=0
bdb_dn2entry("uid=twohund,ou=people,dc=my,dc=org")
bdb_modify_internal: 0x0000189a: uid=twohund,ou=People,dc=my,dc=org
=> access_allowed: delete access to "uid=twohund,ou=People,dc=my,dc=org" "userPassword" requested
=> acl_get: [3] attr userPassword
access_allowed: no res from state (userPassword)
=> acl_mask: access to entry "uid=twohund,ou=People,dc=my,dc=org", attr "userPassword" requested
=> acl_mask: to all values by "uid=passwdchgroot,ou=ldap,dc=my,dc=org", (=0)
OP 128
access_allowed: delete access granted by write(=wrscxd)
=> access_allowed: manage access to "uid=twohund,ou=People,dc=my,dc=org" "sambaPwdMustChange" requested
=> acl_get: [3] attr sambaPwdMustChange
access_allowed: no res from state (sambaPwdMustChange)
=> acl_mask: access to entry "uid=twohund,ou=People,dc=my,dc=org", attr "sambaPwdMustChange" requested
=> acl_mask: to all values by "uid=passwdchgroot,ou=ldap,dc=my,dc=org", (=0)
OP 128
access_allowed: manage access denied by write(=wrscxd)
bdb_modify: modify failed (50)
send_ldap_result: conn=0 op=1 p=3
send_ldap_extended: err=50 oid= len=0
send_ldap_response: msgid=4 tag=120 err=50
Here is one from a successful run:
do_extended
ber_scanf fmt ({m) ber:
ber_scanf fmt (m) ber:
ber_scanf fmt ({) ber:
ber_scanf fmt (m) ber:
ber_scanf fmt (m) ber:
>>> dnPrettyNormal:
,
bdb_dn2entry("uid=twohund,ou=people,dc=my,dc=org")
=> bdb_dn2id("ou=people,dc=my,dc=org") bdb_dn2id("uid=twohund,ou=people,dc=my,dc=org")
bdb_entry_get: found entry: "uid=twohund,ou=people,dc=my,dc=org"
bdb_entry_get: rc=0
bdb_dn2entry("uid=twohund,ou=people,dc=my,dc=org")
=> bdb_entry_get: found entry: "uid=twohund,ou=people,dc=my,dc=org"
bdb_entry_get: rc=0
bdb_dn2entry("uid=twohund,ou=people,dc=my,dc=org")
bdb_modify_internal: 0x0000189a: uid=twohund,ou=People,dc=my,dc=org
=> access_allowed: delete access to "uid=twohund,ou=People,dc=my,dc=org" "userPassword" requested
=> acl_get: [3] attr userPassword
access_allowed: no res from state (userPassword)
=> acl_mask: access to entry "uid=twohund,ou=People,dc=my,dc=org", attr "userPassword" requested
=> acl_mask: to all values by "uid=passwdchgroot,ou=ldap,dc=my,dc=org", (=0)
OP 128
access_allowed: delete access granted by write(=wrscxd)
=> access_allowed: delete access to "uid=twohund,ou=People,dc=my,dc=org" "sambaPwdMustChange" requested
=> acl_get: [3] attr sambaPwdMustChange
access_allowed: no res from state (sambaPwdMustChange)
=> acl_mask: access to entry "uid=twohund,ou=People,dc=my,dc=org", attr "sambaPwdMustChange" requested
=> acl_mask: to all values by "uid=passwdchgroot,ou=ldap,dc=my,dc=org", (=0)
OP 128
access_allowed: delete access granted by write(=wrscxd)
=> access_allowed: delete access to "uid=twohund,ou=People,dc=my,dc=org" "sambaPwdCanChange" requested