Blame HACKING

Packit 6bd9ab
This document tries to describe the software layout and design of
Packit 6bd9ab
nss-pam-ldapd. It should provide some help for contributing code to this
Packit 6bd9ab
package.
Packit 6bd9ab
Packit 6bd9ab
CONTRIBUTING TO NSS-PAM-LDAPD
Packit 6bd9ab
=============================
Packit 6bd9ab
Packit 6bd9ab
Contributions to nss-pam-ldapd are most welcome. Integrating contributions
Packit 6bd9ab
will be done on a best-effort basis and can be made easier if the following
Packit 6bd9ab
are considered:
Packit 6bd9ab
Packit 6bd9ab
* for large changes it is a good idea to send an email first
Packit 6bd9ab
* send your patches in unified diff (diff -u) format, Git patches or Git pull
Packit 6bd9ab
  requests
Packit 6bd9ab
* try to use the Git version of the software to develop the patch
Packit 6bd9ab
* clearly state which problem you're trying to solve and how this is
Packit 6bd9ab
  accomplished
Packit 6bd9ab
* please follow the existing coding conventions
Packit 6bd9ab
* please test the patch and include information on tested platforms, etc.
Packit 6bd9ab
* add a copyright statement with the patch if you feel the contribution is
Packit 6bd9ab
  significant enough (e.g. more than a few lines)
Packit 6bd9ab
* ensure that the code you contribute can be integrated in the project
Packit 6bd9ab
  under the LGPL (when including third-party code, retain copyright
Packit 6bd9ab
  information license, you have permission to distribute the code, etc.)
