Fix OpenLDAP Insufficient Access Error 50

Fix OpenLDAP Error 50 for ldapadd, ldapmodify, ldapdelete, password changes, cn=config, and no-write-access-to-parent ACL failures.

Published

Updated

Read time 23 min read

Reviewed byDeepak Prasad

Diagnose and fix OpenLDAP insufficient access error 50 using olcAccess ACLs

OpenLDAP returns Error 50 when the authenticated identity does not have enough permission to complete an LDAP operation.

Common messages include:

output
ldap_add: Insufficient access (50)

Modify, delete, and bind failures use the same numeric code:

output
ldap_modify: Insufficient access (50)
output
ldap_delete: Insufficient access (50)
output
ldap_bind: Insufficient access (50)

When ldapadd lacks parent children/write, OpenLDAP adds a more specific hint:

output
ldap_add: Insufficient access (50)
        additional info: no write access to parent

In each case the numeric code 50 means authorization failed after bind evaluation. The additional info line often names the missing entry or children permission.

This guide diagnoses and fixes Error 50 for anonymous or incorrect binds, ldapadd, ldapmodify, ldapdelete, ldapmodrdn, password changes, cn=config edits, group-based administrators, SSSD readers, and replication accounts. When the bind itself fails with Error 49 before ACL evaluation, start with Fix OpenLDAP invalid credentials Error 49. It does not replace OpenLDAP ACL examples for full policy design.

The procedure applies to OpenLDAP 2.6 across the RHEL family, including Red Hat Enterprise Linux, Rocky Linux, AlmaLinux, Oracle Linux, and CentOS Stream.

Tested on: Rocky Linux 10.2 with openldap-servers 2.6.10-1.el10_2 from EPEL 10.2.

The lab uses:

Setting Value
OpenLDAP server ldap-server.example.com
OpenLDAP client ldap-client.example.com
Directory suffix dc=example,dc=com
Data administrator cn=admin,dc=example,dc=com
Configuration database cn=config
Data backend MDB
LDAP transport StartTLS on port 389

Complete these lessons first:

IMPORTANT
Do not fix Error 50 by granting write or manage access to users or *. First identify the exact bind identity, target database, and missing operation-specific permission.

Pick the row that matches your failure message or symptom. Each link takes you to the fix section for that case. Complete Diagnose Error 50 Before Changing ACLs first if you have not already confirmed the bind identity and target database.

Error or symptom Most likely cause Go to
ldapadd run without -D fails Anonymous or wrong bind identity Fix 1: Anonymous or Incorrect Bind
ldapadd -Y EXTERNAL fails on the data suffix SASL peercred is not the data root DN Fix 2: SASL EXTERNAL Cannot Write to the Data Suffix
cn=config modification returns Error 50 Data administrator used instead of root SASL EXTERNAL Fix 3: Insufficient Access to cn=config
no write access to parent Missing children/write on the parent Fix 4: ldapadd No Write Access to Parent
Modify works but Add fails Missing entry/write or children/write Fix 4: ldapadd No Write Access to Parent
Attribute modification fails Missing attribute or target-entry permission Fix 5: ldapmodify Insufficient Access
User cannot change password Incorrect userPassword ACL or ACL order Fix 6: Password Change Insufficient Access
Delete fails Missing target entry/write or parent children/write Fix 7: Delete, Rename and Move Errors
Rename or move fails Missing target entry/write or old/new parent children/write Fix 7: Delete, Rename and Move Errors
ACL works as cn=admin but not delegated admin Root DN bypasses ACLs Fix 8: Delegated Group Administrator Does Not Match
Group-based ACL does not match Wrong group model, member DN or rule order Fix 8: Delegated Group Administrator Does Not Match
SSSD or replication account receives Error 50 Service account lacks required search/read access Fix 9: SSSD and Replication Access Errors
ACL was changed but failure remains Wrong database or earlier ACL matched first Apply and Verify the ACL Fix
slapacl -u differs from the real operation Fake target lacks group or attribute data Verify with slapacl

Diagnose Error 50 Before Changing ACLs

Complete these checks once before you edit ACLs, no matter which fix section you opened from the table above. You need three facts: which identity authenticated, which database contains the target DN, and which permission the failed operation requires.

