Arthur de Jong

Open Source / Free Software developer

Design documentation

This page describes the basic design of nss-pam-ldapd. It was started as a fork of nss_ldap to fix a number of shortcomings. The most important problems were:

  • every executable (that does name lookups) on the system will load the LDAP libraries (and dependencies) and opens a connection to the LDAP server
  • NSS lookups done during boot will slow down the system if the LDAP server is not yet available
  • hostname lookups through LDAP can cause deadlocks because the LDAP libraries will need to do (reverse) hostname lookups for connecting to the LDAP server

Furthermore the original implementation had a lot of cross-platform compatibility code throughout the code and a lot of complex constructs to work as an NSS module. This made it hard to maintain.
With nss-pam-ldapd the initial focus has been on getting it to work with glibc on Linux with OpenLDAP. Portability code was added later for most of the platfoms that nss_ldap supported in a way to not have the compatibility burden the normal code.

Design

Most of the problems of nss_ldap were solved by splitting the functionality in two parts:

  • a daemon that connects to the LDAP server and does all the requests and
  • a thin NSS connector that passes requests to the daemon through a socket.

Later on a PAM module was added that also communicates with the daemon.

design overview of nss-pam-ldapd

Communication between the NSS part and the server part is done using a simple request/response protocol. The protocol hides the complexity of transforming NSS and PAM queries into LDAP operations and transforming LDAP replies into a format that is suitable as NSS results.
The protocol is described in the nslcd.h file.

Using a local socket ensures that the availability of the server component can be easily tested. The server component can be started during system boot after the LDAP server is reachable (i.e. when networking is available).

Advantages of nss-pam-ldapd

Apart from fixing some of the problems that were mentioned earlier nss-pam-ldapd has a number of other advantages:

  • easier debugging and logging
  • reloading the configuration can simply be forced by restarting the daemon
  • a lot less locking and complexity in the code is required so we have better performance
  • no more symbol clashes or other side-effects when an application is using a different LDAP or SSL library
  • it is possible to secure the credentials needed to connect to the LDAP server
  • the number of connections to the LDAP server can be controlled
  • simpler, more modular code
  • improved documentation

Since an NSS module (and PAM module to a lesser extent) is loaded into someone else's address space, opening files and connections (especially if they are open for longer periods of time) requires complicated locking, signal masking, checking file descriptors, special fork() handling, etc. The OpenLDAP library and most SSL libraries have not been designed to be used in such environments which make things very difficult. All this complexity is eliminated in nss-pam-ldapd.

Overview of changes

The nss_ldap source was refactored extenisvely removing a lot of compatibility code. The NSS part of the code has been mostly rewritten from scratch digging into glibc source for definitions of all functions (a little more documentation would be useful).

With the design change and removal of lot of complexity some refactoring was done which resulted in a significantly smaller code size. This makes the codebase much more maintainable.

Over the years features and support for other operating systems has been added. The 0.7 release added a PAM module and the 0.8 release included a Solaris NSS module. The 0.9 release included a switch in coding style and a good deal of new functionality (nested groups, password policy support, user modification functionality and more).

SLOC count
releaseNSSPAMnslcdSLOC
nss_ldap-251Oct 200614690
nss-ldapd-0.1Dec 20061014923010526
nss-ldapd-0.2Jun 2007973868510382
nss-ldapd-0.5Dec 200797544726202
nss-ldapd-0.6Feb 200895445516616
nss-ldapd-0.6.8Mar 200997351627485
nss-pam-ldapd-0.7.0Sep 200992062154768383
nss-pam-ldapd-0.7.13Dec 201087851359239207
nss-pam-ldapd-0.8.0Dec 20101949527620910653
nss-pam-ldapd-0.8.12Nov 20121996598716911809
nss-pam-ldapd-0.9.0Apr 20132031679856313542
nss-pam-ldapd-0.9.2Oct 20132034679862913621

The above numbers were generated using David A. Wheeler's 'SLOCCount' over the ANSI C source code and excluding the test code. These numbers are not always 100% comparable because in some releases some features were removed or added and differences in compatibility support.

More information

Some more information on the design and general notes on making modifications is available in the HACKING file.