How To Install mod_authnz_external.c Version 3.2.2 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.2. 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 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. (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 prefered 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 preceed 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 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, 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 file-group The GroupExternal cannot (yet?) be used with multiple external authenticators. * 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 mod_authnz_external 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. To get a 403 error instead of a 401 error on failed group access checks, you would add the following command to your configuration: GroupExternalError 403 This would effect only group checks, never password checks. Bad passwords always result in a 401 error. * INTERACTIONS WITH OTHER AUTHENTICATORS: It is possible to configure more than one different authentication module. If you do so, you will normally want to make them unauthoritative, so that if one fails, the others will be tried. That way, authentication or access will be granted if ANY of the the configured modules finds it valid. If all your password checkers are "authn" modules running under mod_auth_basic, then you need do nothing. The arbitration among such modules is different than the arbitration between top level modules, and does the right thing by default. But if some are not "authn" modules, then you'll want to make mod_auth basic unauthoritative with the "AuthBasicAuthoritative off" directive described in the Apache manual. If you have multiple group checkers, then you will need to make mod_authnz_external un-authoritative for group checking. To do this, use the directive: GroupExternalAuthoritative off Of course, you'll probably also have to make the other module unauthoritative. For example, if you have a "Require user pete" directive and a "Require group admin" directive and expect it to allow either pete or any admin to login, then you need to make mod_authz_user unauthoritative, because that's what checks "Require user" directives. See the Apache manual pages on AuthType, AuthName, AuthBasicProvider, Require, and AuthGroupFile for more information. * OLD DIRECTIVES Some of the directives mentioned above used to have different names. The old names still work for backward compatibility. AuthzExternalAuthoritative equals GroupExternalAuthoritative 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 staticly 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. - 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 255 or -1. 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.