OpenLDAP Error 50 authorization flow: LDAP request, bind identity, olcAccess evaluation, access denied, insufficient access 50

Confirm the Bind Identity

Confirm the DN used by a password bind:

bash
ldapwhoami -x -ZZ -H ldap://ldap-server.example.com -D "cn=admin,dc=example,dc=com" -W

Sample output:

output
dn:cn=admin,dc=example,dc=com

A root shell over the local LDAPI socket uses a different identity:

bash
sudo ldapwhoami -Q -Y EXTERNAL -H ldapi:///

Sample output:

output
dn:gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth

These are not interchangeable:

text
cn=admin,dc=example,dc=com
text
gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth

The first identity is the configured data-database administrator. The second is the local SASL peer-credential identity used by sudo ldapmodify -Y EXTERNAL -H ldapi:///.

Identify the Target Database

Target DN Database Normal administration method
cn=config Configuration database Root SASL EXTERNAL over ldapi:///
cn=schema,cn=config Configuration database Root SASL EXTERNAL
olcDatabase={N}mdb,cn=config Configuration database Root SASL EXTERNAL
ou=people,dc=example,dc=com MDB data database Data root DN or delegated administrator
uid=jdoe,ou=people,... MDB data database Data root DN, self, or delegated administrator
cn=developers,ou=groups,... MDB data database Data root DN or delegated administrator

Inspect the Data Root DN and Current ACLs

Discover the MDB database DN dynamically. The ldapsearch command covers -b, -s, and SASL EXTERNAL binds used here:

bash
MDB_DN=$(sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config '(&(objectClass=olcMdbConfig)(olcSuffix=dc=example,dc=com))' dn | awk '/^dn: / {sub(/^dn: /, ""); print; exit}')

Store the result in a shell variable so later ldapsearch and ldapmodify commands target the correct database entry.

Print the discovered value:

bash
printf 'MDB database DN: %s\n' "$MDB_DN"

Confirm the variable holds a value such as olcDatabase={2}mdb,cn=config before you query it.

Stop if discovery returned nothing:

bash
if [[ -z "$MDB_DN" ]]; then
    echo "No MDB database was found for dc=example,dc=com" >&2
    exit 1
fi

Stop here when no MDB database matches the suffix filter.

Sample output:

output
MDB database DN: olcDatabase={2}mdb,cn=config

Query the suffix root DN and current ACLs:

bash
sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b "$MDB_DN" -s base olcSuffix olcRootDN olcAccess

Sample output on the lab server:

output
dn: olcDatabase={2}mdb,cn=config
olcSuffix: dc=example,dc=com
olcRootDN: cn=admin,dc=example,dc=com
olcAccess: {0}to dn.subtree="ou=people,dc=example,dc=com" by dn.exact="uid=pwdadmin,ou=system,dc=example,dc=com" write by * none
...
olcAccess: {9}to dn.subtree="dc=example,dc=com" by users read by * none

Use the exact olcRootDN shown by your server. The data root DN bypasses ACLs for its MDB database and does not automatically administer cn=config.

Create a protected backup directory before you change ACLs:

bash
sudo install -d -m 0700 /root/openldap-error50-backup

Only root should be able to read ACL exports stored in this directory.

Export cn=config:

bash
sudo slapcat -F /etc/openldap/slapd.d -n 0 -l /root/openldap-error50-backup/cn-config-before-acl.ldif

Keep this LDIF as the restore point if an ACL edit prevents slapd from starting.

Save the current ACL list for comparison:

bash
sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b "$MDB_DN" -s base olcAccess | sudo tee /root/openldap-error50-backup/olcAccess-before.ldif >/dev/null

This file captures the numbered ACL list before you change it. The tee command runs under sudo so the redirect can write beneath /root. Build a usable restore file before you edit live ACLs, as shown in OpenLDAP ACL examples.

Understand the Required Permission

Use this table when you compare a failing operation with slapacl or olcAccess:

Operation Required permission
Add Parent children/write and new entry entry/write; when olcAddContentAcl: TRUE, submitted attributes are also checked against ACLs
Modify Write permission on the attributes being modified
Delete Target entry/write and parent children/write
Rename Target entry/write, old and new parent children/write
Move Target entry/write, old and new parent children/write
Password bind auth on userPassword
Password change self =xw or equivalent write permission

