Using LDAP for single authentication

Version 0.9

Ever think how nice it would be if you didn’t have 9 usernames and passwords to remember for all of the different services on all the different servers you use. Well you can if you have a LDAP directory with you username and password in it, and you configure all the services to use LDAP. This how-to is not the most comprehensive source for doing this, rather a step by step guide that should be enough to get you going in the right direction. This will let users have one account in LDAP and use any service on any server that you choose to allow. i.e. ssh, email, web permissions, samba file shares, ftp, and on and on… And if you need deeper information than I provide in this article, here’s a great resource.
Although I’m explaining this for Debian Linux, it is almost identical for RedHat and most other Linux distributions.This assumes you already have a working install and you’re somewhat familiar with Linux system administration and Pluggable Authentication Modules, or PAM. You should also know a little about LDAP syntax. For example, the domain fatofthelan.com would be dc=fatofthelan,dc=com. The username dstrangelove in the People OU would have the DN of uid=dstrangelove,ou=People,dc=fatofthelan,dc=com. dstrangelove’s group would be cn=dstrangelove,ou=Groups,dc=fatofthelan,dc=com.

First things first, you need to install the LDAP server software and its dependencies. We will be using OpenLDAP for our LDAP server. So non-Debian users install your RPM’s or from source. You’ll need OpenLDAP, PADL’s NSS_LDAP and PAM_LDAP, OpenSSL if you’re planning on using SSL for security, Samba if you want that functionality. Most likely some of this is already on your system. Debian users, all you need to do is enter this:

[root@crm114]# apt-get install libnss-ldap slapd ldap-utils libpam-ldap ca-certificates

…and answer the questions when prompted. When installing slapd, OpenLDAP’s daemon, the Debian install automatically adds an admin user called admin (cn=admin,dc=fatofthelan,dc=com) to the directory and add this user to the ACL’s accordingly. The only problem with this is that if the directory is down or damaged you can’t access it. slapd has a configuration file, /etc/ldap/slapd.conf, that we’ll be adding a new admin to shortly called Manager (cn=Manager,dc=fatofthelan,dc=com) that has full access to the directory. To ease the use of some of our ldap tools, edit your /etc/ldap/ldap.conf file and add the following lines:

HOST 127.0.0.1
BASE dc=fatofthelan, dc=com

The installer should have created a “slapd.conf” located in /etc/ldap/ for Debian users. We need to open it and change some things. First we need to find the schema section and make sure that we have the following schema included:

# 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

This will give us the ability to add the various objectclasses and attributes we’ll need for our users. Next we need to add the “Manager” user that I mentioned earlier. After the “database bdb” entry, add the following:
rootdn “cn=Manager,dc=fatofthelan,dc=com”
rootpw {SSHA}ioFLRifu436G9WiRdfA2ua2wy9+R6ivF

Save and exit. If you’re were wondering how I got “{SSHA}ioFLRifu436G9WiRdfA2ua2wy9+R6ivF” for my rootpw, I used the “slappasswd” command. You could use a plain text password, but that would be very insecure. If security didn’t matter, we’d be using Active Directory. So to get your hashed password with “slappasswd” issue the following command:
[root@crm114]# slappasswd -h {ssha} -s yourPasswdGoesHere
…and it’ll return {SSHA}AyDy6ToNn9h86xgAuI0nMFeb+qLHzayD. Copy this value to your slapd.conf.

The installer will also create the files libnss_ldap.conf, pam_ldap.conf, nsswitch.conf, ldap.secret under /etc with the values you entered during the install. It’s a good idea to verify that they exist and have the correct values. Also you may want to change some of the values you entered sometime, so this is where to do it.
Note to non-Debian users; Debian splits up these files so you may not have them for your distribution. Most likely all of the settings Debian users put in libnss_ldap.conf and pam_ldap.conf will be located in your ldap.conf.

To have PAM use the LDAP libraries we’ll have to edit the /etc/nsswitch.conf file. This file tells PAM what mechanisms to use and in what order. Find these lines and append ldap to them (Some systems will have “files” instead of “compat”. Leave this intact):

