Differences

This shows you the differences between two versions of the page.

Link to this comparison view

en:ressources:dossiers:openldap:openldap_debian [2011/04/16 15:37] (current)
Line 1: Line 1:
 +====== The OpenLDAP Chapter ======
  
 +Identity management IS a big issue. And definitely something you want to take care of in a growing, multi-tiers,​ infrastructure. So the goal of this chapter is to describe the implementation of a reliable LDAP infrastructure using Debian and OpenLDAP.
 +
 +We will discuss the following:
 +  * Installation and Configuration of Slapd 2.4 on Debian Squeeze
 +  * Creation of an annuary for identity management, including groups and custom attributes
 +  * Configuration of the SASL authentication
 +  * Clustering with one master and two slaves
 +
 +That's quite a lot of work, so let's get started ! My main source of information is Mastering OpenLDAP, from Matt Butcher, published at PACKT Publishing, and the official [[http://​www.openldap.org/​doc/​admin24/​|OpenLDAP documentation]].
 +
 +===== OpenLDAP on Debian =====
 +
 +OpenLDAP is a set of tools to use and manage LDAP annuaries. Among them lives Slapd, the OpenLDAP Server. This one can be easily installed using the debian repositories.
 +
 +<​code>​
 +ramiel:/# aptitude install slapd ldap-utils
 +</​code>​
 +
 +ldap-utils is an additional package that contain most of the LDAP tools we will use with the directory, such as **ldapsearch** or **ldapadd**.
 +
 +The installation process then asks for the password of the administrator:​
 +{{:​en:​ressources:​dossiers:​openldap:​ldappasswd.png|}}
 +
 +We have a directory: **/​etc/​ldap** that contains the few following files:
 +<​code>​
 +ses0gnoc:/​etc/​ldap#​ ls -l
 +total 28
 +-rw-r--r-- 1 root root      245 nov.  26 11:12 ldap.conf
 +drwxr-xr-x 2 root root     4096 nov.  10 20:24 sasl2
 +drwxr-xr-x 2 root root     4096 févr. ​ 7 11:17 schema
 +-rw-r----- 1 root openldap 4760 févr. ​ 7 11:38 slapd.conf
 +-rw-r----- 1 root root     4786 févr. ​ 7 10:15 slapd.conf.orig
 +</​code>​
 +
 +Let's backup the original slapd.conf file:
 +<​code>​
 +ses0gnoc:/​etc/​ldap#​ cp slapd.conf slapd.conf.orig  ​
 +</​code>​
 +
 +==== Listen on localhost ====
 +
 +By default, slapd accepts requests from everywhere. We can change this in **/​etc/​default/​slapd**. Simply edit the line **SLAPD_SERVICES**.
 +
 +<​code>​
 +# vim /​etc/​default/​slapd
 +
 +[ ... ]
 +
 +# listen on localhost only
 +SLAPD_SERVICES="​ldap://​127.0.0.1:​389/​ ldapi:///"​
 +</​code>​
 +
 +
 +==== The slapd.conf configuration file ====
 +
 +This is the main configuration file for slapd. We will spend some time here, so understanding its syntax is important.
 +
 +The file is structures as follow:
 +
 +<​file>​
 + ​~~~~~~~~~~~~~~
 +{    GLOBAL ​   }
 + ​~~~~~~~~~~~~~~
 +      This section contains the global configuration parameters, such as the modules ​
 +to load, or the daemon information (pid file and so on...).
 +In this section, we will also declares the **schemas** usuable by the LDAP directory.
 +
 + ​~~~~~~~~~~~~~~
 +{   ​DATABASES ​ }
 + ​~~~~~~~~~~~~~~
 +      This section will contain the trees of the LDAP Directory. Each tree starts with 
 +a declaration of the **database** keyword (that also contains the database type, such 
 +as '​hdb'​) and it has a root defined by the value of **suffix**.
 +The declaration of a new tree starts with the declaration of a new **database** value.
 +
 + ​~~~~~~~~~~~~~~
 +{     ​ACLs ​    }
 + ​~~~~~~~~~~~~~~
 +      Access Control Lists define the rules to access the information inside the LDAP 
 +Directory. ​
 +</​file>​
 +
 +Now, let's dig into **slapd.conf** section by section.
 +
 +
 +=== Global ===
 +
 +== Schemas ==
 +
 +The first part include the global parameters, and in particular the schemas used by OpenLDAP. ​
 +A schema contain the definition of a set of objects and attributes. For example, the **core.schema** file contain the definition of the object **person** as follow:
 +
 +<​file>​
 +407 objectclass ( 2.5.6.6 NAME '​person'​
 +408         DESC '​RFC2256:​ a person'​
 +409         SUP top STRUCTURAL
 +410         MUST ( sn $ cn )
 +411         MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
 +</​file>​
 +
 +This definition clearly state that this object class **person** represents a person as defined in [[http://​www.ietf.org/​rfc/​rfc2256.txt|RFC 2256]]. This object **must** contain one //sn// (surname, or last name) and one //cn// (full name) fields, and may contain several other optional fields. The **$** sign is a separator sign (like a comma or a hyphen).
 +
 +<note important>​You will probably notice that, during your discovery of the LDAP world, many signs and operators have a very different meaning than usually. More of this later when discussing search queries.</​note>​
 +
 +Therefore, when the LDAP administrator will create a new **person**, he will have to respect this definition. Otherwise, the LDAP directory will reject the entry.
 +
 +In addition to the object classes, the schema also contains definitions of attributes, like the **mail** attribute that defines a case un-sensitive string representing a RFC 822 email address.
 +
 +<​file>​
 +558 attributetype ( 0.9.2342.19200300.100.1.3
 +559         NAME ( '​mail'​ '​rfc822Mailbox'​ )
 +560         DESC '​RFC1274:​ RFC822 Mailbox'​
 +561     ​EQUALITY caseIgnoreIA5Match
 +562     ​SUBSTR caseIgnoreIA5SubstringsMatch
 +563     ​SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
 +</​file>​
 +
 +Other schemas, like **inetorgperson**,​ can contain more exotic information,​ such as:
 +<​file>​
 +attributetype ( 0.9.2342.19200300.100.1.60
 +        NAME '​jpegPhoto'​
 +        DESC '​RFC2798:​ a JPEG image'
 +        SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )
 +</​file>​
 +
 +... a jpegphoto (could be anything, but let's say it is your ID photo).
 +
 +
 +By default, slapd on debian includes four schemas:
 +  - core: the main schema
 +  - cosine: a schema definition standardized in 1991 (!) as a pilot for X500 directories
 +  - nis: a schema for unix users, useful to define a login shell or a home directory
 +  - inetorgperson:​ a schema for "​internet"​ users
 +
 +Except for '​nis',​ the three other are linked and reuse objects from each other. So we will keep those three, and comment '​nis'​ out.
 +
 +<​file>​
 +# Schema and objectClass definitions
 +include ​        /​etc/​ldap/​schema/​core.schema
 +include ​        /​etc/​ldap/​schema/​cosine.schema
 +#​include ​        /​etc/​ldap/​schema/​nis.schema
 +include ​        /​etc/​ldap/​schema/​inetorgperson.schema
 +</​file>​
 +
 +<note warning>​By removing the nis schema, we remove the description of some attributes, like '​shadowLastChange'​. We thus need to remove any reference to this attribute from the configuration,​ eg. from the '​ACL'​ rule that references it at **line 109 of slapd.conf**.</​note>​
 +
 +
 +== Logs ==
 +
 +Slapd logs using syslog. It sends its logs to the LOG_LOCAL4 facility. So we need to modify syslogd configuration to send LOCAL4 to an actual file, and adapt the loglevel of slapd to get more information.
 +
 +<note tip>​Debian Squeeze ships rsyslog instead of the old syslogd by default.</​note>​
 +
 +Syslog can be configured in **/​etc/​rsyslog.conf**. Just add the following lines at the end.
 +<​file>​
 +# for slapd
 +local4.* ​       /​var/​log/​slapd.log
 +
 +</​file>​
 +
 +And now, in slapd.conf, set loglevel to **stats** (the loglevel are listed in **man slapd.conf**).
 +
 +<​file>​
 +# Read slapd.conf(5) for possible values
 +loglevel ​       stats
 +</​file>​
 +
 +For additionnal diagnostic, I like to set loglevel to the following items: "​loglevel stats sync ACL config filter"​.
 +
 +The rest of the file is self commented. We do not change these values...yet.
 +
 +<​file>​
 +# Where the pid file is put. The init.d script
 +# will not stop the server if you change this.
 +pidfile ​        /​var/​run/​slapd/​slapd.pid
 +
 +# List of arguments that were passed to the server
 +argsfile ​       /​var/​run/​slapd/​slapd.args
 +
 +# Where the dynamically loaded modules are stored
 +modulepath ​     /​usr/​lib/​ldap
 +moduleload ​     back_hdb
 +
 +# The maximum number of entries that is returned for a search operation
 +sizelimit 500
 +
 +# The tool-threads parameter sets the actual amount of cpu's that is used
 +# for indexing.
 +tool-threads 1
 +</​file>​
 +
 +=== Database ===
 +
 +Slapd support a large number of database backends. I will not cover all of them, because, for the most part, people stick to HDB. 
 +HDB is an enhanced version of Berkeley DataBase.
 +
 +<note tip>​Berkeley DB (BDB) is a computer software library that provides a high-performance embedded database, with bindings in C, C++, Java, Perl, Python, Ruby, Tcl, Smalltalk, and other programming languages. BDB stores arbitrary key/data pairs as byte arrays, and supports multiple data items for a single key. BDB can support thousands of simultaneous threads of control or concurrent processes manipulating databases as large as 256 terabytes, on a wide variety of operating systems including most Unix-like ​ and Windows systems, and real-time operating systems. [[http://​en.wikipedia.org/​wiki/​Berkeley_DB|source:​ wikipedia]]</​note>​
 +
 +HDB is only an optimization of BDB to solve the special needs of hierarchical trees that are LDAP directories. ​
 +
 +Back to **slapd.conf**,​ let's take a look at the declaration of the database.
 +Debian automatically creates a database for the domain of which the system belongs. So, in our case, it would be **linuxwall.info**. Therefore, the default database section looks like this:
 +
 +<​file>​
 +#######################################################################​
 +# Specific Directives for database #1, of type hdb:
 +# Database specific directives apply to this database until another
 +# '​database'​ directive occurs
 +database ​       hdb
 +
 +# The base of your directory in database #1
 +suffix ​         "​dc=linuxwall,​dc=info"​
 +
 +# Where the database file are physically stored for database #1
 +directory ​      "/​var/​lib/​ldap"​
 +
 +# For the Debian package we use 2MB as default but be sure to update this
 +# value if you have plenty of RAM
 +dbconfig set_cachesize 0 2097152 0
 +
 +# Number of objects that can be locked at the same time.
 +dbconfig set_lk_max_objects 1500
 +# Number of locks (both requested and granted)
 +dbconfig set_lk_max_locks 1500
 +# Number of lockers
 +dbconfig set_lk_max_lockers 1500
 +
 +# Indexing options for database #1
 +index           ​objectClass eq
 + 
 +# Save the time that the entry gets modified, for database #1
 +lastmod ​        on
 + 
 +# Checkpoint the BerkeleyDB database periodically in case of system
 +# failure and to speed slapd shutdown.
 +checkpoint ​     512 30
 +
 +[ .. truncated file, we will cover the ACLs later ...]
 +
 +</​file>​
 +
 +== database ==
 +This directive as two functions:
 +  - I defines the type of backend to use for this directory. In our case, that would be HDB.
 +  - I starts the definition of the directory. All of the directives that follow this one will be applied to the current database, until another database directive starts the definition of another directory.
 +
 +== suffix ==
 +This is the root of our database. Nothing can be created before this root, and all of the objects of the directory will have a distinguished name ending with this suffix.
 +For example:
 +<​file>​
 +Distinguished Name: cn=Jean-Kevin Michel,​ou=people,​dc=linuxwall,​dc=info
 +</​file>​
 +
 +== directory==
 +This is the location of the data files.
 +Slapd will store LDAP objects, views and internal data for this directory into files located at **/​var/​lib/​ldap/​**.
 +
 +<​code>​
 +samchiel:/​var/​lib/​ldap#​ ls -al
 +total 1116
 +drwxr-xr-x ​ 2 openldap openldap ​    4096 2010-05-05 11:50 .
 +drwxr-xr-x 23 root     ​root ​        4096 2010-05-05 11:24 ..
 +-rw-r--r-- ​ 1 openldap openldap ​    2048 2010-05-05 11:50 alock
 +-rw------- ​ 1 openldap openldap ​   24576 2010-05-05 11:50 __db.001
 +-rw------- ​ 1 openldap openldap ​  ​253952 2010-05-05 12:20 __db.002
 +-rw------- ​ 1 openldap openldap ​ 2629632 2010-05-05 12:20 __db.003
 +-rw------- ​ 1 openldap openldap ​   98304 2010-05-05 12:20 __db.004
 +-rw------- ​ 1 openldap openldap ​  ​778240 2010-05-05 11:53 __db.005
 +-rw------- ​ 1 openldap openldap ​   32768 2010-05-05 12:20 __db.006
 +-rw-r--r-- ​ 1 openldap openldap ​      96 2010-05-05 10:15 DB_CONFIG
 +-rw------- ​ 1 openldap openldap ​    8192 2010-05-05 12:20 dn2id.bdb
 +-rw------- ​ 1 openldap openldap ​   32768 2010-05-05 12:20 id2entry.bdb
 +-rw------- ​ 1 openldap openldap 10485760 2010-05-05 12:20 log.0000000001
 +-rw------- ​ 1 openldap openldap ​    8192 2010-05-05 12:20 objectClass.bdb
 +</​code>​
 +
 +  - the **db** files contain raw objects
 +  - **DB_CONFIG** contains some tweaking parameters
 +  - **dn2id.bdb** is a view containing a matching between distinguished names of objects and internal storage ID
 +  - **id2entry.bdb** is a view containing the details of each object
 +  - **objectClass.bdb** is the file for the index we defined in the configuration earlier
 +  - **log.0000000001** is the Berkeley DB transaction log file
 +
 +<note important>​OpenLDAP internal engines works as follow: When an operation is to be performed by the engine, slapd will treat it synchronously into the **log** journal file. Then, when it has some spare time, it will update the **index** and **db** file with the content of the journal. However, by default, reading will only be performed on committed values (ie. not in the journal).
 +
 +Therefore, **log** isn't just some activity information,​ it's clearly the heart of the directory.</​note>​
 +
 +If you want to delete a directory, you need to stop slapd and delete the **db* **, ** *.bdb ** and **log* ** files.
 +<​code>​
 +samchiel:/​var/​lib/​ldap#​ rm __db.00* *.bdb log.* 
 +</​code>​
 +
 +== dbconfig ==
 +This directive is used to tweak the database backend. The parameters are specific to each backend. In our case, the parameters have the following meaning:
 +  * set_cachesize:​ size of the cache. The HDB directory tries to keep as much of the directory in memory as possible. It will determine which entries to keep in memory, and it is definitely interesting for response times to have, at least, the most called objects in memory. This directive uses 3 arguments to determine the cache:
 +  - gigabytes of memory space allocated to the cache
 +  - bytes of memory space allocated to the cache
 +  - number of segments of cache
 +The first two arguments are summed up to determine the cache size. The third one should usually be 0 or 1, to have one segment only.
 +The default value is very low on Debian: only 2MB. But since we have no data in the directory yet, it will be enough for now.
 +
 +  * set_lk_max*:​ as commented in the file, those parameters concern the number of locks. Locks are used to ensure that only one threads in manipulating one data at a time, such preventing from inconsistencies. The default value of 1500 is enough for our tiny installation.
 +
 +== index ==
 +To speed up searches and lookup, you can define indexes on certain type of objects or attributes. An index will be stored into a separate datafile, such as objectclass.bdb as seen before, and be optimized for fast lookup.
 +
 +index are very interesting for attributes that are used in searches. Thus, if you plan on using the **uid** attribute, or **cn** attribute, a lot, it's interesting to put an index on those.
 +
 +The default index, on **objectclass**,​ is important because almost all searches will include something like //​objectclass=person//​ or equivalent. Therefore, slapd will have to look for the corresponding objectclass everytime a search is performed, and you should want to speed this up.
 +
 +As explained by Matt Butcher in his book (page 238), we can define two additional indexes as follow:
 +<​code>​
 +index           ​cn ​   eq,​sub,​pres,​approx
 +index           ​uid ​  eq
 +</​code>​
 +The third column determine the type of index:
 +  * eq: match for the exact value
 +  * sub: match for a subpart of the string/​value
 +  * pres: match for existence
 +  * approx: kind of a regular expression with mixed value, etc...
 +
 +We then add those indexes to **slapd.conf** and manually launch the index command to create two new files in **/​var/​lib/​ldap**:​
 +
 +<note warning>​slapindex must be launched:
 +  - while slapd is stopped ​
 +  - under user **openldap** via sudo
 +</​note>​
 +
 +<​code>​
 +samchiel:/​var/​lib/​ldap#​ /​etc/​init.d/​slapd stop
 +Stopping OpenLDAP: slapd.
 +
 +samchiel:/​var/​lib/​ldap#​ sudo -u openldap slapindex -q
 +
 +samchiel:/​var/​lib/​ldap#​ ls -l
 +total 468
 +-rw-r--r-- 1 openldap openldap ​    2048 2010-05-05 15:01 alock
 +-rw------- 1 openldap openldap ​    8192 2010-05-05 15:01 cn.bdb
 +-rw------- 1 openldap openldap ​   24576 2010-05-05 15:01 __db.001
 +-rw------- 1 openldap openldap ​  ​253952 2010-05-05 15:01 __db.002
 +-rw------- 1 openldap openldap ​ 2629632 2010-05-05 15:01 __db.003
 +-rw-r--r-- 1 openldap openldap ​      96 2010-05-05 10:15 DB_CONFIG
 +-rw------- 1 openldap openldap ​    8192 2010-05-05 12:20 dn2id.bdb
 +-rw------- 1 openldap openldap ​   32768 2010-05-05 12:20 id2entry.bdb
 +-rw------- 1 openldap openldap 10485760 2010-05-05 14:59 log.0000000001
 +-rw------- 1 openldap openldap ​    8192 2010-05-05 12:20 objectClass.bdb
 +-rw------- 1 openldap openldap ​    8192 2010-05-05 15:01 uid.bdb
 +
 +samchiel:/​var/​lib/​ldap#​ /​etc/​init.d/​slapd start
 +Starting OpenLDAP: slapd.
 +</​code>​
 +As you can see, we now have to new file: **cn.bdb** and **uid.bdb**.
 +
 +== lastmod ==
 +This function is an **overlay**. An overlay is some sort of module that slapd will call when necessary and that will perform some specification action before the action is operated by the directory.
 +In the case of lastmod, the overlay simply adds 4 additional fields to an object:
 +<​file>​
 +dn: cn=Jean-Kevin Michel,​ou=people,​dc=linuxwall,​dc=info
 +cn: Jean-Kevin Michel
 +[ ... ]
 +createtimestamp:​ 20100505095305Z
 +creatorsname:​ cn=admin,​dc=linuxwall,​dc=info
 +
 +modifiersname:​ cn=admin,​dc=linuxwall,​dc=info
 +modifytimestamp:​ 20100505131013Z
 +</​file>​
 +
 +== checkpoint ==
 +As mentionned before, Slapd works asynchronously for the most part. It means that datas will not be committed to the static files right away, but might stay in memory for a little while (they are, however, committed to the log journal in a synchronous manner).
 +**checkpoint** can be used to trigger a commit by looking at either the amount of data waiting for commit, or the time of the last commit.
 +If either of these limits are reached, checkpoint will trigger a commit.
 +
 +<​file>​checkpoint <amount of data in kbytes> <time limit></​file>​
 +
 +The default value (512kbytes max, or 30 minutes) is satisfying enough for our needs.
 +
 +==== ACL ====
 +Access Control List are at the root of the security policy of the directory: it controls authorization. ACLs are used to define the acess to objects of the directory.
 +
 +An ACL starts with the **access** directive. ACLs can be placed either in the database section, in which case they are specific to a database, or at the top of the configuration,​ in which case they apply globally, to all backends. The most specific ACL is always applied first (thus, the backends ACLs are preferred).
 +
 +As defined in the Admin guide, an ACl has this form:
 +<​file>​
 +access to <​what>​
 +        [by <who> [<​access>​] [<​control>​] ]+
 +
 +where the <​what>​ part selects the entries and/or attributes to which the access applies, the <who> part specifies which entities are granted access, and the <​access>​ part specifies the access granted. Multiple <who> <​access>​ <​control>​ triplets are supported, allowing many entities to be granted different access to the same set of entries and attributes.
 +</​file>​
 +
 +
 +<​file>​
 +access to attrs=userPassword
 +        by dn="​cn=admin,​dc=linuxwall,​dc=info"​ write
 +        by anonymous auth
 +        by self write
 +        by * none
 +</​file>​
 +
 +===== SASL =====
 +There are several ways to bind to a LDAP directory. One of them is using the SASL library, that provides secured method to transport the authentication from the client to the directory.
 +<note tip>The SASL method is necessary to allow cyrus-imap to connect to the directory without passing through saslauthd and pam. See the [[http://​wiki.linuxwall.info/​doku.php/​en:​ressources:​dossiers:​cyrus:​imapd|Cyrus Imapd Chapter]] for more details</​note>​
 +
 +Imagine that we want our users to be able to bind to the directory without using a TLS channel, but still without disclosing their passwords. SASL provides a solution to this, called DIGEST-MD5 ([[http://​www.ietf.org/​rfc/​rfc2831.txt|RFC 2831]].
 +
 +==== Authentication Algorithm ====
 +
 +DIGEST-MD5 works as follow:
 +  * 1. client declares itself to the server and announce it wants to use DIGEST-MD5 to bind to the realm linuxwall.info
 +<​code>​
 +dc=linuxwall,​dc=info....DIGEST-MD5
 +</​code>​
 +  * 2. server replies with a challenge
 +<​code>​
 +SASL(0):​.successful.result:​....nonce="​TY/​UgxW3BtNkYtWVIz/​tOFD8knO1U+wXDESwooOJq9Y=",​realm="​samchiel.linuxwall.info",​qop="​auth,​auth-int,​auth-conf",​cipher="​rc4-40,​rc4-56,​rc4,​des,​3des",​maxbuf=65536,​charset=utf-8,​algorithm=md5-sess
 +</​code>​
 +
 +The format of the challenge sent by the server to the client follows the description of the RFC:
 +<​file>​
 +digest-challenge ​ =
 +         1#( realm | nonce | qop-options | stale | maxbuf | charset
 +               ​algorithm | cipher-opts | auth-param )
 +</​file>​
 +  * 3. the client responds to the server
 +<​code>​
 +dc=linuxwall,​dc=info...5..DIGEST-MD5...%username="​julien",​realm="​samchiel.linuxwall.info",​nonce="​TY/​UgxW3BtNkYtWVIz/​tOFD8knO1U+wXDESwooOJq9Y=",​cnonce="​iI87tfR5Ac7xm58VwaKYZRGn28GnZlzA8Vr//​1axUbE=",​nc=00000001,​qop=auth-conf,​cipher=rc4,​maxbuf=16777215,​digest-uri="​ldap/​samchiel.linuxwall.info",​response=d096305a248894991856767e3258d7ca
 +</​code>​
 +Once again, we can find the description of this string in the RFC:
 +<​file>​
 +   ​digest-response ​ = 1#( username | realm | nonce | cnonce |
 +                          nonce-count | qop | digest-uri | response |
 +                          maxbuf | charset | cipher | authzid |
 +                          auth-param )
 +</​file>​
 +
 +The interesting value is **response**,​ the last one, that contains a MD5 hash of the given field plus the password. The response value is computed as follow:
 +
 +MD5(A1:​nonce:​cnonce:​A2)
 +where:
 +  - A1 = MD5( username:​realm:​password:​nonce:​cnonce:​(authzid))
 +  - A2 = ("​AUTHENTICATE:",​ digest-uri)
 +
 +So, in the end, the response is composed of:
 +**MD5(MD5( username:​realm:​password:​nonce:​cnonce:​(authzid)):​nonce:​cnonce:"​AUTHENTICATE:",​ digest-uri)**
 +
 +  * 3. The server receives the response and validates it by recalculating the same response (this it has all the fields in clear text). If the client'​s response is good, then the server replies with the following string to validate the binding:
 +<​code>​
 +rspauth=89cb4dc5c63c4aab3336e9b01c175cd1
 +</​code>​
 +
 +==== Set Up in OpenLDAP ====
 +LDAP supports SASL by default. However, SASL uses authentication string that are different than the LDAP strings. Therefore, Slapd must be configured to rewrite the string received from SASL into something it can understand.
 +
 +Another important point is that, since Slapd needs to calculate the MD5 response in order to validate the challenge, it needs to have access to the clear version of the password of the user. Therefore, we have to store password in cleartext in the directory. That and important limitation of SASL, and some serious file level protection will have to be deployed in order to cover the risk of loosing the datafiles, with the passwords in clear.
 +
 +=== SASL rewrite rule in Slapd ===
 +
 +SASL string looks like the following:
 +**uid=toto,​cn=linuxwall.info,​cn=DIGEST-MD5,​cn=auth**
 +<​uid>,<​realm>,<​algorithm>,"​auth"​
 +
 +Slapd needs to transform this into something LDAP friendly. To do that, we can add a regular expression into slapd that will take the UID value and put it into a LDAP URI.
 +The rule below needs to be copied inside **slapd.conf** into the database section.
 +
 +<​code>​
 +# SASL rewrite rule
 +authz-regexp "​^uid=([^,​]+).*,​cn=[^,​]*,​cn=auth$"​
 +             "​ldap:///​dc=linuxwall,​dc=info??​sub?​(uid=$1)"​
 +</​code>​
 +The resulting URI will be something like, for example, **ldap:///​dc=linuxwall,​dc=info??​sub?​(uid=julien)**. This request will search the entire directory for an object that has the **uid** '​julien'​.
 +Feel free to adapt the scope of the research to your needs.
 +
 +=== Passwords in clear ===
 +
 +We will discuss the population of the directory later, but for now, we need to ensure that all the passwords are stored in cleartext. It means that, when changing the password of a user with some external tool (like phpldapadmin),​ you need to set '​CLEAR'​ passwords.
 +
 +{{:​en:​ressources:​dossiers:​openldap:​clearpwd.png|}}
 +
 +Also, in the database section of **slapd.conf**,​ we add the following:
 +<​code>​
 +password-hash ​  ​{CLEARTEXT}
 +</​code>​
 +
 +Now, if you want to test this, restart your slapd server and try to perform a search using a SASL binding:
 +
 +<​code>​
 +samchiel:/# ldapsearch -Y DIGEST-MD5 -U julien -R '​linuxwall.info'​ -H ldap://​localhost -D '​dc=linuxwall,​dc=info'​ -b '​ou=people,​dc=linuxwall,​dc=info'​ -LLL '​(uid=julien)'​
 +
 +SASL/​DIGEST-MD5 authentication started
 +Please enter your password: xxxxxxxxxxx
 +
 +SASL username: julien
 +SASL SSF: 128
 +SASL data security layer installed.
 +
 +dn: cn=Julien Vehent,​ou=people,​dc=linuxwall,​dc=info
 +givenName: Julien
 +sn: Vehent
 +cn: Julien Vehent
 +uid: julien
 +objectClass:​ inetOrgPerson
 +objectClass:​ top
 +userPassword::​ Rf6RT48hzznopP0
 +</​code>​
 +
 +The binding works perfectly. You can also check your Slapd logs and you should see the following:
 +
 +<​code>​
 +May  6 16:08:23 samchiel slapd[2675]:​ conn=1 fd=15 ACCEPT from IP=[::​1]:​35019 (IP=[::​]:​389)
 +May  6 16:08:23 samchiel slapd[2675]:​ conn=1 op=0 BIND dn="​dc=linuxwall,​dc=info"​ method=163
 +May  6 16:08:23 samchiel slapd[2675]:​ conn=1 op=0 RESULT tag=97 err=14 text=SASL(0):​ successful result:
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=1 BIND dn="​dc=linuxwall,​dc=info"​ method=163
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=1 BIND authcid="​julien"​ authzid="​julien"​
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=1 BIND dn="​cn=julien vehent,​ou=people,​dc=linuxwall,​dc=info"​ mech=DIGEST-MD5 sasl_ssf=128 ssf=128
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=1 RESULT tag=97 err=0 text=
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=2 SRCH base="​ou=people,​dc=linuxwall,​dc=info"​ scope=2 deref=0 filter="​(uid=julien)"​
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=2 SEARCH RESULT tag=101 err=0 nentries=1 text=
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 op=3 UNBIND
 +May  6 16:08:26 samchiel slapd[2675]:​ conn=1 fd=15 closed
 +May  6 16:08:26 samchiel slapd[2675]:​ connection_read(15):​ no connection!
 +</​code>​
 +
 +==== SASL Proxy Authorization ====
 +
 +Slapd provides another interesting mechanisms. It allow for a user to act on behalf of another user. This is called 'Proxy Authorization'​ and is extremely useful, especially with cyrus-imap.
 +
 +To illustrate this, let's take a look at the '​ldapwhoami'​ command. This command returns your current identity. It's pretty straightforward to use:
 +<​code>​
 +samchiel:/# ldapwhoami -U julien -Y DIGEST-MD5 -H ldap://​localhost
 +
 +SASL/​DIGEST-MD5 authentication started
 +Please enter your password:
 +SASL username: julien
 +SASL SSF: 128
 +SASL data security layer installed.
 +dn:​cn=julien vehent,​ou=people,​dc=linuxwall,​dc=info
 +</​code>​
 +
 +Now, there is an interesting option in this command: **-X**. The manpage of ldapwhoami says the following about it:
 +<​file>​
 +       -X authzid ​                                                                                                                
 +              Specify the requested authorization ID for SASL bind.
 +              authzid must be one of the following formats: dn:<​distinguished name>
 +              or u:<​username> ​
 +</​file>​
 +
 +With this option, we can bind as a user JEANKEVIN using the credential of JULIEN. However, JULIEN needs to possess the good permissions. By default, slapd blocks that command:
 +<​code>​
 +samchiel:/# ldapwhoami -U julien -Y DIGEST-MD5 -X u:jeankevin -H ldap://​localhost
 +
 +SASL/​DIGEST-MD5 authentication started
 +Please enter your password: xxxxxxx
 +
 +ldap_sasl_interactive_bind_s:​ Insufficient access (50)
 +</​code>​
 +
 +This permission is controlled by a directive called **authzTo**. We need to activate this directive at two levels:
 +  - in **slapd.conf**,​ we need to add the authz policy
 +  - in the object that represents JULIEN, we need to give the permission to proxy authorization
 +
 +== authz-policy in slapd.conf ==
 +
 +Let's take a look at the explanation from the man page regarding the **authz-policy** directive
 +<​file>​
 +      authz-policy <​policy> ​
 +            Used to specify which rules to use for Proxy Authorization.
 +            Proxy authorization allows a client to authenticate to the server
 +            using one user's credentials,​ but specify a different identity to
 +            use for authorization and access control purposes. It essentially ​
 +            allows user A to login as user B, using user A's password. The none
 +            flag disables proxy authorization. This is the default setting. The
 +            from flag will use rules in the authzFrom ​ attribute of the 
 +            authorization DN. The to flag will use rules in the authzTo
 +            attribute of the authentication DN. The any flag, an alias for the
 +            deprecated value of both, will allow any of the above, whatever
 +            succeeds first (checked in to, from sequence. The all  flag requires
 +            both authorizations to succeed. ​
 +
 +[...]
 +</​file>​
 +And the manpage continues with a description of the possible values and the format of the **authzTo** directive.
 +In our **slapd.conf** file, we simply add the following directive in the database section:
 +
 +<​code>​
 +authz-policy to
 +</​code>​
 +
 +And then restart the server.
 +
 +== authzTo in entry attributes ==
 +In the definition of user JULIEN, we need to add an attribute. This attribute is called **authzTo** and takes as argument a research rule. This rule will return the list of objects for which the user can identify itself as.
 +
 +Our directive will be the following:
 +<​file>​
 +authzTo: ldap:///​dc=linuxwall,​dc=info??​sub?​(objectclass=inetOrgPerson)
 +</​file>​
 +
 +This rule will search for all of the '​inetOrgPerson'​ object withing the root DN. the '​sub'​ parameters allow the query to walk everywhere in the tree and look for all the objects.
 +Obviously, this rule is way too permissive for production use, but it will serve us well to illustrate the mechanism.
 +
 +So, use you preferate editor and add the previous attribute to user JULIEN. ​
 +
 +Then, go back to the command line and try the ldapwhoami command again:
 +
 +<​code>​
 +samchiel:/# ldapwhoami -U julien -Y DIGEST-MD5 -X u:jeankevin -H ldap://​localhost
 +
 +SASL/​DIGEST-MD5 authentication started
 +Please enter your password: xxxxxxx
 +
 +SASL username: u:jeankevin
 +SASL SSF: 128
 +SASL data security layer installed.
 +
 +dn:​cn=jean-kevin michel,​ou=people,​dc=linuxwall,​dc=info
 +</​code>​
 +
 +Authentication works fine. Now look at the last line that return the current identity. We are authenticated as "​jean-kevin michel"​. The proxy authentication worked !
 +
 +==== LDAPS and TLS ====
 +
 +By default, Slapd listen for queries coming from everything in clear. But it also ships a TLS support (with GNUTLS, if I'm not mistaken).
 +To activate it, we need a server certificate.
 +
 +The configuration takes places in **slapd.conf** and in **/​etc/​default/​slapd**:​
 +
 +=== slapd.conf ===
 +
 +Assuming you have your server certificate,​ private key and CA certificate in **/​etc/​ldap/​certs**,​ you need to add the following to the global section of slapd.conf:
 +
 +<​code>​
 +# TLS configuration for LDAPS
 +TLSCACertificateFile /​etc/​ldap/​certs/​ca-linuxwall.crt
 +TLSCertificateFile /​etc/​ldap/​certs/​ldap.linuxwall.info.pem
 +TLSCertificateKeyFile /​etc/​ldap/​certs/​ldap.linuxwall.info.key
 +</​code>​
 +
 +<note warning>​Do not forget to give ownership to '​openldap'​ user, otherwise the server will crash when trying to read the certificate. <​code>#​ chown openldap /​etc/​ldap/​certs/​ -R</​code></​note>​
 +=== startup parameter ===
 +
 +In **/​etc/​default/​slapd**,​ we need to add a **ldaps** socket to listen for queries on the TLS port (ie. TCP/636).
 +
 +<​code>​
 +SLAPD_SERVICES="​ldap://​127.0.0.1:​389/​ ldapi:/// ldaps:///"​
 +</​code>​
 +
 +Restart slapd and test using openssl:
 +
 +<​code>​
 +# openssl s_client -connect localhost:​636
 +
 +CONNECTED(00000003) ​                                                                                                              
 +depth=1 /​C=FR/​ST=France/​L=Paris/​O=Linuxwall/​CN=Linuxwall Certificate Authority Root Certificate/​emailAddress=root@linuxwall.info  ​
 +verify error:​num=19:​self signed certificate in certificate chain                                                                  ​
 +verify return:​0 ​                                                                                                                  
 +---                                                                                                                               
 +Certificate chain                                                                                                                 
 + 0 s:/​C=FR/​ST=France/​O=Linuxwall/​CN=ldap.linuxwall.info ​                                                                          
 +   ​i:/​C=FR/​ST=France/​L=Paris/​O=Linuxwall/​CN=Linuxwall Certificate Authority Root Certificate/​emailAddress=root@linuxwall.info ​    
 + 1 s:/​C=FR/​ST=France/​L=Paris/​O=L
 +
 +[... ]
 +
 +</​code>​
 +
 +===== Replication =====
 +
 +Openldap 2.4 ships syncrepl, a mechanism to keep several directories synchronized. ​
 +The slave directory will connect to the master on a regular basis and look for changes since the last time it replicated.
 +
 +syncrepl allows for two methods of replication:​ refresh-only and refresh and persist. The difference between the two is that the second one will keep the connection to the master open so the master can inform the slave of any changes that happen to any entry, and that in real time.
 +
 +In our infrastructure,​ we will stick to the first model of replication. The reasons are:
 +  * the two directories are on different sites, thus keeping a connection open over the internet is expensive
 +  * the master will have very few objects to manage, and changes won't happen that often
 +
 +With that in mind, a simple setup with one master and as many slaves as you want is pretty straightforward to configure. We need:
 +  - a replication account
 +  - a module on the master
 +  - a syncrepl directive on the slave
 +
 +
 +==== On the Master ====
 +
 +**slapd.conf** needs a new overlay called "​syncprov"​. ​
 +The '​syncprov-checkpoint'​ directive will ensure that ContextCSN datas will be committed often enough.
 +
 +<​note>​The overlay creates a contextCSN attribute in the root entry of the database which is updated for every write operation performed against the database and only updated in memory.</​note>​
 +
 +So, first, declares the overlay at the top of **slapd.conf**:​
 +<​code>​
 +moduleload syncprov
 +</​code>​
 +
 +Then, in the database section, configure the overlay:
 +<​code>​
 +# SYNCREPL configuration
 +overlay syncprov
 +syncprov-checkpoint 50 10
 +</​code>​
 +
 +Since the replication will query the '​entryCSM'​ and '​entryUUID'​ attributes, we will also add indexes on those two entries.
 +In **slapd.conf**,​ database section:
 +<​code>​
 +index           ​entryCSN,​entryUUID ​     eq
 +</​code>​
 +
 +Then regenerate the indexes.
 +<​code>​
 +root@samchiel:​~#​ /​etc/​init.d/​slapd stop
 +Stopping OpenLDAP: slapd.
 +
 +root@samchiel:​~#​ sudo -u openldap slapindex -q
 +
 +root@samchiel:​~#​ /​etc/​init.d/​slapd start
 +Starting OpenLDAP: slapd.
 +</​code>​
 +
 +=== Replication account ===
 +
 +On the master, we need an entry that can read the whole directory. ​
 +
 +<​file>​
 +dn: cn=syncrepl,​ou=infrastructure,​dc=linuxwall,​dc=info
 +cn:  syncrepl
 +objectclass:​ inetOrgPerson
 +objectclass:​ top
 +sn: syncrepl
 +uid: syncrepl
 +userpassword:​ highsecuritypassword
 +</​file>​
 +
 +The replication account will also need to replicate the '​userPassword'​ attribute, for which we have a special ACL on the master:
 +<​code>​
 +access to attrs=userPassword
 +        by dn="​cn=admin,​dc=linuxwall,​dc=info"​ write
 +        by anonymous auth
 +        by self write
 +        by * none
 +</​code>​
 +
 +By default, only '​admin'​ and '​self'​ can manipulate this attribute. But for the replication to work, we need to grant this access to '​syncrepl'​ as well. The following ACL does the job just fine:
 +
 +<​code>​
 +access to attrs=userPassword
 +        by dn="​cn=admin,​dc=linuxwall,​dc=info"​ write
 +        by dn="​cn=syncrepl,​ou=infrastructure,​dc=linuxwall,​dc=info"​ read
 +        by anonymous auth
 +        by self write
 +        by * none
 +</​code>​
 +
 +<note tip>I noticed that, on some places, they recommand to give full write access on the directory to the '​syncrepl'​ account. I do not think this is necessary (but you're welcome to prove me wrong :) ).</​note>​
 +
 +
 +==== On the slave ====
 +
 +On the slave side, the configuration of **slapd.conf** is very close to the one of the master. We can define the same indexes and ACLs (or define different ones). Since the replication only concerns the objects and attributes, for everything else you need manual replication of the parameters.
 +
 +<note tip>This may give you a reason to look at the configuration backend, so you can replicate you configuration parameters like any other attribute.</​note>​
 +
 +=== Flush your installation ===
 +
 +If your slave is on Debian as well, the installation will create you a directory during the installation. You can flush these file and start over with an empty installation by deleting the data files in **/​var/​lib/​ldap/​**:​
 +
 +<​code>​
 +root@ptitchoun:/​ # /​etc/​init.d/​slapd stop
 +Stopping OpenLDAP: slapd.
 +
 +root@ptitchoun:/​ # cd /​var/​lib/​ldap/​
 +
 +root@ptitchoun:/​var/​lib/​ldap # ls
 +alock   ​__db.001 ​ __db.003 ​ __db.005 ​  ​dn2id.bdb ​    ​log.0000000001 ​  ​uid.bdb
 +cn.bdb ​ __db.002 ​ __db.004 ​ DB_CONFIG ​ id2entry.bdb ​ objectClass.bdb
 +
 +root@ptitchoun:/​var/​lib/​ldap # rm __db.00* *.bdb log.*
 +
 +root@ptitchoun:/​var/​lib/​ldap # ls
 +alock  DB_CONFIG
 +</​code>​
 +
 +Do not restart slapd right away, we need to do some configuration before.
 +
 +=== slapd.conf on the slave ===
 +
 +Giving our previous configuration for the master, the slave'​s **slapd.conf** file looks like the following. Pay particular attention to the ACLs, they are more restrictives than on the master (no write access to anyone here).
 +
 +<​file>​
 +include ​        /​etc/​ldap/​schema/​core.schema
 +include ​        /​etc/​ldap/​schema/​cosine.schema
 +include ​        /​etc/​ldap/​schema/​nis.schema
 +include ​        /​etc/​ldap/​schema/​inetorgperson.schema
 +
 +pidfile ​        /​var/​run/​slapd/​slapd.pid
 +argsfile ​       /​var/​run/​slapd/​slapd.args
 +
 +loglevel ​       stats sync ACL config filter
 +
 +modulepath ​     /​usr/​lib/​ldap
 +moduleload ​     back_hdb
 +
 +sizelimit 500
 +
 +tool-threads 1
 + 
 +backend ​        hdb
 +database ​       hdb
 +suffix ​         "​dc=linuxwall,​dc=info"​
 +rootdn ​         "​cn=admin,​dc=linuxwall,​dc=info"​
 +directory ​      "/​var/​lib/​ldap"​
 +password-hash ​  ​{CLEARTEXT}
 +
 +dbconfig set_cachesize 0 20971520 0
 +dbconfig set_lk_max_objects 1500
 +dbconfig set_lk_max_locks 1500
 +dbconfig set_lk_max_lockers 1500
 +
 +index           ​objectClass eq
 +index           ​cn ​   eq,​sub,​pres,​approx
 +index           ​uid ​  eq
 +
 +lastmod ​        on
 +
 +checkpoint ​     512 30
 +
 +access to attrs=userPassword
 +        by anonymous auth
 +        by * none
 +
 +access to dn.base=""​ by * read
 +
 +access to *
 +        by * read
 +
 +authz-regexp "​^uid=([^,​]+).*,​cn=[^,​]*,​cn=auth$"​
 +              "​ldap:///​dc=linuxwall,​dc=info??​sub?​(uid=$1)"​
 +
 +authz-policy to
 + 
 +# SYNCREPL replication directives
 +syncrepl rid=001
 +   ​provider=ldaps://​ldap.linuxwall.info
 +   ​type=refreshOnly
 +   ​interval=00:​01:​00:​00
 +   ​searchbase="​dc=linuxwall,​dc=info"​
 +   ​scope=sub
 +   ​binddn="​cn=syncrepl,​ou=infrastructure,​dc=linuxwall,​dc=info"​
 +   ​credentials=highsecuritypassword
 +
 +</​file>​
 +
 +Most of the directive have already been described. The new one is the '​syncrepl'​ directive. It takes the following arguments:
 +  * rid: and replication identification number. If you have several slaves replicating a directory, each slave must have its own rid, different from the others.
 +  * provider: the URI of the master, using '​ldaps'​ triggers the use of TLS to contact the master
 +  * type: the type of replication,​ to chose between '​refreshOnly'​ and '​refreshAndPersist'​
 +  * interval: how often does the slave contact the server, the format is "​dd:​hh:​mm:​ss"​
 +  * searchbase: where do we start the replication. can be used to replicate a sub-part of the master only
 +  * binddn: the user to bind to the master, as seen earlier
 +  * credentials:​ its password
 +
 +<note important>​If your directories are all on the same network, and bandwidth is not an issue for you, it is recommended to use '​refreshAndPersist'​. In this case, the '​interval'​ argument is ignored.</​note>​
 +
 +=== Connect from the slave to the master using TLS ===
 +
 +Because, we use LDAPS to connect to the master, we also need to edit **etc/​ldap/​ldap.conf** to add the CA certificate,​ otherwise, the establishment of the TLS connection will fail. So, in **ldap.conf**,​ add the following line:
 +<​code>​
 +TLS_CACERT /​etc/​ldap/​certs/​ca-linuxwall.crt
 +</​code>​
 +An copy the '​ca-linuxwall.crt'​ file to the corresponding folder.
 +
 +<note important>​By default, when establishing a LDAPS connection, OpenLDAP requires that the CN fields of the returned certificate matches the URI. It means that, when using LDAPS, you master server must return a certificate named ldap.linuxwall.info and your client must target ldaps:/​ldap.linuxwall.info.
 +
 +The '​-d8'​ switch can be used with ldapsearch to diagnose such problems:
 +
 +<​code>​
 +# ldapsearch -LL -x -W -D '​cn=syncrepl,​ou=infrastructure,​dc=linuxwall,​dc=info'​ -H ldaps://​samchiel.linuxwall.info '​(uid=syncrepl)'​ -d8
 +
 +Enter LDAP Password:
 +
 +TLS: hostname (samchiel.linuxwall.info) does not match common name in certificate (ldap.linuxwall.info).
 +ldap_sasl_bind(SIMPLE):​ Can't contact LDAP server (-1)
 +</​code>​
 +
 +</​note>​
 +
 +=== Test the replication ===
 +
 +We can now restart slapd on the slave. The directory **/​var/​lib/​ldap/​** should populate itself automatically:​
 +
 +<​code>​
 +root@ptitchoun:/​var/​lib/​ldap # /​etc/​init.d/​slapd start
 +Starting OpenLDAP: slapd.
 +
 +root@ptitchoun:/​var/​lib/​ldap # ls -l
 +total 220
 +-rw-r--r-- 1 openldap openldap ​   4096 mai 12 13:18 alock
 +-rw------- 1 openldap openldap ​   8192 mai 12 13:18 cn.bdb
 +-rw------- 1 openldap openldap ​   8192 mai 12 13:18 __db.001
 +-rw------- 1 openldap openldap 2629632 mai 12 13:18 __db.002
 +-rw------- 1 openldap openldap ​  98304 mai 12 13:18 __db.003
 +-rw------- 1 openldap openldap ​ 565248 mai 12 13:18 __db.004
 +-rw------- 1 openldap openldap ​  24576 mai 12 13:18 __db.005
 +-rw-r--r-- 1 openldap openldap ​     96 mai 11 17:14 DB_CONFIG
 +-rw------- 1 openldap openldap ​   8192 mai 12 13:18 dn2id.bdb
 +-rw------- 1 openldap openldap ​  32768 mai 12 13:18 id2entry.bdb
 +-rw------- 1 openldap openldap ​  90208 mai 12 13:18 log.0000000001
 +-rw------- 1 openldap openldap ​   8192 mai 12 13:18 objectClass.bdb
 +-rw------- 1 openldap openldap ​   8192 mai 12 13:18 uid.bdb
 +
 +</​code>​
 +
 +Also, we can take a look at the log file, you should see things like this:
 +
 +<​file>​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ syncrepl_entry:​ rid=001 be_search (0)                                                     
 +May 12 13:18:52 ptitchoun slapd[10486]:​ syncrepl_entry:​ rid=001 cn=Julien Vehent,​ou=people,​dc=linuxwall,​dc=info ​                  
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => access_allowed:​ add access to "​ou=people,​dc=linuxwall,​dc=info"​ "​children"​ requested ​   ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= root access granted ​                                                                   ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => access_allowed:​ add access granted by manage(=mwrscxd) ​                                
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => access_allowed:​ add access to "​cn=Julien Vehent,​ou=people,​dc=linuxwall,​dc=info"​ "​entry"​
 + ​requested ​                                                                                                                       ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= root access granted ​                                                                   ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => access_allowed:​ add access granted by manage(=mwrscxd) ​                                
 +May 12 13:18:52 ptitchoun slapd[10486]:​ syncrepl_entry:​ rid=001 be_add (0)                                                        ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ syncrepl_entry:​ rid=001 LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_ADD) ​                             ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ syncrepl_entry:​ rid=001 inserted UUID aaecf1d6-f15c-102e-9b7c-f1e0ff67341b ​               ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => access_allowed:​ search access to "​dc=linuxwall,​dc=info"​ "​entry"​ requested ​             ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= root access granted ​                                                                   ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => access_allowed:​ search access granted by manage(=mwrscxd) ​                             ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => bdb_filter_candidates ​                                                                 ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ #​011AND ​                                                                                  
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => bdb_list_candidates 0xa0                                                               
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => bdb_filter_candidates ​                                                                 ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ #​011EQUALITY ​                                                                             ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= bdb_equality_candidates:​ (entryUUID) not indexed ​                                      
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= bdb_filter_candidates:​ id=-1 first=1 last=6 ​                                           ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= bdb_list_candidates:​ id=-1 first=1 last=6 ​                                             ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ <= bdb_filter_candidates:​ id=-1 first=1 last=6 ​                                           ​
 +May 12 13:18:52 ptitchoun slapd[10486]:​ => test_filter ​                                                                           ​
 +May 12 13:18:52 ptitchoun slapd[10486]: ​    ​EQUALITY ​                                                                         ​
 +</​file>​
 +
 +This is how the slave and the master communicate. ​
 +
 +On the slave, we can also test the connection of a user using its password, to make sure all the attributes are synchronized correctly:
 +
 +<​code>​
 +root@ptitchoun:/​var/​lib/​ldap # ldapsearch -U julien -R '​linuxwall.info'​ -H ldap://​localhost -D '​dc=linuxwall,​dc=info'​ -b '​ou=people,​dc=linuxwall,​dc=info'​ -LLL '​(uid=julien)'​
 +
 +SASL/​DIGEST-MD5 authentication started
 +Please enter your password: xxxxx
 +SASL username: julien
 +SASL SSF: 128
 +SASL data security layer installed.
 +
 +dn: cn=Julien Vehent,​ou=people,​dc=linuxwall,​dc=info
 +givenName: Julien
 +sn: Vehent
 +cn: Julien Vehent
 +uid: julien
 +mail: julien@linuxwall.info
 +objectClass:​ inetOrgPerson
 +l: Paris
 +postalCode: 75011
 +telephoneNumber:​ +33.6.23.86.58.73
 +street: 27 rue Keller
 +</​code>​
 +
 +That's seems pretty alright to me :)
 +
 +
 +===== Add an account with ldapadd =====
 +
 +**ldapadd** is the command line tool for adding account to the LDAP directory. It needs an LDIF file that describes the new account, and the information to bind to the directory.
 +We can add an account with the following LDIF file :
 +<​file>​
 +dn: cn=Demo User,​ou=people,​dc=linuxwall,​dc=info
 +givenName: Demo
 +sn: User
 +cn: Demo User
 +uid: demo
 +mail: demo@linuxwall.info
 +objectClass:​ inetOrgPerson
 +l: Trifouilly les Oies
 +postalCode: 27412
 +userPassword:​ iwhefoheiod8394f8293dhohd1092dfo
 +</​file>​
 +
 +And then the following command :
 +<​code>​
 +# ldapadd -h 127.0.0.1 -p 389 -D "​cn=admin,​dc=linuxwall,​dc=info"​ -W -f insert_demo.ldif
 +Enter LDAP Password:
 +adding new entry "​cn=Demo User,​ou=people,​dc=linuxwall,​dc=info"​
 +
 +</​code>​
 +
 +===== Manipulating the attributes of an existing object =====
 +
 +Similarly to ldapadd, **ldapmodify** can add/modify and delete attributes from an existing object. The syntax is identical to ldapadd, except for the argument '​-a'​ that means "​add"​ a new attribute, instead of modifying the existing one.
 +
 +<​code>​
 +$ ldapmodify -a -h 127.0.0.1 ​ -p 389 -D "​cn=admin,​dc=linuxwall,​dc=info"​ -W <<EOF
 +dn: cn=Demo User,​ou=people,​dc=linuxwall,​dc=info
 +changetype: modify
 +add: mail
 +mail: spam-demo@linuxwall.info
 +EOF
 +
 +Enter LDAP Password:
 +modifying entry "​cn=Demo User,​ou=people,​dc=linuxwall,​dc=info"​
 +</​code>​
 +
 +<note tip>In fact, **ldapadd** is just a specific invocation of **ldapmodify**.</​note>​
 +
 +===== Password Policy =====
 +
 +OpenLDAP has the hability to apply password policies to users. This is performed by the ppolicy overlay and must be configured in slapd.conf.
 +The default password policy will be stored has an object in the directory. We will create a new organisational unit called '​policies'​ that will contain this object.
 +Then, the ppolicy configuration directives can be used to define the criterias to apply to the '​userPassword'​ attribute.
 +
 +==== Creating the '​policies'​ OU ====
 +
 +Using the command line, this is pretty straightforward :
 +<​code>​
 +# ldapadd -x -D cn=admin,​dc=linuxwall,​dc=info -W << EOF
 +
 +dn: ou=policies,​dc=linuxwall,​dc=info
 +objectClass:​ organizationalUnit
 +objectClass:​ top
 +ou: policies
 +EOF
 +
 +
 +Enter LDAP Password:
 +adding new entry "​ou=policies,​dc=linuxwall,​dc=info"​
 +</​code>​
 +
 +==== Configuring the overlay ====
 +
 +The ppolicy schema must be included, as well as the ppolicy module.
 +Then, in the database section, we can configure the path of the password policy object. The parameters of the password policy will be contained in the object directly.
 +
 +The pwdPolicy has the following definition, from **ppolicy.schema**.
 +
 +<​file>​
 +141 objectclass ( 1.3.6.1.4.1.42.2.27.8.2.1
 +142       NAME '​pwdPolicy'​
 +143       SUP top
 +144       ​AUXILIARY
 +145       MUST ( pwdAttribute )
 +146       MAY ( pwdMinAge $ pwdMaxAge $ pwdInHistory $ pwdCheckQuality $
 +147       ​pwdMinLength $ pwdExpireWarning $ pwdGraceAuthNLimit $ pwdLockout
 +148       $ pwdLockoutDuration $ pwdMaxFailure $ pwdFailureCountInterval $
 +149       ​pwdMustChange $ pwdAllowUserChange $ pwdSafeModify ) )
 +
 +</​file>​
 +
 +So, we start by adding this new schema and module to **slapd.conf**:​
 +
 +<​file>​
 +include ​        /​etc/​ldap/​schema/​ppolicy.schema
 +
 +[...]
 +
 +moduleload ​     ppolicy
 +
 +[...]
 +
 +backend ​        hdb
 +database ​       hdb
 +suffix ​         "​dc=linuxwall,​dc=info"​
 +
 +[...]
 +
 +# Password policy
 +overlay ppolicy
 +ppolicy_default "​cn=defaultpwpolicy,​ou=policies,​dc=linuxwall,​dc=info"​
 +
 +</​file>​
 +
 +And then, we create the object :
 +
 +<​code>​
 +# ldapadd -x -D cn=admin,​dc=linuxwall,​dc=info -W << EOF
 +dn: cn=defaultpwpolicy,​ou=policies,​dc=linuxwall,​dc=info
 +cn: defaultpwpolicy
 +sn: Default Password Policy
 +objectClass:​ pwdPolicy
 +objectClass:​ top
 +objectClass:​ person
 +pwdAttribute:​ 2.5.4.35
 +pwdAllowUserChange:​ TRUE
 +pwdInHistory:​ 2
 +pwdMaxFailure:​ 10
 +pwdLockout: TRUE
 +pwdLockoutDuration:​ 1800
 +pwdMinLength:​ 6
 +EOF
 +</​code>​
 +<note warning>​TO FIX: ERROR 
 +ldap_add: Invalid syntax (21)
 +        additional info: objectClass:​ value #0 invalid per syntax
 +</​note>​
 +
 +==== TODO: INTEGRATE check_password.c ====
 +http://​ltb-project.org/​wiki/​documentation/​openldap-ppolicy-check-password
en/ressources/dossiers/openldap/openldap_debian.txt · Last modified: 2011/04/16 15:37 (external edit)
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0