Fix 1: Anonymous or Incorrect Bind

Use this section when your command never supplies -D, uses the wrong administrator DN, or binds as a user who only has read access.

Error 8 means the server requires an authenticated identity before accepting the modification. Error 50 means the request was evaluated using the anonymous or otherwise unsuitable bind identity and that identity lacked authorization.

A common failing command omits the bind DN:

bash
ldapadd -x -ZZ -H ldap://ldap-server.example.com -f add-user.ldif

On the lab server, that anonymous request returned stronger authentication required instead of Error 50:

output
ldap_add: Strong(er) authentication required (8)
        additional info: modifications require authentication

Error 8 and Error 50 both mean the operation did not run with a suitable administrator identity. When anonymous binds are permitted, OpenLDAP may return Error 50 after evaluating the request against ACLs as the anonymous identity.

Retry with the data-database root DN:

bash
ldapadd -x -ZZ -H ldap://ldap-server.example.com -D "cn=admin,dc=example,dc=com" -W -f add-user.ldif

Validate the bind before you repeat the failing operation:

bash
ldapwhoami -x -ZZ -H ldap://ldap-server.example.com -D "cn=admin,dc=example,dc=com" -W

The command should print the same DN you passed to -D. A mismatch means the bind identity is still wrong.

Mistake Correction
No -D was supplied Add the correct administrator DN
Wrong suffix in the bind DN Query olcRootDN
Using cn=admin when the server uses cn=Manager Use the configured value
Using a user DN that has only read permission Bind as root DN or grant delegated rights
Using the data admin to modify cn=config Use SASL EXTERNAL — see Fix 3
Using -Y EXTERNAL for data entries Use the data root DN or add a narrow ACL — see Fix 2
Using -w password in published commands Prefer -W or a protected secret file

Do not change ACLs until the intended identity can bind successfully.


Fix 2: SASL EXTERNAL Cannot Write to the Data Suffix

Use this section when you run ldapadd or ldapmodify as root on the server with -Y EXTERNAL -H ldapi:///, the command reaches slapd, and the data entry is still rejected — often with no write access to parent — even though cn=config changes work from the same shell.

That happens because SASL EXTERNAL does not bind as cn=admin,dc=example,dc=com. It binds as the local peer-credential identity:

text
gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth

That identity normally administers cn=config. It does not automatically receive write access to entries below dc=example,dc=com. For routine data changes, bind as the configured data root DN instead of expecting peercred to inherit data-suffix rights.

On the lab server, this command failed with the parent error:

bash
sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f add-user.ldif

The SASL peer-credential identity authenticated successfully but lacked parent children/write access:

output
ldap_add: Insufficient access (50)
        additional info: no write access to parent

The fix is not by users write. For normal data operations, bind as the configured data root DN:

bash
ldapadd -x -ZZ -H ldap://ldap-server.example.com -D "cn=admin,dc=example,dc=com" -W -f add-user.ldif

Add a narrow peercred ACL on the data database only when you intentionally want local root to administer directory data without a simple bind. For delegated administration, use group.exact or dn.exact rules instead of granting broad peercred write access to the suffix.

If you need to test whether peercred can create children under a container, use slapacl with the peer-credential DN against the parent OU. The data root DN bypasses ACL evaluation and is the reliable path for emergency data changes.


Fix 3: Insufficient Access to cn=config

Use this section when ldapmodify or ldapadd targets cn=config, olcDatabase={N}mdb,cn=config, or another configuration entry, but you bound as the data administrator. The data root DN bypasses ACLs on the MDB suffix database only — it does not administer the separate configuration database.

The data administrator:

text
cn=admin,dc=example,dc=com

does not administer:

text
cn=config

An incorrect attempt on the lab server returned:

output
ldap_modify: Insufficient access (50)

Use local SASL EXTERNAL for cn=config changes:

bash
sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f change-config.ldif

Run this from a root shell on the LDAP server so SASL EXTERNAL maps to the peer-credential identity with manage access on cn=config.

Verify access to the configuration database:

bash
sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config -s base dn

A successful query returns dn: cn=config, which confirms SASL EXTERNAL can reach the configuration database.

Inspect the configuration-database ACL:

bash
sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b "olcDatabase={0}config,cn=config" -s base olcAccess olcRootDN

Sample output on the lab server:

