                How To Install mod_authnz_external.c
		           Version 3.3.x

NOTES:

 * If you want to use the HARDCODE function option follow the instructions
   in the INSTALL.HARDCODE file in this directory before following these
   instructions.

 * These instructions are for Apache version 2.4.  This version of
   mod_authnz_external will not work with older versions of Apache.
   Other versions are available for different releases of Apache:

     Apache 1.3   mod_auth_external-2.1.x
     Apache 2.0   mod_auth_external-2.2.x
     Apache 2.2   mod_authnz_external-3.1.x or mod_authnz_external-3.2.x
     Apache 2.4   mod_authnz_external-3.3.x

   You can check your apache version by running it from the command line
   with the -v flag.

 * If you are upgrading from mod_auth_external to mod_authnz_external,
   read the UPGRADE file.

 * Starting with version 3.2.x, mod_authnz_external is designed to work
   on any platform supported by Apache.  Previous versions were Unix-only.
   So mod_authnz_external might work on Windows, but the author doesn't
   really do Windows development and doesn't even own a Windows C compiler.
   So it has not been tested at all, no pre-compiled Windows code is available,
   and there are no installation instructions for non-Unix platforms.  If
   you figure any of this out, please consider contributing your findings.

 * Originally, mod_auth_external was a stand-alone module.  However a new
   authentication module structure was introduced in Apache-2.1, where
   mod_auth_basic and mod_auth_digest are the only top-level authentication
   modules.  All other authentication modules simply provide authentication
   services to these modules, and have names starting with "mod_authn_" for
   authentication modules, or "mod_authz_" for access control modules, or
   "mod_authnz_" for modules that provide both services.  Mod_Authnz_External
   is designed to fit into this new structure.  It has essentially the same
   features as mod_auth_external, but there are differences in the
   configuration commands.  It should be noted that it is still possible to
   use older-style independent authentication modules in Apache 2.2, and
   mod_auth_external-2.2.x can be made to work with only a little difficulty
   arising from mod_auth_basic's reluctance to be turned off.  See the
   mod_auth_external INSTALL document for information on using it with
   Apache 2.2

 * Do not, however, install both mod_auth_external and mod_authnz_external
   in your httpd.  I don't know what exactly would happen, but it won't be
   good.

 * There are two ways of installing mod_authnz_external on a Unix system. 

     (1) You can statically link it with Apache.  This requires rebuilding
	 Apache in such a way that mod_authnz_external will be compiled in. 
         Nobody does this anymore.

     (2) You can make mod_authnz_external a dynamically loaded module.  If
	 your Apache has been built to support dynamically loaded modules
	 you can do this without rebuilding Apache, so it is pretty easy.
	 Performance may be slightly worse with this option.  For information
	 on dynamically loaded modules see http://www.apache.org/docs/dso.html

   Instructions for both options are given here.  The dynamic loading
   option will probably be preferred on virtually all modern installations.

 * There is also documentation in the README file and in the AUTHENTICATORS
   file.  If you find this document unclear, reading those may help.


INSTALL METHOD A: Dynamically Linking Mod_auth_external using apxs:
-------------------------------------------------------------------

Step 1:
	Ensure that your Apache server is configured to handle dynamically
	loaded modules.  To check this, run Apache server with the -l command
	flag, like

	       httpd -l

	If mod_so.c is one of the compiled-in modules, then you are ready
	to go.  Note that some installations may give the http daemon different
	names, like 'apache' or 'httpd2'.  Some may have multiple copies of
	apache sitting in different directories.  Be sure you looking at the
	one that is being run.

Step 2:
	Compile the module using the following command in the
	mod_authnz_external distribution directory:

		apxs -c mod_authnz_external.c

	'Apxs' is the Apache extension tool.  It is part of the standard
	Apache distribution.  If you don't have it, then there may be a
	Apache development package that needs to be installed on your system,
	or your Apache server may not be set up for handling dynamically
	loaded modules.  Some systems rename it weirdly, like 'apxs2' in
	some openSUSE distributions.

	Apxs should create a file named 'mod_authnz_external.so'.

	AIX Note:  For Apache 1.3 on AIX the 'apxs' command compiled
	   mod_authnz_external.c into mod_authnz_external.o correctly, but
	   generation of the shared library file failed with a message like
	   "No csects or exported symbols have been saved."  We don't know
	   if this still happens with Apache 2.0.  If it does happen, the
	   fix under Apache 1.3 was to create a file in the current
	   directory named mod_authnz_external.exp which contained the two
	   lines below:

		 #! mod_authnz_external.o
		 authnz_external_module 

	   Then run 
	    
		apxs -c mod_authnz_external.c -bE:mod_authnz_external.exp
 
Step 3:
	Install the module.  Apxs can do this for you too.  Do the following
	command (as root so you can write to Apache's directories and config
	files):

	       apxs -i -a mod_authnz_external.la

	This will create mod_authnz_external.so and copy it into the proper
	place, and add appropriate AddModule and LoadModule commands to the
	configuration files.  (Actually, it may get the LoadModule command
	wrong.  See below.)

Step 4:
	Go to the CONFIGURATION instructions below.


INSTALL METHOD B: Statically Linking
------------------------------------

Step 1:
	Read the instructions on how to configure the Apache server in the
	INSTALL file provided with the Apache source.

Step 2:
	When you run the ./configure script, include an --with-module flag,
	giving the full pathname to the mod_authnz_external.c file in this
	distribution.  For example, if you have unpacked this distribution
	in /usr/local/src/mod_authnz_external and are building Apache for
	installation in /usr/local/apache, you might do:

    ./configure --prefix=/usr/local/apache \
      --with-module=aaa:/usr/local/src/mod_authnz_external/mod_authnz_external.c

	This will copy the mod_authnz_external.c file into the correct place in
	the Apache source tree and set things up to link it in.

Step 3:
	Type "make" to compile Apache and "make install" to install it.

Step 4:
	Go to the CONFIGURATION instructions below.


CONFIGURATION:
--------------

There are three parts to doing the configuration.  First, if you are using
dynamic loading, you need to configure Apache to load the mod_authnz_external
module.  If 'apxs' is working correctly, it should do this for you
automatically, but it doesn't always.

Second you define the external program and communication method to use in
your httpd.conf file, identifying them with a keyword.

Finally you set up specific directories to use that authenticator, referencing
it by keyword.

These instructions talk about editing the "httpd.conf" file, as it appears in
the standard Apache distributions.  In many version of Linux, however, this
file will actually just include a lot of other configuration files, some of
which may be automatically generated by various GUI configuration tools.  I
include notes on some of these variations that I have encountered, but you
may need to do some of your own figuring to find out how to adapt these
instructions to your server configuration.

(1) Configuring Module Loading:

    This step is only required if you are using dynamic loading.  In theory,
    apxs will have done it for you.  If you are trustful, you can skip ahead
    to step 2 and only come back to this if things don't seem to be working.
    In cases where you are using multiple non-authoritative authenticators
    you'll probably want to check this manually, even if apxs works right, to
    ensure that the modules are loaded (and thus envoked) in the desired order.

    (a) First, you should make sure that there is a proper "LoadModule"
	command in the httpd.conf file.  This should have been put there
	by 'apxs' but, some older Linux distributions, like Redhat 6.1,
	messed it up.  Basically, the 'LoadModule' command should look a
	lot like all the other LoadModule commands.  Something like

	    LoadModule authnz_external_module modules/mod_authnz_external.so

	where the second part is the path from Apache's root directory
	to the location where the module was stored by apxs.

	Make sure that apxs didn't put this directive inside any inappropriate
	<IfDefine> directives, as some Redhat versions have done in the past.

	If you previously had mod_authnz_external or mod_auth_external
	installed and are installing a new version, you may have more than
	one LoadModule command into httpd.conf.  You only need one.  Get rid
	of the old ones.

    (b) Check you httpd.conf file to see if there is a "ClearModuleList"
	command.  If this exists, then you need to add a command like:

	    AddModule mod_authnz_external.c

	somewhere below "ClearModuleList" command (probably somewhere among
	the dozens of other AddModule commands).  If you used 'apxs' to
	install mod_authnz_external, then this should already be done, but
	it may again be stashed in an inappropriate <IfDefine>.

	The standard Apache configuration files don't have a "ClearModuleList"
	command and don't need an "AddModule" command.  However the standard
	RedHat configuration files, among others, do.

(2) Configurating the External Authenticator

    In this section we insert commands into httpd.conf that will be run when
    Apache starts up to tell Apache where your external authenticators are
    and how to communicate with them.

    It is possible to configure several different external authenticators
    into Apache.  For each one you need to configure a name, a method
    of communicating with authenticator, and the location of the
    authenticator.

    The structure of Apache httpd.conf differs widely on different systems.
    The notes below on where to put configuration commands assume that you
    have something close to a straight apache install, but you probably
    don't.  Very likely there will be comments in your httpd.conf file that
    tell you where to put local configuration.

    If you are using virtual hosts, put these commands at the end of the
    appropriate <VirtualHost> block.  The declarations must be *inside*
    the <VirtualHost> block to work for a virtual host.  They are not
    inherited from the primary host to the virtual hosts.  Note that most
    Apache SSL servers are set up as virtual hosts, so you'll probably
    need to put these definitions in the <VirtualHost> block for use with
    an SSL server.

    Otherwise, just put them anywhere (just before the Virtual Hosts
    section of the standard Apache config file might make the most sense).

    Two different command syntaxes are supported in mod_authnz_external.
    One that is compatible with older releases, and one that is a bit
    more compact, using one command instead of two.

    (a) For External Authentication Programs:

	New-Style Syntax:

	   DefineExternalAuth <keyword> <method> <location>

	Old-Style Syntax:

	   AddExternalAuth <keyword> <location>
	   SetExternalAuthMethod <keyword> <method>

	<keyword> is some name you choose.  You can configure multiple
	different external authenticators by using different keywords for them.

	<method> defines how the login and password are passed to the
	external authenticator.  The only values that do anything are:

	  pipe           read newline-terminated strings from stdin.  (default)
	  environment    get args from environment variables.
	  checkpassword  read null-terminated strings from file descriptor 3.
	  function       internal authenticator called as function.

	Pipe is the default.  Environment used to be the default but it is
	insecure on some versions of Unix.  See the README file.

	<location> tells where to find the authenticator.  It's syntax varies
	somewhat by method (which is why we introduced the new syntax - to
	keep it closer to the method declaration):

	For "pipe", "environment", and "checkpassword" methods:

	    <location> is the full path where you installed your external
	    authentication program, like "/usr/local/bin/auth_check".
	    It always starts with a slash.  If you put it in quotes, you
	    can include command-line arguments, but these arguments won't
	    be processed by a shell, so you can't use wildcards or I/O
	    redirects or anything like that.  (If you need shell processing
	    of arguments, write an sh-script wrapper for your authenticator,
	    and put the path to that here.)

	For the "function" method:

	    <location> is a string like "<type>:<data>".  The <type> part
	    is a string that can be used to select from multiple internal
	    functions.  <data> is a string passed to that function and is
	    typically used as config file path.  The ":" is required even if
	    the <data> is an empty string.

	In the old-style syntax, the path declaration should always precede
	the method declaration, and the method declaration can be omitted if
	you want the default.

	Here are some examples.  We give old style syntax only for the first
	example, but it can be used in all cases:

	 * For external authentication programs using a pipe:

	   DefineExternalAuth archive_auth pipe /usr/local/bin/authcheck

	      - or -

	   AddExternalAuth archive_auth /usr/local/bin/authcheck
	   SetExternalAuthMethod archive_auth pipe

	 * For external authentication programs using environment variables:

	   DefineExternalAuth archive_auth environment /usr/local/bin/authcheck

	 * For external authenticators using the checkpassword protocol:

	   DefineExternalAuth archive_auth checkpassword "/bin/checkpassword /bin/true"

	 * For HARDCODE functions with a configuration file:

	   DefineExternalAuth archive_auth function RADIUS:/usr/local/raddb

	 * For HARDCODE functions with no configuration file:

	   DefineExternalAuth function archive_auth RADIUS:

    (b) For External Group-Checking Programs:

	If you want to use an external program to do group checking, add one
	of the following to your server's httpd.conf.

	New-Style Syntax:

	    DefineExternalGroup <keyword> <method> <location>

	Old-Style Syntax:

	    AddExternalGroup <keyword> <location>
	    SetExternalGroupMethod <keyword> <method>

	<keyword> is some name you choose to identify this particular
	group checking method.  The keywords for login authenticators and
	group authenticators are separate name spaces, so it doesn't matter
	if these keywords match any you defined with DefineExternalAuth or
	AddExternalAuth

	<method> defines how the login and group names are passed to the
	external authenticator.  Legal values are:

	   pipe - authenticator reads data from standard input.
	   environment - authenticator gets data from environment variables.

	Pipe is the default.  Environment used to be the default in older
	versions.  The "checkpassword" keyword also works, but doesn't
	really make a lot of sense since there are no checkpassword
	authenticators for groups.

	Examples:

	* For external authentication programs using a pipe:

	  DefineExternalGroup archive_group pipe /usr/local/bin/grpcheck

	     - or -

	  AddExternalGroup archive_group /usr/local/bin/grpcheck
	  SetExternalGroupMethod archive_group pipe

	* For external group check programs using environment variables:

	  DefineExternalGroup archive_group environment /usr/local/bin/grpcheck

