LDAP System Administration
Page 16
dn: uid=gcarter,ou=People,dc=plainjoe,dc=org
uid: gcarter
cn: Gerald (Jerry) Carter
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
uidNumber: 780
gidNumber: 100
homeDirectory: /home/queso/gcarter
userPassword: {crypt}GoYLwzMD6cuZE
host: queso.plainjoe.org
host: pogo.plainjoe.org
host: tumnus.plainjoe.org
This listing shows that the user gcarter is allowed to access the hosts queso, pogo, and tumnus. To enable pam_ldap's host-checking functionality, you must enable the pam_check_host_attr parameter in ldap.conf:
## Enable host attribute lookups.
pam_check_host_attr yes
If the list of hosts does not contain the hostname of the system that the user wants to access, he is denied access. If the host list is empty (i.e., no host attribute is present), the user is denied access by default.
Netgroups
Netgroups have become a daily staple for NIS administrators. They allow machines and/or users to be collected together for various administrative tasks such as grouping machines together for use in the tcp_wrappers files /etc/hosts.allow and /etc/hosts.deny . In this next example, you restrict access via ssh only to members of the sysadmin netgroup:
# /etc/hosts.deny
sshd: ALL
. . .
# /etc/hosts.allow
sshd: @sysadmin
Netgroups can be composed solely of individual hosts:
sysadmin (garion.plainjoe.org,-,-)(silk.plainjoe.org,-,-)
or other netgroups:
all_sysadmin sysadmin secure_clients
or of any combination of the two.
RFC 2307 describes the structural nisNetgroup object class (Figure 6-7), which can be used to represent netgroups as directory entries. The cn attribute holds the name of the netgroup, the nisNetgroupTriple attribute stores the (host, user, NIS-domain) entries, and the memberNisNetgroup attribute stores the names of any nested netgroups.
Figure 6-7. nisNetgroup object classes
Before adding any netgroup entries to the directory, you must create the container ou. By convention, I will use the ou=netgroup organizational unit for storing netgroups in this example:
dn: ou=netgroup,dc=plainjoe,dc=org
objectclass: organizationalUnit
ou: netgroup
After passing through PADL's migrate_netgroup.pl tool, the sysadmin netgroup will be represented by this LDIF entry:
$ ./migrate_netgroup.pl /etc/netgroup
dn: cn=sysadmin,ou=netgroup,dc=plainjoe,dc=org
objectClass: nisNetgroup
objectClass: top
cn: sysadmin
nisNetgroupTriple: (garion.plainjoe.org,-,-)
nisNetgroupTriple: (silk.plainjoe.org,-,-)
The all_sysadmin netgroup contains the sysadmin and the secure_clients netgroups, so it will use the memberNisNetgroup attribute:
dn: cn=all_sysadmin,ou=netgroup,dc=plainjoe,dc=org
objectClass: nisNetgroup
objectClass: top
cn: all_sysadmin
memberNisNetgroup: sysadmin
memberNisNetgroup: secure_clients
After adding these entries to your directory, you must configure the nss_base_netgroup parameter in /etc/ldap.conf to use the correct search suffix:
## /etc/ldap.conf
##
## Configure the search parameters for netgroups.
nss_base_netgroup ou=netgroup,dc=plainjoe,dc=org?one
Finally, you must inform the the operating system to pass off netgroup queries to the LDAP directory by updating the netgroup entry in /etc/nsswitch.conf:
## /etc/nsswitch.conf
## . . .
netgroup: ldap
The getent tool can be used to query NSS for specific netgroups by giving the group name as a command-line parameter:
$ getent netgroup sysadmin
sysadmin (garion.plainjoe.org,-,-)(silk.plainjoe.org,-,-)
It would also be a good idea to verify that the /etc/hosts.allow listed in the beginning of the section obeyed the netgroups membership by actually attempting to log on to the machine using ssh from a host other than garion or silk.
There are many services that can use netgroups. The tcp_wrappers security package is only one example. Another frequent use of netgroups is to utilize them to restrict access to exported NFS file systems (refer to the exports(5) manpage). Any place where these administrative groups were used in your NIS domain should remain valid for these new nss_ldap-enabled systems.
Security
Up to this point, we haven't discussed security. You've put a lot of sensitive information into your directory, which is now controlling whether users can log into machines on your network. And you could certainly put a lot more information into the directory: telephone numbers, human resources information, etc. Some of this information might be genuinely useful to the public at large; some of it may be highly confidential. But you don't yet know how to keep users from accessing information they shouldn't have access to. In order to have any confidence in a solution, we must examine how certain security issues are addressed by both the PAM and NSS modules.
First, it is important to understand what level of security is desired and exactly what information is being protected. Are you concerned only with protecting passwords? What about usernames as well? From the perspective of system administration, the most important information to protect is related to user and group accounts. Few sysadmins worry about someone being able to snoop a hosts file as it is copied across the network from one machine to another. However, everyone should be concerned about using a clear-text protocol, such as FTP, to transfer /etc/passwd and /etc/shadow from one machine to another.
To protect user passwords, we must look at how the PAM module binds to the directory. pam_ldap always uses a simple bind to authenticate a user against an LDAP server. You should avoid sending account credentials across the network in a form that is readable by anyone viewing traffic.
LDAPv3 provides two mechanisms that can be used to protect passwords. One is to use SASL to support more secure methods of authentication such as Kerberos 5 or DIGEST-MD5. However, while this mechanism protects passwords, it doesn't necessarily protect information other than the user's password. It is not supported by pam_ldap at this time. The second solution is to negotiate a secure transport layer that will protect the information used in the LDAP bind request as well as all other information sent to and from the directory server.
Security must be implemented by both the server and the client. It makes no difference if one party is willing to communicate securely but the other is not. Recall the StartTLS-extended command added in RFC 2830. This command allows the client to request a secure transport layer prior to binding to an LDAP server. Both the pam_ldap and nss_ldap modules support using the StartTLS command to negotiate transport layer security. In addition, these modules also support the LDAPS (tcp/636) protocol, which is an older method for accessing an LDAP server securely.
The following ldap.conf directive instructs the PADL LDAP modules to issue a StartTLS command prior to binding to the server:
## Use the StartTLS command to negotiate an encrypted transport layer. A value of
## on defines the use of LDAPS when connecting to the directory server.
ssl start_tls
Once you have configured the client, use a tool such as Ethereal or tcpdump to view the network traffic; it's a good idea to verify that things are working as expected.[6] After the initial LDAP Extended Request (i.e., StartTLS), you should see no clear-text traffic between the client and server. It is easy to spot an LDAP simple bind. The following is a bind request using the DN "uid=gcarter,ou=people,dc=plainjoe,dc=org" and the password testing:
00 30 f1 11 98 da 00 00 f4 d8
6c 0d 08 00 45 00 .0........l...E.
00 71 b9 a2 40 00 40 06 fd 21 c0 a8 01 4a c0 a8 .q..@.@..!...J..
01 28 a3 2f 01 85 26 8e 13 41 30 62 21 3a 80 18 .(./..&..A0b!:..
19 20 51 ef 00 00 01 01 08 0a 16 aa ab 72 16 ab . Q..........r..
09 2f 30 3b 02 01 03 60 36 02 01 03 04 28 75 69 ./0;...`6....(ui
64 3d 67 63 61 72 74 65 72 2c 6f 75 3d 70 65 6f d=gcarter,ou=peo
70 6c 65 2c 64 63 3d 70 6c 61 69 6e 6a 6f 65 2c ple,dc=plainjoe,
64 63 3d 6f 72 67 80 07 74 65 73 74 69 6e 67 dc=org..testing
When the StartTLS command is working correctly, you will be able to notice the initial extended (OID 1.3.6.1.4.1.1466.20037) request and the downloading of the server's certificate, but the remainder of the conversation will appear as gibberish (technically speaking).
Of course, encrypting all of the traffic between the clients and servers does no good if an unauthorized user can obtain information using normal means such as ldapsearch. To prevent access to information that could compromise an account (e.g., the userPassword attribute), you must specify access controls that secure account information. The following two access control entries (ACEs) in the database section of slapd.conf prevent users from viewing passwords belonging to accounts other than their own:
## Users can change their own passwords. Other users can attempt to authenticate, but
## can't read the userPassword value.
access to dn=".*,dc=plainjoe,dc=org" attr=userPassword
by self write
by * auth
## Default to read access.
access to dn=".*,dc=plainjoe,dc=org"
by * read
It's worth looking at these ACEs in some detail to understand exactly what they say. The first ACE allows a user who has been authenticated by the directory to have write access to his password (self write). Write access implicitly includes read access, and is necessary to allow users to change their passwords. Other users are granted only the ability to authenticate against the given DN (* auth). This is not the same as read access because the client can never obtain the userPassword value. The server compares the password sent by the client in the bind request to the value stored in the directory entry; the password never leaves the server.
The second ACE grants read access to all directory information to all users. Unless you have configured a more privileged account for use by nss_ldap (binddn and bindpw), you must allow anonymous read access to clients using an anonymous bind. However, note that the clients can't obtain the userPassword attribute; the previous ACE blocks access to passwords other than their own.
Remember that access control entries follow the "first match wins" rule. Therefore, the more restrictive ACEs must be defined first. In this example, reversing the order of the ACEs has an ill effect: every read request will match the rule allowing anonymous reads, and the rule restricting access to passwords is never processed.
If you have configured a binddn (uid=nssldap,ou=people,dc=plainjoe,dc=org) for searching the directory, the last ACE can be changed to disallow anonymous reads altogether:
## Default to read access.
access to dn=".*,dc=plainjoe,dc=org"
by dn="uid=nssldap,ou=people,dc=plainjoe,dc=org" read
by * none
* * *
[6] More information on Ethereal can be found at http://www.ethereal.com/. News regarding tcpdump can be found at http://www.tcpdump.org/.
Automount Maps
In order to use the automount information stored in your directory, you must shift your focus to the automount daemon itself, specifically Linux's kernel-based autofs. As it currently stands, autofs (v3.1.7 and the 4.0 preview releases) supports the undocumented automount and automountMap object classes. However, Red Hat has updated the package in its distribution (autofs-3.1.7-28) to look up mount points based on the nisObject and nisMap classes described in RFC 2307 (and included in nis.schema). The LDAPbis workgroup's revisions to RFC 2307 will include new schema items for storing automount information, but for the moment, nisObject and nisMap have the largest support base from Red Hat, Sun, and PADL. Figure 6-8 shows the required and optional attributes for these two new object classes.
Figure 6-8. nisObject and nisMap object classes
* * *
Tip
Red Hat's automount patches can be obtained from either http://people.redhat.com/nalin/autofs/ or in the latest autofs SRPM at ftp://ftp.redhat.com/pub/redhat/linux/rawhide/SRPMS/SRPMS/.
* * *
PADL's migration tools include a script (migrate_automount.pl ) for converting an automount map to LDIF. Here, you will convert a single automount point in /opt to a directory entry. You can see from the /etc/auto.opt excerpt that the LDIF entry contains all of the information needed for mounting /opt/src. This time, PADL's script does create the top-level container (nisMapName=auto.opt) for you:
$ grep src /etc/auto.opt
src -rw,hard,intr queso.plainjoe.org:/export/u1/src
$ ./migrate_automount.pl /etc/auto.opt /tmp/auto.opt.ldif
$ cat /tmp/auto.opt.ldif
dn: nisMapName=auto.opt,dc=plainjoe,dc=org
objectClass: top
objectClass: nisMap
nisMapName: auto.opt
dn: cn=src,nisMapName=auto.opt,dc=plainjoe,dc=org
objectClass: nisObject
cn: src
nisMapEntry: -rw,hard,intr queso.plainjoe.org:/export/u1/src
nisMapName: auto.opt
After adding the new automount entries to the directory using ldapadd, the autofs server must be informed of auto.opt's map location, the LDAP server's hostname, and the search base. The following line in /etc/auto.master instructs the autofs package to look up mounts for /opt on the host ldap1 beneath ou=auto.opt,dc=plainjoe,dc=org:
## Look up mounts for /opt in the LDAP directory.
/opt ldap:ldap1:nisMapName=auto.opt,dc=plainjoe,dc=org --timeout 300
Now you can launch the automount daemon; it will obtain all information for mount points in /opt from the directory server. If you're curious about what's going on, I recommend viewing the slapd log file on your server for more information on the autofs LDAP queries.
PADL's NIS/LDAP Gateway
If configuring all your Unix clients to use PAM and installing the various NSS modules is a little more work than your IT shop can bear at the moment, you may prefer the NIS/LDAP gateway solution mentioned at the beginning of this chapter (refer to Figure 6-1 for an illustration). This section examines PADL Software's ypldapd daemon as a migration path from NIS- to directory-based information storage. The following excerpt from the ypldapd(8) manpage describes ypldapd's position within a network:
YPLDAP(8)
ypldapd emulates the equivalent process ypserv by providing an RPC call-compatible interface. Rather than consulting `map' files as ypserv does, however, ypldapd draws its data from LDAP databases.
In theory, ypldapd allows an NIS domain to be replaced with a directory-based solution without any client machines being aware of the change. Even non-Unix NIS clients, such as the Windows NT NISgina DLL, will function correctly. As far as NIS clients are concerned, nothing has changed: they still get their data using the NIS protocol from an NIS server. Where the server gets its data from is another matter.
The ypldapd package is available in binary form for Solaris, Linux, FreeBSD, and AIX, and can be downloaded with a 30-day evaluation license. PADL's web site provides instructions for obtaining a temporary license via an email request. The user's guide is also available online in either Postscript or MS Word format (http://www.padl.com/Products/NISLDAPGateway.html).
Configuring ypldapd is fairly easy. Because it supports the RFC 2307 information service schema, you can use the PADL migration tools described earlier in this chapter to populate the directory with host and user information. PADL includes a copy of its migration tools with the ypldapd distribution. However, you may want to download the latest version separately.
PADL provides i
nstallation scripts for ypldapd that can be executed after unpacking the tar archive in /opt/ypldapd. Before beginning the installation, you should have or know:
A license key for ypldapd
The hostname of the LDAP server to query
The base DN used for searches
The NIS domain name of the ypldapd server
These settings will be stored in /opt/ypldapd/etc/ypldapd.conf. You can use ypldapd's -c option to specify an alternative configuration file. All other configuration files must be located in /opt/ypldapd/etc/. Here's an initial ypldapd.conf :
## NIS domain to serve
ypdomain yp.plainjoe.org
## LDAP server
ldaphost 192.168.1.77
## Search base
basedn dc=plainjoe,dc=org
## Enable caching.
caching on
## Dump caches every half hour.
cache_dump_interval 30
## Use the default naming context mappings.
namingcontexts namingcontexts.conf
All of the parameters are fairly self-explanatory. Refer to the ypldapd(8) manpage and the ypldapd user's manual for complete information on the directives you can use in the configuration file.
Depending on how you have configured access control for the entries in your directory, you may need to assign ypldapd a privileged DN to use when it binds to the LDAP server, as it needs to view all user information (i.e., the userPassword attribute value). Otherwise, ypldapd uses an anonymous bind, and may therefore be unable to access certain attributes or entries. Here's how to set up a privileged DN:
## Define a DN used for binding to the LDAP server.
binddn uid=ypldapproxy,ou=people,dc=plainjoe,dc=org
## Include the clear-text password for the binddn.
bindcred secret