What's Actually Happening
OpenLDAP server rejects authentication attempts. Users cannot bind to the LDAP directory or login fails.
The Error You'll See
```bash $ ldapsearch -x -H ldap://localhost -D "cn=user,dc=example,dc=com" -W
ldap_bind: Invalid credentials (49) ```
Connection error:
ldap_bind: Can't contact LDAP server (-1)TLS error:
ldap_bind: TLS error -8172: Peer's certificate issuer has been marked as not trustedAccount locked:
ldap_bind: Constraint violation (19)
additional info: Account is lockedWhy This Happens
- 1.Wrong credentials - Invalid password or DN
- 2.TLS/SSL issues - Certificate or protocol problems
- 3.Connection refused - Server not running or unreachable
- 4.Account locked - Password policy lockout
- 5.ACL restrictions - Access control blocking bind
- 6.Schema issues - Invalid DN or attribute
Step 1: Check LDAP Server Status
```bash # Check OpenLDAP service: systemctl status slapd
# Check process: ps aux | grep slapd
# Check listening ports: netstat -tlnp | grep slapd ss -tlnp | grep slapd
# Default ports: # 389 - LDAP (non-TLS) # 636 - LDAPS (TLS/SSL)
# Check logs: journalctl -u slapd -f tail -f /var/log/slapd.log
# Test connection: ldapsearch -x -H ldap://localhost -b "" -s base
# Test LDAPS: ldapsearch -x -H ldaps://localhost -b "" -s base
# Check configuration: cat /etc/ldap/slapd.conf cat /etc/openldap/slapd.conf
# Or dynamic config: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(objectclass=olcGlobal)"
# Check backend: ldapsearch -Y EXTERNAL -H ldapi:/// -b "olcDatabase={1}mdb,cn=config"
# Check server info: ldapsearch -x -H ldap://localhost -b "" -s base namingContexts ```
Step 2: Test Anonymous Bind
```bash # Test anonymous bind first: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com"
# If anonymous fails: # Check if anonymous bind disabled: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcAllowAnonymousBind=TRUE)"
# Enable anonymous bind: ldapmodify -Y EXTERNAL -H ldapi:/// << EOF dn: cn=config changetype: modify add: olcAllowAnonymousBind olcAllowAnonymousBind: TRUE EOF
# Or in config file: # In slapd.conf: allow bind_anon_dn
# Check ACL for anonymous: # Need ACL that allows anonymous read access to attrs=userPassword by anonymous auth by self write by * none
# Test root DN: ldapsearch -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W -b "dc=example,dc=com" ```
Step 3: Verify Bind Credentials
```bash # Check user DN format: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(uid=username)"
# Find user entry: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(cn=user)"
# Verify DN: # DN must match exactly # Example: cn=John Doe,ou=Users,dc=example,dc=com
# Test with correct DN: ldapsearch -x -H ldap://localhost \ -D "cn=John Doe,ou=Users,dc=example,dc=com" \ -W \ -b "dc=example,dc=com"
# Check password: # Ensure password is correct # Check if password attribute exists: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(uid=user)" userPassword
# Password should be hashed: # {SSHA}hashedpassword # {SHA}hashedpassword # {CRYPT}...
# Reset password: ldappasswd -x -H ldap://localhost \ -D "cn=admin,dc=example,dc=com" -W \ -S "uid=user,ou=People,dc=example,dc=com"
# Or modify: ldapmodify -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W << EOF dn: uid=user,ou=People,dc=example,dc=com changetype: modify replace: userPassword userPassword: newpassword EOF
# Check for simple bind: # If using simple bind: ldapsearch -x -H ldap://localhost -D "uid=user,ou=People,dc=example,dc=com" -w password
# Check SASL bind: ldapsearch -Y DIGEST-MD5 -H ldap://localhost -U user ```
Step 4: Fix TLS/SSL Issues
```bash # Check TLS configuration: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(objectclass=olcGlobal)" olcTLSC*
# Check certificates: ls -la /etc/ldap/ssl/ ls -la /etc/openldap/certs/
# Required files: # TLSCACertificateFile - CA certificate # TLSCertificateFile - Server certificate # TLSCertificateKeyFile - Server private key
# Verify certificates: openssl x509 -in /etc/ldap/ssl/ldap.crt -text -noout | head -20
# Check certificate expiration: openssl x509 -in /etc/ldap/ssl/ldap.crt -noout -dates
# Verify certificate chain: openssl verify -CAfile /etc/ldap/ssl/ca.crt /etc/ldap/ssl/ldap.crt
# Check private key: openssl rsa -in /etc/ldap/ssl/ldap.key -check
# Test LDAPS: ldapsearch -x -H ldaps://localhost -b "dc=example,dc=com"
# Enable TLS: ldapmodify -Y EXTERNAL -H ldapi:/// << EOF dn: cn=config changetype: modify add: olcTLSCertificateFile olcTLSCertificateFile: /etc/ldap/ssl/ldap.crt - add: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.key - add: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ldap/ssl/ca.crt EOF
# Start TLS on standard port: ldapsearch -x -H ldap://localhost -ZZ -b "dc=example,dc=com"
# Ignore certificate errors (testing): ldapsearch -x -H ldaps://localhost -b "dc=example,dc=com" -d 1
# Client config for TLS: # In /etc/ldap/ldap.conf: TLS_CACERT /etc/ldap/ssl/ca.crt TLS_REQCERT allow ```
Step 5: Check Account Lock Status
```bash # Check password policy: ldapsearch -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W \ -b "cn=config" "(objectclass=olcPasswordPolicy)"
# Check user lock status: ldapsearch -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W \ -b "dc=example,dc=com" "(uid=user)" pwdAccountLockedTime pwdFailureTime
# Check ppolicy overlay: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcOverlay=ppolicy)"
# Unlock account: ldapmodify -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W << EOF dn: uid=user,ou=People,dc=example,dc=com changetype: modify delete: pwdAccountLockedTime EOF
# Or reset failure count: ldapmodify -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W << EOF dn: uid=user,ou=People,dc=example,dc=com changetype: modify delete: pwdFailureTime EOF
# Check password expiration: ldapsearch -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W \ -b "dc=example,dc=com" "(uid=user)" pwdChangedTime pwdExpirationTime
# Reset expired password: ldappasswd -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W \ "uid=user,ou=People,dc=example,dc=com"
# Password policy config: # pwdMaxAge - Maximum password age # pwdMinLength - Minimum length # pwdMaxFailure - Lockout threshold # pwdLockout - Enable lockout # pwdLockoutDuration - Lock duration ```
Step 6: Check ACL Configuration
```bash # Check ACLs: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(objectclass=olcAccess)"
# Or in slapd.conf: cat /etc/ldap/slapd.conf | grep access
# Common ACLs: access to attrs=userPassword by anonymous auth by self write by dn="cn=admin,dc=example,dc=com" write by * none
access to * by self read by dn="cn=admin,dc=example,dc=com" write by * read
# Check bind ACL: # Anonymous must have auth access access to attrs=userPassword by anonymous auth
# Test bind ACL: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(uid=user)" dn
# Add ACL: ldapmodify -Y EXTERNAL -H ldapi:/// << EOF dn: olcDatabase={1}mdb,cn=config changetype: modify add: olcAccess olcAccess: to attrs=userPassword by anonymous auth by self write by * none EOF
# Check ACL order: # ACLs evaluated in order, first match wins
# Debug ACL: # In config: loglevel 256 # ACL debug: 256
# Check in logs: grep "acl" /var/log/slapd.log ```
Step 7: Check Schema and DN
```bash # Check user DN exists: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(uid=user)"
# Verify entry exists: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" -s base "(objectclass=*)"
# Check schema: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=schema,cn=config" "(objectclass=olcSchemaConfig)"
# Check required attributes: # For inetOrgPerson: # cn, sn required # uid optional but commonly used
# Check user objectclass: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(uid=user)" objectClass
# Verify objectclass: ldapsearch -x -H ldap://localhost -b "dc=example,dc=com" "(uid=user)" | grep objectClass
# Add missing attributes: ldapmodify -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W << EOF dn: uid=user,ou=People,dc=example,dc=com changetype: modify add: sn sn: User EOF
# Check DN format: # Must follow directory structure: # uid=user,ou=People,dc=example,dc=com
# Test different DN formats: ldapsearch -x -H ldap://localhost -D "cn=User Name,ou=People,dc=example,dc=com" -W
# Check parent exists: ldapsearch -x -H ldap://localhost -b "ou=People,dc=example,dc=com" -s base ```
Step 8: Fix Connection Issues
```bash # Check server running: systemctl status slapd
# Start server: systemctl start slapd
# Check listening: netstat -tlnp | grep 389
# Check firewall: iptables -L -n | grep 389 ufw status | grep 389
# Allow LDAP: ufw allow 389/tcp ufw allow 636/tcp
# Check socket: ls -la /var/run/slapd/
# Use Unix socket: ldapsearch -Y EXTERNAL -H ldapi:///
# Check network connectivity: ping ldap-server
# Test port: nc -zv ldap-server 389
# Check host resolution: nslookup ldap-server
# Debug connection: ldapsearch -x -H ldap://localhost -d 1
# Check service URL: systemctl status slapd | grep Listen
# Set listen URL: # In config: olcServerURL: ldap://localhost:389 ldaps://localhost:636 ldapi:/// ```
Step 9: Debug Authentication
```bash # Enable debug logging: ldapmodify -Y EXTERNAL -H ldapi:/// << EOF dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: 256 # ACL olcLogLevel: 128 # Connection management EOF
# Or in slapd.conf: loglevel 256 512 128
# Check logs: tail -f /var/log/slapd.log
# Test with verbose: ldapsearch -x -H ldap://localhost -D "uid=user,ou=People,dc=example,dc=com" -W -v
# Debug SASL: ldapsearch -Y DIGEST-MD5 -H ldap://localhost -U user -v
# Test bind operation: ldapwhoami -x -H ldap://localhost -D "uid=user,ou=People,dc=example,dc=com" -W
# Should return DN of authenticated user
# Check backend: ldapsearch -Y EXTERNAL -H ldapi:/// -b "olcDatabase={1}mdb,cn=config"
# Monitor connections: watch 'netstat -an | grep 389'
# Check bind statistics: ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=Monitor" "(objectclass=monitorCounter)"
# Use slapd debug: slapd -d 256 -h "ldap:// ldapi:///" ```
Step 10: OpenLDAP Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-openldap.sh #!/bin/bash
echo "=== OpenLDAP Service ===" systemctl status slapd 2>/dev/null || echo "Service not running"
echo "" echo "=== Process ===" ps aux | grep slapd | grep -v grep || echo "No slapd process"
echo "" echo "=== Listening Ports ===" netstat -tlnp 2>/dev/null | grep slapd || ss -tlnp | grep slapd || echo "Not listening"
echo "" echo "=== Anonymous Bind Test ===" ldapsearch -x -H ldap://localhost -b "" -s base namingContexts 2>&1 | head -10
echo "" echo "=== Base DN ===" ldapsearch -x -H ldap://localhost -b "" -s base namingContexts 2>/dev/null | grep namingContexts
echo "" echo "=== TLS Configuration ===" ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(objectclass=olcGlobal)" olcTLS* 2>/dev/null | head -10
echo "" echo "=== Certificates ===" ls -la /etc/ldap/ssl/ 2>/dev/null || ls -la /etc/openldap/certs/ 2>/dev/null || echo "No certificates directory"
echo "" echo "=== Certificate Expiration ===" for cert in /etc/ldap/ssl/*.crt /etc/openldap/certs/*.crt; do if [ -f "$cert" ]; then echo "$cert:" openssl x509 -in $cert -noout -dates 2>/dev/null fi done
echo "" echo "=== Password Policy ===" ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(objectclass=olcPasswordPolicy)" 2>/dev/null | head -20 || echo "No password policy"
echo "" echo "=== ACLs ===" ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcAccess=*)" olcAccess 2>/dev/null | head -20 || echo "Cannot read ACLs"
echo "" echo "=== Recent Logs ===" journalctl -u slapd --no-pager -n 10 2>/dev/null || tail /var/log/slapd.log 2>/dev/null | tail -10
echo "" echo "=== Recommendations ===" echo "1. Verify bind DN is correct and exists" echo "2. Check password is correct" echo "3. Ensure account not locked by password policy" echo "4. Verify TLS certificates valid if using LDAPS" echo "5. Check ACL allows authentication" echo "6. Enable anonymous auth if needed" echo "7. Test connection with ldapwhoami" EOF
chmod +x /usr/local/bin/check-openldap.sh
# Usage: /usr/local/bin/check-openldap.sh ```
OpenLDAP Authentication Checklist
| Check | Expected |
|---|---|
| Server running | slapd process active |
| Port listening | 389 or 636 accessible |
| Bind DN correct | Entry exists in directory |
| Password valid | Matches stored hash |
| Account not locked | No pwdAccountLockedTime |
| TLS valid | Certificates not expired |
| ACL configured | Auth access allowed |
Verify the Fix
```bash # After fixing OpenLDAP authentication
# 1. Test anonymous bind ldapsearch -x -H ldap://localhost -b "" -s base // Returns namingContexts
# 2. Test user bind ldapsearch -x -H ldap://localhost -D "uid=user,ou=People,dc=example,dc=com" -W -b "dc=example,dc=com" // Returns user entries
# 3. Test LDAPS ldapsearch -x -H ldaps://localhost -D "uid=user,ou=People,dc=example,dc=com" -W // TLS connection works
# 4. Check account ldapwhoami -x -H ldap://localhost -D "uid=user,ou=People,dc=example,dc=com" -W // Returns user DN
# 5. Check logs tail -f /var/log/slapd.log // No authentication errors
# 6. Verify ACLs ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcAccess=*)" // ACLs configured correctly ```
Related Issues
- [Fix FreeIPA Authentication Failed](/articles/fix-freeipa-user-cannot-change-password-via-web-ui)
- [Fix Active Directory Login Failed](/articles/fix-active-directory-login-failed)
- [Fix SSSD Authentication Failed](/articles/fix-sssd-authentication-failed)