(3) Configuring Web Pages to Use Authentication

    For any directory you want to protect, you need either a .htaccess file
    in the directory or a <Directory> block for the directory in your
    httpd.conf file.

    Note that for .htaccess files to work, you must specify "AllowOverride
    AuthConfig" in the httpd.conf file for any directories they appear
    under.  As distributed, Apache sets "AllowOverride None" for most
    directories.  If this is not changed, .htaccess files will be ignored.

    * EXTERNAL PASSWORD CHECKING:

    For normal user authentication, the following directives should be in
    the .htaccess file or <Directory> block:

	AuthType Basic
	AuthName <authname>
	AuthBasicProvider external
	AuthExternal <keyword>
	Require valid-user

    Here <authname> identifies what we are authenticating for - it usually
    appears in the browser's pop-up login window.  <keyword> matches a
    keyword you defined with DefineExternalAuth or AddExternalAuth in step 2.

    If you only want some users to have access to the directory, as opposed
    to all valid users, you can list the users on the "require" line,
    changing it to:

	Require user <username1> <username2> ...

    Or if you want to allow only user's whose login name matches the
    login name of the unix user who owns the file being accessed, you
    can say (assuming you have mod_authz_owner installed):

	Require file-owner

    It is possible to list more than one authenticator on the AuthExternal
    command:

        AuthExternal <keyword1> <keyword2>...

    Here each keyword should match an authenticator defined with the
    DefineExternalAuth command.  If the first authenticator fails, then
    the second one will be run, and so on, until either one authenticator
    accepts the user's login/password combination or all reject it.

    * EXTERNAL GROUP CHECKING:

    If you want to use the external group check program to allow only
    users in a given group to have access, you could do:

	AuthType Basic
	AuthName <authname>
	AuthBasicProvider external
	AuthExternal <keyword>
	GroupExternal <groupkeyword>
	Require external-group <groupname1> <groupname2> ...

    Here <groupkeyword> matches a name you defined with with the 
    DefineExternalGroup or AddExternalGroup command in step 2.

    Normally if you have multiple group names on your "Require group"
    command, then the group checker will be run only once, passing it the
    whole space-separated list of groups.  Some older group checking
    programs may only be able to handle one group name at a time.  So if
    you want the group checker to be run once for each group name, you can
    add the directive:

        GroupExternalManyAtOnce off

    If you have GroupExternalManyAtOnce turned off, then you can have
    spaces in your group names by enclosing the names in quote marks.
    If it is on, then all parsing of the group name list is up to your
    authenticator.

    If, instead of listing group names, you want to allow access only
    to users whose group name (as determined by whatever group database
    your external group checker uses) matches the unix group name that
    owns the file being accessed, you can configure an external group
    checker and then install mod_authz_owner and do:

        Require external-file-group

    The GroupExternal directive cannot (yet?) be used with multiple external
    authenticators.

    * USE WITH MOD_AUTHN_SOCACHE

    Mod_authnz_external version 3.3.1 and later can be used with the
    Apache mod_authn_socache module, which caches authentications. If
    you do this, then after a successful authentication, mod_socache
    will remember the user for a settable time (5 minutes by default)
    and not rerun the external authenticator again to check their password
    until after the timeout.  This can be a very substantial performance
    improvement.

    It can also be a very substantial security problem.  One common use of
    mod_authnz_external is to authenticate from databases that are not readable
    by Apache, and should not be.  For example, if you are authenticating out
    of the a unix password file with pwauth, you don't want make the password
    file readable to Apache because then an Apache bug would risk exposing
    your entire password file to the net. But if you turn on caching with
    mod_authn_socache, then the cache it builds up is essentially an
    Apache-readable copy of the most sensitive data from your password file.
    With some settings, it may even be stored on disk rather than on memory.
    The only good thing you can say for it is that all the passwords in that
    cache will be encrypted (even if you are dopey enough not to encrypt them
    in your actual password database). But encryption is a pretty weak
    defense all by itself.

    So using mod_authnz_external with mod_authn_socache might be dumb, but,
    what the heck, when have we passed up a chance to give you more rope to
    hang yourself with?

    One note: normally when you use mod_authn_socache with one of the standard
    Apache modules, a cache entry is created everytime it looks up a user's
    password in the database, even if the password they submitted wasn't
    the correct one.  With mod_authnz_external it only happens after
    successful authentications. That's because mod_authnz_external doesn't
    have direct access to the password database. After a successful
    authentication we can fake-up something that looks to mod_authn_socache
    like some credentials out of a database by simple encrypting the password
    that the user sent us and pretending we got that out of a database. This
    means we don't get quite the performance gains that mod_authn_socache
    would give with something like mod_authn_dbd, but we get pretty close.

    So here's how you do it. First you AuthBasicProvider statement should
    list both 'socache' and 'external', and it's important that 'socache'
    should be listed first, so that it tries to look up users in the cache
    before mod_authnz_external runs the authenticator:

       AuthBasicProvider socache external

    Then you need to tell mod_authnz_external to start forging credentials
    for mod_authn_socache:

       AuthExternalProvideCache On

    And you need to tell mod_authn_socache to accept credentials from
    mod_authnz_external:

       AuthnCacheProvideFor external

    And that should do it. You should see many fewer runs of the external
    authenticator, and perhaps a slight decline in your overall security.

    * PASSING CONTEXT INFORMATION INTO AUTHENTICATORS:

    If you want the authentication to work slightly differently in
    different directories, then you can add a directive like:

        AuthExternalContext <context>

    This will simply pass whatever <context> string was given to the
    authenticator in an environment variable called CONTEXT.  The
    authenticator can use that to modify it's behavior.

    * MODIFYING ERROR CODES FOR GROUP CHECKING:

    Normally, if a group authentication fails, then apache will return a
    401 error, which will normally cause the browser to pop up a fresh
    login box so the user can try logging in with a different ID.  This
    may not always be appropriate.  If you rejected him because he has a
    blocked IP address, returning a 403 error, which displays an error
    page (which you can configure) may be a better choice than asking him
    to endlessly try new logins and passwords.

    Previous versions of mod_authnz_external had a 'GroupExternalError'
    directive that allowed you to change this. This no longer exists
    Under Apache 2.4 you can control the return code using the
    'AuthzSendForbiddenOnFailure' directive.

    * USING GROUP CHECKING INDEPENDENT OF USER CHECKING:

    Normally, the group authorization process checks that a user was 
    successfully authenticated by the user authentication module before 
    actually running the external group checking program.  This may be 
    undesirable if your goal is to use mod_authz_external on its own as 
    a group checker, without any user checking. You can use the 
    following directive in your Apache config to disable the user 
    authentication check:
    
    GroupExternalAuthNCheck Off
    

    * INTERACTIONS WITH OTHER AUTHENTICATORS:

    Previous versions of mod_authnz_external had 'GroupExternalAuthoritative'
    directive. In Apache 2.4, the notion of authoritativeness is
    thankfully almost entirely gone, so this directive is too.
    
    * OLD DIRECTIVES

    Some of the directives mentioned above used to have different names.
    One old name still works for backward compatibility.

	AuthExternalGroupsAtOnce      equals   GroupExternalManyAtOnce

