[ Team LiB ] |
8.4 FreeRadiusThe 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 = "\263\033\037\2760@3\022X\327\334\343\025\265\347}" 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. 8.4.1 FreeRadius and OpenLDAPIf 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.
The next step required to put this new module instance into play is adding a definition to the authenticate section that can be used as a value for the Auth-Type attribute in the users file: authenticate { authtype LDAP { ldap } } Now you can change the authentication default in raddb/users to LDAP: ## raddb/users file defined by the files authorize component ## ## Authenticate all users by binding to the LDAP directory. DEFAULT Auth-Type := LDAP After restarting radiusd (again in debug mode), test the new configuration using a preexisting LDAP user entry (uid=kristi and userPassword=testpass): $ ./radtest kristi testpass localhost 0 testing123 Sending Access-Request of id 147 to 127.0.0.1:1812 User-Name = "kristi" User-Password = "1q\325\026\020\315p\214X\310\227\376\014]F\332" NAS-IP-Address = garion NAS-Port = 0 rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=147, length=20 From the client's point of view, nothing appears to be different. The server, however, yields much more information. You should be able to locate a line where the module binds to the directory on behalf of the user. auth: type "LDAP" modcall: entering group authtype < . . . reminaing output omitted . . . > rlm_ldap: bind as uid=kristi,ou=people,dc=plainjoe,dc=org/test to ldap.plainjoe.org:389 rlm_ldap: waiting for bind result ... rlm_ldap: user kristi authenticated successfully modcall[authenticate]: module "ldap" returns ok This is definitely the least intrusive way to integrate FreeRadius with an existing directory and will work with any LDAPv3 server. The next step is to use your directory as a data store for the information currently stored in FreeRadius's users file. This, however, will require that you learn about some new schema items. The FreeRadius project provides an LDAP schema file for use with OpenLDAP 2.x servers. The RADIUS-LDAPv3.schema file can be found in the doc/ directory of the FreeRadius source code distribution. The schema defines many new attributes used to store RADIUS attribute values and a single structural object class named radiusprofile, shown in Figure 8-5, which is used to represent RADIUS users. To keep our focus on LDAP and not RADIUS, we will only concern ourselves with how radiusAuthType maps the Auth-Type RADIUS attribute. Descriptions of the other attributes can be found in the RADIUS RFC. Figure 8-5. The radiusprofile object class used by the FreeRadius serverFirst, copy the new schema file to /usr/local/etc/openldap/schema/: root# cp RADIUS-LDAPv3.schema /usr/local/etc/openldap/schema/ Next, you must include a reference to this file in slapd.conf. Because a radiusprofile object includes the lmPassword and ntPassword attributes from the samba.schema file, it must be placed after the latter file has been parsed: ## /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 7 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 ## Support for FreeRadius depends on samba.schema for LM/NT password attributes. include /usr/local/etc/openldap/schema/RADIUS-LDAPv3.schema The mapping between LDAP attributes and RADIUS attributes is stored in a text file named ldap.attrmap by default. Conventionally, this file is stored in the raddb/ directory, but both the name and location are configurable via the rlm_ldap module's dictionary_mapping parameter. Because we will be using the default schema file, the corresponding attribute dictionary is sufficient. If you decide to use a custom schema, you may have to modify the dictionary as well. Your next hurdle is decide where to store the radiusprofile entries in the directory. Your first choice might be to store them with the other user account information below the people ou. The problem is that you cannot add the radiusprofile object to your existing users' accounts. You can either change the radiusprofile definition to an auxiliary object or choose to store objects of this type somewhere else. Following the trend of using provided schemas whenever possible, we will create a new organizational unit to hold FreeRadius users and establish a link between the posixAccount and the radiusprofile objects. First, create a new ou=radius entry below the services ou (created in Chapter 7 for Sendmail): dn: ou=radius,ou=services,dc=plainjoe,dc=org objectclass: organizationalUnit ou: radius Next, create a profile for the user kristi. The difficulty with this is choosing the RDN for the entry. You have already chosen the uid attribute as the unique naming convention for entries below ou=people. However, the radiusprofile object includes only the cn attribute. The informational RFC 2377 defines an auxiliary uidObject class for situations such as this one. This allows you to include the uid attribute as the RDN for new entries regardless of the structural object class and still maintain your internal naming conventions. You could just use an extensibleObject, but the uidObject is a cleaner approach. Here is the resulting RADIUS user entry: dn: uid=kristi,ou=radius,ou=services,dc=plainjoe,dc=org objectclass: radiusprofile objectclass: uidObject uid: kristi cn: Kristi Carter radiusAuthType: LDAP Finally, link the posixAccount entry for kristi to her RADIUS information by storing the DN of the radiusprofile object in uid=kristi,ou=people,dc=plainjoe,dc=org. This time we will use the extensibleObject to add the extra attribute. To make the new attributes easier to see, most of the existing optional attributes have been omitted from this LDIF excerpt. Added attributes are shown in bold. ## Existing optional attributes have been omitted from the display. dn: uid=kristi,ou=people,dc=plainjoe,dc=org objectClass: inetOrgPerson objectClass: posixAccount objectClass: sambaAccount objectclass: extensibleObject cn: Kristi Carter cn: Kristi W. Carter sn: Carter loginShell: /bin/bash uidNumber: 781 gidNumber: 100 homeDirectory: /home/kristi uid: kristi rid: 2570 radiusprofileDN: uid=kristi,ou=radius,ou=services,dc=plainjoe,dc=org The two module configuration changes to be made are changing the locations of the dictionary file for LDAP/RADIUS attributes (dictionary_mapping) and specifying the LDAP attribute containing the DN of the user's RADIUS information (profile_attribute): 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 profile_attribute = "radiusProfileDn" dictionary_mapping = ${raddbdir}/ldap.attrmap } You can now remove the local copy of the users file from the RADIUS server and add the ldap module to the authorize block in radiusd.conf. The files module is still listed because it also contains directives affecting local accounting policies. ## ## Authorization: obtain information about the user ## authorize { files ldap } This example brings up two important points:
I'll leave it up to you to use the radtest tool to verify that the server is working correctly. |
[ Team LiB ] |