OpenLDAP with Linux and Windows
The "Students" Project at the University of Verona is based on OpenLDAP (it's an open-source implementation of LDAP) for managing the centralized authentication of both Windows and Linux laboratories, as well as mail accounts for professors and students from all departments (use of Qmail, Courier and Imp). The "Students" server manages five laboratories: the alpha laboratory (only Linux workstations), the beta laboratory (only Linux workstations), the gamma laboratory (only Windows 2000 workstations), the delta laboratory (Linux and Windows 2000 system, workstations have two different boots) and the tesi laboratory (only Linux workstations).
Two different problems emerged: 1) how do we create a database that allows access to PCs with the Linux OS rather than to PCs with the Windows OS? and 2) how do we allow the correlation between a single server and PCs with both Linux and Windows systems?
These problems have been solved by using OpenLDAP and Samba TNG software. A Linux cluster (Red Hat with the Piranha package) manages all the laboratories. Because the server needs to support some heavy work (each student is supposed to have an entry in the database), we have set up the Linux cluster to provide services with continuity.
LDAP (Lightweight Directory Access Protocol) is a directory service that runs over TCP/IP. It is a specialized database optimized for reading, browsing and searching. In many companies, its structure is used to generate a distributed structure. The details of these protocols are defined in RFC 2251.
A directory is a collection pieces of information about objects arranged in some order that provides details about it. It's a specialized database (data repository) that stores typed and ordered information. Directories are accessed to search, or to read, much more often than they are written to; thus, they are optimized systems allowing many queries. They aren't appropriate for storing information that changes frequently. The type of information stored in a directory usually does not require strict consistency. A database uses SQL (Structure Query Language), whereas LDAP uses a simplified and optimized access protocol.
The entries are the primary aspect of LDAP's structure; they are a collection of attributes having a unique ID that is called a distinguished name (DN). The DN allows an optimized and univocal search in LDAP's tree. The class "entry" is composed of a type and values.
The first class is characterized by a mnemonic string that marks an object, such as "mail" for e-mail addresses, "cn" for common name and "sn" for surname. The values attribute is correlated with the type class. In fact, if it refers to the previous type it will have values, such as Francesco for the cn attribute, Tornieri for the sn attribute and francesco.tornieri@duke.it for the mail attribute.
The classical structure of an LDAP scheme is similar to a hierarchical tree. At the bottom of the tree is a "root", and then some branches. The branches of the tree can be states or organizations (i.e., a university department). The leaves of the tree represent the units: students or other. Each unit is marked by attributes that make it different from the others. This structure is similar to the domain space.
The particularity of an LDAP protocol is the possibility to use a special attribute called objectClass. The value of these classes will determine the entry rules of LDAP's scheme. When an entry is inserted into LDAP's hierarchical tree, it's defined by its DN, which is generated by the name of the entry, called the relative distinguished name, or RDN (DN format is described in RFC 2253). An example of this structure may be:
Uid: tmpprova Dn : ou=2001,ou=in,ou=People,ou=Scienze,dc=univr,dc=it
LDAP defines operations to interrogate and update its tree. Operations are divided into add an entry, delete an entry and modify an entry.
From a technical viewpoint, LDAP is a directory access protocol based on X.500 directory service (OSI directory service). It's derived from DAP (X.500 directory service), a heavyweight protocol that operates over an OSI protocol and is required to operate very powerful computers. Unlike DAP, LDAP is designed to operate over TCP/IP and maintains most features of DAP without using its expensive resources.
The "Students" server manages about 250 workstations. LDAP service is based on a client-server model. Server LDAP contains information, and clients connect to it to search information in the hierarchical tree (several server LDAPs can work together to make a better service). When a client makes a query to the server, the server replies by answering the question or suggesting another LDAP server to obtain further information. Some features of OpenLDAP are:
LDAPv2 and LDAPv3: versions of LDAP's scheme. At the University we use scheme v2.
Simple Authentication (Security Layer): it's possible to use strong authentication services to protect transactions between the server and the client (Cyrus SASL software).
Transport Layer Security: it's possible to use OpenSSL software to protect the privacy of students and professors (used in the "Students" Project).
Access Control: the policy of access to LDAP's tree may be based on IP address, domain name or other criteria.
Choice of Databases: LDAP permits us to select the types of databases from different back-end databases, such as LDMB (BerkleyDB or GDBM), SHELL and PASSWD. We use the LDMB (GDBM) database.
Multiple Database Instances: a single server is able to manage different portions of the LDAP tree (using different databases).
Replication: it's possible to configure the LDAP server to maintain replica copies of its database (similar to the DNS structure of single master with multiple slaves).
For more information about the structure of the LDAP service, see OpenLDAP 2.0 Administrator's Guide.
How are the Microsoft workstations correlated to the LDAP Linux server? They use Samba TNG to connect to the LDAP tree. A new version of Samba (3.0) supports protocol LDAP, but it's only available in the experimental mode and its development is still embryonic. Samba TNG, a project to implement the dce*/rcp library, has good support for LDAP, so it allows a greater correlation with LDAP's environment (www.samba-tng.org).
The first step is to obtain and to install a copy of OpenLDAP. You can download it from www.openldap.org. There are two different releases of this package: version 1.2.x and the latest version 2.0.x (my colleague, Dr. Massimiliano Pontarollo, and I have noticed the two versions are not perfectly compatible). The scheme used at the University, built by Dr. Mirko Manea, is based on version 1.2.x.
After downloading the package, unpack it with command:
tar -zxvf openldap-v.tar.gz
Now you need to run configure, make depend, make (I used make test to ensure a correct building of package) and, after obtaining superuser access, make install. Or, if you have no superuser privileges, run:
su root -c "make install"
I also installed the following packages: openldap-devel-1.2.11-15, openldap-servers-1.2.11-15, openldap-1.2.11-15, nss_ldap-172-2, courier-imap-ldap-1.3.12-1.7.2, openldap-clients-1.2.11-15 and auth_ldap-1.4.3-2.
The central file of OpenLDAP is slapd.conf, which usually is located in /usr/local/etc/openldap/slapd.conf (I prefer to install the configuration file in /etc/openldap). It'll be similar to Listing 1.
Listing 1. Sample slapd.conf File
Here are the directives that you'll find in slapc.conf:
include: read additional configuration information from the given file before continuing with the next line of the current file (we have a scheme for UNIX, Qmail, Samba TNG, Lpd and Personal).
schemacheck: scheme checking on (the default is off).
sizelimit: specifies the maximum number of entries to return from a search operation.
loglevel: specifies the level at which debugging statements and operation statistics should be syslogged.
pidfile: the name of a file that will hold the slapd server's process ID (without the debugging command).
argsfile: the name of a file that will hold the slapd server's command-line options (without the debugging command).
database: marks the beginning of a new database instance definition. Database type should be one of ldbm, shell or passwd, depending on which back end will serve the database.
suffix: the DN suffix of queries that will be passed to this back end.
database: multiple suffix lines can be given, and at least one is required for each database definition.
rootdn: the DN of an entry that is not subject to access control or administrative limit restrictions for operations on this database.
rootpw: the password (or hash of the password) for the rootdn. This option accepts all password formats known to the server, including {SHA}, {MD5}, {CRYPT} and clear text. Clear-text passwords are not recommended.
directory: the directory where the LDBM files containing the database and associated indexes live.
index { <\attrlist> | default } [ pres,eq,approx,sub,none ]}: specify the indexes to maintain for the given attribute. If only an <\attr> is given, all possible indexes are maintained.
access to: grant access (specified by <\accesslevel>) to a set of entries and/or attributes (specified by <\what>) by one or more requestors (specified by <\who>).
So we've created a configuration file of an LDAP server. How can the client connect to LDAP's tree? It's easy. Edit the /etc/ldap.conf file and define LDAP nameservice, switch library and LDAP PAM modules:
host ldaps.sci.univr.it dc=univr,dc=it pam_filter objectclass=account pam_login_attribute uid ssl no pam_password md5
The ldap.conf configuration file is used to set system-wide defaults to be applied when running LDAP clients, so we add the following directives (it's in the LDAP configuration file):
BASE dc=univr,dc=it HOST ldaps.sci.univr.it
where the attribute BASE is used to specify the default base DN to use when performing LDAP operations. The base has to be specified as a DN in LDAP format, and HOST is used to specify the name of the LDAP server to which the LDAP library should connect. A user authentication is then needed to permit the exchange of information between the clients and the server. All information usually is contained in passwd, shadow and group.
OpenLDAP, to enable exchange, uses the Name Service Switch. It uses a common API and a configuration file /etc/nsswitch.conf. The configuration file looks like this:
passwd: files ldap shadow: files ldap grou group: files lda protocols: files ldap services: files ldap netgroup: files lda automount: files ldap
Listing 2. A Query to the LDAP Tree
I can make a query to the LDAP tree, as shown in Listing 2, so it implements the maps above using LDAP. Remember that optimizing service is important for several reasons:
ACL syntax and structure--poorly written ACLs will make the biggest impact on performance.
Proper indexing will improve performance dramatically. An occasional slap index is a good thing too (eq, pres and sub).
Code efficiency. Good queries are fast and efficient. Don't do any iterative queries (if possible), especially those ones that are on non-indexed attributes and require a lot of ACL checks.
Socket resources.
Client buffering and caching settings (nscd, cachesize and dbcachesize).
One of the sets of operations supported by LDAP is the interrogation operation, which accesses the directory for data. It uses the search filter, which is quite flexible. LDAP search filters include, for example, equality, substring and presence. Indexes generally are used to improve the performance of searches.
It now should be clear how to use indices. Create index types that match the types of searches being performed. Conveniently, the OpenLDAP index types map exactly onto the LDAP server. If clients are going to do a lot of trailing substring searches on the cn attribute type, you probably will want to generate an index exactly for this type of search. Add the following line to your slapd.conf file: index, cn, subfinal. Then use the slap index utility to regenerate it.
How do we authenticate Microsoft workstations? There are two (similar) methods: the Samba Project (only 3.0 alpha) and the Samba TNG Project. Samba 3.0 alpha supports LDAP only in experimental mode. Many options aren't supported yet, so we have chosen Samba TNG. You can download it via CVS:
cvs -d :pserver:anoncvs@anoncvs.dcerpc.org: /home/cvsroot login (password is "anoncvs") cvs -z3 -d :pserver:anoncvs@anoncvs.dcerpc.org: /home/cvsroot co tng
Then install it:
./configure --prefix=/usr/local/tng --with-ldap make all install
We have defined the schema of samba in slapd.conf with the directive:
include /etc/openldap/sambatng.schema-v2
This contains some specific attributes (the configuration schema is different if you using OpenLDAP v3):
objectclass sambaAccount objectclass sambaGroup objectclass sambaBuiltin objectclass sambaAlias objectclass sambaConf
Listing 3. An LDAP Object Class for a User's Account on the Samba Server
Listing 4. Adding Basic Users to the LDAP Tree
We insert the sentences as shown in Listing 3. You have to add the next basic users in your LDAP tree, as shown in Listing 4. After this, you'll be able to create a standard group. (You can see an example of this at www.mami.net/univr/tng-ldap/howto/builtin.ldif.depreciated). You should remember to create "users" and "groups" records where it is necessary to specify RID and SID. SID is an NT security ID, and RIDs are like UIDs in UNIX. Within the TNG directory, create:
private: create the file "ldappassword"; put the LDAP password here in clear text (it's needed to bind to the LDAP tree).
profile/default: create a mandatory profile (rename NTUSER.DAT as NTUSER.MAN; it was created the first time you logged in to a Windows system). Be careful: user template has to be the owner of this file.
netlogon: this directory contains your policy templates.
In the smb.conf file add:
ldap suffix = "ou=Students,dc=sci,dc=univr,dc=it" ldap bind as = "uid=root,dc=sci,dc=univr,dc=it" ldap passwd file = /usr/local/tng/private/ldappasswd ldap server = localhost ldap port = 389 ldap scope = sub
If you use this structure you'll have three different passwords; they are maintained in sync. (Dr. Mirko Manea has created a useful script that you can download from www.mami.net/univr/tng-ldap/howto/ldapsync.pl.) It's necessary to generate a password for user "Administrator", so use the samedit command:
samedit -S . -U root -c 'samuserset Administrator -p my_password'
Finally, create an entry in /etc/passwd for each machine.
Francesco Tornieri graduated in Statistics at the Catholic University Sacro Cuore in Milan, Italy. At the moment, he's working as a freelance consultant for the Department of Computer Science at the University of Verona.