output
dn: olcDatabase={0}config,cn=config
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by * none

If SASL EXTERNAL itself receives Error 50:

  • Confirm the command runs with sudo.
  • Confirm the LDAPI socket is enabled.
  • Check the exact SASL identity with ldapwhoami.
  • Inspect the olcDatabase={0}config ACL.
  • Restore or repair the configuration using OpenLDAP cn=config and MDB explained.

Do not recommend directly editing files beneath /etc/openldap/slapd.d/ as the routine fix.


Fix 4: ldapadd No Write Access to Parent

Use this section when ldapadd authenticated successfully but returned Insufficient access (50) with no write access to parent, or when add fails while modify on the same OU still works. OpenLDAP is denying the operation because the bind identity lacks children/write on the parent container or entry/write on the new entry. When olcAddContentAcl is TRUE, submitted attributes are also checked against ACLs.

If the failure came from ldapadd -Y EXTERNAL, complete Fix 2 first. The steps below assume you are already binding as the intended administrator or delegated user.

Every add requires parent children/write and new entry entry/write:

text
Add:
uid=jdoe,ou=people,dc=example,dc=com

Requires:
entry/write on uid=jdoe,ou=people,dc=example,dc=com
children/write on ou=people,dc=example,dc=com

When olcAddContentAcl is enabled on the MDB database, OpenLDAP also checks write permission on each attribute in the LDIF. Inspect the current setting:

bash
sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b "$MDB_DN" -s base olcAddContentAcl

An ACL that grants attribute write access alone may still produce:

output
ldap_add: Insufficient access (50)
        additional info: no write access to parent

Check parent access with slapacl

Test whether the bind identity may create children under ou=people:

bash
sudo slapacl -F /etc/openldap/slapd.d -D "uid=jdoe,ou=people,dc=example,dc=com" -b "ou=people,dc=example,dc=com" "children/write"

Sample output on the lab server:

output
authcDN: "uid=jdoe,ou=people,dc=example,dc=com"
write access to children: DENIED

DENIED confirms the bind identity lacks children/write on the parent OU.

The data root DN bypasses ACL evaluation on its database:

bash
sudo slapacl -F /etc/openldap/slapd.d -D "cn=admin,dc=example,dc=com" -b "ou=people,dc=example,dc=com" "children/write"

Sample output:

output
authcDN: "cn=admin,dc=example,dc=com"
write access to children: ALLOWED

The data root DN bypasses normal ACL evaluation, so ALLOWED here is expected even when delegated users are denied.

Check target-entry access

For an existing entry, test entry/write on the target DN:

bash
sudo slapacl -F /etc/openldap/slapd.d -D "uid=admin1,ou=people,dc=example,dc=com" -b "uid=jdoe,ou=people,dc=example,dc=com" "entry/write"

A delegated administrator who lacks entry access will see DENIED for entry/write even when attribute rules look correct. Modify can succeed while add still fails when attribute access exists but entry or children does not.

Narrow ACL pattern for delegated user administration

WARNING
These are troubleshooting fragments, not a complete ACL policy. Sensitive-attribute rules must appear before broader subtree rules.

Grant only the missing container rights:

text
to dn.base="ou=people,dc=example,dc=com"
   attrs=children
    by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write
    by * none

Grant entry access on user entries created beneath the container:

text
to dn.children="ou=people,dc=example,dc=com"
   attrs=entry
    by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write
    by users read
    by * none

Optional subtree rule for ongoing user and group administration:

text
to dn.subtree="ou=people,dc=example,dc=com"
    by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write
    by self read
    by users read
    by * none

Use equivalent rules for ou=groups,dc=example,dc=com, ou=policies,dc=example,dc=com, and other delegated containers.

Do not use:

text
by users write

because that grants every authenticated LDAP user write access. For the complete delegated-administration policy, see OpenLDAP ACL examples. Apply the change using Apply and Verify the ACL Fix.


Fix 5: ldapmodify Insufficient Access

Use this section when ldapmodify returns Error 50 on an attribute change such as mail or telephoneNumber, and the problem is not a password change. The bind identity may be correct, but OpenLDAP still denies the modification because the target entry, the attribute, or an earlier matching rule blocks the request.

A typical failing command looks like this:

bash
ldapmodify -x -ZZ -H ldap://ldap-server.example.com -D "uid=jdoe,ou=people,dc=example,dc=com" -W -f change-mail.ldif

Start with the bind identity shown in the command, then work through these checks:

  • Does the user have access to the target entry?
  • Does self match the complete target DN?
  • Is the target attribute listed in a self-service rule?
  • Does an earlier broad ACL prevent the self-service ACL from being reached?
  • Is an implicit deny being applied?

Modify checks attribute access on an existing entry. It does not require parent children/write. If add fails while modify works, compare the required permission table and test entry/write separately.

Example self-service rule:

text
to dn.subtree="ou=people,dc=example,dc=com"
   attrs=mail,telephoneNumber,displayName
    by self write
    by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write
    by users read
    by * none

Password changes use different ACL semantics. When userPassword modification fails, continue with Fix 6.


Fix 6: Password Change Insufficient Access

Use this section when ldappasswd or a userPassword modify through ldapmodify returns Error 50, even though other attributes on the same entry work. Password rules are separate from general attribute rules: binds need auth on userPassword, self-service changes need by self =xw or equivalent write permission, and the userPassword rule must appear before any broad to * rule that would block it.

A working password ACL usually looks like this:

text
to attrs=userPassword
    by self =xw
    by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write
    by anonymous auth
    by * none
  • by anonymous auth allows OpenLDAP to verify credentials during a simple Bind without allowing the password value to be read. It does not grant general LDAP Compare access.
  • by self =xw allows self-service password changes.
  • A delegated password administrator needs explicit write on userPassword.
  • Place the userPassword rule before any broad to * rule that would block it.

Test with:

bash
ldappasswd -x -ZZ \
  -H ldap://ldap-server.example.com \
  -D "uid=jdoe,ou=people,dc=example,dc=com" \
  -W \
  -S

When ACL evaluation denies the change, the command returns Error 50 before the new password hash is stored.

If password policy is enabled, Error 50 may also involve password-administrator ACLs, pwdReset, policy operational attributes, or an earlier password ACL that blocks the intended rule. Keep lockout and expiration behavior in OpenLDAP password policy with ppolicy.


Fix 7: Delete, Rename and Move Errors

Use this section when ldapdelete, ldapmodrdn, or a superior change returns Error 50 on an entry you can otherwise read or modify. These operations check entry/write on the target entry and children/write on the parent container. A move also requires children/write on the new parent.

The table below summarizes what each operation evaluates:

Operation Target entry Old parent children New parent children Attribute write
Add Write Write Not applicable Only when olcAddContentAcl: TRUE
Modify Access to the entry No No Write on modified attributes
Delete Write Write Not applicable No
Rename in same OU Write Write Same parent No separate attribute permission
Move to another OU Write Write Write No separate attribute permission

Use Manage OpenLDAP users and groups for the operational commands once the ACL permits the action.

Delete Fails

The entry you want to remove:

text
uid=jdoe,ou=people,dc=example,dc=com

requires:

  • entry/write on the user
  • children/write on ou=people

Test both permissions with slapacl before you broaden the ACL.

Rename Within the Same OU Fails

Renaming uid=jdoe to uid=john.doe requires:

  • entry/write on the target entry
  • children/write on its parent

The parent children/write requirement still applies because rename changes the RDN beneath the same superior. OpenLDAP checks the new RDN for schema and naming validity, but that is distinct from requiring a separate ACL grant on the naming attribute.

Move to Another OU Fails

Moving from ou=people to ou=contractors requires:

  • entry/write on the user
  • children/write on the old parent
  • children/write on the new parent

Test both parent OUs with slapacl when move operations return Error 50.


Fix 8: Delegated Group Administrator Does Not Match

Use this section when the same operation works as cn=admin,dc=example,dc=com but fails for uid=admin1 or another delegated administrator bound through a group.exact rule. The data olcRootDN skips normal ACL evaluation, so a successful test with cn=admin does not prove your delegated policy is correct. You must bind as the delegated user and confirm group membership, ACL syntax, and rule order.

Verify that the delegated user is actually a member of the authorization group:

bash
ldapsearch -x -ZZ -H ldap://ldap-server.example.com -D "cn=admin,dc=example,dc=com" -W -b "cn=directory-admins,ou=groups,dc=example,dc=com" -s base -LLL objectClass member

The delegated administrator DN must appear exactly as a member value in the result.

Expected model:

ldif
objectClass: groupOfNames
member: uid=admin1,ou=people,dc=example,dc=com

The ACL must reference the complete group DN:

text
by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write

Check:

  • The member value is a complete DN.
  • The authenticated administrator DN exactly matches that value.
  • The ACL uses groupOfNames with member, not RFC2307 memberUid.
  • The group rule appears before a broader matching rule.

After the group entry looks correct, repeat the failing operation while bound as the delegated administrator — not as cn=admin. DN-based group membership belongs with Configure OpenLDAP memberOf and referential integrity overlays. POSIX posixGroup authorization is a separate design.


Fix 9: SSSD and Replication Access Errors

Use this section when a dedicated service account — such as uid=sssd-reader for SSSD lookups or uid=replicator for Syncrepl — receives Error 50 while normal user administration still works. These accounts are ordinary LDAP identities. They need explicit olcAccess permission for the entries and attributes each client reads. This section shows how to test the exact bind each service uses. Full account design and schema choices stay in the linked SSSD and replication guides.

SSSD Reader Receives Error 50

SSSD fails during user or group lookup when its bind DN cannot search or read the attributes configured in sssd.conf. Test the same bind, URI, and search filter SSSD uses:

bash
ldapsearch -x -ZZ -H ldap://ldap-server.example.com -D "uid=sssd-reader,ou=service-accounts,dc=example,dc=com" -W -b "ou=people,dc=example,dc=com" -LLL "(uid=jdoe)" uid uidNumber gidNumber homeDirectory loginShell

Error 50 here means the service account lacks search, read, or entry access to the attributes SSSD needs.

Grant only the attributes required by the selected SSSD schema. Do not give SSSD read access to userPassword, pwdHistory, or pwdFailureTime unless a specifically tested feature requires additional policy-state access. Client setup belongs in OpenLDAP client authentication with SSSD. Centralized sudo policy belongs in Store Linux sudo rules in OpenLDAP with SSSD.

Replication Account Receives Error 50

Syncrepl fails when the replication bind DN cannot search and read the full scope it must synchronize. The replicator needs a read rule that matches before broader deny rules take effect:

text
to *
    by dn.exact="uid=replicator,ou=service-accounts,dc=example,dc=com" read
    by * break

The replicator receives read and stops at this rule. For every other identity, by * break continues evaluation at the next olcAccess rule instead of denying access here.

Place it before broader rules and verify the account using the same URI, TLS mode, and search base used by Syncrepl. Keep full replication ACL configuration in OpenLDAP provider-consumer replication and OpenLDAP multi-provider replication.


Apply and Verify the ACL Fix

Use this section after you identify the missing permission in one of the fixes above and are ready to change olcAccess. Work through the steps in order: confirm you have a backup, check rule order, apply one indexed change, repeat the operation that failed, confirm unrelated access is still denied, and inspect logs if needed.

Back Up the Current Policy

If you have not already exported the current policy, repeat the backup commands under Inspect the Data Root DN and Current ACLs.

Check Numeric ACL Order

OpenLDAP evaluates olcAccess values in numerical order:

text
{0}
{1}
{2}
...

The first matching to rule controls the request unless break changes the flow.

Bad order:

text
{0}to *
    by users read
    by * none

{1}to attrs=userPassword
    by self write
    by anonymous auth
    by * none

The broad {0}to * rule matches first, so the password rule is never evaluated.

Correct order:

text
{0}to attrs=userPassword
    by self =xw
    by anonymous auth
    by * none

{1}to *
    by users read
    by * none

List every numbered olcAccess value on the data database before you choose an insertion point:

bash
sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b "$MDB_DN" -s base olcAccess

Note the {N} index you plan to replace or the position where a new rule should appear.

Replace One Indexed ACL Value Safely

Use the numeric index when replacing one rule:

ldif
dn: REPLACE_WITH_MDB_DN
changetype: modify
delete: olcAccess
olcAccess: {3}
-
add: olcAccess
olcAccess: {3}to dn.subtree="ou=people,dc=example,dc=com"
  by group.exact="cn=directory-admins,ou=groups,dc=example,dc=com" write
  by self read
  by users read
  by * none

