All configuration examples and data templates will be included for your own use.
LDAP is modeled after the larger X.500 DAP and was originally designed to be a gateway to X.500 DAP servers. X.500 is an enormous topic in itself and won't be covered here beyond what I've already said. LDAP is client-server in nature. An LDAP client (e.g. Netscape) contacts an LDAP server with a query and the server responds with a result set based on the query.
Information stored in an LDAP entry can include names, e-mail addresses, phone numbers, and even encrypted passwords for authentication. Entries are defined within special files called schemas. There are many schemas available for use in OpenLDAP, and they can even be extended with custom attribute types and object classes.
Why would you want to run an LDAP server? Many businesses depend on having managed, centralized directories of employees, customers, and vendors. If you are responsible for managing these resources, OpenLDAP is a powerful and inexpensive way to achieve this. It is also a popular way to incorporate user authentication. In this day and age of home networking, the ease of setting up an LDAP server makes creating centralized e-mail directories at home a cinch. So the question becomes, why wouldn't you want to run an LDAP server? ;^)
slapd - The main LDAP server binary
slurpd - The binary for replication to primary LDAP servers
slapd.conf - The config file for the slapd daemon
ldap.conf - Global defaults for LDAP clients
There are typically other config files for things like search preferences and filters, but those are beyond the scope of this paper (i.e. I don't really understand them fully myself so I'm not qualified to discourse on them ;^).
The only components you need to get your LDAP server running are slapd, ldap.conf, and slapd.conf. This will not give you a very functional LDAP server, but it will give you a running LDAP server. To really get some use out of your server you will need schemas and a list of entries for your server, which we'll cover in the next two sections. First you will need to install OpenLDAP either off of your Linux CD's or download and compile it from ftp://ftp.openldap.org/pub/openldap/openldap-release. As of this writing version 2.1.6 is current. If you choose to download and compile the current release, you will need a C compiler and POSIX REGEX software. OpenSSL and Cyrus SASL are recommended but not required. To compile, simply extract the openldap-2.1.6.tgz file into a temporary directory and run:
./configure ; make
Depending on the processor speed compiling may take a few minutes, but not an inordinate amount of time. Once things are done you can either type 'make install' to finish the install, or 'make test' to test the compile. I strongly recommend the latter. It is rather time consuming but it will test all aspects of the program and alert you if things aren't working properly. After the test complete successfully type 'make install'. I tested the previous compile and install on a SuSE 8.0 installation without errors.
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
You'll notice that we added two additional schemas, cosine and inetorgperson. These schemas are not required but are very useful and therefore
recommended. You can optionally add the following entries:
pidfile /var/run/slapd.pid # file that hold the process id of the slapd daemon
argsfile /var/run/slapd.args # file that hold the command line arguments to the slapd daemon
Again the above two entries are not required, but some find them helpful. The next step is the database definitions. For this example we will use foo.org and FooBar Inc. for our databases. Make the following entries in slapd.conf:
database ldbm
suffix "dc=foo,dc=org"
suffix "o=FooBar Inc.,c=US"
First we told slapd that we want the database to be in ldbm format, and then we define foo.org as a valid suffix through the use of the attribute type dc, which is short for "domain component". Lastly we also define the organizationName (o) as FooBar Inc. and the countryName (c) as US. Next we need to specify a rootdn for the server. The rootdn is basically the "superuser" of the server, and is not subject to access control or other restrictions. The default is an empty rootdn (no root access) which mean you must grant access to populate the database and create entries. While this is the more secure method, we will declare a rootdn to make populating the database easier. Add the following lines to slapd.conf:
rootdn "cn=manager,dc=foo,dc=org"
rootpw insecure
Here we've set the rootdn to "manager" and granted a password of "insecure". Hopefully you can see the inherent problems with this method. Your only method of preventing someone from taking over your ldap server is to make slapd.conf non-world readable. This is a Bad Thing in its classic form. A better method would be to at least create a password hash:
rootpw {SHA}ojN+jsbELZbRJeRb0qj9+MMjPUs=
If you don't know how to create password hashes, I'll provide links at the end of this paper where you can download a handy script to do this. If you install openldap from sources you will have a utility called slappasswd that will create password hashes too.
Our last step is to tell slapd where to store the database and create an index:
directory /var/lib/ldap
index objectClass eq
This tells slapd to keep the database files in /var/lib/ldap and create an equality index on the attribute type "objectClass". There are other types of indexes you can create, but which are beyond the scope of this paper.
You have now completed the initial configuration of your openldap server! Save slapd.conf and start the server:
/usr/lib/openldap/slapd # This is for SuSE Linux
/usr/local/etc/libexec/slapd # This is typically for from-source installs
rcldap start # Many distributions will provide their own rc-style script
You should now have a running slapd process listening for connections on port 389, the default port for LDAP. Now we'll move on to entering some useful data into the database...
dn: dc=foo,dc=org
objectclass: organization
o: foo.org
description: The Foo Organization
dn: cn=manager,dc=foo,dc=org
objectclass: organizationalRole
cn: manager
description: Directory Manager
This creates an organization entry for "foo.org" and adds an entry for "manager". Analyzing the entries, the first line specifies a "distinguished name" (dn:) with a "domain component" (dc) of foo and org. The second line specifies that this has an objectclass of "organization". The third line declares the organization (o) name is "foo.org". Line four is an optional description. The second entry is similar with the exception of a "cn:" instead of an "o:". "cn:" is short for "canonical name" and is used for person and role entries.
Now to get this information into the ldap server, we use the 'ldapadd' command. 'ldapadd' is actually just a hard link to 'ldapmodify -a', but it is usually there by default so we'll use it:
/usr/bin/ldapadd -f /etc/openldap/foobar_db.ldif -x -D "cn=manager,dc=foo,dc=org" -w insecure
To break down the above command, we tell 'ldapadd' to read entries from the file (-f) foobar_db.ldif, use simple authenication (-x), bind to the server as "manager" (-D "....") with the password (-w) of "insecure". For the security conscious you can alternatively use -W instead of -w to have ldapadd prompt for the password. This will keep your ldap password out of your .history file. ;)
We can create further entries following the above examples:
dn: cn=Ken Hughes,dc=foo,dc=org
cn: Ken
surname: Hughes
objectclass: organizationalperson
Now we change things a bit. This is a normal entry with no special role (like the "manager") so we've made them a simple "organizationalperson". Lets add a little more information to this entry:
dn: cn=Ken Hughes,dc=foo,dc=org
cn: Ken Hughes
givenname: Ken
surname: Hughes
objectclass: inetorgperson
mail: ken@foo.org
Notice we changed this entry to "inetorgperson"? The reason for this is that the attributes "givenname" and "mail" are referenced in the "inetorgperson" schema and therefore are not allowed under the default "core" schema. Feel free to browse through the various schemas and experiment with different attributes.
Now that we've made some entries in the server, let's query the server to see our listing. Type the following to get a listing of all entries:
ldapsearch -x -b 'dc=foo,dc=org' '(objectclass=*)'
Again we use simple authentication (-x) and specify a searchbase (-b) of all entries (objectclass=*) in foo.org (dc=foo,dc=org).
That should be enough to get you started on populating your LDAP server. There is a wealth of information on the web related to LDAP on Linux, but I have included a few links at the bottom of this paper that I personally found helpful. Remember that Google is Your Friend. Next I'll touch briefly on authenticating Linux to an LDAP server.
http://www.padl.com/download/pam_ldap.tgz
http://www.padl.com/download/nss_ldap.tgz
There are a handful of helpful migration tools also available here:
http://www.padl.com/download/MigrationTools.tgz
These tools will do things like extract your user account information from /etc/passwd into ldap-readable ldif format. You can then import those entries using the same methods detailed previously.
Once you have these packages installed and your passwords entered in your ldap server, you will need to make sure the following entries are added to your slapd.conf:
defaultaccess read
access to attr=userpassword
by self write
by * read
access to *
by self write
by dn=".+" read
by * read
Then edit /etc/pam.d/login, and /etc/pam.d/ssh (for remote access authentication) and add the following:
#%PAM-1.0
auth sufficient /lib/security/pam_ldap.so
account sufficient /lib/security/pam_ldap.so
password sufficient /lib/security/pam_ldap.so
session sufficient /lib/security/pam_ldap.so
Next edit /etc/ldap.conf and put the following in:
BASE dc=foo,dc=org # Change this to reflect your ldap server settings
HOST ldap # Change this to the hostname of your ldap server
pam_crypt local # This tells pam to encrypt the password before sending
Lastly you will need to edit /etc/nsswitch and make the following changes:
passwd: ldap files nis
shadow: ldap files nis
group: ldap files nis
As a side note, many major Linux distributions provide mechanisms to automatically make the above changes to enable LDAP authentication. If you are using one of these distributions (i.e. SuSE) then you may wish to use these mechanisms instead of editing the files manually.
You should now have the mAd SkiLL7 required to install, configure, and run a fully functional OpenLDAP server!
--begin hashit.pl--
#!/usr/bin/perl -I /usr/lib/perl5/site_perl/5.005/i386-linux
# Perl code to create and print SHA1 and MD5 hashes of passwords
# shamelessly stolen from the openLDAP Faq-O-Matic
# written 19-Jul-01 by Ed Truitt
# Updated 12-Oct-01 to include a {crypt} version of the password
$theGoodWord = $ARGV[0];
chomp($theGoodWord);
# First, print the clear text version
print "\n" ;
print "The Good Word is ==> $theGoodWord \n " ;
print "\n" ;
# Now generate and print the SHA1 hash
use Digest::SHA1;
use MIME::Base64;
$ctx = Digest::SHA1->new;
$ctx->add($theGoodWord);
$hashedSHAPasswd = '{SHA}' . encode_base64($ctx->digest,'');
print 'userPassword: ' . $hashedSHAPasswd . "\n";
# Now generate and print the MD5 hash
use Digest::MD5;
use MIME::Base64;
$ctx = Digest::MD5->new;
$ctx->add($theGoodWord);
$hashedMD5Passwd = '{MD5}' . encode_base64($ctx->digest,'');
print 'userPassword: ' . $hashedMD5Passwd . "\n";
# Now generate and print the CRYPT version
# first we need to generate the salt
@chars = ("A" .. "Z", "a" .. "z", 0 .. 9, qw(. /) );
$salt = join("", @chars[ map { rand @chars} ( 1 .. 4) ]);
# now to generate the password itself
$cryptPasswd = '{crypt}' . crypt($theGoodWord,$salt);
print 'userPassword: ' . $cryptPasswd . "\n";
print "\n";
--end hashit.pl--
hashit.sh - Simple 5 liner to make generating multiple passwords easy.
--begin hashit.sh--
#!/bin/sh
for x in $@
do
./hashit.pl ${x}
done
--end hashit.sh--
Don't forget to chmod +x hashit.pl hashit.sh. Stick these two scripts in the same directory and run:
./hashit.sh password1 password2 password3 ...
--begin slapd.conf--
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
pidfile /var/run/slapd.pid
argsfile /var/run/slapd.args
database ldbm
suffix "dc=foo,dc=org"
suffix "o=FooBar Inc.,c=US"
rootdn "cn=manager,dc=foo,dc=org"
rootpw insecure
directory /var/lib/ldap
index objectClass eq
--end slapd.conf--