authnz_external configuration for apache2 with pwauth

Introduction

About

Configuring authnz external is rather difficult, as there is nowhere a real good list of instructions how to do that. This document will provide you with an installation procedure for Ubuntu, to get authnz_external running with pwauth and PAM authentification.

Why

Sometimes you want to configure Apache to ask for a password, when a user tries to access a page. One option is to use the apache password system for each website, or another possibility is to authenticate against the shadow file of your linux distro, where all users are in a central system.

Several options exist to realize this configuration. You might have already tried auth_pam. Unfortunately this module is no longer maintained. It's still possible to get it running for Apache 2.2, but a central flaw remains: apache needs read access to the systems shadow file.

Another possibility you might have found to work is auth_shadow. While this module is still being maintained and works quite easily, this also requires Apache to access the shadow file.

Granting access to the shadow file could lead to security problems when using apache with any script language that can execute files as the apache user. It is possible this way to read the contents of the password file and get the passwords of the system.

Authnz_external offers the possibility to use the PAM system via pwauth, without requiring access to the shadow file and therefore is much more secure.

Comments and Contact

If you have any comments, any additional information for me to add or mistakes I should correct, you can contact me via email at "mallox [at] pyxzl [dot] net" or visit me at my homepage www.pyxzl.net.

Document History

A list of changes throughout the versions of this document:

v1.01 added info about pwauth access rights and proper pam_modules
v1.00 document published

Preparation

Program Versions

The following Versions are being used and installed during this tutorial:

Ubuntu Server 8.04.1
Apache2 2.2.8-1
libapache2-mod-authnz-external 3.1.0
pwauth 2.3.8

Requirements

Part of this installation is to compile pwauth, as there is no package available on ubuntu. For this you will need gcc and make. These are usually already included in the ubuntu server distro.

Another requirement, as we want to compile pwauth with pam capabilities, is the development version of libpam. To install it just type:

sudo apt-get install libpam0g-dev

pwauth

Compiling pwauth

First you need to download the sources from the pwauth website, as there is no package in the standard ubuntu repositories as of the writing of this document. You can get it at:
unixpapa.com/pwauth

Unpack the archive (the version might be different):

tar -xf pwauth-2.3.6.tar.gz

Before going on we need to know the user id of the apache user. In Ubuntu that user is called www-data. To get the id you can use the following command:

id www-data
As a result let's assume 50 and use that for further references.

Next we need to configure the file config.h in the extracted pwauth directory. Set the following options:

/* #define SHADOW_NONE */
/* #define SHADOW_BSD */
/* #define SHADOW_SUN */
/* #define SHADOW_JFH */
/* #define SHADOW_MDW */
/* #define SHADOW_AIX */
/* #define SHADOW_HPUX */
#define PAM
/* #define PAM_OS_X */
/* #define PAM_SOLARIS */
/* #define PAM_SOLARIS_26 */
/* #define LOGIN_CONF_OPENBSD */

/* #define FAILLOG_JFH */
/* #define FAILLOG_OPENBSD */
/* #define FAILLOG_PWAUTH */

/* #define PATH_FAILLOG "/var/log/faillog" */
/* #define MAX_FAIL_COUNT 40 */
/* #define RESET_FAIL_COUNT */
#define UNIX_LASTLOG
#define HAVE_LASTLOG_H

#define NOLOGIN_FILE "/etc/nologin"
#define MIN_NOLOGIN_UID 1

#define CHECK_LOGIN_EXPIRATION
#define CHECK_PASSWORD_EXPIRATION

#define SERVER_UIDS 50

#define MIN_UNIX_UID 500

/* #define IGNORE_CASE */

/* #define DOMAIN_AWARE */

#define SLEEP_LOCK "/var/run/pwauth.lock"

/* #define ENV_METHOD */

#define PATHS_H

Most of the settings are explained in thorough inside the file and the defaults of most settings are fine in this version. Important changes here are:

Next we want to compile pwauth, but we still need to do a small adjustment as it won't compile otherwise. open the file Makefile and change the following line:

#LIB= -lcrypt
LIB= -lpam -ldl

Now you can go ahead an compile pwauth for use with your system. Inside the pwauth directory run:

make

If all went well there should be no error and inside of your pwauth folder you should have a file called pwauth. You can try to run it, but it won't work yet, as we have to do some adjustments to the PAM configuration.

To make pwauth able to read the shadow file via pam the access rights need to be adjusted. Without this the binary will not work pam_unix.so and an actual check of the password is impossible:

chmod u+s pwauth

You probably want to copy the executables in the pwauth directory to a standard directory like /usr/local/bin or something similar, where they are accessible by system users. Don't forget to copy the unixgroup executable as well. Usually you can use the command sudo make install but the installation routines must be defined within the makefile, which isn't the case here.

Configuring PAM

pwauth now needs to have a PAM configuration. Otherwise we can't access the PAM system and the program is basically useless.
Create the pwauth pam file:

sudo vi /etc/pam.d/pwauth
pwauth will access PAM, which will then check in here what access will be granted.

The following is a simple configuration. You might want to set your own config for further security improvements, but this should work for a start.

auth    required        pam_succeed_if.so user=www-data
auth    required        pam_unix.so
account required        pam_localuser.so
The first line will check if the user accessing is the httpd user. Change it to the appropriate name, if the user is called differently on your system.
The second line will check if the user accessing is one of the local accounts.