(4) Install the Authenticator

    Install your external authentication program in the location named
    by the pathname on your AddExternalAuth directive.

    Make sure everything is permitted so that whatever account the httpd
    runs under can execute the authenticator.  Typically this requires
    'execute' access to the script and all the directories above it.  If
    it is a script, then read access to the script will also be needed.  

    If your script is an set-uid script, then make sure the file is owned
    by the user it is supposed to run as, and that the suid-bit is set.

(5) Restart Apache

    Restart Apache, so that all the new configuration commands will be
    loaded.  If you have the apachectl command do:

	apachectl restart

    For some systems which doesn't have apachectl, you'll want to manually
    run the startup script for apache.  The locations of these vary somewhat
    in different Unix systems, but they typically are something like this:

	/etc/init.d/httpd restart

(6) Test It

    Test your changes/code by trying to view a protected page.
    
    If it doesn't work, check the apache error logs.  They are loaded
    with helpful information.  Some common problems and their usual causes:

      - Miscellaneous odd behaviors.

	Did you restart the httpd after the last time you edited the
	httpd.conf file or recompiled Apache?  Confirm that an
	"Apache configured -- resuming normal operations" message appeared
	in the error log when you restarted.

      - Apache complains about not recognizing mod_authnz_external commands
        in the httpd.conf file like "DefineExternalAuth" and "AddExternalAuth".

	Either the module didn't get installed (if you statically linked
	the module, are you running the newly compiled copy of httpd?),
	or it isn't enabled (if it is dynamically linked, the AddModule
	LoadModule commands described above in step (1) may be missing,
	incorrect, or commented out by an inappropriate <IfDefine>).
	Sometimes I've found that the httpd.conf file I've been editing is
	not actually the one being used by the copy of Apache that is
	running.  Sometimes I test this by inserting deliberately invalid
	commands and checking to see if error messages are generated when
	Apache is restarted. We leave the choice of invalid command words
        to be used to your imagination.

      - It displays pages in a protected directory without asking for
	a login and password.

	For some reason Apache is not seeing the directory configuration
	commands that set up authentication for that directory.  If you
	are using .htaccess files, does your httpd.conf file say
	"AllowOverride AuthConfig" for the directory?  Apache is usually
	distributed with "AllowOverride None" set, which will cause
	.htaccess files to be quietly ignored.

      - All logins are rejected, and the error log says it cannot execute the
        authentication module.  Error messages might look like:
	
	    exec of '/foo/bar/authcheck' failed: (2) No such file or directory
	    [Thu Nov 15 12:26:43 2007] [error] AuthExtern authcheck
	       [/foo/bar/authcheck]: Failed (-1) for user foo
            [Thu Nov 15 12:26:43 2007] [error] user foo: authentication
	       failure for /mae/index.html": Password Mismatch

	The first of these three messages is from Apache's process launching
	library, and gives the clearest information about what caused the
	error.  Typically it will be either "No such file", which means that
	the pathname you specified for the authenticator in step (2) does
	not match the actual location of your external authenticator, or
	it will be "permission denied", indicating that either the file
	or one of the directories above it is permitted so whatever account
	apache is configured to run as does not have execute permission.
	If it's a script, it also needs read opinion.

	The second error message is actually generated by mod_auth_external.
	It just says authentication failed for the user.  Normally it would
	give the status code returned by the authenticator in parenthesis,
	but if the authenticator could not be executed it will show a
	phoney status code of -1 (which some systems display as 255).

	The third error message is from Apache.  Don't be mislead by it's
	saying "Password Mismatch".  When mod_auth_external fails, it
	rejects all access attempts.  To apache this looks like a
	Password Mismatch.
	
      - Authentications failed and the message in the error log says it
        failed with a status code of -2 or 254, for example:

	    [Thu Nov 15 12:26:43 2007] [error] AuthExtern authcheck
	       [/foo/bar/authcheck]: Failed (-2) for user foo
            [Thu Nov 15 12:26:43 2007] [error] user foo: authentication
	       failure for /mae/index.html": Password Mismatch

        A status code of -2 (or 254) indicates that the authenticator
        crashed or was killed before it could return a status code.  This
	could either be because some other process sent it a signal to
	terminate it, or it crashed due to some kind internal error in
	the code, causing a segmentation fault or some other similar
	crash.

      - Error log says "Failed (X) for user foo" with X being some number
        other than -1, -2, 255 or 254.
      
	The authenticator ran, and exited with the given non-zero return
	code.  You'll have to check the authenticator to see under what
	conditions it exits with that return code.
