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