passwd:		compat ldap
group:		compat ldap
shadow:		compat ldap

You’ll also have to add the following information to the PAM files for the services you’d like to use LDAP (located in /etc/pam.d/) . NOTE: RedHat users can use a utility called “authconfig” to do this for them, but be sure to verify the results! Some Linux distributions just have one file called “login” whereas Debian splits them up into several called common-auth, common-account, common-session, common-password. If a service has it’s own file in /etc/pam.d/ it will use that file, otherwise it will user other, which points to the “common-*” files. Be aware that order DOES matter in here. You’ll want to add the pam_ldap entries ABOVE the pam_unix entries. Now add…

auth	sufficient	pam_ldap.so    use_first_pass
to /etc/pam.d/common-auth
account	sufficient	pam_ldap.so
to /etc/pam.d/common-account
session	sufficient	pam_ldap.so
to /etc/pam.d/common-session
password	sufficient	pam_ldap.so
to /etc/pam.d/common-password

You may want to take advantage of the pam_mkhomedir library that will automatically create the user’s home directory upon first logon. I do NOT like this and make user’s home directories with my ldapuser tool. But if you want to use it enter:
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
to the /etc/pam.d/common-session file.

To keep things tidy I make the directory /root/ldap to make/import/alter my ldif files. LDIF is the format that we’ll be using to import/export/modify/delete records in the LDAP directory. Be aware that the LDIF format is VERY sensitive to white space. Spaces and newlines matter!
…so [root@crm114]# mkdir /root/ldap

The Debian installer scripts will automatically create the root DN (dc=fatofthelan,dc=com). If installing from source or another distribution be sure to create this. Debian users skip to the next section on creating ou’s. Create the file mkBase.ldif and enter the following with your settings:

#mkBase creates the base of the LDAP tree
dn: dc=fatofthelan,dc=com
dc: fatofthelan
objectClass: dcObject
objectClass: organizationalUnit
ou: Fat of the LAN

Now create the base by entering the following:
[root@crm114]# slapadd –v –l /root/ldap/mkBase.ldif (that is a lower case L)

If all has been done correctly, you should see something like this:
added: “dc=fatofthelan,dc=com” (00000001)

To keep users and groups organized we’ll be creating organizational units (OU) to hold our users and groups. You can copy the following file and enter your values. To build the People and Group ou’s create the file mkOu.ldif with the following contents:

## Build the People and Groups ous
dn: ou=People,dc=fatofthelan,dc=com
ou: People
objectClass: organizationalUnit

dn: ou=Groups,dc=fatofthelan,dc=com
ou: Groups
objectClass: organizationalUnit

Now add mkOu.ldif to LDAP. Note that the “slap*” tools access the database directly and the “ldap*” tools access the LDAP server. So the “slap*” tools work when slapd isn’t running. To add mkOu.ldif to LDAP using slapadd, run:
[root@crm114]# slapadd –v –l /root/ldap/mkOu.ldif (that is a lower case L)

Alternatively, to add mkOu.ldif to LDAP using “ldapadd” run:
[root@crm114]# ldapadd -x -D “cn=admin,dc=fatofthelan,dc=com” -W -f mkOu.ldif

Note that the cn=admin user only exsists on Debian systems.

To have all of this stuff running securely and not sending cleartext usernames and passwords we’ll be installing some self-signed certificates and enabling TLS. To generate the certificates we’ll be using a script that exists on just about every system that has OpenSSL installed called CA.pl. I think it may just be CA on RedHat systems.
First navigate to /usr/lib/ssl/misc/ and execute the command:
[root@crm114]# ./CA.pl –newcert

To generate your CA certificate, it will ask you for site specific values, so just answer appropriately, noting that CommonName is the FQDN of your server, i.e. ldap.fatofthelan.com.

We want slapd to start without any intervention so we’ll need to remove the password from our key. To remove the password from our key, run the following command, entering the password when prompted that you used in the previous step:
[root@crm114]# openssl rsa -in newreq.pem -out newkey.pem

We’ll want to store these key in /etc/ldap/ssl, so:
[root@crm114]# mkdir /etc/ldap/ssl

