« Autoset SSH GSSAPIDelegateCredentials on MacOS X | Main | Add a free, signed SSL certificate to Leopard Server »

Connecting 10.5 to Stanford's LDAP

On the Libraries’ cluster computers we need to allow Stanford people to log in with their SUNet IDs and passwords. This means that we need to authenticate against Stanford’s LDAP server. Previous documents have described how to do this for 10.4, and this document will cover the much easier process for 10.5.

In addition, we will be covering how to auto-mount the users AFS home directory as their home directory.

Note: Auto-mounting the home directory can cause problems if your users move back-and-forth between OS versions. You should be aware of this potential problem.

A few notes before we begin:

  1. I am assuming that if you are going to use that AFS is already setup. The easiest way of doing that is to use the Stanford installer for OpenAFS (found on http://www.stanford.edu/services/openafs/).
  2. If you have not installed the Stanford OpenAFS package, then you need to configure Kerberos to work correctly on Stanford’s network (the users’ passwords are verified through Kerberos).
  3. You must be an admin on this computer. That is a bit of a silly requirement, as this is not a useful process for an individual’s computer.
  4. I am assuming that this computer has not otherwise been setup for Directory Authentication. If that is not true then you will need to do more work, and should not be using this guide for anything other than reference. This goes doubly for computers that are bound to an Active Directory domain.
  5. This will be covering both using the users AFS home directory, and using a local home directory. The local one is the easier of the two and is mostly maintenance free. But if you do use the AFS directory as the home directory pay attention to the entire setup instructions, and realize that that option requires more maintenance as things will break.

Binding to LDAP:

As of 10.5 is it now very easy to bind to the Stanford LDAP server. It is now a generic process, almost without any custom configuration. We will be using the GUI for this, but in theory the command line could be used as well.

Binding to LDAP - the GUI way:

Step 1: Open “Directory Utility” (/Applications/Utilities/Directory Utility), and click on the padlock icon in the lower left-hand side. This will prompt you for your admin password. Once you have supplied this you should have something like this:


If you don’t have the icons along the top of the window, then click on the “Show Advanced Settings” button.

Note: If you are already bound to a server (there is anything other than “No Direcory Server Configured” in the window), especially if you are bound to an Active Directory server, then you will probably need to do more work than is in this walk-though.

Step 2: Because Stanford is not using an Apple or Microsoft server (this is not a bad thing), we will need to use the “Advanced” configuration utility. To do this, click on the “Services” icon at the top of the Window. This should bring you to a window that looks like this:


Step 3: LDAPv3 should default to being on, and so we can double-click on it to configure a server. That should bring out a sheet like this:


Click on the “New…” button. This will bring up another window asking you to create a new LDAP connection.

Step 4: In this new window enter in “ldap.stanford.edu”, and leave the check-boxes as they start out: “Encrypt using SSL” must be unchecked, and “Use for authentication” checked. The other checkbox (Use for contacts) decides whether Stanford people will automatically appear in AddressBook.app when searched for. I prefer to leave this checked, but things will work either way. At the end of this you should have something that looks like this:


Step 5: Once you have entered this in, and clicked “Continue” it will ask you for one more piece of information:


The template you should pick is “RFC 2307 (Unix)”, and the searchbase should already be set correctly (“dc=stanford,dc=edu”). Once you hit “Continue” it should work for a few seconds, and the “Continue” button should become an “OK” button. Hit this “OK” button, and it will take you back to the second screen you were on.

It will now allow you to name your new LDAP connection, and I would suggest using “Stanford LDAP”. This is not necessary, and will only show up in this screen:


Step 6: You now have most of a working connection, and people can log in this way, but their login will hang in the middle of logging in because by default this system will try to use the users AFS space as their home directory. Here we have a choice: we can either change their settings so that they don’t use the AFS directory, or we need to finish setting up a connection to the AFS server. You will need to choose one of the following two options:

Changing the home directory away from AFS

If you don’t want to use the users AFS home directory as their home directory on this computer then we need to decide where their home directory will be. There are many options, but we will be covering two simple ones:

  1. Each user gets their own home directory on the computer, and everything gets saved - this option is ideal if you have a fixed number of users logging into the machine, but once you get a lot of different users, it becomes unwieldy.
  2. All users share a single home directory - this is a little more work, but is a good one for a Kiosk-style machine.

Each user gets their own home directory

This option is similar to Apple’s “mobile users” concept, with the exception that we are not going to cache the user information on the computer. We are going to have the system auto-create a home directory for each user in the /Users directory, and name it with their SUNet ID. This should insure that no two users ever wind up in the same home folder. To do this we are going to start where we left off, Directory Utility.app’s “Advanced” LDAP pane.

Step 1: In the LDAP pane select the “Stanford LDAP” line that we created, and click on “Edit…”. This should bring up the configuration page. Switch tabs to the “Search & Mappings” tab, and it should look like this (I have made the window a little bit bigger):


Step 2: In the “Record Types and Attributes” area expand the “Users” item, and highlight the “NFSHomeDirectory” item. This should have defaulted to “homeDirectory”, but since that value in LDAP is a afs path, we want to change that. Double click on “homeDirectory” and change it to “#/Users/$uid$”. This will “statically” map the NFSHomeDirectory (where the user’s home folder should be) to a folder named with the user’s SUNet ID, inside of the /Users folder. You might also notice that as you make this change the “Access this LDAPv3 server using” to “Custom” (it was “RFC 2307 (Unix)”). The window should now look like this:


Once you click on “OK” on a couple of screens, you are complete. You might want to check out the general outline of the “Managing MCX Settings” section below for some ideas, and you should probably check out the “Troubleshooting” section as well (on general principal). But at this point you should be able to log out, then back in as an LDAP user.

Sharing a common home directory

A common way of managing a computer that people only log onto occasionally (or maybe only once) when you don’t want to have a network home directory (like AFS), is to have everyone share the same home directory, and then clean up that directory between users. This requires a three tricks to work:

  1. Change the home directory information that is coming out of LDAP
  2. Change the user-id value so that you don’t get permissions issues sharing the same home folder (this is bad in some ways, but for a limited use computer like a Kiosk this is acceptable)
  3. Create a loginscript that will clean up the changes someone might have made to the home folder.

The first item is remarkably similar to the the process in the “Each user gets their own home directory” section above (please reference that). The only real change is that the value you need to change the “NFSHomeDirectory” to be is “#/Users/LDAPUser” (actually, anything that will not collide with other users who might use this computer will do, but that is the one I am using for this walk-through). Once you have this setup it should look like this:


We will stay in the LDAP Mapping window for the second item, but we will switch to edit the “UniqueID” property (also under the “User” item), and change this to be “#900”. Note that this can be any positive integer number. I am choosing 900 for this walk-through because it is far enough above the range that local users use (they start with 501), well above the reserved range for non-person users (under 500), but not yet up to the range that Apple’s OpenDirectory uses (starts at 1025). You might have to adjust this number to taste, or to not collide with a range that is in use at your location. The filled out window looks like this:


The third and final part of this portion of the walk-through is a little more complicated. It involves three items itself:

  1. Create a user directory that will be used as the template directory
  2. Create a script that will be used on login and logout to make the home directory look like the template directory
  3. Setting that script to fire when someone logs out or logs in

Creating a template user directory

The easiest way of creating a template user directory is to create a user on the computer, and set up that users home directory exactly the way you want it. For this walk-through we will call this user “LDAPUserTemplate”. You can create this user the way you normally create local users on a computer.

There are a few things you might want to do: You might want to change the permissions on folders such as the “Documents” folder to not allow writing. While the method we are using here will allow users to change this, this will get across to most people that they should not be writing things to this computer. Along this line I would also make a background image for this user explaining that everything on this computer gets wiped out when they log out, so they should not save things to it.

Once you have it setup exactly the way you want it, you log out, then back in as an administrative user. We are then going to go in on the command line to edit a few things, and create the user folder for the LDAP users:

  1. Open up Terminal.app
  2. First type in “sudo -s”, this will prompt you for your password, and will get you running as “root” so that you can do more things than usual (but just in this terminal window). Your prompt should change to something like “bash-3.2#”.
  3. Change directories into the LDAPUserTemplate’s home directory (cd /Users/LDAPUserTemplate)
  4. Remove any cache files (rm -R /Users/LDAPUserTemplate/Library/Caches/*)

Now we will create the new home folder that the LDAP users will share. Still in Terminal.app (and still under sudo -s) do the following:

  1. Go to the /Users directory (cd /Users)
  2. Copy the LDAPUserTemplate folder (and all its contents) to a new folder called LDAPUser (cp -R LDAPUserTemplate LDAPUser)
  3. Change the owner of the new LDAPUser folder to be LDAPUser (chown -R 900 LDAPUser)

Note that we used the same number here as we did when modifying the “UniqueID” field in the LDAP mappings.

The login script

The script that we are going to create does one thing only: it makes sure that every time we run it that the contents of the LDAPUser folder exactly mirror those of the LDAPUserTemplate folder, except that everything in the LDAPUser folder should belong to user id 900.

A few notes:

  • We are running this at login. That can take a moment if there were a lot of changes made, but usually does not appreciably add to the login-time.
  • A version that also would run at log-out time could also be done (trading longer log-in for longer log-out), but that might run into permissions problems.
  • This will wipe out the directory every time, so you need to make sure that people know that they can’t save things to this directory and expect to keep them. They will not be in the trash, they will be gone.
  • This will run every time someone logs in, even if they are a local user. Since this will not take much time this should not be an issue in most cases.
  • Loginhooks run as root

So the script should look like this:


templateDir = “/Users/LDAPUserTemplate”;
targetDir = “/Users/LDAPUser”;
targetOwner = 900;

# this script must be run as root, bail if it is not
if [ “$(whoami)” != “root” ]; then
echo “This script must be run as root!”
exit 0;

# here we test to make sure both the directories we are using exist on this system
if [ !-d $templateDir || !-d $targetDir ]; then
echo “Either $templateDir or $targetDir did not exist!”;
exit 0;

# now we use rsync to make the target mirror the template
# note that we are not preserving owner
rsync —quiet —recursive —links —perms —group —delete —extended-attributes $templateDir $targetDir

# and then we make sure everything has the correct owner
chown -R $targetOwner $targetDir

exit 0;

You need to put this somewhere that the system, and for this walk-through I am going to choose to create a folder for it in /Library, specifically /Library/Management. Create that folder, and then create a text file in it with the contents of the script (you need a plain text editor for that). I will name it “LDAPUserCleanup.bash”.

Once you have to script in place you have to make sure it is runable by root, but should make sure that no-one else can change it. This can be accomplished on the command line with these steps:

sudo -s
chown root:wheel /Library/Management/LDAPUserCleanup.bash
chmod 755 /Library/Management/LDAPUserCleanup.bash

Setting the loginhook

There are actually a few ways of making things run at login, but because we need to have this run before the user’s home directory is used, we need to use the LoginHook method. Setting this is actually quite easy, but has us back at the command line for this one command (must be run with sudo -s, or sudo):

sudo defaults write com.apple.loginwindow LoginHook /Library/Management/LDAPUserCleanup.bash

With that you should now have a working LDAP, and reasonably complete setup. I would advise looking at the troubleshooting section below on general principal.

Using the AFS home directory

Using the users AFS home directory is probably the trickiest of all of the options, but the most elegant user experience. There are a number of pitfalls that you have to be aware of, many of them specific to individual computers. As part of this section I will try and list some of them, but this should not be taken as a complete list, and you will have to do a lot of testing. These things are also prone to change/break with changes made to: the AFS system, any updates to the OS, and any updates to the specific programs. So this is best attempted when you have people dedicated to maintaining your images.

Getting a Kerberos ticket

Before we can actually use the user’s AFS directory, we have to make sure that they have a Kerberos ticket. There are two ways of getting them a ticket as part of the login process:

  • Use /etc/authorization and have all login-methods try to get Kerberos tickets
  • Modify the LDAP schema to tell LDAP to use Kerberos to authenticate the user (which will leave the TGT for us to use)

Obviously the second option is the more attractive, and the one to encourage, but here are the directions for both:

Modifying /etc/authorization to get use Kerberos to authenticate

While this is a bit more brutish of an approach, it is the less complicated to setup, and is the tried-and-true one.


Editing the LDAP AuthenticationAuthority attribute


The login hook

The first things you need to do is to create a login-hook that will allow the system to mount the users home directory at login time. Just installing the Stanford AFS installer should have already setup AFS generically, and the login process from above has already gotten your users their Kerberos TGT against the stanford.edu domain, all that is left to do is to call “aklog”. So our login-hook can be relatively simple:

# this script must be run as root, bail if it is not
if [ “$(whoami)” != “root” ];
then echo “This script must be run as root!”
exit 0;
# this will run aklog as the user that loginwindow says is loging in
/usr/bin/sudo -u $1
# we need to always need to exit 0, otherwise the loginwindow will cancel the login
exit 0

You need to put this somewhere that the system, and for this walk-through I am going to choose to create a folder for it in /Library, specifically /Library/Management. Create that folder, and then create a text file in it with the contents of the script (you need a plain text editor for that). I will name it “aklog.bash”. Once you have to script in place you have to make sure it is runable by root, but should make sure that no-one else can change it. This can be accomplished on the command line with these steps:

sudo -s chown root:wheel /Library/Management/aklog.bash chmod 755 /Library/Management/aklog.bash

And then a single command to set the loginhook that must be run with root permissions (sudo):

sudo defaults write com.apple.loginwindow LoginHook /Library/Management/aklog.bash

At this point your users should be able to log in. There are still a number of issues that you need to take care of, but you should take the time to conduct a quick test.

Some of the issues with AFS logins

I am going to try and briefly cover some of the issues that you will have to deal with. Once again this is not meant to be a complete listing, but should get you started:

  • You should deal with the ~/Library/Caches folder - this folder can get very big very fast, and can burn through 200MB on web surfing alone. You should probably map this folder to something local during login, and then purge it at log-out. Luckily everything in this folder is always replaceable.
  • Similarly you should remap the ~/Movies directory. iMovie will happily fill this up with data and exceed your users quota with a single small project. This is a little trickier as the user probably wants the contents of this folder. You might want to look at this at logout, and inform the user that they are about to lose this information.
  • There are applications that will simply fail with any sort of network user. Apple’s “Color” (part of the Final Cut Studio package) is one of these applications. Sometimes there is no work-around.
  • If your user exceeds their AFS quota things will start to go bad (they get slow, and preference lists can start eating themselves). You should probably do something to make sure they know when they go over quota.

Apple has built a nice, extensible system for authenticating users, and we have already taken some advantage of it in this note, but sometimes things go wrong, so you need to understand some of the fundamentals.


At the heart of this system is Apple’s OpenDirectory framework. It is a bit confusingly named because the system is not open-source, and Apple’s LDAP implementation on MacOS X Server is also known as OpenDirectory. So for the rest of this note I will be referring to it by its other name: DirectoryServices.

DirectoryServices is a process that is always running at least one instance on your computer (owned by root, and auto-launched). If you kill off the running process with that name another one will jump up to takes its place within a second or two. It is in charge of figuring out a lot of things, but for this conversation its job is figuring out what users exist on the computer (or can exist on a computer). It does so by working with a list of repositories of users. For a quick overview of where users can come from, take a look at this example of Directory Utility.app’s “Search Policy” pane on a computer that is connected to both an LDAP server, and a ActiveDirectory server:


Quick notes about the items:

  • /Local/Default is the new place to store local users on 10.5. It replaces NetInfo completely.
  • /BSD/local handles all of the Unix/POSIX style users that might exist on the system. This is provided for compatibility reasons, and should generally be ignored.
  • The first two items are grayed out even though I have authenticated. This is because they are always the first two items to be consulted, and cannot be turned off.
  • If the Active Directory domain that you are connected to is in a forrest with multiple domains you might have each one of them listed here. If it is listed, then users from that domain can log in. You can remove them if you wish to not allow them to log in (or add more with the “+” button)
  • This is the complete list of places that are consulted when trying to log in a user, and they are consulted in order from top to bottom. The first place to match for a user is the one that is used to authenticate that user. So a local user with a login name will always be the one consulted, and will override one on an LDAP connection.

Another, more complete, view on this same information can be found on the command line through the “dscl” program (Directory Services Command Line). As of 10.5 this is a fairly powerful tool, and it is worth reading through the man pages on it (man dscl), as well as looking through it some.

As a quick walk-though that might be useful in troubleshooting:

  1. Open a Terminal.app window and run “dscl” (you do not need to be an admin to do this)
  2. At the new prompt “>” type in “ls” and hit return, you should get a list of the sorts of directories that you are attached to.
  3. Use the “cd” command to change into the LDAPv3 section (hints: this is case-insensitive, and tab-completion works).
  4. Use “ls” to show that you are connected to the “ldap.stanford.edu” LDAP server, and then use “cd ldap.stanford.edu/Users” to get into the users section of that server.
  5. You could just “ls” to get a list of users, but since there are so many that is going to return just the first group. Rather than that use “read <you SUNet ID> RecordName” to get a list of all the different things that the loginwindow would accept to have you log in.
  6. Then use “quit” to get back to the regular command prompt.

This should look something like this:


There is a wealth of information available from the different directory servers available through this interface, and you would be well advised to be comfortable with the information in here.

Troubleshooting DirectoryServices connections

At some point you might need more information for troubleshooting a complicated problem, and want to see the stream of events that DirectoryServices goes through. While this is not for the faint-of-heart, and is very difficult ot interpret the output sometimes, you can tell DirectoryServices to log everything by issuing this command:

sudo killall -USR1 DirectoryServices

This will start logging everything to /Library/Logs/DirectoryService/DirectoryService.debug.log. Issuing the same command a second time (or rebooting) will stop this waterfall.


This is obviously a lot of information, but I hope it has been helpful. Please send any feedback to larkost@stanford.edu.


TrackBack URL for this entry:

Comments (2)

Steve Nguyen:

Some of the code samples presented here are have some errors. For instance, they have curly quotes rather than standard quotes needed for scripts. Assignment of variable should have no spaces between the = sign. And the boolean expression with OR "||" has incorrect syntax. Be careful!

Steve Nguyen:

Also, the rsync command needs some modifications, the options should have '--' in front of them and the src folder should have a /* after it, as in: $templateDir/* since we want to sync the files in the template dir, not the directory itself into the targetDir

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)


This page contains a single entry from the blog posted on March 12, 2008 3:49 PM.

The previous post in this blog was Autoset SSH GSSAPIDelegateCredentials on MacOS X.

The next post in this blog is Add a free, signed SSL certificate to Leopard Server.

Many more can be found on the main index page or by looking through the archives.

Creative Commons License
This weblog is licensed under a Creative Commons License.
Traffic analyzed by Google Analytics. Site powered by Movable Type 4.32-en