LDAP user authentication.

LDAP (Lightweight Directory Access Protocol) is a centralized way of keeping track of user passwords and "stuff". LDAP keeps track of basically all the information that a person would "in the good old days" have gotten from the /etc/passwd file on their local machine.

There have been a score of such schemes, and it is unlikely that this is the last. We had kerberos, Yellow Pages, NIS, and so forth, now LDAP. There is no denying that if you have a fair sized user community and many machines, such a scheme will make your life simpler. Maybe. It also puts all your eggs in one basket and when something goes wrong, lots of machines are affected.

Using LDAP once it is set up

Adding a new user:

You create the user in the usual non-LDAP way, then migrate them to LDAP (well, this is one way to do it).
useradd -u 555 -c "John Doe" jdoe
passwd jdoe
ldapusermigrate jdoe

The ldapusermigrate script (csh) is as follows:

set username = jdoe
setenv LDAP_BASEDN dc=myserver,dc=mydomain
grep "^${username}:" /etc/passwd > /tmp/${username}.passwd
/usr/share/migrationtools/migrate_passwd.pl /tmp/${username}.passwd | ldapadd -ZZ -D "cn=Directory Manager" -y /etc/ldap.secret -x
/bin/rm /tmp/${username}.passwd
grep "^${username}:" /etc/group > /tmp/${username}.group
/usr/share/migrationtools/migrate_group.pl /tmp/${username}.group | ldapadd -ZZ -D "cn=Directory Manager" -y /etc/ldap.secret -x
/bin/rm /tmp/${username}.group
userdel ${username}

Changing a users shell

One way is to use the following csh script:
set newshell = tcsh
set username = jdoe

if (`grep $newshell /etc/shells` != $newshell) then
    echo $newshell not in /etc/shells
    exit
endif

/bin/echo -e "dn: uid=$username,ou=People,dc=myserver,dc=mydomain\nchangetype: modify\nreplace: loginShell\nloginShell: $newshell\n" | ldapmodify -D "cn=Directory Manager" -y /etc/ldap.secret -ZZ -x

Deleting a user in a given domain

To delete the user "jdoe" in domain "myserver.domain":
ldapdelete -ZZ -D "cn=Directory Manager" -y /etc/ldap.secret -x uid=jdoe,ou=People,dc=myserver,dc=mydomain
ldapdelete -ZZ -D "cn=Directory Manager" -y /etc/ldap.secret -x cn=jdoe,ou=Group,dc=myserver,dc=mydomain
After this, manually remove the home directory, mail inbox, and crontabs on all machines.

Adding a new non-user group

groupadd idiots
ldapgroupmigrate idiots
The groupmigrate script (csh) is as follows:
set groupname = idiots
setenv LDAP_BASEDN dc=myserver,dc=mydomain
grep "^${groupname}:" /etc/group > /tmp/${groupname}.group
/usr/share/migrationtools/migrate_group.pl /tmp/${groupname}.group | ldapadd -ZZ -D "cn=Directory Manager" -y /etc/ldap.secret -x
/bin/rm /tmp/${groupname}.group
groupdel ${groupname}

Adding a user to a group

No clue as yet.

Changing a users password

There is a command ldappasswd, but it is not what we want to use, plain old passwd will do the job (see below).

When I do try to use the ldappasswd command as root, I get:

SASL/EXTERNAL authentication started
ldap_sasl_interactive_bind_s: Unknown authentication method (-6)
	additional info: SASL(-4): no mechanism available: 
It turns out this is because ldappasswd defaults to trying to use SASL authentication, which is the wrong thing when you have an OpenLDAP server. There is a "-x" switch to tell it not to use SASL, but never mind all of this.

The story is that the good old passwd command is LDAP aware and can be used in the same way it always has been, both by individual users on any machine, and by root also, but with some limitations.

When root tries to change a users password on an LDAP client machine, root must have that users existing login password. So, if root has no clue what the users password is (the usual case is that a user has forgotten his password and root never knew it in the first place), root must change the password on the LDAP server machine.

Linux and LDAP

In the ever changing linux landscape you once used openLDAP to do LDAP. I think openLDAP replaced some prior scheme, but it has in turn now been replaced by a set of packages called "389", presumably named after the LDAP port number.

A number of LDAP related things have assigned ports:

The standard LDAP port is 389.
The secure (SSL) LDAPS port is 636.
The Administration Server port is 9830. 

TLS is another acronym that pops up right away in this LDAP business. TLS stands for "Transmission Layer Security". It is apparently a standardized form of SSL.

SSL was initially a Netscape protocol, then it went through a standardization process and now is called TLS (Transmission Layer Security). It is commonly referred as SSL/TLS.

Setting up an LDAP server

I have not yet had to deal with setting up an LDAP server. All I know at this point is that you probably want to set up more than one machine to be an LDAP server, so that if one machine goes down, all the machines on your network are not hamstrung.

As near as I an tell, the name for the LDAP service currently in vogue is "dirsrv" (even in the "389" scheme of things. Therefore, if you want to start (or restart) the LDAP service, you do:

service dirsrv restart
Note that you only do this on an LDAP server. This runs the executable /usr/sbin/ns-slapd, but anyone would have known that.

There is also something called dirsrv-admin, but I don't have a clue what it is, you might also want to start it (or maybe you wouldn't):

service dirsrv-admin restart

Setting up an LDAP client

I first tried working with LDAP under Fedora 11, and was immediately bitten by an "issue" (a policy change actually). Apparently as of Fedora 11, the root user is not allowed to login from the console if X is running. Root login via ssh or from a text console is fine (use a virtual console or telinit 3 if you are desperate). I guess there are too many X based security issues and it was felt that the root password was too sensitive or some logic like that. I am pretty sure this was straightened out to my liking by hacking on some file in the /etc/pam.d directory, but I cannot remember.

The file /etc/nsswitch.conf governs whether LDAP or files or who knows what gets used. The relevant lines are:

	#passwd:     files ldap
	#shadow:     files ldap
	#passwd:     files ldap

	passwd:     files
	shadow:     files
	group:      files
The first group of lines, if enabled, would first try to find a user in the passwd/shadow files, and if that failed use ldap. The second group of lines are the "good old way" using passwd and shadow files only.

LDAP configuration

Take a look at /etc/openldap/ldap.conf.

The actual user and group information is kept in a database. You use the ldapadd, ldapdelete, and ldapmodify commands to make changes. There are nice long intricate man pages for all of these, with more options than you can shake a stick at. I am told that these commands are really useful for non-priveleged users to make changes to things that they are allowed to change.

Apparently under ldap, there is an "identity" refered to as the "directory manager" which is allowed to do any kind of fiddling with LDAP entries, and which/who has its/his/her own password.

Low user ID numbers

For a variety of reasons, at my site we have many users with uid numbers less than 500, even as low as 104. LDAP performs a number of tests that invalidate logins for uid numbers less than 500, and so at my site, we must change this threshold to 100. The usual symptom is that after a system update, a subset of users (those with user id numbers less that 500) can no longer use their passwords to login.

Note that ssh authentication using key encryption is not affected. Even though I am one of these low numbered users, I never get hit by the problem because my desktop is not part of the PAM/LDAP world, and I jump from there to other systems using ssh keys. This means that I don't get tripped up by this issue until I am sitting at one of these machines and trying to log in at the console.

What is happening is that system updates are wrongly overwriting files in the /etc/pam.d directory. PAM is the "pluggable authentication module" system, which is a generic "tap" to insert whatever flavor of authentication you might presently be enamoured with. The files that usually get screwed up are:

The file: password-auth controls gdm logins in particular.
As near as I can tell, the file system-auth is a global kind of thing.

getent

There are times when you find yourself wondering about things you once answered by poking around in the /etc/passwd file. With ldap, all the information is no longer in the passwd file. The ldap information augments the password file. You use the getent utility instead (and this works for both file and ldap, i.e. it will always work, so it is the sensible thing to build into scripts).
Have any comments? Questions? Drop me a line!

Adventures in Computing / tom@mmto.org