Defindit Docs and Howto Home

This page last modified: Jul 26 2005
keywords:ldap,mini,howto,openldap,config,configuration,set,setup
description:Tom's mini howto and notes about setting up LDAP
title:LDAP, Tom's mini howto

Tom's LDAP Mini Howto
Academic Computing Health Sciences - ACHS
University of Virginia
twl8n@virginia.edu

Get a tar file with this document and example ldif files:

http://tull.achs.virginia.edu/~twl8n/readme_files/ldap_mini_howto.tar

http://defindit.com/readme_files/ldap_mini_howto.tar



Introduction
------------


I set up LDAP in order to authenticate users of Flow LIMS from the Fox
Chase Cancer Center. If you aren't using LIMS, please ignore any
references to it. I didn't modify any of the standard LDAP schemas,
therefore it is possible that this procedure is generalized. After
looking at the LDAP schemas, I would strongly recommend that you not
modify the LDAP schemas, nor create new attributes unless you are a
member of the inner priesthood of LDAP. It appears that nearly every
sensible use of LDAP has been anticipated by these schemas.

I'm using OpenLDAP which is part of the standard Fedora
installation. It is close to the build-from-source OpenLDAP
package. If you build from source you'll need at least one other
package. There is no uninstall for OpenLDAP built from source.

These instructions pertain to OpenLDAP and Fedora. File locations may
vary with other versions, but the concepts and file names should be
the same.

I've included several example files. (See the .tar file URLs above).

LDAP can be a huge nightmare, however, if things go well it is easy to
configure.

The LDAP setup instructions begin far below at "Step 1.", after the
Examples section

Before the instructions I've listed more than a dozen example LDAP
commands that worked for me. These are useful in tracking down
problems, and verifying that the system is working. You can run these
as a normal user. I only run them on my host. I've got iptables set to
block LDAP requests from other machines.



Example Commands
----------------

(Installation is in the next section)


Example 1. ldapsearch for namingContexts

The following ldapsearch should return your suffix as entered in
slapd.conf. However, I suspect it won't work until you've imported the
initial ldif file (see below).

ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts


Example 2. ldapsearch for everything related to a base.
This is handy. It returns everything for the -b base in your LDAP database.

ldapsearch -v -x -b 'dc=virginia,dc=edu' -s sub


Example 3. Authenticated search.

This is the same as the namingContexts query above, but does simple
authentication as the Manager. You will be prompted "Enter LDAP
Password:" which means the Manager password. 

ldapsearch -b '' -s base '(objectclass=*)' namingContexts -x -W -D "cn=Manager,dc=virginia,dc=edu"

See the ldapadd notes below for more details on authentication.


Example 4. ldapadd for a user.

This works when exmaple.mst3k.ldif is properly formatted, and probably
will NOT work until you have added example.init.ldif. As far as I
know, you could have several user records in a single ldif file.

Note that some example ldif files that you'll see in documentation on
the Web have the line:

objectClass: posixAccount

That line caused a descriptive error, and I commented out the
line. After that the ldapadd worked. 

Also note that ldapadd has funny behavior with regard to the
userPassword attribute. Apparently ldapadd hashes the userPassword. If
you give it something like:

userPassword: {MD5}wT2Iy0ywIAPa7bioTl0nKg==

what ends up in the LDAP database is something like this:

userPassword:: e01ENX13VDJJeTB5d0lBUGE3YmlvVGwwbktnPT0=

With all the things that were went wrong getting LDAP working,
I first thought this was some bizarre mistake. It is apparently
a feature.

I have tested ldapadd with clear text (non-encrypted, sometimes
written "cleartext"), {CRYPT}, and {MD5} passwords. All work fine. For
security reasons, avoid the clear text passwords. I'm guessing that
the hash is reversible, which would reveal your password.

If simple authentication doesn't work, first suspect your command line
args or your LDAP entry. For simple authentication as a particular
user you must have

-x -W -D <valid dn>

where <valid dn> is a valid distinguished name (dn, DN) from your LDAP
database. -x and -W are not order dependent. -D must be immediately
followed by the dn. I suggest testing authentication with ldapsearch.

-x is simple authentication
-W is prompt for password
-D is authenticate as this DN

Note that without -x LDAP will attempt SASL authentication. Also note
without -W the authentication will assume that you are trying to login
without a password, and that will fail too.

ldapadd -x -D "cn=Manager,dc=virginia,dc=edu" -W -f example.mst3k.ldif


Example 5. ldapsearch authenticated as a user.

After reading in the ldif for mst3k, the following command worked. It authenticated as
mst3k. 

ldapsearch -v -D 'uid=mst3k,cn=Mary,dc=virginia,dc=edu' -W -x -b 'dc=virginia,dc=edu' -s sub


Example 6. ldapdelete.

This works. It does simple authentication, and deletes that Barbara J
Jensen example in the OpenLDAP documentation. For delete or modify to
work, the search field (the last arg on the following command line)
must exactly match the dn of the record. I get the impression that
every record in the LDAP directory must have a unique dn.

