= LDAP based on video series https://www.youtube.com/watch?v=7Y0pHUZ7M6Q == FOSS implementations • slapd (common port: 636 for encrypted, 389 for unencrypted) … superseded by/part of OpenLDAP • OpenLDAP (OpenLDAP Public License) • ApacheDS (Apache License 2.0) • OpenDJ (Common Development and Distribution License) • 389 Directory Server (GPL) • FreeIPA (GPL) == terminology root → domain component (DC) → organization unit (OU) → common/canonical name (CN) commonly DC is used as root directly OU might be inside OU e.g. cn=Lukas,ou=rust,ou=dev,dc=example,dc=org how to represent groups? create an OU groups where a group cn=Admins contains a uniqueMember attribute o:: organization name (c.f. ou) sn:: surname dn:: distinguished name RDN:: one or more (plus-separated) key-value pairs separated by "=" representing the attribute of a node in the tree (like "uid=john.doe" or "dc=example" or "cn=John Doe+mail=jdoe@example.com") colloquially, RDN is the leftmost (= most specific) attribute pair of a DN DN:: a comma-separated string of RDNs == syntax RFC 4514 specifies the syntax of DNs: • space, hash, double quote, plus, comma, semicolon, less-than, greater-than, and backslash symbols need to be escaped • escaping occurs as (e.g.) "\ " or "\20" for space objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' … MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ seeAlso $ description ) ) RDN also allows "multiple attribute values" for unique reference: uid=j.doe+uidNumber=10042 LDIF = LDAP Data Interchange Format … file format to share/dump LDAP entries == executables CLI utilities: • ldap_search -x -b "dc=fragmentix" • ldap_compare "uid=j.doe,ou=users,dc=fragmentix,dc=at" • ldap_bind "uid=j.doe,ou=users,dc=fragmentix,dc=at" "my-secret-pwd" … verify login credentials • ldapadd -x -H "ldap://ldap.mydomain.at" -D $admindn -w $adminpwd -f file.ldif • ldapadd -x -H "ldap://ldap.mydomain.at" -b $entrypoint_dn -D $admindn -W == advanced notes === bind user to prevent disclosure of company structure, bind user shall be used. app should take {username,password} and verify it with a DN via LDAP. If so, {username,password} is not used anymore, but only the DN … the so-called "bind user". Since we don't reveal publicly how we created the DN out of {username,password}, the company structure is not revealed === ACL entries "access to $what by $whom $access" e.g. access to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=example,dc=org" write "base" = current node "one" = direct children of current node "children" = recursive set of children of current node "subtree" = recursive set of children of current node AND current node "anonym" = unauthenticated user "user" = authenticated user "*" = set of unauthenticated and authenticated users "self" = the current user itself $access ∈ {none, disclose, auth, compare, search, read, write, manage} LDAP server permission hierarchy: none → disclose → auth → compare → search → read → write → manage /etc/ldap/acl.conf returns result of first matching rule → write specific rules first, generic rules at the end === System Security Service Daemon (sssd) by RedHat caches LDAP credentials (e.g. authenticate in Wifi before network connection is established) /etc/sssd/sssd.conf contains "offline_credentials_expiration" (in days) in section "[pam]" in section "[nss]"