This setup might not be secure enough for you, or you want to authenticate against other modules like samba. In that case check the manual for PAM and the modules at:
kernel.org

With this pwauth should be ready to run, and no further configuration should be needed on this.

Testing pwauth

Now that everything is setup, we need to test if it actually works, before going on. First we will try to run pwauth as root and check if it works in general. Run pwauth (you might have to prepend the path to pwauth, if you haven't copied it to the proper location):

sudo pwauth

The program doesn't output anything. You will be left with a blank line where you should enter a username, after pressing return the corresponding password and pwauth will terminate after pressing return again. Be warned though, the password will be displayed clearly on the command line, so you might want to setup a temporary user for these tests. To check whether the user authenticated correctly you need to run the following command:

echo $?

If the response is 0, you have successfully authenticated. Any other result means you made a mistake somewhere and need to recheck your configuration.

Now we want to test if the same works as apache user. Run (change www-data to appropriate apache user of your system):

sudo -u www-data pwauth

If the results are the same as with the root user, you are ready to go and everything is working just fine. In this case you can jump to the next chapter and skip this part.

If you had problems a number of things can have happened:


To check your pam configuration, you can do a number of things:

authnz_external

Installing authnz_external

Installing authnz_external is pretty easy in comparison. Just run:

sudo apt-get install libapache2-mod-authnz-external

Check if it the module is enabled and do so if not through the following command:

sudo a2enmod authnz_external

If it wasn't already enabled it will be now.

Configuring an Apache virtual host

I'm assuming you already have you apache configured properly and maybe a few virtual hosts running. We now want to add a password protection to one of the vhosts. Your initial vhost file can be as simple as this:

<VirtualHost *:80>
    DocumentRoot /var/www/my/private/area
    ServerName private.mysite.com
</VirtualHost>

We now have to add the following directives to the virtual host to tell it where the authentication programs are and how to use them. If you copied them to a different location adjust the following lines accordingly:

AddExternalAuth pwauth /usr/local/bin/pwauth
SetExternalAuthMethod pwauth pipe
AddExternalGroup unixgroup /usr/local/bin/unixgroup
SetExternalGroupMethod unixgroup environment

Next we need to tell which part of the virtual host is supposed to be protected and by what means. In this example we're going to protect the entire host, by adding an authentication request to the root location of the document root here:

<Location />
    AuthType Basic
    AuthBasicProvider external
    AuthExternal pwauth
    GroupExternal unixgroup
    AuthName "My Test"
    Require group users
    Require user myaccount
</Location>	

I'm not sure why, but authenticating only against a group works, whereas authenticating just a user requires also a group directive. Adjust the directives according to you users and groups that you wish to grant access.

Finally the entire configuration should look like this:

<VirtualHost *:80>
    DocumentRoot /var/www/my/private/area
    ServerName private.mysite.com

    AddExternalAuth pwauth /usr/local/bin/pwauth
    SetExternalAuthMethod pwauth pipe
    AddExternalGroup unixgroup /usr/local/bin/unixgroup
    SetExternalGroupMethod unixgroup environment

    <Location />
        AuthType Basic
        AuthBasicProvider external
        AuthExternal pwauth
        GroupExternal unixgroup
        AuthName "My Test"
        Require group users
        Require user myaccount
   </Location>
</VirtualHost>

All that is left to do now is to restart apache and test if the password is accepted once you logon to the configured virtual host.
You can test the apache configuration with the following command:

apache2ctl configtest
If everything is okay, try to restart apache with:
sudo apache2 -k restart
If you now check your website at the configured address of the virtual host, you should be prompted to enter a password, which is the one of your system user account. Apache is configured and we're done.

If you had a previous configuration with auth_pam or auth_shadow, don't forget to remove access to the shadow file for the apache user, otherwise this whole procedure was all for nothing.

You can check if apache can access the shadow file by entering:

sudo -u www-data cat /etc/shadow

Again, adjust the username to your configuration if necessary. The response should be a friendly "permission denied!"


Comments

Click to post a comment

Name:
Submit Cancel

Michael L. 2009-05-12 08:47:16

Great article, thanks for the walkthrough. One small problem that came up during my install on a jaunty (9.04) system is that the users weren't actually being authenticated - any valid username was authenticating regardless of the password submitted. Turned out I needed to add:

auth required pam_unix.so

to a third line in my '/etc/pam.d/pwauth' file. Works like a charm now!

(Ubuntu forum thread on the subject here: http://ubuntuforums.org/showthread.php?p=7262450#post7262450 )


Michael L. 2009-05-12 20:05:59

Okay, my previous comment wasn't a complete solution. I needed to 'setuid' my pwauth as well. Please see the discussion on the thread mentioned above.


andreask 2009-08-27 20:46:11

Hi,

Thanks for the walkthrough. I did the PAM authentication a bit differntly, but basically this gets my Apache2 server to authenticate against my unix accounts, exactly the way I wanted it!

Once again, thanks!


Ravi 2009-08-27 23:15:54

Your welcome, glad I could help.

Maybe you can post your configuration, just for others to see an alternative? would be cool.


Nick 2010-08-27 03:24:04

Thanks a lot for this guide, it was very useful. The one change I had to make to get my pwauth to authenticate against NIS (not local accounts) was to just tell it to use ubuntu's common-auth and common-accounts:

# cat /etc/pam.d/pwauth

auth requisite pam_nologin.so
# Standard Un*x authentication.
" [at] include" common-auth
# Standard Un*x account
" [at] include" common-account