Now move your private LDAP key:
[root@crm114]# mv newkey.pem /etc/ldap/ssl/slapd-key.pem

…and secure it by making it readable by root only:
[root@crm114]# chmod 600 /etc/ldap/ssl/slapd-key.pem

Now we must remove our private key from newreq.pem. Using a text editor, open newreq.pem and remove private key, the section starting with:
—–BEGIN RSA PRIVATE KEY—–
…and ending with:
—–END RSA PRIVATE KEY—–

Now move our new public certificate to it’s home:
[root@crm114]# mv newreq.pem /etc/ldap/ssl/slapd-cert.pem

To have slapd use these keys we need to add the following to our /etc/ldap/slapd.conf:

# Certificate/ssl
TLSCipherSuite HIGH
TLSCertificateFile /etc/ldap/ssl/slapd-cert.pem
TLSCertificateKeyFile /etc/ldap/ssl/slapd-key.pem

Have slapd start using ldaps (ldap over SSL), open /etc/default/slapd and add the following line:
SLAPD_SERVICES=”ldap://127.0.0.1:389/ ldaps:///”

What this does is let all localhost traffic go plaintext and all remote traffic will be encrypted. You must restart slapd to make effective:
[root@crm114]# /etc/init.d/slapd restart

Note: Since this is a self-signed certificate, other systems won’t be able to verify the CA in your certificate. To remidy this you can either purchase a certificate from a trusted root CA, import your self-signed CA to the other systems, or tell the other systems to not verify the root by adding this to your ldap.conf:

 TLS_REQCERT allow

If this is a new network install or you don’t have any current users in /etc/passwd that you want to import, you can skip to the next section.
To migrate current users from /etc/passwd to an easily importable ldif file, we’ll be using PADL’s Miration tools. To get them, just download them form padl.com into our /root/ldap directory:
[root@crm114]# wget ‘http://www.padl.com/download/MigrationTools.tgz’

Untar them:
[root@crm114]# tar -zxvf MigrationTools.tgz

and cd into the MigrationTools-45 directory.
Locate and edit the defaults file “migrate_common.ph”, entering your settings.
Adjust these:

$DEFAULT_MAIL_DOMAIN
$DEFAULT_BASE
$DEFAULT_MAIL_HOST

…and save. I had to adjust the migrate_passwd.pl script a little to produce the output that I needed for my network. You may not need to do this. I wanted to alter and add some attributes for my environment and have the output look like the record below. Edit migrate_passwd.pl to taste.To test the results we’ll have it print to the screen to see the output. Run:
[root@crm114]# ./migrate_passwd.pl /etc/passwd
You should see a list of names like this:

dn: uid=dstrangelove,ou=People,dc=fatofthelan,dc=com
uid: dstrangelove
cn: Dr. Strangelove
givenName: Dr.
sn: Strangelove
mail: dstrangelove@fatofthelan.com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
userPassword: {crypt}$1$iorFDDPCfdadfd7yyXjLg7StvxBGJ1D5ON.
shadowLastChange: 12477
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/dstrangelove
gecos: Dr. Strangelove,,,

Now direct the output to the LDIF file /root/ldap/allUsers.ldif:
[root@crm114]# ./migrate_passwd.pl /etc/passwd > /root/ldap/allUsers.ldif

You’ll want to get the groups too, so:
[root@crm114]# ./migrate_group.pl /etc/group > /root/ldap/allGroups.ldif

Edit the output files and remove any users you don’t want added to LDAP. Now import them to LDAP:
[root@crm114]# ldapadd -x -D “cn=admin,dc=fatofthelan,dc=com” -W -f /root/ldap/allUsers.ldif
[root@crm114]# ldapadd -x -D “cn=admin,dc=fatofthelan,dc=com” -W -f /root/ldap/allGroups.ldif

You should now be able to see the contents with “getent”.
For example:
[root@crm114]# getent passwd dstrangelove
…should give: dstrangelove:x:1001:1001:Dr.Strangelove,109,555-1212,555-2121:/home/dstrangelove:/bin/bash

If you still have the user dstrangelove in your local /etc/passed file it won’t pull from LDAP. If you want to check that it’s really working, delete the user from /etc/passwd and /etc/group or create and import a new ldif file using an entry from the allusers.ldif as your template. After you’ve successfully created and imported your new user, issue the “getent” command for the name you just added. If this doesn’t work do not proceed! Go back and find what’s wrong.
At this point you should have a working LDAP directory to authenticate against. You may want to download my “ldap tools” to aid in the creation/deletion/modification of users and groups. Get them here:
http://www.fatofthelan.com/downloads/index.php?did=28

Samba Integration

If you would like to also tie Samba into your LDAP directory, you will need to complete a few extra steps. First you’ll need tell OpenLDAP how to handle the new objectclasses and attributes by adding the samba.schema to your slapd.conf. This will most likely not be on the system.
Note: Samba 2.x and 3.x use VERY different schema! Be sure to use the proper schema. This how-to explains the procedure for Samba 3.x.
To get the samba.schema, as well as lots of great documentaion, just “apt-get install samba-doc” and gunzip the /usr/share/doc/samba-doc/examples/LDAP/samba.schema.gz. For non-Debian users (who are probably wishing that they were right now 😉 ) you’ll probably need to download the Samba 3.x source, untar, and locate the samba.schema in the examples/LDAP/ directory. Once you have the samba.schema copied into your schema directory you need to edit your “slapd.conf” file. Add this to the schema section:

     include /etc/ldap/schema/samba.schema

…and restart slapd.

We’ll now need a “Computers” ou, so create it using the mkOu.ldif as your template. Make and import your new ldif file, thus creating the new ou. Now locate your “smb.conf” which is located in /etc/samba for us Debian folk. Since we have to really alter it quite a bit, it’s a good idea to make a copy of it, just in case. Open smb.conf and add the following to it, noting that you may already have some of these settings in the file. Be sure to comment out the old values!

# Samba config file
[global]
## Browsing/Identification ###
# Change this to the workgroup/NT-domain name your Samba server will part of
workgroup = FATLAN
netbios name = CRM114
# server string is the equivalent of the NT Description field
server string = %h server (Samba %v)
# LDAPsam part
ldap admin dn = "cn=Manager,dc=fatofthelan,dc=com"
passdb backend = ldapsam:ldap://127.0.0.1:389
ldap ssl = off
ldap suffix = dc=fatofthelan,dc=com
ldap delete dn = no
unix password sync = yes
#(leave commented out due to bug)ldap filter = (&(uid=%u)(objectclass=sambaSamAccount))
ldap user suffix = ou=People
ldap group suffix = ou=Groups
ldap machine suffix = ou=Computers

To allow Samba to edit the LDAP directory you probably noticed that we’ve added the “ldap admin dn = “cn=Manager,dc=fatofthelan,dc=com”” line. Just for simplicity I used the same Manager user. This is a big security risk! Do create a user that can only access the appropriate ou’s via ACL’s in your slapd.conf and use that user here. Although this how-to is written assuming all services will be on one server, it doesn’t have too. You will most likely have several servers in the equation. Since Samba and LDAP are on the same server it isn’t necessary to encrypt the traffic passing between them, hence the line “ldap ssl” is off. If communications are passing over the network your should set this to start_tls. You have been warned.
To have the ability to write to the directory the Manager (or the user you SHOULD have added) has to authenticate to LDAP. You probably noticed there isn’t any passwd line in the smb.conf. The password is stored elseware, so you’ll have to use the “smbpasswd” utility to add it. Enter this:
[root@crm114]# smbpasswd –w yourUsersPassword
…and you should see this:
Setting stored password for “cn=Manager,dc=fatofthelan,dc=com” in secrets.tdb

The nice thing about Samba is that it updates the LDAP records for you and adds all the new objectclasses and attributes. To see what I mean look at the record for dstrangelove.