Packit 6bd9ab
Packit 6bd9ab
Please email nss-pam-ldapd-users@lists.arthurdejong.org if you want to
Packit 6bd9ab
contribute. All contributions will be acknowledged in the AUTHORS file.
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
BUILD DEPENDENCIES
Packit 6bd9ab
==================
Packit 6bd9ab
Packit 6bd9ab
For building Git snapshots the following tools are needed:
Packit 6bd9ab
Packit 6bd9ab
* autoconf (2.65 is currently used but 2.61 is minimal)
Packit 6bd9ab
* automake (1.14 is currently used but older versions may also work)
Packit 6bd9ab
* OpenLDAP libraries (2.4 is generally used)
Packit 6bd9ab
* PAM libraries
Packit 6bd9ab
* optionally a Kerberos library (MIT Kerberos is tested)
Packit 6bd9ab
* optionally a SASL library (only Cyrus SASL is tested)
Packit 6bd9ab
* docbook2x for generating the manual pages
Packit 6bd9ab
Packit 6bd9ab
To build the Git snapshot run the autogen.sh shell script to build the
Packit 6bd9ab
configure script. When developing patches please use --enable-warnings with
Packit 6bd9ab
configure and avoid introducing new warnings.
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
RELEASE VERSIONING
Packit 6bd9ab
==================
Packit 6bd9ab
Packit 6bd9ab
The versioning scheme of nss-pam-ldapd is a simple major.minor.micro
Packit 6bd9ab
numbering. The idea is to keep a stable (x.y) branch that only gets bug fixes
Packit 6bd9ab
and small enhancements while development goes in another branch. Backwards
Packit 6bd9ab
incompatible changes should be announced clearly.
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
GENERAL DESIGN
Packit 6bd9ab
==============
Packit 6bd9ab
Packit 6bd9ab
The basic design splits the functionality in three parts. The NSS part
Packit 6bd9ab
interfaces with libc and translates the NSS requests into simple generic
Packit 6bd9ab
requests (e.g. "get user with name test", "get group with gid 101" or "get all
Packit 6bd9ab
shadow entries").
Packit 6bd9ab
Packit 6bd9ab
Another part is the PAM module which handles authentication requests from the
Packit 6bd9ab
system. The PAM operations are also translated into atomic, stateless
Packit 6bd9ab
requests.
Packit 6bd9ab
Packit 6bd9ab
Both these parts translate the queries in a simple protocol used to
Packit 6bd9ab
communicate with the nslcd daemon. This daemon translates the requests into
Packit 6bd9ab
LDAP searches. As a result, the NSS and PAM modules don't need to known
Packit 6bd9ab
anything about LDAP (in fact replacing it with another lookup method should be
Packit 6bd9ab
very simple) and don't have to link with the LDAP libraries.
Packit 6bd9ab
Packit 6bd9ab
  libc NSS -> libnss_ldap.so
Packit 6bd9ab
                 \
Packit 6bd9ab
                  |->  nslcd  -> OpenLDAP -> LDAP server
Packit 6bd9ab
                 /
Packit 6bd9ab
  PAM stack -> pam_ldap.so
Packit 6bd9ab
Packit 6bd9ab
An alternative implementation of nslcd in Python is provided as pynslcd. This
Packit 6bd9ab
implementation is less mature but it easier to add advanced features there. A
Packit 6bd9ab
collection of utilities is also provided that communicate with nslcd that can
Packit 6bd9ab
provide additional functions.
Packit 6bd9ab
Packit 6bd9ab
design goals
Packit 6bd9ab
------------
Packit 6bd9ab
* make it as simple as possible
Packit 6bd9ab
* simpler configuration and semantics
Packit 6bd9ab
* simpler, clearer and completer documentation
Packit 6bd9ab
* split source code into manageable parts
Packit 6bd9ab
* get rid of unneeded code and complexity
Packit 6bd9ab
* have a stable, easily maintainable piece of high quality software
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
NSS MODULE
Packit 6bd9ab
==========
Packit 6bd9ab
Packit 6bd9ab
The NSS module is implemented in the nss directory. The functions are split
Packit 6bd9ab
into files according to the database they support. The files support multiple
Packit 6bd9ab
NSS implementations.
Packit 6bd9ab
Packit 6bd9ab
The NSS interface is specific to the C library that is used. The original
Packit 6bd9ab
implementation was for the GNU C Library but now also includes an
Packit 6bd9ab
implementation for Solaris' C Library and has some support for FreeBSD.
Packit 6bd9ab
Packit 6bd9ab
GNU C Library notes
Packit 6bd9ab
-------------------
Packit 6bd9ab
Packit 6bd9ab
Function definitions for glibc look like:
Packit 6bd9ab
Packit 6bd9ab
_nss_ldap_FUNCTION_r(...)
Packit 6bd9ab
  This function opens the connection to the nslcd (with a time-out), builds
Packit 6bd9ab
  the correct data structures and does a request (write()) to the nslcd
Packit 6bd9ab
  waiting for an answer (again with a time-out)
Packit 6bd9ab
Packit 6bd9ab
The complete list of exported functions can be found in exports.linux and
Packit 6bd9ab
prototypes.h.
Packit 6bd9ab
Packit 6bd9ab
Currently a number of macros are used to build most of the function bodies for
Packit 6bd9ab
these functions. Part of this is defined in the common/nslcd-prot.h file and
Packit 6bd9ab
the NSS-specific stuff is in nss/common.h.
Packit 6bd9ab
Packit 6bd9ab
For memory management, the general mechanism that is expected to be used is to
Packit 6bd9ab
return NSS_STATUS_TRYAGAIN and set errno to ERANGE. This causes glibc to retry
Packit 6bd9ab
the request with a larger buffer.
Packit 6bd9ab
Packit 6bd9ab
Some useful links:
Packit 6bd9ab
http://www.gnu.org/software/libc/manual/html_node/index.html
Packit 6bd9ab
Packit 6bd9ab
Solaris C Library notes
Packit 6bd9ab
-----------------------
Packit 6bd9ab
Packit 6bd9ab
The Solaris C library uses a different mechanism. For each map a back-end
Packit 6bd9ab
object is allocated per thread which is used to do queries. The object is
Packit 6bd9ab
created with a constructor (e.g. _nss_ldap_passwd_constr()) that returns a
Packit 6bd9ab
back-end that contains a list of function pointer to lookup methods and a
Packit 6bd9ab
destructor.
Packit 6bd9ab
Packit 6bd9ab
A buffer is passed with every request but a local buffer that is stored in the
Packit 6bd9ab
back-end can presumably also be created.
Packit 6bd9ab
Packit 6bd9ab
Earlier versions of Solaris expected the NSS functions to return the binary
Packit 6bd9ab
representation of the lookups (e.g. struct passwd) but later versions expect a
Packit 6bd9ab
string representation of the data to be returned (just like a single line out
Packit 6bd9ab
of /etc/passwd was read) but only if running from nscd. If args->buf.result is
Packit 6bd9ab
NULL a string representation is requested (except for ether by address lookup
Packit 6bd9ab
which is special).
Packit 6bd9ab
Packit 6bd9ab
Source and documentation pointers for Solaris NSS:
Packit 6bd9ab
https://java.net/projects/solaris/sources/on-src/show/usr/src/lib/nsswitch
Packit 6bd9ab
https://java.net/projects/solaris/sources/on-src/content/usr/src/head/nss_common.h
Packit 6bd9ab
https://java.net/projects/solaris/sources/on-src/content/usr/src/head/nss_dbdefs.h
Packit 6bd9ab
https://hg.openindiana.org/upstream/illumos/illumos-gate/file/tip/usr/src/lib/nsswitch
Packit 6bd9ab
https://hg.openindiana.org/upstream/illumos/illumos-gate/file/tip/usr/src/head/nss_common.h
Packit 6bd9ab
https://hg.openindiana.org/upstream/illumos/illumos-gate/file/tip/usr/src/head/nss_dbdefs.h
Packit 6bd9ab
Packit 6bd9ab
FreeBSD C Libarary notes
Packit 6bd9ab
------------------------
Packit 6bd9ab
Packit 6bd9ab
The FreeBSD C library seems to have support for exposing GNU C Library NSS
Packit 6bd9ab
module functions through a wrapper function. This makes it very easy to
Packit 6bd9ab
implement NSS support on FreeBSD.
Packit 6bd9ab
Packit 6bd9ab
Pointers for more documentation on this is welcome. Some information is
Packit 6bd9ab
available here:
Packit 6bd9ab
http://www.freebsd.org/cgi/man.cgi?query=nsdispatch
Packit 6bd9ab
https://github.com/freebsd/freebsd/blob/master/include/nss.h
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
PAM MODULE
Packit 6bd9ab
==========
Packit 6bd9ab
Packit 6bd9ab
The PAM module is implemented in the pam directory. Implementation is fairly
Packit 6bd9ab
straight-forward. The PAM module stores some state between calls to nslcd in a
Packit 6bd9ab
struct. The calls to nslcd are however stateless. The PAM module may supply
Packit 6bd9ab
some information that help lookups (most notably DNs of user entries).
Packit 6bd9ab
Packit 6bd9ab
Care must be taken with the communication because the nslcd requests are not
Packit 6bd9ab
authenticated (e.g. changing passwords requests should include all
Packit 6bd9ab
credentials). The PAM requests may result in state changes on the LDAP server
Packit 6bd9ab
and this is where they are most notably different from the NSS requests.
Packit 6bd9ab
Packit 6bd9ab
Some useful links:
Packit 6bd9ab
http://www.kernel.org/pub/linux/libs/pam/
Packit 6bd9ab
http://www.opengroup.org/tech/rfc/rfc86.0.html
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
THE COMMUNICATIONS PROTOCOL
Packit 6bd9ab
===========================
Packit 6bd9ab
Packit 6bd9ab
The protocol used for communicating between the NSS library and PAM module on
Packit 6bd9ab
one end and the nslcd daemon on the other is very simple and almost fully
Packit 6bd9ab
described in the nslcd.h header file. The common/nslcd-prot.h header file
Packit 6bd9ab
defines some macros that are used for reading and writing protocol entities
Packit 6bd9ab
(strings, 32-bit integers, etc).
Packit 6bd9ab
Packit 6bd9ab
Every NSS database has a corresponding source file in the nss and the nslcd
Packit 6bd9ab
directory. The PAM module is built up of a single file in both the pam and
Packit 6bd9ab
nslcd directories.
Packit 6bd9ab
Packit 6bd9ab
If the protocol is changed in an incompatible way the protocol version should
Packit 6bd9ab
be incremented in nslcd.h. There is currently no versioning scheme available
Packit 6bd9ab
for this.
Packit 6bd9ab
Packit 6bd9ab
A communications module (common/tio.c) was made so we can define simpler
Packit 6bd9ab
semantics for time-out values and buffer sizes. All components use this module
Packit 6bd9ab
which means that it includes functionality that is needed for both (e.g. large
Packit 6bd9ab
write buffers for the server part and large resettable read buffers for the
Packit 6bd9ab
NSS part). Maybe building two modules from the same source with different
Packit 6bd9ab
features in them is an option (e.g. the NSS part needs the read buffers and
Packit 6bd9ab
handling of SIGPIPE and the nslcd part needs the write buffers and possibly
Packit 6bd9ab
flushing in the background).
Packit 6bd9ab
Packit 6bd9ab
The common directory also contains some other generally useful modules that
Packit 6bd9ab
are used in some components.
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
SERVER PART
Packit 6bd9ab
===========
Packit 6bd9ab
Packit 6bd9ab
At the server end a dispatcher picks up the request and delegates it to one of
Packit 6bd9ab
the database specific functions.
Packit 6bd9ab
Packit 6bd9ab
nslcd_FUNCION(...)
Packit 6bd9ab
  This functions fills in the correct parameters from the request. This
Packit 6bd9ab
  function should write responses to the stream.
Packit 6bd9ab
Packit 6bd9ab
Big parts of the request handling functions are generated by macros because
Packit 6bd9ab
the structure is very similar across the different NSS requests.
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
SECURITY NOTES
Packit 6bd9ab
==============
Packit 6bd9ab
Packit 6bd9ab
This design does open up the system to more potential security issues
Packit 6bd9ab
(relative to nss_ldap) because there is now a local interface to a daemon with
Packit 6bd9ab
privileges. With nss_ldad, processes could only potentially exploit bugs in
Packit 6bd9ab
the library and gain the privileges of the process that was doing the name
Packit 6bd9ab
lookups. In this case the privileges of the daemon are potentially exposed.
Packit 6bd9ab
Packit 6bd9ab
Extra care should be taken with processes that normally require extra
Packit 6bd9ab
privileges (getting shadow entries, authentication, updating session
Packit 6bd9ab
information, etc).
Packit 6bd9ab
Packit 6bd9ab
Any user on the system can perform nslcd queries so either the nslcd daemon
Packit 6bd9ab
needs to check the userid of the caller or the request needs to contain the
Packit 6bd9ab
needed credentials itself.
Packit 6bd9ab
Packit 6bd9ab
On the other hand the design also offers some security improvements. It is
Packit 6bd9ab
much easier to handle security updates of the LDAP, SSL or related libraries
Packit 6bd9ab
and access to privileged LDAP configuration information can be much better
Packit 6bd9ab
constrained.
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
TEST SET-UP
Packit 6bd9ab
===========
Packit 6bd9ab
Packit 6bd9ab
In the test directory there are a number of tests available. See the file
Packit 6bd9ab
README in the test directory for more details.