Replace REPLACE_WITH_MDB_DN with the value stored in $MDB_DN before you apply the LDIF.

Do not use replace: olcAccess with a single indexed value unless you intentionally replace and review the complete ACL policy.

Apply the change:

bash
sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f fix-access.ldif

A successful modify exits without an LDAP error.

Confirm the new rule index and order immediately:

bash
sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b "$MDB_DN" -s base olcAccess

The {N} values should reflect the intended order before you retest the live operation.

Repeat the Exact Failed Operation

Repeat the exact ldapadd, ldapmodify, ldapdelete, ldapmodrdn, ldappasswd, or ldapsearch command that previously failed, using the same URI, TLS mode, and bind DN.

On the lab server, the same ldapadd LDIF succeeded when bound as the data root DN after EXTERNAL produced Error 50.

Repeat ldapwhoami first when the failure might still be an identity problem.

Test an Expected Denial

A delegated administrator should be able to add beneath the delegated OU, modify permitted entries, rename within scope, and delete test entries. The same administrator should not be able to modify cn=config, modify entries outside the delegated subtree, or read password hashes.

Confirm unrelated access remains denied after your fix.

Verify with slapacl

Run slapacl with the same bind DN as the failing live command. Test attribute, entry, and parent permissions separately.

Check whether the delegated administrator may change the mail attribute:

bash
sudo slapacl -F /etc/openldap/slapd.d -D "uid=admin1,ou=people,dc=example,dc=com" -b "uid=jdoe,ou=people,dc=example,dc=com" "mail/write"

Confirm write access to the user entry itself:

bash
sudo slapacl -F /etc/openldap/slapd.d -D "uid=admin1,ou=people,dc=example,dc=com" -b "uid=jdoe,ou=people,dc=example,dc=com" "entry/write"

Confirm the administrator may add or remove entries under ou=people:

bash
sudo slapacl -F /etc/openldap/slapd.d -D "uid=admin1,ou=people,dc=example,dc=com" -b "ou=people,dc=example,dc=com" "children/write"

Each test should print ALLOWED only for the permissions your ACL was meant to grant.

slapacl -u uses a fake entry and cannot accurately test rules that depend on real target attributes or group.exact membership. Prefer a live operation when group-based ACLs are involved.

Enable Temporary ACL Logging

olcLogLevel belongs on the global cn=config entry, not on the MDB database. Check the current value first:

bash
sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config -s base olcLogLevel

When acl is not already enabled, add it temporarily:

bash
sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<'EOF'
dn: cn=config
changetype: modify
add: olcLogLevel
olcLogLevel: acl
EOF

Monitor the server while you repeat the failing operation:

bash
sudo journalctl -u slapd -f

Watch for ACL evaluation lines that name the matched rule and the permission that was denied.

Remove the temporary value afterward:

bash
sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<'EOF'
dn: cn=config
changetype: modify
delete: olcLogLevel
olcLogLevel: acl
EOF

Troubleshoot Remaining Error 50 Cases

Use this table when your case did not match one of the main fixes above.

Symptom Most likely cause Recommended check
ldapadd fails immediately Anonymous or wrong bind DN Run ldapwhoami
no write access to parent Missing parent children/write Test parent with slapacl
Add fails despite attribute write Missing target entry/write Test entry/write
Modify works but add fails Attribute access exists; entry or children does not Compare operation requirements
Delete fails Missing target entry or parent children access Test both
Rename fails Missing target entry/write or parent children/write Test the target entry and parent
Move fails Missing target entry/write or old/new parent children/write Test the target and both parent OUs
Password bind fails No auth access to userPassword Review password ACL order
Password reset fails Administrator lacks write or manage permission Review ACL and ppolicy
cn=config modification fails Data administrator was used Use root SASL EXTERNAL
SASL EXTERNAL data add fails Peercred identity is not the data root DN Use the data root DN or delegated ACL
Group administrator does not match Wrong group type or member DN Inspect groupOfNames/member
SSSD search fails Read account lacks search, read, or entry access Test exact SSSD bind
Replication fails Replicator cannot read full synchronization scope Test replication search
Later ACL never applies Earlier broad to rule matched Review numbered order
ACL works only as cn=admin Root DN bypasses normal ACLs Test a delegated identity
Error remains after ACL update Wrong MDB database was modified Rediscover database by suffix
slapacl -u says allowed but live request fails Dry run lacked real group or target content Run a full live test
Server returns Error 53 instead Database may be read-only Check olcReadOnly
File permission changes do not help Error is LDAP authorization, not filesystem DAC Inspect olcAccess

