Samba's smbpasswd(8) utility is normally used to perform duties such as manipulating user entries in the smbpasswd(5) file, joining the Samba server to a Windows domain, and changing passwords for remote Windows users. Use it to store the ldap admin dn password by executing:
root# /usr/local/samba/bin/smbpasswd -w secret
Setting stored password for "cn=smbadmin,ou=people,dc=plainjoe,dc=org" in secrets.tdb
Because secrets.tdb can be read or written only by root, you must execute this command as root. If the smbpasswd command does not support the -w option, either LDAPsam support was not properly enabled when compiling Samba, or a non-LDAP-enabled version of the tool exists in your $PATH.
Currently, the Samba server uses a simple bind when contacting the directory server to retrieve user information. Given the access rights required by the ldap admin dn account and the clear text-equivalent nature of the LanManager and NT password hashes, it is strongly advised that the ldap ssl parameter be left enabled or set to use the StartTLS operation.
Configuring OpenLDAP
To store sambaAccount entries in the directory, your LDAP server must support the appropriate schema. Samba developers provide a definition of the sambaAccount schema for use with OpenLDAP 2 servers in the file examples/LDAP/samba.schema (included in the Samba source distribution). Copy samba.schema to an appropriate location, such as /usr/local/etc/openldap/schema/, and include it in the server's configuration by adding the appropriate include statements to the slapd.conf file. Two dependencies are noted at the beginning of the samba.schema file: cosine.schema (for the uid attribute) and inetorgperson.schema (for the displayName attribute). After you've finished editing the schema portion of slapd.conf, it should look like this:
## /usr/local/etc/openldap/slapd.conf
## core.schema is required for all servers.
include /usr/local/etc/openldap/schema/core.schema
## Included from Chapter 6
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/nis.schema
## Included from Chapter 4
include /usr/local/etc/openldap/schema/inetorgperson.schema
## Dependencies for samba.schema: cosine.schema and inetorgperson.schema needed to
## support --with-ldapsam in Samba
include /usr/local/etc/openldap/schema/samba.schema
Figure 8-3 shows attributes used by the sambaAccount object class. The Samba-LDAP-HOWTO file (also distributed with the Samba source distribution) defines each attribute and its expected values. All of the attributes are stored as ASCII string values (IA5String).
Figure 8-3. sambaAccount object class
In addition to the schema changes, you must add a new access control rule to prevent normal users (authenticated or not) from retrieving LanMan/NT password hashes (the lmPassword and ntPassword attributes) from the directory. Since OpenLDAP never uses these attributes for authenticating a bind request, there is no reason for a user to access these attributes. The other attributes of the sambaAccount object class do not contain any sensitive information, so it doesn't matter who reads them. The first and last slapd.conf ACLs are repeats from Chapter 6. The second access rule denies all users except smbadmin access to the lmPassword and ntPassword attributes. This ACL could be modified to allow users to change their own password hashes without any adverse security affects. The third allows the cn=smbadmin user to write to all entries in the ou=people subtree. You could tighten down this ACL by restricting the smbadmin's access to the attributes of the a sambaAccount object only, but the simpler version is presented here:
## Previous ACL from Chapter 6
access to attrs=userPassword
by self write
by * auth
## Don't let users snoop Windows passwords.
access to attrs=lmPassword,ntPassword
by dn="cn=smbadmin,ou=people,dc=plainjoe,dc=org" write
by * none
## Allow the Samba admin user to add new entries and modify existing ones.
access to dn.subtree="ou=people,dc=plainjoe,dc=org"
by dn="cn=smbadmin,ou=people,dc=plainjoe,dc=org" write
by * read
## Previous ACL from Chapter 6
access to dn.subtree="ou=group,dc=plainjoe,dc=org"
by * read
I have already added Samba's ldap admin dn to smb.conf, but have yet to explain what its directory entry looks like. Samba will bind to the directory as the user, so it must possess a userPassword attribute value. However, it is not necessary that this entry have a numeric UID or other POSIX attribute. The person structural object class in OpenLDAP's core.schema file includes just the attributes you need: a name and a password. Figure 8-4 displays the required and optional attributes held by a person in the directory.
Figure 8-4. person object class
A simple LDIF representation of the cn=smbadmin entry would be:
dn: cn=smbadmin,ou=people,dc=plainjoe,dc=org
objectclass: person
cn: smbadmin
sn: smbadmin
userPassword: {SSHA}xDG3/Cfj7ATgJ9yP0exS2lGD+infJqCj
In this case, the userPassword attribute holds the SSHA hash of the passphrase string "secret."
You have now finished all the configuration details, and are ready to add a real sambaAccount entry. When you've done this, you can start testing.
Adding and Using a sambaAccount
Just as entries in the smbpasswd(5) file supplement entries in the local system passwd file, the sambaAccount entries in the directory supplement the basic Unix account information. smbd always queries the server's operating system for attributes such as the Unix home directory and user ID. By using both the posixAccount and the sambaAccount auxiliary object classes, you can store all of this information in your directory.
The only requirement Samba places on sambaAccount or smbpasswd entries is that the operating system must provide a valid set of Unix attributes for the user (e.g., a Unix UID and primary GID). The example presented here uses the directory structure presented earlier in this chapter and therefore assumes that a posixAccount entry already exists for all valid Unix users.
To add the sambaAccount information required for validating Windows users, we turn to the smbpasswd(8) utility. The -a option specifies the username of the account to be added, and the -s option specifies the initial password. For example, to add a user named kristi, execute the following command as root:
root# smbpasswd -a kristi -s testpass
LDAP search "(&(uid=kristi)(objectclass=sambaAccount))"
returned 0 entries.
Added user kristi.
The message about the LDAP query returning 0 entries is normal. smbpasswd(8) initially looks for a preexisting account with the specified username. Since you are adding a new account, this search returns 0 entries. The resulting entry in the directory (with sambaAccount attributes highlighted), including the preexisting posixAccount attributes, appears as:
dn: uid=kristi,ou=people,dc=plainjoe,dc=org
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: sambaAccount
cn: Kristi Carter
cn: Kristi W. Carter
sn: Carter
mail: [email protected]
labeledURI: http://www.plainjoe.org/~kristi
roomNumber: 102 Ramsey Hall
telephoneNumber: 222-555-2356
userPassword: {SSHA}7eXyEM+Q+1BVUGFz/MOWYUCONdovP3uM
loginShell: /bin/bash
uidNumber: 781
gidNumber: 100
homeDirectory: /home/kristi
gecos: Kristi Carter
uid: kristi
pwdLastSet: 1040186720
logonTime: 0
logoffTime: 2147483647
kickoffTime: 2147483647
pwdCanChange: 0
pwdMustChange: 2147483647
rid: 2570
primaryGroupID: 1201
> lmPassword: 3AE6CCCE2A2A253F93E28745B8BF4BA6
ntPassword: 35CCBA9168B1D5CA6093B4B7D56C619B
acctFlags: [UX ]
We can confirm that Samba can authenticate the new user by using smbclient:
$ smbclient //tashtego/files -Ukristi%testpass
Domain=[PEQUOD] OS=[Unix] Server=[Samba 2.2.7a]
smb: >
* * *
[3] The LDAP support in Samba 2.2 has no relationship to the LDAP support in a Windows 2000 domain or in Windows 2000 Active Directory servers.
FreeRadius
The FreeRadius server project (http://www.freeradius.org/) is the implementation of the Remote Authentication Dial-In User Service (RADIUS) protocol used by many corporations and Internet service providers to authenticate users connecting from remote locations. Complete coverage of FreeRadius or RADIUS servers goes beyond the scope this chapter. RFC 2865 explains the details of the protocol. For a more practical look at RADIUS, you should refer to the FreeRadius web site as well as RADIUS, by Jonathon Hassel (O'Reilly).
The FreeRadius server daemon, radiusd , can use an LDAP directory in two different ways. First, it can use LDAP as a data store for RADIUS attribute values. RADIUS attributes are defined by the RADIUS protocol and should not be confused with LDAP attributes.[4] The only similarity between the two types of attributes is that both have names and are used to store values. The FreeRadius administrator defines the mapping between RADIUS attributes and the LDAP attributes used to represent them. We'll look at the configuration details after we have compiled a working RADIUS server. The second option is to use the directory as an authentication service by binding to the LDAP server on behalf of a user. In this way, radiusd can determine whether to accept or reject incoming connection requests.
In the 0.8 release, the rlm_ldap module used by radiusd to access a directory is included in a default installation. No additional flags are required to enable LDAP support at compile time. Running the basic configure && make && /bin/su -c "make install" is enough to achieve a working radiusd in most environments.
Without getting too bogged down in the specifics of the FreeRadius configuration file, radiusd.conf , it is worth explaining the general layout. Configuration options can be described as either existing within the scope of a section bounded by { }s or global. Global parameters define information such as the location of directories necessary to the general operation of radiusd or the number of threads that the main server should spawn. Scoped parameters can be subdivided into module settings and component implementations.
FreeRadius modules are shared libraries defined by the project's RLM interface. The modules block in radiusd.conf contains parameters specific to each library. The RLM interface describes several different components that a module can implement. The two components of interest to us are authorize and authenticate.
The authorization component is used by radiusd to look up information about a user account. The authorize section can contain several different module names. Each module is queried in order for an entry matching the login name of the user in question until a record is located or all modules have reported failure. Part of the authorization component's responsibility is to describe the authentication method used to validate this account. The authenticate section defines possible authentication mechanisms. The method actually used for a specific request is determined by the information returned by the authorize section.
Here is the working configuration file for a basic server to authenticate connections against the list of local accounts:
## radiusd.conf: FreeRADIUS server configuration file
##
## Global parameters: directory/logfile locations, etc.
##
prefix = /opt/radius
exec_prefix = ${prefix}
sysconfdir = ${prefix}/etc
localstatedir = ${prefix}/var
sbindir = ${exec_prefix}/sbin
logdir = ${localstatedir}/log/radius
raddbdir = ${sysconfdir}/raddb
radacctdir = ${logdir}/radacct
confdir = ${raddbdir}
run_dir = ${localstatedir}/run/radiusd
log_file = ${logdir}/radius.log
libdir = ${exec_prefix}/lib
pidfile = ${run_dir}/radiusd.pid
# CLIENTS CONFIGURATION
$INCLUDE ${confdir}/clients.conf
##
## MODULE CONFIGURATION
##
modules {
## Unix /etc/passwd-style authentication
unix {
passwd = /etc/passwd
shadow = /etc/shadow
group = /etc/group
radwtmp = ${logdir}/radwtmp
}
## Local files. The user's file contains a single entry to default all
## authentication to the local system.
## DEFAULT Auth-Type := System
files {
usersfile = ${confdir}/users
acctusersfile = ${confdir}/acct_users
compat = no
}
}
##
## Authorization: obtain information about the user
##
authorize {
files
}
##
## Authentication: validate the user request
##
authenticate {
unix
}
To test your server, you must make sure that the following entry is defined in radiusd's clients.conf file to allow connections over the loopback interface:
## Allow connection requests from localhost.
client 127.0.0.1 {
secret = testing123
shortname = localhost
nastype = other
}
You can test your configuration by starting radiusd in debug mode. This will produce a large amount of log information printed to standard output.
root# radiusd -X -A
< . . . preceding output omitted . . . >
Ready to process requests.
Using radtest(1) , you can verify that the local user guest1 with password test1 can be successfully authenticated:
$ radtest guest1 test1 localhost 0 testing123
Sending Access-Request of id 50 to 127.0.0.1:1812
User-Name = "guest1"
User-Password = "26333372760@322X32733434325265347}"
NAS-IP-Address = garion
NAS-Port = 0
rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=50, length=20
Now that you have a working RADIUS configuration, it is time to move on and integrate the new server with your directory.
FreeRadius and OpenLDAP
If you want the RADIUS server to utilize the directory for authentication only, no schema modifications to your existing LDAP server are necessary. You can simply use the posixAccount entry for a user, as you did with the ProFTPD server.
The first step is to define the parameters for the rlm_ldap module instance. All of the parameters shown here should be intuitive. The module will perform an anonymous bind to our LDAP server and search for a posixAccount entry whose uid attribute matches the username of the connecting user. Once this entry is found, the library will attempt to bind to the directory as the user to verify the user's credentials. All of the communication takes place after the StartTLS command has been executed to ensure privacy.
ldap {
server = "ldap.plainjoe.org"
port = "389"
basedn = "ou=people,dc=plainjoe,dc=org"
filter = "(&(objectclass=posixAccount)(uid=%{Stripped-User-Name:-%{User-Name}}))"
start_tls = yes
}
There are many more parameters that can be defined for the rlm_ldap module. A complete list is given, along with descriptions, in Table 8-4.
Table 8-4. rlm_ldap module parameters
Parameter
Default
Description
access_attr<
br />
None
The attribute located below the basedn that must exist in the user's entry. The user is denied access if the attribute is not returned by the initial search.
access_attr_used_for_allow
yes
Controls how the access_attr directive is used. When disabled, the presence of the access_attr in an entry will deny the user access.
basedn
None
Searches base DN.
compare_check_items
no
Specifies whether the module should compare the check items in the RADIUS request with the check items in the directory.
default_profile
None
DN of the entry containing the default RADIUS profile.
dictionary_mapping
{confdir}/ldap.attrmap
Location of the file containing the RADIUS/ LDAP attribute mappings.
filter
(uid=%u)
An RFC 2254 search filter.
groupname_attribute
cn
Attribute used when searching for a RADIUS groupname.
groupmembership_attribute
None
The attribute containing the DN of the group of which the user is a member.
groupmembership_filter
(|(&(objectClass=
GroupOfNames)(member=%
{LdapUserDn}))(&
(objectClass=
GroupOfUniqueNames)
(uniquemember=%
{Ldap-UserDn})))
The RFC 2254 search filter used to query a group for membership.
LDAP System Administration Page 22