Digest Authentication using DBM based storage

Here Apache HTTP Server makes use of Digest Authentication using DBM storage for authentication files. Make sure to read Setting up Authentication and Authorization before proceeding.
There is no official support available from Apache for using DBM based storage with Digest Authentication. A discussion was started on 24th July 2005 in the httpd-dev mailing list with the intention of adding more features to htdigest utility. But this discussion sadly ended in itself.

However an unofficial solution has been presented by Berend de Boer, which we will be using in this setup.

Flatfile based storage stores usernames and passwords in plaintext. Everytime a user is verified, a request is made to the server. So, as the number of user entries increase, the process slows down in proportional to the size of the password file. This is because the server has to open up the password file, and go down the list of users until it gets to the required one. And this has to be done every time a request is made. So there is a practical limit to how many users can be put in a password file. This limit will vary depending on the performance of a particular server, but slowdowns are expected once we get above a few hundred entries.

A solution to this is to store usernames and passwords in a database. Apache HTTP Server currently supports the DBM databases Berkeley DB 2, NDBM, GDBM and SDBM.
We can make use of Apache HTTP Server‘s htdbm utility for creating and managing DBM authentication databases that use Digest HTTP authentication.
There are a number of different DBM file formats in existence. All these libraries use different file formats. htdbm currently has no way of determining what type of DBM file it is looking at. If used against the wrong format, htdbm may simply return nothing, or may create a different DBM file with a different name, or at worst, it may corrupt the DBM file if we were attempting to write into it.
We can use the file utility supplied with most Linux/Unix systems to see what format a DBM file is in.
EXAMPLE: # file testfile.dbm

htdbm prefers the Berkeley DB 2 file format. This is because the order in which htdbm will look for system libraries is Berkeley DB 2, NDBM, GDBM and SDBM. The first library found will be the library htdbm will attempt to use for all DBM file transactions.
This format preference is made possible by @AnyDBM::ISA array near the beginning of the htdbm. This ordering is slightly different than the standard @AnyDBM::ISA ordering in Perl, as well as the ordering used by the simple dbmopen() call in Perl. So if we use any other utilities to manage our DBM files, they must also follow this preference ordering.



Digest Authentication using DBM based storage involves the following steps.
1) Modifying Apache HTTP Server’s source code
2) Configuring Apache HTTP Server
3) Managing Apache Users and Groups
4) Examples

 

 

1) Modifying Apache HTTP Server’s source code

WARNING: Modifying Apache HTTP Server's source code can result in unforeseen complications. Neither me nor Apache will be responsible for any damages caused. Do it on your own risk.

Apache HTTP Server does not comes with suppport for Digest Authentication using DBM based storage. To unofficially support this, we must modify Apache HTTP Server‘s source code. This has to be done during install time. The procedure is explained here.

 

 

2) Configuring Apache HTTP Server
Open Apache HTTP Server‘s main configuration file httpd.conf.

Digest authentication requires the module mod_auth_digest.so. mod_auth_digest.so is compiled by default on an Apache HTTP Server installation unless we explicitly disable it using the configure option --enable-mods-shared=few or --disable-auth-digest. We need to enable it manually.
Look for the line containing mod_auth_digest.so. Uncomment the line so it looks as shown below.

LoadModule auth_digest_module modules/mod_auth_digest.so


User authentication using DBM files require the module mod_authn_dbm.so. mod_authn_dbm.so is compiled by default on an Apache HTTP Server installation unless we explicitly disable it using the configure option --enable-mods-shared=few or --disable-authn-dbm. We need to enable it manually.
Look for the line containing mod_authn_dbm.so. Uncomment the line so it looks as shown below.

LoadModule authn_dbm_module modules/mod_authn_dbm.so


Group authentication using DBM files require the module mod_authz_dbm.so. mod_authz_dbm.so is compiled by default on an Apache HTTP Server installation unless we explicitly disable it using the configure option --enable-mods-shared=few or --disable-authz-dbm. We need to enable it manually.
Look for the line containing mod_authz_dbm.so. Uncomment the line so it looks as shown below.

LoadModule authz_dbm_module modules/mod_authz_dbm.so

Save and close the file.


Restart the apache service gracefully.

# service apache graceful

 

 

3) Managing Apache Users and Groups
We can use the htdbm utility provided by Apache HTTP Server for creating and managing authentication databases that use Digest HTTP authentication.
Currently htdbm can only be used to create and manage users. There is no concept of groups in htdbm. Hopefully support for groups will be added in future.


Before proceeding further we must understand the usage of Realm in Digest Authentication. Realm is a concept in Digest Authentication defined by RFC2617.