Parse the offline configuration when startup fails after an ACL edit:

bash
sudo slaptest -F /etc/openldap/slapd.d -u

A successful check prints config file testing succeeded.

Review recent server messages when a live operation still fails:

bash
sudo journalctl -u slapd -n 100 --no-pager

Search the output for insufficient access, no write access, or ACL debug lines from the time of the failed request.


References


Summary

You learned how to choose the matching symptom from the quick-fix table, confirm the actual authenticated identity, distinguish cn=config from the data database, find the configured data root DN, understand operation-specific permissions, fix anonymous binds, SASL EXTERNAL data-suffix failures, cn=config access, ldapadd parent errors, ldapmodify attribute failures, password ACL problems, delete/rename/move requirements, delegated group administrators, SSSD and replication readers, apply ACL changes in the correct order, and verify the fix with live operations, expected denials, slapacl, and logs.


Frequently Asked Questions

1. What does OpenLDAP Error 50 mean?

Error 50 is an authorization failure. The client authenticated or remained anonymous, OpenLDAP evaluated olcAccess, and the requested operation was not granted.

2. Why does ldapadd return insufficient access even when I run it as root?

Linux root affects the local shell, not a remote LDAP simple bind. SASL EXTERNAL over LDAPI authenticates as the peer-credential identity, which is separate from the data-database root DN and does not automatically receive data-suffix write access.

3. Why does OpenLDAP say no write access to parent?

ldapadd needs write access to the new entry entry pseudo-attribute and to the parent children pseudo-attribute. Attribute write on the parent alone is not enough.

4. What is the difference between the entry and children ACL permissions?

entry controls access to the LDAP object itself. children controls whether an identity may add or remove entries beneath a parent container.

5. Why can I modify an entry but not add a new one?

Modify checks attribute access on an existing entry. Add also requires children/write on the parent and entry/write on the new entry.

6. Why can I modify LDAP data but not cn=config?

cn=config is a separate configuration database. The data root DN bypasses ACLs only on its MDB database, not on olcDatabase={0}config.

7. What identity does ldapmodify -Y EXTERNAL -H ldapi:/// use?

It uses the local SASL peer-credential identity, typically gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth on a root shell, not cn=admin,dc=example,dc=com.

8. Is the OpenLDAP data root DN also the cn=config administrator?

No. The data olcRootDN bypasses ACLs on the suffix database only. cn=config is administered through SASL EXTERNAL unless you add a separate policy.

9. Why does the ACL work as cn=admin but fail for another administrator?

The configured olcRootDN bypasses normal olcAccess evaluation on that database. Delegated administrators are subject to the full ACL policy.

10. Why does an LDAP group-based ACL not match?

group.exact expects a groupOfNames entry with DN-valued member attributes, an exact member match, and a rule that appears before a broader matching rule.

11. Which permissions are required to rename or move an LDAP entry?

Rename or move requires entry/write on the target entry and children/write on both the old and new parent entries. For a rename within one OU, the old and new parent are the same entry.

12. How do I fix Error 50 when changing a password?

Confirm the bind identity, then verify userPassword ACL order and privileges. Self-service changes usually need by self =xw or write, and binds need by anonymous auth on userPassword.

13. How do I test OpenLDAP permissions with slapacl?

Run slapacl -F /etc/openldap/slapd.d with the bind DN, target entry or parent DN, and the pseudo-attribute or attribute permission such as children/write or mail/write.

14. Why can slapacl -u produce a different result from the live operation?

The -u dry-run mode uses a fake entry and does not load real group membership or target attributes, so group.exact and attribute-dependent rules can differ from live evaluation.

15. Should I grant by users write to fix Error 50?

No. That grants every authenticated LDAP user write access. Identify the missing entry, children, or attribute permission and add the narrowest rule for the delegated role.

16. Does changing Linux file ownership fix LDAP Error 50?

No. Error 50 is LDAP authorization through olcAccess, not filesystem DAC on /var/lib/ldap or certificate files.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …