Revision 3 as of 2008-06-21 22:43:31

Clear message

/!\ This is a work in progress!

LDAP for the Lazy Sysadmin

Introduction

The point of this document is to explain to sysadmins how to set up LDAP as a distributed naming and authentication service for a small network. There exist plenty of guides that purport to do this, but they're all just cargo-cult "copy this and run this command" without any explanation of what's actually going on or how to fix it when it breaks. [http://techpubs.spinlocksolutions.com/dklar/ldap.html Debian GNU: Setting up OpenLDAP] is somewhat of an exception to the rule, so if you're really short on time check it out. This guide includes parts of it but also covers areas it doesn't. Some analogies to SQL will be made, as that's the dominant database metaphor at the moment.

LDAP can be used for much more than just naming and authentication, but this is by far the most common case and often the base for more advanced setups. (The second most common case is as an address book, which might be dealt with in a later supplement.) If you want a full-on introduction to LDAP, this guide is not it - there are several listed in the references.

This guide will focus on using the OpenLDAP server, as it's the premiere open source LDAP server and is widely packaged. Other LDAP servers can be used and much of the information will be applicable to them, but performance and OpenLDAP-specific overlays will not. On the client side, configuration for Linux, Solaris, OS X, Tru64 and Windows (using Samba) will be discussed.

TableOfContents

LDAP basics

So, what is LDAP? The acronym expands to "Lightweight Directory Access Protocol", and it was originally intended to provide IP (lightweight) access to X.500 servers, which required the use of the heavy OSI stack. Over time, directory servers that could be directly accessed by LDAP were written, cutting X.500 out of the loop. X.500 was a directory system designed by telcos in the 80s, back when the ISDN was the future of telephony. As such, it has several design decisions that presume a central delegating authority which have been inherited by pure LDAP servers. X.509, the security/certificate specification is one of these, and it lives on as the base of SSL/TLS, the internet PKI.

While LDAP strictly refers to the protocol, it is commonly used to refer to the database accessed via the protocol, which is more correctly called the Directory Information Tree (DIT). The DIT consists of a tree structure of entries, each of which belongs to a set of object classes and has a set of key/value attributes. An entry is the fundamental object of LDAP, and its type is determined by the values of its objectClass attribute. Common values include inetOrgPerson, posixAccount and organization.

Each objectClass is defined in a schema that lists the mandatory and optional attributes, which are themselves specified in schema. [2] For this document the important schema files are core.schema, inetorgperson.schema, cosine.schema <insert more>. An objectClass has one or more SUPerior objectClasses, from which it inherits the list of MUST and MAY attributes, and come in three types - ABSTRACT, STRUCTURAL and AUXILIARY. Every entry must have one structural objectClass, and any number of auxiliary objectClasses. Abstract objectClasses are only used to inherit from, and all objectClasses must derive from the abstract top objectClass. The limitation on an entry having only one structural objectClass can be worked around by creating a new structural objectClass that inherits from all the structural objectClasses required. This is getting into creating schema however and is beyond the scope of this document. While an entry can only have one structural objectClass, the superior objectClasses can be listed, style issue. Attribute inheritence

The tree is composed of entries, which can be both leaves and nodes. The path from an entry to the base of the tree identifies an object and is referred to as its distinguished name (DN), e.g. uid=trs80,ou=people,dc=example,dc=com. The components of the DN are the naming attribute? RDN? of each level of the tree, separated by commas. The naming attribute can be any attribute [3] but there are conventions detailed below, and it must be unique at that level of the tree, although it need not be globally unique. DNs and attribute names are generally case-insensitive, so UID=TRS80,ou=People,dc=Example,dc=COM is the same as the previous example.

The original X.500 specification envisioned a global directory service, divided by geographical regions and then companies, resulting in DNs like o=Widgets Inc.,st=Western Australia,c=AU. This doesn't map well to the internet, so the domain objectClass was defined in RFC ???? (and is included in cosine.schema) which MUST have a domainComponent (dc) attribute [4] that is by convention used as the RDN. So a domain like engineering.example.com is split at the periods to become the DN dc=engineering,dc=example,dc=com.

Administration domains. At this point you might be wondering who runs the dc=com domain and provides referrals. The answer is nobody - instead, PTR records in the DNS are used.

LDAP filters are the equivalent of the SELECT statement in SQL, but are formed of s-expressions. The full syntax is specified in RFCs ???? and ????, but the basic format is (attribute=value). Boolean operations are written like (&(a=b)(c=d)(e=f)) where & is the symbol for logical and, | is logical or, ! is logical not etc. Substring matching is allowed if the schema specifies it for that attribute...

LDIF

LDAP entries are transmitted over the wire in a binary ASN.1 format called BER, but there's an alternative text representation, the LDAP? Data Interchange Format (LDIF). This is specified in RFC ????, and there are several extensions, but the core of the format is <code>attributeName: value</code>. Here's the LDIF for an example entry:

<code> </code>

Binary attributes are base64 encoded, and the separator is change to be two colons (::) to indicate this. This also applies to ASCII characters outside a safe range.

OpenLDAP setup

OpenLDAP is the best-performing and most powerful LDAP server available. Unfortunately it has historically been somewhat poorly documented and unfriendly to newbies. The admin guide for 2.4 is good, but still requires a certain level of background knowledge. So I'll take the traditional method of providing a slapd.conf, but unlike other guides I'll explain what's going on.

<insert slapd.conf>

LDAP as a name service

What is a name service?

A naming service is one of those infrastructure things that mostly just sits behind the scenes and works. More details.

To use LDAP as a naming service, entries need to be created for the accounts in the DIT. These entries typically have an objectClass of posixAccount as specified in RFC 2307, however this is an auxiliary objectClass so we still need a structural objectClass. For this document we'll use inetOrgPerson, as it contains a useful set of attributes that can be used for other things later on, such as mail, <insert more>.

The account entries are located in a subtree, typically called ou=People. Groups are located in ou=Group. Together with the base entry, the DIT initially looks like this:

dn: dc=example,dc=com dc: example objectClass: domain

dn: ou=People,dc=example,dc=com u: People objectClass: organizationalUnit

dn: ou=Group,dc=example,dc=com ou: People objectClass: organizationalUnit

LDAP authentication

LDAP can be used as an authentication service in several ways. The easiest, and the one used here, is to perform a 'simple bind' operation where the password provided by the user is used to authenticate against the LDAP server. Other methods include SASL and client certificates. Kerberos binds can also be used, but are not much use as an authentication service since it requires an existing Kerberos authentication service. SASL offers the ability to use a variety of methods that ensure the password isn't passed in plaintext over the network, however most of thses require that the password is stored in plaintext on the server. In my opinion, having everyone's password in plaintext is a much bigger risk (link to reddit) than sending it over the wire, particularly since SSL/TLS provides wire encryption these days. SASL/SRP doesn't suffer from the plaintext problem, but it's not implemented widely (or arguably, at all) and so is not an option. SASL/EXTERNAL uses client certificates, which if you're happy to deploy and maintain you have enough expertise to not require this guide.

The authentication process takes two steps - first, a search is conducted for the full DN using the provided username in the subtree specified in the configuration, then a bind is performed with the DN and the provided password.

Linux

Most Linux distributions (Slackware being the notable exception, but I doubt many lazy sysadmins use it) use Linux-PAM, Pluggable Authentication Modules, as their authentication system. The LDAP PAM module was also written by PADL, and uses a similar file (in some cases the same file) as the LDAP NSS module.

Solaris

Tru64

OS X

Samba/Windows

[2] discuss what can be specified in schemaBR [3] including a binary attribute, say jpegPhoto, leading to a DN thousands of characters longBR [4] itself in core.schema - a common mistake is include core.schema but not cosine.schema leading to objectClass unknown errors.