Synchronizing Your Accounts Between Windows and Linux

Microsoft’s Windows Services for UNIX provides a number of services and tools to facilitate integration between Windows and UNIX-based systems. Among these services is Password Synchronization, which allows you keep Windows Active Directoy user accounts in sync with NIS networks or stand-alone UNIX hosts. In this article, we walk through setting up Password Synchronization between a Windows 2000 domain and and a stand-alone Red Hat Linux 8 host using Windows Services for UNIX 3.0. This involves setting up the Windows Password Synchronization server running Windows Services for UNIX, configuring Active Directory groups, and then configuring UNIX systems to plug into the password sync services.

The instructions in the Windows Services for UNIX manual are pretty straightforward and easy to follow. To set up Password Synchronization, you can find the checklist you need to follow in the documentation at Password Sychronization > Checklists > Checklist: Setting up Password Synchronization for use with standalone UNIX hosts. Following the checklist for "Configuring Windows systems" will bring us to the Windows Services for UNIX SFU Password Synchronization console. On this screen, you must check "two-way synchronization" if you want passwords to be updated both ways. additionally, there are a couple highly recommended configuration options to choose at this stage:

Change encryption key. This is the key used to encrypt passwords as they travel across the network between systems.

Enable extensive logging. This logs stuff to the Application event log.

Also on Windows, be sure to copy the Linux host’s /etc/passwd and /etc/group files and add it to the "User Name Mapping" configuration.

On the advanced tab, add the Linux host. You can further configure customized values that are on the default tab for that particular computer, but I left it alone. Repeat this for every Linux host you wish to synchronize passwords with.

There are a couple Active Directory groups used to manage the permissions of password synchronization. Create a new group called "PasswordPropAllow" using the Active Directory Users and Computers console. Only users in this group will be able to propagate their Windows password. I added all the users that I want password synchronization for to this group. If this group doesn’t exist, and the "PasswordPropDeny" group does not exist either, everyone’s password can be synced. By default, my user name was in the PasswordPropDeny group. I just removed the PasswordPropDeny group, since anyone who qualifies for password sychronization needs to be in the PasswordPropAllow group. We’re done configuring the Windows domain controller. Repeat these steps for any additional domain controllers.

Back to the checklist. The items outlined in "Configuring UNIX systems" are easy to follow. You will first install the Password Synchronization single sign-on daemon (ssod) on the Linux computer. This is accomplished by putting ssod daemon in the /usr/bin directory, then copying configuration file as sso.conf in the /etc directory.

Edit the /etc/sso.conf file. Add the domain controller to SYNC_HOSTS with the encryption key specified in the Windows domain controller’s SFU Password Synchronization console. To specify which UNIX users are allowed password propagation, add the user names (except root) to SYNC_USERS Since it’s a standalone host, USE_NIS=0. By default, Linux enables shadow passwords. The USE_SHADOW configuration should be set to 1 and the default location for the shadow password file is /etc/shadow. The sso.conf file should only be readable and writable by root.

Now that we’ve put ssod in the right place and we’ve set up the /etc/sso.conf configuration file, we’re almost finished setting up password synchronization on the Linux box. Right now, if you started up ssod and tried to change a password in Windows and watched it propagate to the Linux host, you’d see this in the domain controller’s event log:

Unable to update password for user.

user = user id

Check if user account is locked, expired or disabled.

That’s because there’s one task left. The Password Sychronization PAM needs to be installed on the Linux box for this to work. The instructions included in the Windows Services for UNIX documentation for Linux "7.0 and 7.1" worked fine for RH 8.

At this point, we’ve successfully set up Password Synchronization and it should be working swimmingly. But let’s turn our attention to one final matter on the Linux side, making sure ssod comes up properly at boot time. This would be a good time to take a closer look at Linux’s system initialization process and learn how to add a run-level script to start a daemon when the system’s run level changes (such as when it boots up).

This is going to be a matter of adding a script to our /etc/init.d directory that contains functions to start, stop and restart ssod. Then, using the chkconfig command, we’ll configure the daemon to start in run levels 3, 4 or 5 and terminate in any other run level.

First, we’ll put the script below in /etc/init.d as ssod.



# chkconfig: 345 88 12

# description: Single Sign On Daemon

# processname: ssod

# Source function libarary

. /etc/rc.d/init.d/functions


start() {

echo -n $"Starting ssod: "

daemon $ssod



[ $RETVAL = 0 ] && touch /var/lock/subsys/ssod

return $RETVAL


stop() {

echo -n $"Stopping ssod: "

killproc $ssod



[ $RETVAL = 0 ] && rm -f /var/lock/subsys/ssod


# See how we were called.

case "$1" in












echo $"Usage: $0 {start|stop|restart}"

exit 1


exit $RETVAL

Let’s see what this script is up to. First of all, following the #!/bin/bash directive that tells the system what interpreter to use, note the comments:

# chkconfig: 345 88 12

# description: Single Sign On Daemon allows Linux to sync passwords wtih a Windows domain

# processname: ssod

With these lines in place, we will be able to run the command:

# chkconfig –add ssod

to start ssod automatically when we boot up or change runlevels. The runlevels we want ssod to run in are specified by the 345 after chkconfig: . The 88 and 12 on the same line specify the priority to start and stop the daemon, respectively.

Next, the the /etc/rc.d/init.d/functions script is imported, which contains functions such as daemon() and killproc(). There are two functions in the ssod script, start() and stop(). As you can see in the case statement, if ssod is called with the "start" argument, as in:

# /etc/init.d/ssod start

then start() is called and likewise with the "stop" argument. Running ssod with the argument "restart" simply calls stop() then start().

The start() function calls daemon() to begin the ssod process. If that’s successful, then it creates an empty file in /var/lock/subsys to signify that it’s running. The stop() function calls killproc() to end the ssod process and then deletes the file in /var/lock/subsys.

This script by itself gives us a convenient way to manually start and stop our daemon. But it does more than that. Specifically, it allows us to automate the starting and stopping of the daemon in the particular runlevels we want and in a particular order relative to other run-level scripts. Once we run the following command:

# chkconfig –add ssod

a number of things happen behind the scenes that determine what happens with our daemon at system start-up or shutdown. Running the chkconfig command with the –add option creates symbolic links in the /etc/rcX.d directories (where X is a number representing the runlevel). With our configuration, it will have created the following symbolic links:








Each of these links point to our original script, /etc/init.d/ssod. When the run-level changes, usually because the system is starting up or shutting down, the /etc/rc.d/rc script is run, which controls most of the services running on the system. The ASCII collating sequence of the symbolic links in the /etc/rcX.d directories drives much of the logic for the /etc/rc.d/rc script. The /etc/rc.d/rc script does the following:

It finds all the links beginning with K (in ASCII collating sequence order), in the /etc/rcX.d directory (where X is the number for the run level we’re entering).

For each link, it checks to see if the subsystem is up. How does it tell if the subsystem is up? By checking for the existence of the file /var/lock/subsys/subsystem. Now we can look back at our /etc/init.d/ssod script and see why we created or removed /var/lock/subsys/ssod in the start() and stop() functions. It’s so /etc/rc.d/rc can behave cleanly if the system is changing run-levels. For example, say we were moving from runlevel 1 to 2. In each of these runlevels, the ssod daemon is not supposed to be up. But if it’s already not running in runlevel 1, there’s no reason to kill the process in runlevel 2.

If the subsystem is up, /etc/rc.d/rc calls the script in /etc/init.d that the link points to, passing the "stop" argument to the script.

It repeats the process for the links in /etc/rcX.d that begin with S, checking to see if the subsystem is already up, and if not, calling the referenced script in /etc/init.d with the "start" argument.

Now, just by looking back at the symbolic links created using the chkconfig command, we can easily tell that our original script, /etc/init.d/ssod, will be run with the "start" argument in runlevels 3, 4 and 5, and it will be run with the "stop" argument in any other runlevel.

Leave a Comment