Table of Contents
Previous | Next
Apache Server Survival Guide

Chapter 15: Access Control and User Authentication


Access Control and User Authentication


User authentication and access control allow you to restrict access to your Web server's document tree. If you are building a site that will be accessible to the world and you don't need to restrict access to your materials, you may want to skip this chapter.

Servers with sensitive information should be behind a firewall or should use encryption technology that protects your materials from unauthorized viewing. Directly connecting to the Internet with a server that has sensitive information is asking for trouble.

Apache provides several methods you can use to restrict unauthorized access to your documents. These access control and user authentication extensions are implemented in the form of modules. Modules extend the functionality of Apache by adding new functionality that is not part of the Apache core itself. Modules provide additional directives that allow you to control the behavior of the server much the same way you control other aspects of the server's configuration.

As with any resource that needs to be secured, security factors depend on many issues. If the information you are publishing is of a highly sensitive nature, you should consider an alternative publishing medium. You may want to consider using a secure server, such as Apache-SSL or Stronghold. Both of these servers are based on the Apache source, but they add Secure Socket Layer (SSL) technology, which encrypts transactions between the server and the client when accessed with a compatible browser. Information on SSL servers is covered in Chapter 14, "Secure Web Servers."

The topics in this chapter offer an extremely basic measure of security, if you can call it that. User authentication and access control put a basic barrier between the user accessing your data and your server. If your data is sensitive, don't place your trust in any piece of software unless you understand the potential risks that could create a hole in your security scheme. Once again, do not place highly sensitive information on a publicly accessible server!

Apache provides a simple authentication scheme by which a user can prove his identity to the server: Basic authentication. While the mechanisms used to verify the authentication information are reliable, you should be aware that Basic authentication is not secure. It assumes that your network connection to the server is trustworthy—an assumption that is questionable once you access your server from outside your local network. Be aware when you transmit a password that unless you are using a secure server, the password transaction is not encrypted in any way by the client browser. It is encoded using a similar process to the UNIX uuencode program, which ensures its integrity during transmission. However, this method of encoding doesn't provide any encryption or other means of securing the data. Anyone with some technical ability who intercepts the request could decode the password information and use it to access your restricted materials. You should also be aware that when you authenticate, this process is repeated for every document you request (your password and user id are sent with every page request, thus your password is sent not once but many times).

Apache 1.1 adds a new form of authentication called Digest authentication, which uses RSA MD5 encryption technology. The use of Digest authentication requires a supporting Web browser. Be aware that unless you are using a secure server to access your documents, the information that you transmit is still sent in world-readable form.

Now you understand that not one single measure of security is enough or infallible; that passwords can be compromised by someone decoding them or intercepting them; and that your networking wires can be tapped, or someone with access to a Domain Name System (DNS) server could make any machine masquerade as if it were in your network. The tools Apache provides can help you build a basic barrier to discourage and stop most unauthorized users from accessing your information.

Apache provides two methods you can use to control access to the documents you make available on the Web:

You can enable access control and user authentication on a serverwide basis or on a per-directory basis by using the appropriate access control file (ACF):


A section is a special type of directive that follows an SGML-type syntax: <directive option...>...</directive>. Apache implements a few sections: <VirtualHost>, <Directory>, <Limit>, and new to 1.1, <Location>. The <Location> directive allows you to implement access control on a URL basis.
Access control on a per-file basis is not available to Apache versions prior to 1.1. If you need to restrict access to a file, you will need to create a directory for that file and restrict access to the directory instead.
Apache 1.1 introduces the <Location> section, which allows you to restrict access based on an uniform resource locator (URL) or file address.
Apache 1.2 will introduce a new section directive, <File>, which is similar in functionality to the <Location> section.


In general, per-directory ACFs are not a good idea for a site that needs tight security because some of the directives can override settings you specified on your global ACF. However, if for administration reasons you want to relegate access control management to the owners of the materials, per-directory access control files are the only way to go.

The name of the per-directory ACF is set by the AccessFileName directive. This directive is typically found in conf/srm.conf. The default value for AccessFileName is

AccessFileName .htaccess

Note that the period in the filename will make the file invisible to most users, unless they use the -a flag to ls (the program used for listing directories). Access control directives are usually found inside a <Limit> section. A <Limit> section contains control directives enclosed by a <Limit>...</Limit> tag pair:

<Limit method method ...>
ControlDirective
...
</Limit>

method refers to any HTTP valid access method (GET, POST, HEAD, and so on). Apache only enables GET, POST, and HEAD. The HEAD method returns an HTTP header describing the document, not the document itself. Other potentially dangerous methods are not implemented in Apache: PUT, DELETE, LINK, and UNLINK. So you should not have to worry about those. However, always read the documentation and be aware of HTTP methods that may compromise your security.

The enclosed directives only apply to the directory tree listed in a <Directory> section if the <Limit> section is in the global ACF. If they are found on a per-directory ACF, then all directories under that tree will share the requirements listed. If they are found outside a <Directory> section on the global ACF, then the requirement applies globally to all directories, even to documents outside your DocumentRoot pointed to by an Alias directive. (For more information, please refer to Chapter 10, "Apache Modules."

Host-Based Access Control (Domain-Level Access Control)


Host-based access control grants or denies access depending on the Internet Protocol (IP) address of the machine that generated the request. This system is the least intrusive to legitimate users because access is granted on the basis of the machine address. Machines matching a description are allowed or denied access to the document tree without requesting further information from the client.

Host-based access control is provided by the mod_access module. The mod_access module is compiled into Apache by default, so the directives it provides can be used without the need for additional configuration.

The mod_access module provides three directives to help you control access to your site:


The order Directive


The order directive defines the order in which the allow and deny directives are evaluated within the <Limit> or <Directory> section. The syntax for the order directive is

order [deny,allow] | [allow,deny] | [mutual-failure]

The possible options are
deny,allow Evaluates the deny directive first and then grants exceptions based on the allow directive.
allow,deny Evaluates the allow directive first and then grants exceptions based on the deny directive.
mutual-failure Evaluates so that only hosts that appear in the allow list and do not appear on the deny list are granted access.

The allow Directive


The allow directive lists hosts that are allowed access to the directory. allow has the following syntax:

allow from host host...

host can be specified by [all] | [fully qualified host name] | [partial domain name] | [IP address] | [partial IP address].

The deny Directive


The deny directive lists hosts that are denied access to the directory. deny has the following syntax:

deny from host host...

host can be specified by [all] | [fully qualified host name] | [partial domain name] | [IP address] | [partial IP address].

Host-based Access Control Examples


To limit access control to your server's DocumentRoot to hosts in your domain (assuming that your document root is htdocs), you would have an entry in your conf/access.conf file that looks like this:

<Directory /usr/local/etc/httpd/htdocs>
<Limit GET POST>
order deny,allow
deny from all
allow from yourdomain.dom
</Limit>
</Directory>

If you were limiting access to a directory inside your DocumentRoot (using .htaccess), you would specify this:

<Limit GET POST>
order deny,allow
deny from all
allow from yourdomain.dom
</Limit>

As described in the syntax, you can also specify hosts by IP or partial IP address. Using an IP address to list hosts may be more secure than by name. The following is a more complex example. To only allow access to hosts in the your.domain domain and the marketing subnet of the friendly.com domain and to all hosts from network 204.95.160 (in this case, this is a C class address so there are 254 possible hosts), the <Limit> section would look like this:

<Limit GET POST>
order deny,allow
deny from all
allow from yourdomain.dom marketing.friendly.com 204.95.160
</Limit>

User Authentication Control


User authentication allows you to control access to the document tree on an individual user basis by utilizing user and passwords lists to provide the necessary authentication. When a user accesses a restricted portion of the site, the server requires him to log in by specifying a username and a password. If the user supplies the proper information, access is granted for him to roam across the site without additional login requests. (Although the user does not enter a password, the username and password get re-sent by the browser with each new request to the protected realm.) See Figure 15.1 for an example of a login panel and Figure 15.2 for an example of a rejected login.

Figure 15.1. A login panel. The message You need a password to access this page was added by the AuthName directive.

Figure 15.2. A rejected login. This is the message Apache displays if the client doesn't provide the correct authentication information.

User authentication based on access control provides more selective security because access permission is validated on a per-user basis. Apache requires login and a password validation before granting access to a restricted portion of your site. It is important to note that there is no correlation between the UNIX password file (/etc/passwd) and the server's password files; it is not necessary for a user to have an account on your system to be able to access protected materials on your Web server. Also, it goes without saying that security is only as good as the passwords and the secrecy used to guard them.


Because passwords are transmitted as encoded text, there are no safeguards preventing someone from intercepting a request and decoding the password. The security of your information really depends on the trustworthiness of the networks used to access your server; a condition that is nonexistent when your server is accessed from the Internet.

To provide user authentication you will need to create and maintain password files. You can have many different password files within your site; however, you may find it easier to create a single password file and create a group file to further refine permissions. By also using a group file, you can establish access restrictions based on the user's group memberships.

Currently, user authentication is provided by the following modules:

The previous modules provide the following directives:

Module


User Authentication Directive

mod_auth AuthUserFile file
mod_auth_dbm AuthDBMUserFile dbmfile
mod_auth_db AuthDBUserFile dbfile

The only difference between the modules, besides the small change in the naming of the directive, is the database format used to store the user and password information. The modules providing DBM and DB support offer incredible performance enhancements over the flat files used by mod_auth. DBM and DB formats are hashed tables. A hashed table orders all entries with a unique index, otherwise known as a key, which is generated from the username and a value. In order to look up a password, the hashing algorithm computes the key for the user and retrieves the password. In contrast, the flat file version (mod_auth) needs to read every user in the file, and when it finds a match, it retrieves it. This process becomes very inefficient and slow as soon as there are more than a few hundred users in the database.

The DBM version of the module was originally developed for HotWired ( http://www.hotwired.com), which has over 150,000 users.

Requesting a Password


To request authentication for your document tree to users within your network, just modify your access.conf configuration file to have an entry like this:

<Directory /usr/local/etc/httpd/htdocs>
 AllowOverride None
 AuthUserFile /usr/local/etc/httpd/passwords/passwordfile
# Group authentication is disabled by pointing it to /dev/null
 AuthGroupFile /dev/null
 AuthName These documents are only available to authorized users in our domain name
 AuthType Basic
 <Limit Get>
 require valid-user
 order deny,allow
 deny from all
 allow from domain
 </Limit>
</Directory>

The order, deny, and allow directives limit who will get a login panel. If you want users to be able to use your server from outside your network, just omit these directives. Otherwise, just replace domain with the domain name for your organization, or better yet, specify your domain by using an IP address notation.

The previous example defines the location of the database using the AuthUserFile and AuthGroupFile directives provided by the mod_access module. If you wish to use the DBM or DB supporting modules, just replace the authentication configuration directives with the equivalent version provided by the module you wish to use.

Next, you'll need to create the password directory on your httpd tree:

# mkdir /usr/local/etc/httpd/passwords

Make sure the /usr/local/etc/httpd/ passwords directory is readable by the user or group your server runs under. If the server cannot access the file, no one will be able to get in.

The tools you use to manage the password file depend on the type of authentication you use. If you are using flat files, you'll use the htpasswd program. If you are using database files, you'll use the dbmmanage script.

Managing Flat-File Password Files with htpasswd


To add users to your password file, you'll need to use the htpasswd program. The source code for this program is included in the support directory (/usr/local/etc/httpd/support), but it is not compiled by default. You'll need to edit the CC= directive in the makefile in that directory to match the name of your compiler. And then issue a make. After a few seconds, the binary htpasswd and other utilities will be built. Once htpassword is built, you can create a password file. The htpasswd program has the following syntax:

htpasswd [-c] passwordfile username

The -c flag creates the password file passwordfile. Here's a sample session:

# cd /usr/local/etc/httpd
# support/htpasswd -c passwords/passwordfile user
Adding password for user.
New password:
Re-type new password:

The passwords won't be displayed on the terminal as you type, so as a security measure, htpasswd will ask for the password twice. If the username you entered exists, htpasswd will ask you for the new password.

You can create as many password files as you like. However, you'll have to use different filenames to reference them.


Do not put a password file in the directory you are trying to protect. The best place for a password file is outside of your server's document root.


Managing DBM and DB Password Databases with dbmmanage


If you have more than a few visitors, you will need to authenticate; you'll want to use DBM or DB password databases. Password lookups using hashed databases are much more efficient. To manage DBM password files, you'll use the dbmmanage script. dbmmanage is a Perl script, so you'll need to have Perl installed. Perl is an interpreted programming language that is widely used for CGI program development. The Perl program is located in the support directory. You may have to edit the location of the Perl binary on the first line of the script to match the location of your copy. You'll also need to set the execute bit on the script so that your shell will execute it. The syntax to the dbmmanage program is

dbmmanage dbmfile [adduser] [add] [delete] [view] username password group

The name of your DBM database is dbmfile; if it doesn't exist, it will be created for you. Note that DBM databases may be implemented as two files: dbmfile.pag and dbmfile.dir. DBM files are not user readable. They contain binary information. Don't try to edit them by hand or alter their contents with anything besides the dbmmanage tool. The hashed database routine needs them both to operate correctly.


When I refer to dbmfile I am talking about the base name of the file without the .pag or .dir extensions! The DBM code used to access the files automatically references whichever of these files it needs to work with. All your references to DBM files should just specify the base name of the file, excluding any suffixes.

The adduser option to dbmmanage encrypts the password field. You can specify as many groups as you like. Just separate them with a comma (,) without any surrounding whitespace. Adduser is the option you'll use for adding users to your database. Here's an example:

# support/dbmmanage passwords/password adduser user1 pw group1,group2
User user1 added with password pw:group1,group2, encrypted to XXZx5yHFQJRp.: group1,group2
# support/dbmmanage passwords/password adduser user2 pw group2
User user2 added with password pw:group2, encrypted to XXZx5yHFQJRp.:group2

The add option adds a key/value pair. You can use this to add descriptions or notes to your DBM file. Just make sure your key value doesn't overwrite a username. Also, if your value has more than one word, quote the contents:

# dbmmanage dbmfile add key "This is a multiword value"

The delete option deletes a entry matching key:

# dbmmanage dbmfile delete key

The view option displays all entries in dbmfile:

# support/dbmmanage passwords/password view
user1 = XXZx5yHFQJRp.:group1,group2
user2 = XXZx5yHFQJRp.:group2

Group Authentication


Besides authenticating users on an individual basis, you can group users. This grouping process is similar to the grouping concept used for permissions under UNIX. Grouping users is a convenient method for providing a finer degree of access control. It allows you to manage many users as a single entity.

If you request membership to a particular group as a requirement to access materials, then users not only need to provide a valid login and password, but they also need to be members of the specific group in order to gain access.

To enable group authentication to your document root, you'll need to edit your AuthGroupFile directive to point to a valid group file. As in the previous section, the directive you use to specify the location of your group file will vary depending on the module you use to provide the authentication. AuthGroupFile is available on the base release because the module mod_auth is compiled by default into Apache. The other variants, AuthDBMGroupFile and AuthDBGroupFile, are available if you reconfigure and recompile Apache to include mod_auth_dbm or mod_auth_db, respectively. Here's a sample configuration:

<Directory /usr/local/etc/httpd/htdocs>
 AllowOverride None
 AuthUserFile /usr/local/etc/httpd/passwords/passwordfile
 AuthGroupFile /usr/local/etc/httpd/passwords/groupfile
 AuthName These documents are only available to authorized users in our domain name
 AuthType Basic
 <Limit Get>
 require group group1 group2 ...
 order deny,allow
 deny from all
 allow from domain
 </Limit>
</Directory>

The only changes made to the previous section were to the AuthGroupFile directive. Previously, I disabled group authentication by pointing it to /dev/null as the group file. I also modified the require directive. Earlier I was allowing any valid users in the password file. Now I am requiring that, besides being in the password file, the user belong to either group1 or group2.

As previously, both the directive and the file used for group authentication depend on the module you are using:

Module


Group Authentication Directive

mod_auth AuthGroupFile groupfile
mod_auth_dbm AuthDBMGroupFile dbmgroupfile
mod_auth_db AuthDBGroupFile dbgroupfile

To create a group file for use with the mod_auth module (AuthGroupFile directive), you'll need a text editor.

The format of the file is simple:

groupname: user1 user2 user3 ...

groupname is the name for the group followed by a colon (:), and then followed by a list of usernames that appear in the password file separated by spaces. Different groups are separated by a new line (\n) character:

group1: user1 user2 user3
group2: user2 user3

You'll need to restart httpd for your changes to take effect.

If you are using mod_auth_dbm or mod_auth_db, the group management process is a little easier. dbmmanage allows you to specify group memberships right on the password file.

Using the adduser option to dbmmanage, you can assign group memberships at the same time you add a user. You can specify as many groups as you like for each user. Just separate them with a comma (,) without any surrounding whitespace:

# support/dbmmanage passwords/password adduser user1 pw group1,group2
User user1 added with password pw:group1,group2, encrypted to XXZx5yHFQJRp.: group1,group2
# support/dbmmanage passwords/password adduser user2 pw group2
User user2 added with password pw:group2, encrypted to XXZx5yHFQJRp.:group2

Then all you need to do is reference the same password file for group information:

 AllowOverride None
 AuthDBMUserFile /usr/local/etc/httpd/passwords/passwordfile
 AuthDBMGroupFile /usr/local/etc/httpd/passwords/passwordfile
 AuthName These documents are only available to authorized users in our domain name
 AuthType Basic
 <Limit Get>
 require group group1 group2
 order deny,allow
 deny from all
 allow from domain
 </Limit>

In case it was not obvious, the examples have been using two or more forms of authentication at the same time. Using domain-level access plus user and group authentication methods provides additional levels of security because users need to meet several criteria before gaining access: They need to access the material from a specified domain, then they need to have a valid login and password, and finally their login name must belong to a group.

Summary


As mentioned earlier, the access control and authentication methods provided by Apache can help to make your server relatively safe; however, no single mode of protection is bulletproof. If you can trust your DNS, then access control is a safe method for restricting access.

Passwords are transmitted in clear text form and encoded to ensure that they arrive intact. However, this encoding does not provide an encryption layer, so any user along the network could intercept a request to your server and decode the password. Finally, even if you trusted that no one will listen for passwords, remember that transactions on plain vanilla versions of Apache are not encrypted. Your materials are sent in world-readable form.

Beginning with Apache 1.1, some new authentication modules and methods are available. One of them, mod_auth_msql, allows you to store authentication information on a relational database (mSQL). For more information on how to use the mod_auth_msql directives, please refer to Chapter 10.