[root@crm114]# ldapsearch –x –D “cn=Manager,dc=fatofthelan,dc=com” “(uid=dstrangelove)” –W
…results:

   dn: uid=dstrangelove,ou=People,dc=fatofthelan,dc=com
   uid: dstrangelove
   cn: Dr. Strangelove
   givenName: Dr.
   sn: Strangelove
   mail: dstrangelove@fatofthelan.com
   objectClass: inetOrgPerson
   objectClass: posixAccount
   objectClass: shadowAccount
   userPassword: e2NyeXB0fSQxJFBNDFdsfFDF99SdfyRzFZTVB1cGFIWURJYjA=.
   shadowLastChange: 12477
   shadowMax: 99999
   shadowWarning: 7
   loginShell: /bin/bash
   uidNumber: 1001
   gidNumber: 1001
   homeDirectory: /home/dstrangelove
   gecos: Dr. Strangelove,,,

Now update dstrangelove with the “smbpasswd” command and compare the differences.
[root@crm114]# smbpasswd -a dstrangelove -s SecretPasswd

   dn: uid= dstrangelove,ou=People,dc=fatofthelan,dc=com
   uid: dstrangelove
   cn: Dr. Strangelove
   givenName: Dr.
   sn: Strangelove
   mail: dstrangelove @fatofthelan.com
   objectClass: inetOrgPerson
   objectClass: posixAccount
   objectClass: shadowAccount
   objectClass: sambaSamAccount
   userPassword:: e2NyeXB0fSQxJFBNDFdsfFDF99SdfyRzFZTVB1cGFIWURJYjA=
   shadowLastChange: 12558
   shadowMax: 99999
   shadowWarning: 7
   loginShell: /bin/bash
   uidNumber: 1001
   gidNumber: 1001
   homeDirectory: /home/dstrangelove
   gecos: Dr. Strangelove,,,,
   sambaSID: S-1-5-21-1344450970-2161234372-36654443257-3034
   sambaPrimaryGroupSID: S-1-5-21-1383250970-2163672372-3665153257-3035
   displayName: Dr. Strangelove,,,,
   sambaPwdCanChange: 1085753893
   sambaPwdMustChange: 2147483647
   sambaLMPassword: 2E025795A2EFE447AC3CB3EC7G38287
   sambaNTPassword: 416DFFA3FF0D4019E5BD5FFSA4166
   sambaPwdLastSet: 1085753893
   sambaAcctFlags: [U ]

You should see a lot of additions. Notice the sambaLMPassword and sambaNTPassword attributes. Since these Microsoft (weak) hashes can be cracked by a Commadore 64, you’ll want to change the ACL’s in your slapd.conf only letting the Samba Manager user (that you already created, right?) to have any kind of access. No one else should be able to see them! Again, edit your slapd.conf and enter this:

   # Setting access for Samba passwords.
   ## allow the "ldap admin dn" access, but deny everyone else
   access to attrs=sambaLMPassword,sambaNTPassword
   by dn="cn=Manager,dc=aorganise,dc=com" write
   by * none

You’ll need to update slapd’s indices to improve performamce, so change your slapd.conf indices to:

# Indices to maintain
index objectclass             eq

index cn                      pres,sub,eq
index sn                      pres,sub,eq
# required to support pdb_getsampwnam
index uid                     pres,sub,eq
# required to support pdb_getsambapwrid()
index displayName             pres,sub,eq

index uidNumber               eq
index gidNumber               eq
index memberUid               eq

index   sambaSID              eq
index   sambaPrimaryGroupSID  eq
index   sambaDomainName       eq
index   default               sub

You’ll have to let slapd know about the new indices by running the command:
[root@crm114]# slapindex -f /etc/ldap/slapd.conf

I have some shares that I want only “Admins” to have access to. To do this we have to make a new UNIX group and map it to a Samba group. Make and import the following group with your settings and gidNumber:

dn: cn=admins,ou=Groups,dc=fatofthelan,dc=com
objectClass: posixGroup
objectClass: top
cn: admins
userPassword: {crypt}x
gidNumber: 1002

Now you’ll need to map UNIX group “admins” to the NT group “Domain Admins” even if you’re not using Samba in a domain. This adds the neccesary attributes in LDAP. In case you’re wondering, the NT group RID number is 512 (See appendix D). Issue the command:
[root@crm114]# net groupmap add rid=512 ntgroup=”Domain Admins” unixgroup=admins