ldapdelete -v -x -D "cn=Manager,dc=virginia,dc=edu" -W "cn=Barbara J Jensen,dc=virginia,dc=edu"


deleting entry "dn:uid=mst5k,dc=virginia,dc=edu"
Delete Result: Invalid DN syntax (34)


Example 7. ldapmodify

This also workd to modify a record. There are some clever commands
that can go inside an ldif file for ldapmodify, however, you can also
feed ldapmodify a changed file, and it updates any fields as necessary.

ldapmodify -x -W -D "cn=manager,dc=virginia,dc=edu" -f example.modify.ldif

If you get an error like:

ldap_modify: Server is unwilling to perform (53)
        additional info: referral missing

it probably means that you are asking to change something and one of
the fields in the modified file doesn't match the current contents of
the directory. Usually this means that your dn or one of the dn's in
your ldif aren't matching up. ldap doesn't say where the problem occured.


Example 8. Non-authenticated search for a single user's info.

ldapsearch -v -x -b 'dc=virginia,dc=edu' -s sub uid=mst3k


Example 9. Authenticated search for a single user's info.

ldapsearch -v -x -W -D "uid=mst3k,dc=virginia,dc=edu"  -b 'dc=virginia,dc=edu' -s sub uid=mst3k


Example 10. You can get slapd into the attached-to-tty debug mode with the

following command (as opposed to a daemon which is not attached to a
tty). -d is debug level. I only got it to work with odd numbered
arguments that are a power of two -1. 1 and 255 are fine.

/usr/sbin/slapd -u ldap -h ldap:/// -d 1




(Note: LIMS does not use SASL. I didn't realize this when installing
LIMS, so I learned a few things about SASL. The following few commands
and their notes are not necessary for LIMS installation)


Example 11. Search for supportedSASLMechanism.

If you are doing SASL, this can be handy.

ldapsearch -x -s base -b "" supportedSASLMechanisms

Example 12. SASL user listing. I don't understand the point of separate SASL
user lists, but this lists them (could be a shadow password thing). I
think there is sasldblistusers and sasldblistusers2. Again, I don't
know wny, and the docs didn't give any hints.

/usr/sbin/sasldblistusers2


Example 13. This is SASL authentication. You must add these users to the sasl

password db with the "saslpasswd2" utility (works just like passwd).
Note that -x and -U are not compatible arguments. -W doesn't seem
to have any effect.

ldapdelete -v -n -U manager@lims.med -W "cn=Barbara J Jensen,dc=virginia,dc=edu"


Example 14. This works fine, but requires the password that I entered via

saslpasswd2 (logged in as root), not the password in mst3k's LDAP entry.

ldapsearch -v -b 'dc=virginia,dc=edu' -s sub -U mst3k@lims.med


Example 15. This command failed because it wouldn't authenticate. I thought I

had this working at one point. If I wanted to fix it, I would start by
checking the sasl-regex in slapd.conf. I'd probably run slapd in debug
mode with -d 255. The second command with "cn=manager..." didn't work either.

ldapsearch -v -b 'dc=virginia,dc=edu' -s sub -D "uid=mst3k,dc=virginia,dc=edu"

ldapsearch -v -b 'dc=virginia,dc=edu' -s sub -D "cn=manager,dc=virginia,dc=edu"





Installation and Setup
----------------------


The LDAP documentation is interesting. I never saw any documentation
that told what command to use to verify that some step was successful,
and LDAP commands often didn't have the expected effect. These web
sites might be useful. It takes a lot of reading between the lines of
to make sense of the documentation.

http://www.openldap.org/lists/openldap-software/200301/msg00715.html
http://www.openldap.org/doc/admin22/dbtools.html
http://www.openldap.org/lists/openldap-software/200202/msg00414.html
http://www.spiritdancers.org/LDP/HOWTO/LDAP-HOWTO/dbonline.html



Step 1. Edit slapd.conf

See the enclosed file minimum_slapd.conf. The comments have been removed to
focus on the settings. The default slapd.conf has copious (and even
extraneous) comments.

su -l root
cd /etc/openldap
cp slapd.conf slapd.conf.safe
emacs slapd.conf
(or edit with your favorite editor)

I won't bother putting the defaults here, only the things you need to
change relative to your hardware/software.

You need to include the schemas. This is the default.

LIMS uses ldap version 2 binding.  Allow that. This is not the default.

  allow bind_v2


The pidfile location is default.

The database type is ldpm. I don't know why, but it works.

  database	ldbm


I not sure what the requirements are for suffix, although you must be
consistent in how you use it. I just used the top two levels of my
domain name. It is ok to repeat attributes such as "dc". 

  suffix		"dc=virginia,dc=edu"


Root dn (distinguished name) should consist of "cn=Manager," and your
suffix.

  rootdn		"cn=Manager,dc=virginia,dc=edu"


rootpw is the encrypted password.

  rootpw         "{MD5}pX4CtShLwtHNhJJcmVFvkQ=="

Use the command line utility

slappasswd -h {MD5}

which will prompt you for a password, the print the encrypted
string. Just paste the encrypted string along with the encryption type
into the rootpw field.

Directory is default.

All the index settings are default.

sasl-regexp is not necessary for LIMS because LIMS uses simple
authentication.

  sasl-regexp uid=(.*),cn=lims.med,cn=DIGEST-MD5,cn=auth uid=$1,dc=virginia,dc=edu

Regex one:
uid=(.*),cn=lims.med,cn=DIGEST-MD5,cn=auth

Regex two:
uid=$1,dc=virginia,dc=edu

I didn't know that SASL was unnecessary. I'm pretty
sure that the only way to determine the format of these two regexp's
is to run slapd with debugging, and in attached mode (attached to the
tty, not as a daemon). When you try to authenticate, there will be
debugging info about what string it has as a DN. The first
regex must match the string that you see SASL trying to authenticate
against. The second regex must match your rootdn. The usual regex syntax
seems to apply. There's a note in the output to the effect: "Using
regex, resulting string is ..." You'll need your xterm/console set to
have thousands of lines of scrollback.

Step 2. Start the ldap daemon slapd.

/etc/rc.d/init.d/ldap start



Step 3. Import some base dn ldif info.

I'm not sure this is necessary. However, it worked, and LDAP says that
I can't delete this entry because other stuff depends on it. I entered
this command from memory, so I hope this is correct. Edit the
example.init.ldif to correspond to your hardware, slapd.conf, etc.

ldapadd -x -D "cn=Manager,dc=virginia,dc=edu" -W -f example.init.ldif


Step 4. Import one or more users.
The example is for the mythical mst3k. Edit for your users. One user
should be enough to test LIMS.

ldapadd -x -D "cn=Manager,dc=virginia,dc=edu" -W -f example.mst3k.ldif

I've included some example modify files. They are basically a user
file with changes. Different values will be updated. I couldn't find a
way to change the dn of a record, or the uid. The way to fix that
seems to be to delete the record.

Note that ldapdelete is different from ldapadd and ldapmodify. If you
use -f with ldapdelete, the file must consist only of one or more
valid dn's without (!!) the "dn:". ldapdelete apparently does not
understand comments. If you are only deleting one record it is best to
use a command line arg and forget the file. That's what is in the
ldapdelete example above. This would delete the mst3k from the example.mst3k.ldif:

ldapdelete -v -n -D  -W "uid=mst3k,dc=virginia,dc=edu"


Now you should be able to login to LIMS from a web browser on the LIMS
server. Some iptables modifications may be necessary to use the LIMS
web site from other computers.




Notes on iptables
--------------------

If you get "connection refused" messages that often means that the
server is running and doesn't want to talk to you, as opposed to
iptables is blocking access to the server. (server being LDAP or Tomcat)

Modern iptables setups might give a "connection rejected" response,
but the usual recommendation is for iptables to 'drop' access instead
of 'reject'. Using 'drop' silently fails to connect. Attackers
can't tell why the machine is non-responding. 

As long as your LDAP connection is to your local machine (127.0.0.1),
then the standard iptables will allow this connection. Your iptables
has a rule:

-A INPUT -i lo -j ACCEPT

which means accept any connection from the lo (loopback) address which
is 127.0.0.1 which a special ip address meaning "myself".

LIMS and Tomcat use port 8080 which you'll probably have to open so
other machines can get to LIMS.

Test for iptables blocking your connections by briefly shutting
iptables off. As root:

/etc/rc.d/init.d/iptables stop

Try your LDAP search or LIMS web page request or whatever. If iptables
is the problem, open up the required port, and start iptables. I
recommend that you always make a copy of your iptables before editing
it.

The following iptables line will open access to 192.168.20.0 through
192.168.20.255 on port 8080. This is a typical situation where you
want to allow access to LIMS from one subnet within your organization,
but not from the entire organization, and not from the entire internet.

-A input-chain-name -s 192.168.20.0/24 -p tcp -m tcp --dport 8080 -m state --state NEW -j ACCEPT 

Explanation.

-A is "add to chain"

input-chain-name is the name of your chain. Get this from a line in
you iptables file that looks something like

:input-chain-name - [0:0]

-s 192.168.20.0/24 is apply this rule to ip addresses 192.168.20.0 through
192.168.20.255. The /24 means that the address mask applies to the
left most significant 24 bits. That means 192.168.20 is significant,
and the last 8 bits are not checked (allowed in). A broader subnet
could be 192.168.0.0/16, and a single machine could be 192.168.20.1.

-p tcp -m tcp probably apply to tcp protocol. I'm not sure about the meaning.

--dport 8080 means this rule applies to port 8080

--state NEW applies this rule to new connections.

-j ACCEPT is jump to accepting the connection (if all the criteria are
 met).

Below is a more standard RedHat rule, which I think accomplishes the
same thing. I'm not sure about the meaning of the --tcp-flags.

-A RH-Lokkit-0-50-INPUT -s 192.168.20.0/24 -p tcp -m tcp --dport 8080 --tcp-flags SYN,RST,ACK SYN -j ACCEPT