Concepts / Identity and access

Identity and access

LDAP and directories

Also called directory, OpenLDAP, slapd, Active Directory, DN, distinguished name, bind, simple bind, LDAPS, StartTLS, nslcd, pam_ldap

One central tree of people and groups, which every server asks at login instead of keeping its own accounts.

A directory holds entries, each named by a DN that spells its place in the tree (uid=alice,ou=people,dc=office,dc=lab) and made of attributes whose object classes say which are allowed (posixAccount for a Unix login, posixGroup for a group). Clients search from a base DN with a filter ((&(objectClass=posixGroup)(memberUid=alice))) and bind to prove who they are; a simple bind sends the DN and the password itself, so on plain LDAP (TCP 389) it is readable on the wire unless StartTLS or LDAPS (TCP 636) wraps it. Servers use the directory for logins through PAM (pam_ldap, sssd) and for user names through NSS: a password or group changed once applies everywhere, and a removed person can log in nowhere. Microsoft's Active Directory is an LDAP directory with Kerberos beside it.

How an LDAP login works, step by step

In the LDAP lab the directory (10.0.1.10, OpenLDAP slapd) holds the tree dc=office,dc=lab. The fileServer (.11) and buildServer (.12) keep no passwords; alice logs in from the laptop (.13). LDAP v3 is RFC 4511, over TCP 389.

  1. sshd hands the password to PAM. /etc/pam.d/sshd starts with auth sufficient pam_ldap.so, so the directory is asked first and a yes is enough.
  2. nslcd finds the entry. It searches from the base dc=office,dc=lab for (uid=alice) and gets the DN uid=alice,ou=people,dc=office,dc=lab.
  3. It binds as alice. A BindRequest with that DN and the password (a simple bind, RFC 4513). The server compares it with the entry's userPassword, a salted {SSHA} hash, and answers BindResponse result 0 (success) or 49 (invalidCredentials). A server never needs the password itself, and no server has a copy.
  4. The account step checks authorization. On buildServer a pam_authz_search filter (&(objectClass=posixGroup)(cn=builders)(memberUid=$username)) must find an entry, or PAM's account step says no, even with the right password.
  5. NSS supplies the Unix identity. The uid number, group and home come from the entry's posixAccount attributes, so id on the server shows uid=2001(alice).

Change alice's password or delete carol's entry once, in the directory, and every server follows on the next login. Plain LDAP sends a simple bind readable on the wire; StartTLS (extended operation OID 1.3.6.1.4.1.1466.20037) upgrades port 389 to TLS first, and LDAPS uses TLS from the start on TCP 636 (TLS).

What it looks like on a Linux machine

ldapsearch reads the tree. -x is a simple bind (anonymous here), -LLL prints plain LDIF:

$ ldapsearch -x -LLL -H ldap://directory.lab -b ou=people,dc=office,dc=lab '(objectClass=posixAccount)' uid cn uidNumber
dn: uid=alice,ou=people,dc=office,dc=lab
uid: alice
cn: Alice Archer
uidNumber: 2001

ldapwhoami binds and asks who the server thinks you are:

$ ldapwhoami -x -H ldap://directory.lab
anonymous
$ ldapwhoami -x -H ldap://directory.lab -D uid=alice,ou=people,dc=office,dc=lab -w correct-horse
dn:uid=alice,ou=people,dc=office,dc=lab
$ ldapwhoami -x -H ldap://directory.lab -D uid=alice,ou=people,dc=office,dc=lab -w letmein
ldap_bind: Invalid credentials (49)

Access control decides what each identity may do. Alice may not delete carol's entry:

$ ldapdelete -x -H ldap://directory.lab -D uid=alice,ou=people,dc=office,dc=lab -w tidy-lantern-77 uid=carol,ou=people,dc=office,dc=lab
ldap_delete: Insufficient access (50)
	additional info: no write access to parent

slapd's log (-d stats) records each bind with its security strength factor, ssf=0 for plain LDAP and ssf=256 over StartTLS or LDAPS:

conn=1003 op=0 BIND dn="uid=alice,ou=people,dc=office,dc=lab" mech=SIMPLE bind_ssf=0 ssf=0

What goes wrong, and how you see it

Wrong password, or wrong DN. ldap_bind: Invalid credentials (49). LDAP gives the same answer for a wrong password and a DN that does not exist, so check the DN with an anonymous search first.

The server is unreachable. ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1), exit 255. Every directory login on every server fails at once; check the address, port 389 or 636, and the firewall.

A search finds nothing. No such object (32) with a Matched DN: line means the base DN is wrong; the matched part is how far the server got down the tree.

Right password, still refused. sshd logs Access denied for user bob by PAM account configuration and nslcd logs found no matches: authentication passed, the group filter did not (authentication vs authorization). Add the user to the group in the directory.

Passwords on the wire. A capture on port 389 shows the bind password in clear. Use -ZZ (StartTLS, required) or ldaps://; a server without TLS set up answers StartTLS with Protocol error (2).

Questions people ask

What port does LDAP use? TCP 389 for LDAP and StartTLS, TCP 636 for LDAPS. Active Directory adds the global catalog on 3268 and 3269.

LDAP vs Active Directory? LDAP is the protocol; Active Directory is Microsoft's directory service, which speaks LDAP for searches and binds and uses Kerberos for logins. OpenLDAP is a directory server too.

LDAP vs Kerberos? LDAP stores who people are and which groups they are in, and can check a password by binding. Kerberos proves identity with tickets, so the password is not sent to each server. Many networks use both, as AD does; single sign-on builds on them.

See it on real machines

Learn it on real machines.

Every lab is a small network of real Linux machines in your browser. Start with a free account: Google or email, no card.

Open this lab