[ Team LiB ] |
8.2 An FTP/HTTP CombinationThe first set of services that we will explore is the combination of the ProFTPD server (http://www.proftpd.org/) and Apache (http://www.apache.org/). In this scenario, we would like to build a new web server and allow users to publish web content using an FTP client. All user and group accounts already exist in the LDAP directory, but just to make things interesting, assume that your theoretical web server platform cannot make use of either PAM or NSS to access any of this information. The solution we would like to deploy is illustrated in Figure 8-2. Users should be able to put files into ~<username>/public_html on the web server using FTP. ProFTPD must authenticate user connections using information stored in the LDAP directory. These files should then be accessible via a web browser at http://www.plainjoe.org/~<username>. Because the server is not using an nss_ldap library, Apache must obtain the home directory path for users directly from the LDAP server. Figure 8-2. Interaction between ProFTPD, Apache, and the LDAP directory on www.plainjoe.orgTwo add-ins, both developed by John Morrissey (http://www.horde.net/~jwm), will help you implement your new web server. We will begin by looking at ProFTPD's LDAP features. 8.2.1 ProFTPDMorrissey's LDAP authentication module (mod_ldap) is included with current releases of the ProFTPD server.[2]
Our focus will be on the ProFTPD Release v1.2.7. Building mod_ldap is controlled by an option to the configure script (—with-modules=mod_ldap). After extracting the source code, the following commands build the binaries and tools to include support for mod_ldap: $ ./configure --with-modules=mod_ldap $ make $ /bin/su -c "make install" You can specify multiple modules as arguments to the —with-modules option by separating each module name in the list with a colon (e.g., —with-modules=mod_ldap:mod_linuxprivs). For more information on the various modules supported by the ProFTPD package, refer to the documentation included with the software or the online versions at http://www.proftpd.org/docs/. ProFTPD's -l command-line option can be used to verify that the mod_ldap module was included in the final binary. The actual list of modules may vary depending on the OS used during compilation, but at a minimum, you must see mod_ldap listed: $ proftpd -l Compiled-in modules: mod_core.c mod_auth.c mod_xfer.c mod_site.c mod_ls.c mod_unixpw.c mod_log.c mod_ldap.c The sample-configurations/ subdirectory included in the source distribution contains settings for several common scenarios. We'll use the following proftpd.conf file as starting point. The parameters are fairly self-explanatory, but you can review the configuration documentation included in the docs/ directory of the proftpd source distribution if you need more information. ## ################################################### ## ProFTPD configuration file ## (/usr/local/etc/proftpd.conf) ## Global directives ## ################################################### ServerType standalone DefaultServer on Port 21 Umask 022 User nobody Group nobody ## <- LDAP parameters will go here. -> # Normally, files should be overwritable. <Directory /*> AllowOverwrite on </Directory> Your first step is to restrict a user to her individual ~/public_html subdirectory when connecting. We will assume that this directory already exists. The DefaultRoot option defines the path that will be passed to the chroot( ) call by the proftpd server. ## Limit users to their web directory. DefaultRoot ~/public_html The next step is to instruct the proftpd daemon to use the mod_ldap module for authentication. The LDAPDoAuth keyword accepts up to three arguments. The first either turns the module on or off. The second argument is the base suffix to use when searching the directory. The final argument allows an administrator to define a customized search filter. In the absence of an explicit filter string, the default of (&(uid=%u)(objectclass=posixAccount)) is used. ## Limit users to their web directory. Use the default search filter. LDAPDoAuth on "ou=people,dc=plainjoe,dc=org" Of course, you also must define the hostname of the directory server: ## Define the LDAP server to contact. LDAPServer ldap.plainjoe.org By default, the ProFTPD daemon uses an anonymous bind when searching an LDAP directory. However, if you include the LDAPDNInfo directive in the configuration file, the daemon uses a DN and password to bind to the LDAP server. We'll stick with anonymous binds since Chapter 6 allowed nss_ldap clients to enumerate account information this way. The mod_ldap module supports two means of authenticating user connections once their directory entries are located. The LDAPAuthBinds directive controls which method is used. If it is set to off, mod_ldap searches the LDAP server anonymously (or uses a simple bind as the LDAPDNInfo entry) to retrieve all of the user information including the userPassword attribute. The module then hashes the password entered by the user (if necessary) using the local system's crypt( ) function and compares it to the value obtained from the directory search. This means that the userPassword must be stored in either {CLEAR} or {CRYPT} formats. The preferred and default method (LDAPAuthBinds on) authenticates the connecting user by binding to the directory server. In this case, ProFTPD locates the DN of the connecting user by searching the directory (either anonymously or as the LDAPDNInfo). However, the userPassword attribute is never requested from the LDAP server under this configuration. The module then binds to the directory again, using the user's DN and the password that the user entered. If this bind succeeds, ProFTPD considers the user to be authenticated. To configure ProFTPD for the preferred authentication method, add the following line to proftpd.conf: ## Require that an incoming user can successfully bind to the LDAPServer. LDAPAuthBinds on The final hurdle to overcome is to inform proftpd how to resolve UIDs and GIDs when listing files without using the standard getpwuid( ) and getgrgid( ) calls. The LDAPDoUIDLookups and LDAPDoGIDLookups directives instruct proftpd to query the directory server using the specified base suffix. Each directive accepts an optional parameter if you find it necessary to override the respective default search filters of (&(uidNumber=UNIX uid)(objectclasses=posixAccount)) and (&(gidNumber=UNIX gid) (objectclasses=posixGroup)). These filters work well with your directory, so there is no need to change them. ## Look up UIDs and GIDs in the directory. LDAPDoGIDLookups on "ou=group,dc=plainjoe,dc=org" LDAPDoUIDLookups on "ou=people,dc=plainjoe,dc=org" Assuming that you have a valid user named kristi in the directory, you can verify that mod_ldap and proftpd are working by connecting to the server (www.plainjoe.org) and uploading a file: $ ncftp -u kristi -p testpass www.plainjoe.org NcFTP 3.1.3 (Mar 27, 2002) by Mike Gleason (ncftp@ncftp.com). Connecting to 192.168.1.100... ProFTPD 1.2.7 Server (ProFTPD Default Installation) [www.plainjoe.org] Logging in . . . User kristi logged in. Logged in to localhost. ncftp / > put index.html index.html: 1.38 kB 69.43 kB/s ncftp / > ls -l -rw-r--r-- 1 kristi ftpusers 464 Dec 18 2002 index.html Table 8-1 lists the entire set of directives for mod_ldap.
8.2.2 ApacheNow that users can upload files to your web server, Apache must be configured to resolve URLs such as http://www.plainjoe.org/~kristi. Traditionally, Apache administrators have used a subdirectory named public_html in home directories to provide a simple mechanism for users to publish personal web pages. This associates the tilde (~) with a home directory by asking the operating system to provide the details about the user from the local system password file, NIS map, or LDAP directory via NSS modules. Because we have chosen not to implement any nss_ldap functionality on the server, we will have to use another means of instructing Apache how to determine a user's home directory location. Morrissey's mod_ldap_userdir module allows us to do just that. This module obtains the path to a user's home directory by searching an LDAP directory for a posixAccount entry with a matching uid value. Our LDAP directory already supports the schema required for mod_ldap_userdir, so the new work to be done is localized to the web server. As usual, we focus only on the aspects of Apache needed to integrate the server with an LDAP directory. Full coverage of Apache configuration is well beyond the scope of a single chapter, as is the case with all of the server packages discussed in this chapter. For more information on Apache and its httpd.conf, refer to Apache: The Definitive Guide, by Ben and Peter Laurie (O'Reilly). The first step is to download the latest version of the module from http://www.horde.net/~jwm/software/mod_ldap_userdir/. Building mod_ldap_userdir requires adding only a single option (—with-activate) to the configure script. However, unless the Apache eXtenSion tool is located in a directory in your $PATH, it will also be necessary to set the absolute path to the apxs binary. These are the steps I used to build the module for an Apache 1.3.23 installation, although an Apache 2.0 installation is no different: $ ./configure --with-activate --with-apxs=/usr/sbin/apxs $ make $ /bin/su -c "make install" /usr/sbin/apxs -i -a mod_ldap_userdir.so [activating module 'ldap_userdir' in /etc/httpd/conf/httpd.conf] cp mod_ldap_userdir.so /usr/lib/apache/mod_ldap_userdir.so chmod 755 /usr/lib/apache/mod_ldap_userdir.so cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak cp /etc/httpd/conf/httpd.conf.new /etc/httpd/conf/httpd.conf rm /etc/httpd/conf/httpd.conf.new The build process will fail if configure cannot locate the necessary LDAP libraries and header files. The two options, —with-sdk-headers=<path> and —with-sdk-libs=<path>, can be used to specify the path to the LDAP SDK header files and libraries. The final make install command should copy the compiled library to the directory containing the other installed Apache modules (normally /usr/lib/apache/) and activate the module in httpd.conf. Here is the LoadModule line created in Apache's configuration from the installation (the comments are my own): ## Activate the LDAP userdir module (this may also require an AddModule ## mod_ldap_userdir.c directive later in the file depending on the server's ## configuration). LoadModule ldap_userdir_module /usr/lib/apache/mod_ldap_userdir.so The module itself has seven directives, which are presented in Table 8-2. Your web server uses four of these directives: <IfModule mod_ldap_userdir.c> LDAPUserDirServer ldap.plainjoe.org LDAPUserDirSearchScope subtree LDAPUserDirBaseDN ou=people,dc=plainjoe,dc=org LDAPUserDir public_html </IfModule>
The values for each directive in your configuration are fairly self-explanatory. LDAPUserDirServer, LDAPUserDirSearchScope, and LDAPUserDirBaseDN set the standard LDAP search parameters: the server's hostname (ldap.plainjoe.org), the search scope (subtree), and the base suffix (ou=people,dc=plainjoe,dc=org). The search filter is not set explicitly because the default filter string, (&(uid=%v)(objectclass=posixAccount)), works nicely with your directory; it matches the current username against the uid attributes of all posixAccount objects. By default, Apache binds to the directory anonymously. However, you could specify a DN and password to be used when binding to the LDAP server by defining the LDAPUserDirDNInfo parameter. There is no need to avoid anonymous searches in this case because the uid and homeDirectory attributes have already been made available anonymously to support other services such as ProFTPD. Once all of these pieces are in place, you can verify that the module is working correctly by viewing the index.html file uploaded to ~kristi/public_html in the previous section. If there are any errors, the two places to look for clues are Apache's error_log and OpenLDAP's syslog messages. |
[ Team LiB ] |