Setting up a Synchronization Solution between ActiveDirectory and OpenLDAP
Introduction
This documentation is quite technically advanced, which is why you need some basic knowledge before attempting it. I recommend reading this documentation first.
For authentication, we want to use an OpenLDAP directory as a cache/backup of an Active Directory (AD) server. Authentication will be performed from different applications and Unix-type machines. The goal is also to be able to continue authenticating in case of an AD crash.
Note: Because objectively, in case of a crash, here are the approximate reinstallation and restore times:
Linux: ~30 min
Windows: ~4 h
The choice is quickly made, and this solution truly holds up. (Pure Windows users who say Windows never crashes can leave now!)
Some other information can be stored locally in OpenLDAP.
To simplify installation on the Unix side (Linux or Solaris), Microsoft SFU is installed on AD, which allows maintaining Unix account information such as gid/uid/homedirectory, shell... (this will modify the AD schema).
To access the user passwords contained in AD (unicodePwd), the connection between the OpenLDAP server and AD will be encrypted via SSL. This is the only way to send requests to AD that touch this attribute. PS: This does not allow reading it, only modifying it.
This document will present the installation for the most advanced configuration. This allows you to have an independent OpenLDAP server with content synchronized in different ways: by a Python script for all attributes of all entries, by SSOD for Unix and Samba passwords, and by PAM for Unix and Samba passwords.
However, the code provided in this file is not portable and does not work on 64-bit systems... I had to modify these sources to make it portable.
Windows
For Windows, you need a DNS server, a configured AD, and the small SFU that you will need to download and install.
During installation, you can perform a custom installation and check only:
Password synchronization
NIS server
Then start the installation.
Launch the Unix Services Configuration utility and configure it like this:
Click apply.
Add your OpenLDAP server here:
Click apply.
Then, if you already have a MASTER (like DELL1800 here), connect to the utility on the master and add it. Otherwise, if this server must serve as the master, add it in this MMC:
Click apply.
Then you'll need to reboot and you're done.
Clients
Configuration
Server
slapd.conf
For the following information
Edit the configuration file /etc/ldap/slapd.conf and add these lines:
# Schema and objectClass definitionsinclude/etc/ldap/schema/core.schema
include/etc/ldap/schema/cosine.schema
include/etc/ldap/schema/nis.schema
include/etc/ldap/schema/inetorgperson.schema
include/etc/ldap/schema/microsoft.schema
include/etc/ldap/schema/microsoft.sfu.schema
include/etc/ldap/schema/microsoft.exchange.schema
# For sambainclude/etc/ldap/schema/samba.schema
So here we have the schemas so that OpenLDAP can recognize the different Microsoft attributes. We also include Samba (because we also want to integrate Samba with OpenLDAP).
The Samba schema is in /usr/share/doc/samba-doc/examples/LDAP and should be copied to /etc/ldap/schema, but first you need to install a package for Samba:
# The base of your directory in database #1suffix"dc=openldap,dc=mydomain,dc=local"# rootdn directive for specifying a superuser on the database. This is needed# for syncrepl.rootdn"cn=admin,dc=openldap,dc=mydomain,dc=local"rootpw{SSHA}V2c83+XHO/DNrUjeNjyTwAA9W+yKm/4h
accesstoattrs=userPassword,shadowLastChange
bydn="cn=admin,dc=mydomain,dc=local"write
byanonymousauth
byselfwrite
by*none
accessto*
bydn="cn=admin,dc=openldap,dc=mydomain,dc=local"write
by*read
#######################################################################databasemeta
suffix"dc=ad,dc=mydomain,dc=local"uri"ldap://192.168.0.30/dc=ad,dc=mydomain,dc=local"suffixmassage"dc=ad,dc=mydomain,dc=local""dc=mydomain,dc=local"rootdn"cn=admin,dc=ad,DC=mydomain,DC=local"# local admin accountrootpw{SSHA}V2c83+XHO/DNrUjeNjyTwAA9W+yKm/4h# local password#acl-authcDN "CN=Administrateur,CN=Users,DC=mydomain,DC=local"#acl-passwd {SSHA}V2c83+XHO/DNrUjeNjyTwAA9W+yKm/4haccesstoattrs=userPassword,shadowLastChange
bydn="CN=Administrateur,CN=Users,DC=ad,DC=mydomain,DC=local"write
byanonymousauth
byselfwrite
by*none
accesstodn.base=""by*read# The admin dn has full write access, everyone else# can read everything.accessto*
bydn="CN=Administrateur,CN=Users,DC=ad,DC=mydomain,DC=local"write
by*read# Save the time that the entry gets modified, for database #1lastmodon
cachesize20directory/var/lib/ldap/real-ad
indexobjectClasseq
indexcn,sn,uid,mailpres,eq,sub
Schemas
We'll copy the schemas to the right place. Download the archive: Microsoft Schemas
The advantage of SSOD is that password synchronization is done in real time. This synchronization can be done via PAM, which allows updating any backend or password type (LDAP, shadow, Samba, Kerberos, ...)
This last point is very interesting for synchronizing passwords for Samba servers that use their own LDAP attributes to store passwords. Indeed, we can use both pam_smbpass and SSOD to fill the sambaNTPassword, sambaLMPassword and other associated attributes when a password is changed on the AD server.
SSOD compilation The SSOD utility provided by Microsoft does not work in 64 bits. I therefore had to modify the source code, and it is this modified version that should be used.
Configuration
To compile SSOD, the packages g++ and libpam0g-dev must be installed:
Copy the binary obtained after compiling to /usr/bin/ssod on the server where OpenLDAP is installed. Download the file ssod-conf.tgz to /tmp and decompress it while in the root directory:
SYNC_HOSTS must contain the name or IP address of the AD server with which you want to synchronize.
ENCRYPT_KEY must be identical to what is indicated in the SFU configuration on the AD server.
PORT_NUMBER must contain the port number used by SFU on the AD server.
With this configuration file, SSOD is configured to update passwords using PAM. So you need to create a file corresponding to the SSOD service in the PAM configuration directory (/etc/pam.d). A priori, this file is a copy of /etc/pam.d/passwd. So:
/etc/pam.d/ssod normally contains an include directive for the file /etc/pam.d/common-password-ldap. The content of the latter varies according to the desired functionality. A priori it should reference the pam-ldap and possibly pam-smbpass modules.
Once the installation of SSOD and the various PAM modules necessary for your configuration is complete, you can verify that the SSOD daemon is working correctly by modifying a password on AD and checking the file /var/log/auth.log on the server where SSOD is running. You should see a line like:
Successfully updated password via PAM User: dummyuser
for each changed password.
Configuration libpam-ldap and libnss-pam
Refer to the chapter of the same name in the client configuration part concerning the files /etc/nsswitch.conf, /etc/libnss-ldap.* and /etc/pam_ldap.conf
Configuration/use of libpam-smbpass
For this module to work, you must configure libnss-pam, otherwise the execution of pam-smbpass.so will end with a core dump :(. This module must be able to find the information of users and/or groups that are in the LDAP directory.
The file /etc/samba/smb.conf must be configured to use the LDAP backend. See the chapter relating to the Samba configuration.
Libpam-smbpass allows authentication using the sambaNTPassword and/or sambaLMPassword attributes. It also allows updating these attributes when the password is changed or when a user logs in after being authenticated by a third-party module (pam_ldap for example). It is these last two functionalities that particularly interest us. Indeed, to be able to authenticate with Samba servers, these attributes must be filled and these are a priori the only ways to fill them.
To synchronize Samba passwords from those contained in the LDAP directory when a user authenticates, you must modify the file /etc/pam.d/common-auth-ldap. It should contain:
To modify Samba passwords when a user changes their password on AD or on a Unix machine, you must modify the file /etc/pam.d/common-password-ldap. It should contain:
Now at the crontab level, we'll add a small script that will allow us to do the sync. Edit the script and modify it according to your needs: AD import script
Put the script archive somewhere and decompress it:
You can edit the script and modify the following variables:
LOGLEVEL: contains an integer. The larger the integer, the more verbose the script is
GENLDIF: 0 or 1. If it's 1, the script generates an LDIF file containing the modified LDAP entries intended for the OpenLDAP server
SYNCHRONIZE: 0 or 1. If it's 1, the script directly modifies the entries on the OpenLDAP server
LOGSTDOUT: 0 or 1. If it's 1, the script displays its messages on standard output.
FULLSYNC: 0 or 1. If it's 1, the script retrieves all entries contained in AD, otherwise it only retrieves those that have been modified since the last synchronization (incremental). If you change the source AD server (or do a complete sync), you must either set this variable to 1, or set the uSNChanged attribute of the base DN in your OpenLDAP directory to 0.
src*: various parameters to connect to the source server.
srcuri: URI of the source server
srcadmin: DN of the user used for replication
srcpassword: his password
srcbasedn: the base of the hierarchy to synchronize.
dst*: same as above but for the target server
dstsamba: where to store info about the samba domain.
Then we add it to the crontab and run it every 10 min:
In general, Unix clients can authenticate using the information contained in the LDAP directory via PAM and NSS. So you just have to install and configure these components on the different systems.
Debian
You have the choice of installing libpam-ldapd or libpam-ldap. libpam-ldapd is newer and avoids some bugs seen in libpam-ldap. It's up to you to decide what you want :)
libpam-ldapd
If you opt for libnss-ldapd, then you simply need to install this and answer the questions.
If you have chosen to install libpam-ldap instead of libpam-ldapd, you will need to do this manually.
By default, debian creates two different configuration files for libpam-ldap and libnss-ldap. This is unnecessary since these two files will contain the same thing. You need to delete the libpam-ldap configuration files and create links from those of libnss-ldap to those of libpam-ldap:
In /etc/libnss-ldap.secret, indicate the password of the user indicated on the rootdn line of the file /etc/libnss-ldap.conf.
You must then modify the file /etc/nsswitch.conf to indicate that the search will be done among others in the LDAP directory for the different services. This gives for example:
Finally, you need to modify the PAM chains so that they allow authentication via the LDAP directory. This is done by copying the different files /etc/pam.d/common-* to /etc/pam.d/common-*-ldap:
Once these common-*-ldap files are created, you can edit the files of the different services for which you want to authorize authentication by LDAP... If for example you want to allow users contained in the LDAP directory to connect via SSH to the machine, you edit the file /etc/pam.d/ssh and replace the common-qqc with common-qqc-ldap.
For automounting partitions according to the user, edit the file /etc/security/pam_mount.conf:
One common method is to only authorize one or certain LDAP groups to access a machine. For this, the groups must have the posixGroup attribute named login.
As on debian, you must also modify the file /etc/nsswitch.conf.
Force a shell at login
If you have PAM authentication via LDAP, it is possible to force a particular shell at login. It will override the information sent by NSS and replace it with the desired shell. We will use lshell here for all people connecting via LDAP:
##ident "@(#)pam.conf 1.28 04/04/21 SMI"## Copyright 2004 Sun Microsystems, Inc. All rights reserved.# Use is subject to license terms.## PAM configuration## Unless explicitly defined, all services use the modules# defined in the "other" section.## Modules are defined with relative pathnames, i.e., they are# relative to /usr/lib/security/$ISA. Absolute path names, as# present in this file in previous releases are still acceptable.## Authentication management## login service (explicit because of pam_dial_auth)#loginauthrequisitepam_authtok_get.so.1
loginauthrequiredpam_dhkeys.so.1
loginauthrequiredpam_unix_cred.so.1
loginauthsufficientpam_ldap.so.1try_first_pass
loginauthsufficientpam_unix_auth.so.1
loginauthrequiredpam_dial_auth.so.1
## rlogin service (explicit because of pam_rhost_auth)#rloginauthsufficientpam_rhosts_auth.so.1
rloginauthrequisitepam_authtok_get.so.1
rloginauthrequiredpam_dhkeys.so.1
rloginauthrequiredpam_unix_cred.so.1
rloginauthsufficientpam_ldap.so.1try_first_pass
rloginauthsufficientpam_unix_auth.so.1
## Kerberized rlogin service#krloginauthrequiredpam_unix_cred.so.1
krloginauthbindingpam_krb5.so.1
krloginauthsufficientpam_ldap.so.1
krloginauthsufficientpam_unix_auth.so.1
## rsh service (explicit because of pam_rhost_auth,# and pam_unix_auth for meaningful pam_setcred)#rshauthsufficientpam_rhosts_auth.so.1
rshauthrequiredpam_unix_cred.so.1
## Kerberized rsh service#krshauthrequiredpam_unix_cred.so.1
krshauthbindingpam_krb5.so.1
krshauthsufficientpam_ldap.so.1
krshauthsufficientpam_unix_auth.so.1
## Kerberized telnet service#ktelnetauthrequiredpam_unix_cred.so.1
ktelnetauthbindingpam_krb5.so.1
ktelnetauthsufficientpam_ldap.so.1
ktelnetauthsufficientpam_unix_auth.so.1
## PPP service (explicit because of pam_dial_auth)#pppauthrequisitepam_authtok_get.so.1
pppauthrequiredpam_dhkeys.so.1
pppauthrequiredpam_unix_cred.so.1
pppauthsufficientpam_ldap.so.1
pppauthsufficientpam_unix_auth.so.1
pppauthrequiredpam_dial_auth.so.1
## Default definitions for Authentication management# Used when service name is not explicitly mentioned for authentication#otherauthrequisitepam_authtok_get.so.1
otherauthrequiredpam_dhkeys.so.1
otherauthrequiredpam_unix_cred.so.1
otherauthsufficientpam_ldap.so.1
otherauthsufficientpam_unix_auth.so.1
## passwd command (explicit because of a different authentication module)#passwdauthrequiredpam_passwd_auth.so.1
## cron service (explicit because of non-usage of pam_roles.so.1)#cronaccountrequiredpam_unix_account.so.1
## Default definition for Account management# Used when service name is not explicitly mentioned for account management#otheraccountrequisitepam_roles.so.1
otheraccountrequiredpam_unix_account.so.1
## Default definition for Session management# Used when service name is not explicitly mentioned for session management#othersessionrequiredpam_unix_session.so.1
## Default definition for Password management# Used when service name is not explicitly mentioned for password management#otherpasswordrequiredpam_dhkeys.so.1
otherpasswordrequisitepam_authtok_get.so.1
otherpasswordrequisitepam_authtok_check.so.1
otherpasswordrequiredpam_authtok_store.so.1
## Support for Kerberos V5 authentication and example configurations can# be found in the pam_krb5(5) man page under the "EXAMPLES" section.#
Configure the file /etc/nsswitch.ldap
Leave "ldap" only where it's useful: for now on the passwd: and group: lines. For the rest, put the content of the file /etc/nsswitch.dns. Which gives:
## Copyright 2006 Sun Microsystems, Inc. All rights reserved.# Use is subject to license terms.### /etc/nsswitch.dns:## An example file that could be copied over to /etc/nsswitch.conf; it uses# DNS for hosts lookups, otherwise it does not use any other naming service.## "hosts:" and "services:" in this file are used only if the# /etc/netconfig file has a "-" for nametoaddr_libs of "inet" transports.# DNS service expects that an instance of svc:/network/dns/client be# enabled and online.passwd:filesldap
group:filesldap
# You must also set up the /etc/resolv.conf file for DNS name# server lookup. See resolv.conf(4).hosts:filesdns
# Note that IPv4 addresses are searched for in all of the ipnodes databases# before searching the hosts databases.ipnodes:filesdns
networks:files
protocols:files
rpc:files
ethers:files
netmasks:files
bootparams:files
publickey:files
# At present there isn't a 'files' backend for netgroup; the system will# figure it out pretty quickly, and won't use netgroups at all.netgroup:files
automount:files
aliases:files
services:files
printers:userfiles
auth_attr:files
prof_attr:files
project:files
tnrhtp:files
tnrhdb:files
Once that is done, we will be able to set up the configuration. Warning: if you are in a cluster environment, adapt to the initial configuration!:
Attention: it seems that the ldapclient command is buggy and requires the proxyDN and proxyPassword parameters even if they are unused! (and even if they contain anything).
## Copyright 2003 Sun Microsystems, Inc. All rights reserved.# Use is subject to license terms.## ident "@(#)auto_home 1.6 03/04/28 SMI"## Home directory map for automounter#+auto_home
*localhost:/export/home/&
In case you want to automatically create the home directory, you must port the pam_mkhomedir from Linux: