|
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.
|