Translation(s) : English - Français

(!) ?Discussion


LDAP PAM Authentication

This method utilizes the pam_ldap or pam_ldapd PAM modules from the libpam-ldap package to check credentials against a LDAP server.

PAM Setup with libpam-ldapd

libpam-ldapd is a newer alternative to the original libpam-ldap. libpam-ldapd uses the same backend (nslcd) as libnss-ldapd, and thus also shares the same configuration file (/etc/nslcd.conf) for LDAP connection parameters. If you're already using libnss-ldapd for NSS, it may be more convenient to use libpam-ldapd's pam_ldap implementation.

The /etc/pam.d/common-* files are managed by pam-auth-update (from libpam-runtime).

The libpam-ldapd package includes /usr/share/pam-configs/ldap, and running dpkg-reconfigure libpam-runtime will let you configure the pam_unix/pam_ldap module(s) to use in /etc/pam.d/common-*.

Installing the libpam-ldapd package will automatically select the pam_ldap module for use in /etc/pam.d/common-*. The generated configuration is more suitable for use via @include in the various services in /etc/pam.d than the example configuration given below for libpam-ldap (e.g. login applies the auth optional pam_group.so after the @include common-auth).

PAM setup with libpam-ldap

/!\ Caution -- libpam-ldap is not available in Debian 12 'bookworm', given lack of maintenance upstream. See 1032123 libpam-ldap and 1024140 libnss-ldap.

In order to globally enable LDAP authentication through PAM, configure /etc/pam_ldap.conf and edit the /etc/pam.d/common-* files so that they contain something like this:

/etc/pam.d/common-account:

account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     [default=bad success=ok user_unknown=ignore] pam_ldap.so
account     required      pam_permit.so

/etc/pam.d/common-auth:

auth    sufficient      pam_unix.so nullok_secure
auth    requisite       pam_succeed_if.so uid >= 1000 quiet
auth    sufficient      pam_ldap.so use_first_pass
auth    required        pam_deny.so

/etc/pam.d/common-password:

password    sufficient    pam_unix.so md5 obscure min=4 max=8 nullok try_first_pass
password    sufficient    pam_ldap.so
password    required      pam_deny.so

/etc/pam.d/common-session:

session     required      pam_limits.so
session     required      pam_unix.so
session     optional      pam_ldap.so

Note that there are numerous ways to configure PAM, depending on your particular situation and preference. The above only attempts to use pam_ldap if the userid is not below 1000 (i.e. normal user accounts).

Allowing logins on a per-host basis

The pam_ldap module provides the ability to specify a list of hosts a user is allowed to log into, in the "host" attribute in LDAP. The host attribute can be specified multiple times for each user. If any of the entries match the hostname of the machine logging in to, login is succesful. Otherwise, login is denied.

This feature is enabled by specifying pam_check_host_attr yes in /etc/pam_ldap.conf.

When it is enabled, the account facility of pam_ldap will perform the checks and return an error when no proper host attribute is present.

The hostname in the host attribute on the user can be prefixed with ! to deny access to that host for that user. This is mostly useful in conjunction with the special entry "*", which allows access to all hosts.

To add the host attribute to a user, they should have a LDAP objectClass that supports this. The account objectClass has the attribute, but is not compatible with the inetOrgPerson objectClass. To work around this, you can use the ldapns schema, supplied with the libpam-ldap package. This schema provides the hostObject objectClass, which has the proper host attribute.

To enable this schema, add the following line to your slapd.conf:

include         /usr/share/doc/libpam-ldap/ldapns.schema

Finally, take care that the hostname of the server is resolvable. pam_ldap will try to resolve the hostname, to find any aliasses (such as listed in /etc/hosts). If the hostname is not resolvable, access is denied.

In order to enable host based authentication with libpam-ldapd one can use nslcd with pam_authz_search option. The pam_check_host_attr option can be emulated with this filter:

(&(objectClass=posixAccount)(uid=$username)(|(host=$hostname)(host=$fqdn)(host=\\*)))

You might need something more elaborate if you want to have negation (!host) capability. E.g.:

(&(objectClass=posixAccount)(uid=$username)(|(host=$hostname)(host=$fqdn)(&(host=\\*)(!(|(host=!$hostname)(host=!$fqdn))))))

See nslcd.conf for more details.

Allowing logins on a per-group basis

A common task is to restrict logins to a given LDAP group. With NIS, you would do this with careful tweaking of your /etc/passwd file. With LDAP, the easiest way is to use the pam_access module that comes with libpam-modules. Add the following line to /etc/pam.d/common-auth:

auth required    pam_access.so

Circa 2011-08-03 this didn't seem to affect logins using an SSH key unless auth is replaced by account ; unclear per status in 2023

This will activate /etc/security/access.conf, which you can tweak as follows:

# disallow all except people in the login group and root
-:ALL EXCEPT root (login):ALL EXCEPT LOCAL

This assumes you have a posixGroup named login in your LDAP tree with LDAP/NSS set up properly. Be careful about ensuring that you can still allow local users to login in case LDAP fails.

An alternative way for "logins on a per-group basis" is nslcd. With pam_authz_search option, one can define not only primary groups as with pam_access but also check against secondary groups or even mixture of primary and secondary groups.

For example we want to allow users whose primary LDAP group is admins (gidNumber 1234) and also members of group developers (secondary group). The following filter should do the trick:

#allow only memebers of secondary group developers and users with primary group admins
pam_authz_search (|(&(objectClass=posixGroup)(cn=developers)(memberUid=$username))(&(objectClass=posixAccount)(uid=$username)(gidNumber=1234)))

Permissions on the LDAP server

To get chsh and chfn to work for updating LDAP, you have to have the right settings in their /etc/pam.d/ entries, and you have to setup slapd.conf to allow access for users to update their entries. If needed, add something like this to slapd.conf:

  access to attrs=loginShell
         by dn="cn=admin,dc=FOO,dc=BAR" write
         by self write
         by * read

  access to attrs=gecos
         by dn="cn=admin,dc=FOO,dc=BAR" write
         by self write
         by * read

Caching LDAP credentials for offline use (Laptops)

Page refactoring in progress below this point. This information is quite possibly outdated

While continuous LDAP connectivity can be assumed for workstations and servers in a LAN, laptop users often do not have network connectivity. From a system administrators point of view it is tempting to create local users on the laptop but this causes trouble because you have to manage several password stores. On the other side, the situation where a user cannot login because the laptop cannot reach the LDAP server is unacceptable too.

Luckily the PAM stack has a way to cache the password information through the use of the PAM module libpam-ccreds. In short terms this module stores the password hash if a user has correctly authenticated through the PAM LDAP module. If the LDAP server is later unavailable to PAM, it uses ccred's locally cached credentials to authenticate the user.

The documentation in /usr/share/doc/libpam-ccreds/ is not using the default Debian Lenny scheme of splitted PAM config files in /etc/pam.d/ but it is easy to split the pam.conf in the examples dir into the several common-* files in /etc/pam.d/. At a minimum /etc/pam.d/common-auth has to be changed.

Unfortunately the example PAM configuration does not work out of the box with a standard Lenny installation. In some offline situations the ccred module is not used at all (you get a message in a text-mode login when libpam-ccreds is used). You can change /etc/pam.d/common-auth like this to get it working:

auth sufficient /lib/security/pam_unix.so
auth [authinfo_unavail=ignore success=1 default=2] /lib/security/pam_ldap.so use_first_pass
auth [default=done]     /lib/security/pam_ccreds.so action=validate use_first_pass
auth [default=done]     /lib/security/pam_ccreds.so action=store
auth [default=bad]      /lib/security/pam_ccreds.so action=update

Other alternatives:

Hint: Offline caching of LDAP credentials is only useful if LDAP information about users and groups is also available offline through NSS. This can be accomplished through the use of NSCD. See LDAP/NSS for more information.

LDAP server in Pass-through-mode

(Tested with wheezy.)

This setup example is a solution, if you have your own LDAP-server for e.g. a workgroup, but account management is done from a central LDAP server e.g. from a university. Point is: You have to be able to authenticate to 2 different LDAP servers. If server 1 accepts you, you should be logged in. If not, you should be delegated to server 2.

Solution 1 would be to configure the pam-stack with 2 pam_ldap.so entries with different config files, cf. this debian bug report. However, as mentioned there, you have to patch and build your own version of pam_ldap - at least at the moment. Furthermore, this is not the most elegant solution. Your client and server 1 both have 1 unsuccessful authentication attempt each time a user from server 2 logs in.

Solution 2 is LDAP pass-through authentication. It's an elegant solution, but it's not easy to configure:

Testing your solution

PAM setup with pam_unix

These instructions are possible quite out of date. There have been reports that the following does not work as described, please correct if needed

It is also possible to use plain old pam_unix by making sure /etc/nsswitch.conf contains something like shadow: files ldap and getent shadow shows password hashes.

If only authentication is needed, no changes to PAM configuration files should be necessary. For changing passwords, login shell and gecos install libpam-ldap, configure /etc/pam_ldap.conf and edit /etc/pam.d/common-password to contain something like this:

password   required   pam_ldap.so ignore_unknown_user md5
password   optional   pam_unix.so nullok obscure min=4 max=8 md5 try_first_pass

Note the 'md5' setting. This will ensure passwords are encrypted into MD5 digests when they are changed. You may also need to add pam_password md5 to /etc/pam_ldap.conf for this to work.


CategorySystemAdministration | CategoryNetwork | CategorySoftware