Technically,
Realm value is a string, assigned by the origin server. It is required for the challenge issued by digest authentication scheme. It allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication schemes and/or authorization databases.
The realm value is also a part of the digested data stored in the password file. So if one Digest Authentication password file is compromised, it does not compromise other password files with same username and password.

For end users,
The realm value is a string to be displayed to users, so they know which username and password to use. An example might be [email protected].
For those thinking what is difference between Realms & Groups
Consider a company with two buildings. Each building can be considered as a realm. Let there be a specific worker who is friends with few other workers, whom together form a group. This group has access to first building, which means this group has access to the first realm. Again let this specific worker be allowed access to the second building, which means this worker has access to the second realm. Also, Realms in addition to Groups provide separate protection spaces and authentication schemes.

When defining a Realm value, the following points should be kept in mind.
• Realm string should be the same value used for AuthName directive.
• Realm string should be unique among all realms which any single user is likely to use.
• Realm string should contain at least the name of the host performing the authentication and might have additional semantics for end user to identify the realm.
• Realm string is case-insensitive.


Let us create an authentication database .htdbm_digest in /usr/local/apache2/, with Apache user auser1 in realm [email protected]. Execute the below command in terminal. We will be asked to type a new password for the user. Type it and press Enter.

# htdbm -cB /usr/local/apache2/.htdbm_digest "auser1:[email protected]"

NOTE: If there is an existing password file, the option -c will only work if the password file was created by or follows the exact format as expected by htdbm utility. Otherwise the new authentication details will be appended resulting in a corrupt authentication file.

OPTIONS EXPLAINED

-c
Create the passwdfile. If passwdfile already exists, it is rewritten and truncated. This option cannot be combined with the -n option.

-B
Use bcrypt encryption for passwords. This is currently considered to be very secure.

filename
The filename of the DBM format file. Usually without the extension .db, .pag, or .dir. If -c is given, the DBM file is created if it does not already exist, or updated if it does exist.

username
The username to create or update in passwdfile. If username does not exist in this file, an entry is added. If it does exist, the password is changed.



Let us also add three other Apache users auser2, auser3 and auser4 in realm [email protected], to the authentication database .htdbm_digest.

# htdbm -B /usr/local/apache2/.htdbm_digest "auser2:[email protected]"
# htdbm -B /usr/local/apache2/.htdbm_digest "auser3:[email protected]"
# htdbm -B /usr/local/apache2/.htdbm_digest "auser4:[email protected]"
OPTIONS EXPLAINED

-B
Use bcrypt encryption for passwords. This is currently considered to be very secure.

filename
The filename of the DBM format file. Usually without the extension .db, .pag, or .dir. If -c is given, the DBM file is created if it does not already exist, or updated if it does exist.

username
The username to create or update in passwdfile. If username does not exist in this file, an entry is added. If it does exist, the password is changed.



The authentication database .htdbm_digest is currently owned by root and is world readable. Let us set proper permissions for this file. Change the user and group ownership of .htdbm_digest file to apache.

# chown apache:apache /usr/local/apache2/.htdbm_digest


Remove read permissions of others for the .htdbm_digest file.

# chmod o-r /usr/local/apache2/.htdbm_digest
OPTIONS EXPLAINED

o-r
Unset read permission for other users who are not members of the file's group

 

Deleting a user
If we have to delete a user named baduser in realm [email protected] from the authentication database .htdbm_digest, execute the below command in terminal.

# htdbm -x /usr/local/apache2/.htdbm_digest "baduser:[email protected]"
OPTIONS EXPLAINED

-x
Delete user. If the username exists in the specified DBM file, it will be deleted.

filename
The filename of the DBM format file. Usually without the extension .db, .pag, or .dir. If -c is given, the DBM file is created if it does not already exist, or updated if it does exist.

username
The username to create or update in passwdfile. If username does not exist in this file, an entry is added. If it does exist, the password is changed.

This will delete the user named baduser from .htdbm_digest. The permissions of .htdbm_digest file will remain intact.


Verifying the password of a user
If we have to verify the password of user named auser1 in realm [email protected], execute the below command in terminal.

# htdbm -v /usr/local/apache2/.htdbm_digest "auser1:[email protected]"
OPTIONS EXPLAINED

-v
Verify the username and password. The program will print a message indicating whether the supplied password is valid. If the password is invalid, the program exits with error code 3.

filename
The filename of the DBM format file. Usually without the extension .db, .pag, or .dir. If -c is given, the DBM file is created if it does not already exist, or updated if it does exist.

This will ask us the password of user auser1 in realm [email protected] for verification.

 

 