Check that is was successful with the “net” command:
[root@crm114]# net groupmap list
Domain Admins (S-1-5-21-3442250970-2163992372-367753257-512) -> admins

Now I add dstrangelove to the admins group with the ldapuser tool:
[root@crm114]# ldapuser dstrangelove admins

To set up the share I enter this in my smb.conf:

[Doomsday]
   comment = Secret Software
   valid users = @admins
   delete readonly = yes
   writeable = yes
   path = /home/doomsday
   write list = @admins

I don’t think that Samba (or Windows) should ever be exposed to the internet, but I like to give web-based Samba access to my users so they can access their home shares from anywhere. I also think that web-based is the way to go because it will work on any platform that can open a web browser. There is an excellent PHP script that I like to use called SmbWebClient and you can get it here:
http://www.nivel0.net/SmbWebClient
It’s a snap to setup. Download and untar it to a directory in your webservers path, for example, /var/www/samba/. Now open it with your favorite editor and configure for your environment. You’ll probably only need to edit the cfgSambaRoot line. Here is what I’ve set mine to:
@define (‘cfgSambaRoot’, ‘FATLAN/CRM114’);
…to have access to all allowable shares. To limit users to their home shares, change it to:
@define (‘cfgSambaRoot’, ‘FATLAN/CRM114/homes’);
You may want to restrict access to the “Samba” web directory with Apache’s PAM module. See the next section for details.

Apache Integration

To tie Apache in to the mix, you have several options. You can have Apache query the LDAP server on its own, or have Apache use PAM for authentication. I like to use PAM so users on the system that aren’t in LDAP can still have access. Go ahead and apt-get install libapache-mod-auth-pam. (Debian users obviously) The install script doesn’t update the /etc/apache/modules.conf file properly so you are instructed to use “modules-config apache” to add it. I just added this to my modules.conf AFTER the auth_module:
LoadModule pam_auth_module /usr/lib/apache/1.3/mod_auth_pam.so
Now open your /etc/apache/httpd.conf file and add the following stanza:

   
   	AuthPAM_Enabled on
   	AllowOverride None
   	AuthName "User Files"
   	AuthType "basic"
   	require group users

Edit your /etc/pam.d/httpd file to allow it to use PAM. For Debian users add the following ABOVE the current entries:

@include common-auth
@include common-account

You’ll need to create the “Domain Users” group in LDAP and map it to the UNIX users group. Do it like we did the admins group and add it with the “net” command, and use Appendix A for the proper RID.
[root@crm114]# net groupmap add rid=513 ntgroup=”Domain Users” unixgroup=users

Now restart Apache and uses the ldapusers tool to add your users to the proper group. Note: You don’t have to use the groups I did, this is just an example.

Email Integration

My article How To Install Postfix, Amavis, ClamAV, and Spamassassin will guide you through setting this all up. It is written to be PAM enabled so nothing more needs to be done to work with within this framwork.

Summery

As you’ve seen, configuring your system to use LDAP will let you centralize your users and easily leverage the directory for all sorts of services and applications. Next I’ll be using this system and PHP’s robust LDAP functions to build a web-based company directory.

Appendix A – NT Group RIDS

From the Samba docs:

Table 12.1. Well-Known User Default RIDs

Well-Known Entity RID Type Essential
Domain Administrator 500 User No
Domain Guest 501 User No
Domain KRBTGT 502 User No
Domain Admins 512 Group Yes
Domain Users 513 Group Yes
Domain Guests 514 Group Yes
Domain Computers 515 Group No
Domain Controllers 516 Group No
Domain Certificate Admins 517 Group No
Domain Schema Admins 518 Group No
Domain Enterprise Admins 519 Group No
Domain Policy Admins 520 Group No
Builtin Admins 544 Alias No
Builtin users 545 Alias No
Builtin Guests 546 Alias No
Builtin Power Users 547 Alias No
Builtin Account Operators 548 Alias No
Builtin System Operators 549 Alias No
Builtin Print Operators 550 Alias No
Builtin Backup Operators 551 Alias No
Builtin Replicator 552 Alias No
Builtin RAS Servers 553 Alias No