4) Examples
The sample configurations provided in the below examples should be placed inside the <Directory> or <Location> block of Apache HTTP Server‘s configuration files or inside .htaccess files.
Make sure to read Setting up Authentication and Authorization before proceeding.

TIP: Read about htaccess directives.
WARNING: The authentication files should never be accessible to the outside world. If possible they should not be placed within the webserver's URI space. Even if they are placed, Access Control must be implemented denying any access to them.

Apache HTTP Server's main configuration file httpd.conf contains the following lines, that denies access to any files having a filename starting with .ht.
    <Files ".ht*">
         Require all denied
    </Files>
Follow the naming of your authentication files according to this configuration.


EXAMPLE 1: To password protect a directory, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			user auser1 auser2

This will present the user with a Username & Password prompt when they try to access the specified directory. Only users auser1 and auser2 in the realm [email protected] are authorized to access.


EXAMPLE 2: To password protect a directory, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user

This will present the user with a Username & Password prompt when they try to access the specified directory. All users in the realm [email protected] are authorized to access.


EXAMPLE 3: To password protect a file, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
<Files "file1.jpg">
  Require valid-user
</Files>

This will present the user with a Username & Password prompt when they try to access the specified file file1.jpg. All users in the realm [email protected] are authorized to access.


EXAMPLE 4: To password protect multiple files, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
<FilesMatch "(file1.jpg)|(file2.zip)|(file3)">
  Require valid-user
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access the specified files file1.jpg, file2.zip, file3. All users in the realm [email protected] are authorized to access.


EXAMPLE 5: To password protect a filetype, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
<FilesMatch ".jpg">
  Require valid-user
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access the files with extension .jpg. All users in the realm [email protected] are authorized to access.


EXAMPLE 6: To password protect multiple filetypes, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
<FilesMatch ".(jpg|pdf|zip|rar)$">
  Require valid-user
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access the files with extensions .jpg, .pdf, .zip, .rar. All users in the realm [email protected] are authorized to access.


EXAMPLE 7: To password protect multiple files/filetypes, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
<FilesMatch "file*">
  Require valid-user
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access all files whose filename starts with file. All users in the realm [email protected] are authorized to access.
OR

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
<FilesMatch "(file[1-2].jpg)|(file3)">
  Require valid-user
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access the files file1.jpg, file2.jpg and file3. All users in the realm [email protected] are authorized to access.


EXAMPLE 8: To password protect everything in a directory, except a single file, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user
<Files "file1.jpg">
  Require all granted
</Files>

This will present the user with a Username & Password prompt when they try to access anything in the directory except the file file1.jpg. All users in the realm [email protected] are authorized to access.


EXAMPLE 9: To password protect everything in a directory, except multiple files, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user
<FilesMatch "(file1.jpg)|(file2.zip)|(file3)">
  Require all granted
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access anything in the directory except the files file1.jpg, file2.zip, file3. All users in the realm [email protected] are authorized to access.


EXAMPLE 10: To password protect everything in a directory, except a specific filetype, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user
<FilesMatch ".jpg">
  Require all granted
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access anything in the directory except the files with extension .jpg. All users in the realm [email protected] are authorized to access.


EXAMPLE 11: To password protect everything in a directory, except multiple filetypes, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user
<FilesMatch ".(jpg|pdf|zip|rar)$">
  Require all granted
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access anything in the directory except the files with extensions .jpg, .pdf, .zip and .rar. All users in the realm [email protected] are authorized to access.


EXAMPLE 12: To password protect everything in a directory, except multiple files/filetypes, with access to all users in a specific realm, add the below content to configuration file.

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user
<FilesMatch "file*">
  Require all granted
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access anything in the directory except the files whose filename starts with file. All users in the realm [email protected] are authorized to access.
OR

AuthName		"[email protected]"
AuthType		Digest
AuthDigestProvider	dbm
AuthDBMType		DB
AuthDigestDomain 	/
AuthDBMUserFile		/usr/local/apache2/.htdbm_digest
Require			valid-user
<FilesMatch "(file[1-2].jpg)|(file3)">
  Require all granted
</FilesMatch>

This will present the user with a Username & Password prompt when they try to access anything in the directory except the files file1.jpg, file2.jpg and file3. All users in the realm [email protected] are authorized to access.


EXAMPLE 13: If we want to disable password protection for a specific directory, add the below content to configuration file.

Require all granted

This will not present the user with the Username & Password prompt when they try to access that directory.

 

 

 

It is recommended to view the following sections.
Basic Authentication using Flatfile based storage
Basic Authentication using DBM based storage
Digest Authentication using Flatfile based storage

OR

You may go back to the following section.
Securing Apache HTTP Server