mod_authnz_external-3.3.2/ 0000755 0001750 0000144 00000000000 12252354121 014255 5 ustar jan users mod_authnz_external-3.3.2/TODO 0000644 0001750 0000144 00000001705 11205135454 014753 0 ustar jan users Jan Wolter:
- Look into developing a "socket" method, in which we first try open a
socket connecting to the external authenticator, and only launch a new one
if the initial connection attempt fails. This would avoid launching a
new authenticator for each hit. Instead the authenticator would be a
persistant process that can hold open a connection to the database and
even do caching of recent authentications.
- Improve Windows support. Theoretically version 3.2.0 should work on
windows, but I don't do windows development and can't test it or
document installation procedures.
- I think the apache data structure r->subprocess_env is a table into which
various modules place environment variable definitions that they want to
have passed into CGI programs, for example, mod_ssl puts HTTPS and a
bunch of other variables here. Should I load all of them into the
environment for the external authenticator? Needs study.
mod_authnz_external-3.3.2/mod_authnz_external.c 0000644 0001750 0000144 00000072604 12252136725 020514 0 ustar jan users /* ====================================================================
* Copyright (c) 1995 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 5. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see .
*
*/
/* Uncomment if you want to use a HARDCODE'd check (default off) */
/* #define _HARDCODE_ */
#ifdef _HARDCODE_
/* Uncomment if you want to use your own Hardcode (default off) */
/* MUST HAVE _HARDCODE_ defined above! */
/* #include "your_function_here.c" */
#endif
#include "apr_lib.h"
#include "ap_config.h"
#include "ap_provider.h"
#include "mod_auth.h"
#include "apr_signal.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apr_strings.h"
#include "apr_sha1.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/
#if APR_HAVE_UNISTD_H
#include
#endif
#ifndef STANDARD20_MODULE_STUFF
#error This module requires Apache 2.2.0 or later.
#endif
/* Names of environment variables used to pass data to authenticator */
#define ENV_USER "USER"
#define ENV_PASS "PASS"
#define ENV_GROUP "GROUP"
#define ENV_URI "URI"
#define ENV_IP "IP"
#define ENV_HOST "HOST" /* Remote Host */
#define ENV_HTTP_HOST "HTTP_HOST" /* Local Host */
#define ENV_CONTEXT "CONTEXT" /* Arbitrary Data from Config */
/* Undefine this if you do not want cookies passed to the script */
#define ENV_COOKIE "COOKIE"
/* Maximum number of arguments passed to an authenticator */
#define MAX_ARG 32
/* Default authentication method - "pipe", "environment" or "checkpass" */
#define DEFAULT_METHOD "pipe"
/*
* Structure for the module itself. The actual definition of this structure
* is at the end of the file.
*/
module AP_MODULE_DECLARE_DATA authnz_external_module;
/*
* Data types for per-directory and per-server configuration
*/
typedef struct
{
apr_array_header_t *auth_name; /* Auth keyword for current dir */
char *group_name; /* Group keyword for current dir */
char *context; /* Context string from AuthExternalContext */
int groupsatonce; /* Check all groups in one call? */
int providecache; /* Provide auth data to mod_authn_socache? */
} authnz_external_dir_config_rec;
typedef struct
{
apr_table_t *auth_path; /* Hash mapping auth keywords to paths */
apr_table_t *auth_method; /* Hash mapping auth keywords to methods */
apr_table_t *group_path; /* Hash mapping group keywords to paths */
apr_table_t *group_method; /* Hash mapping group keywords to methods */
} authnz_external_svr_config_rec;
/* mod_authz_owner's function for retrieving the requested file's group */
APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
/* mod_authn_socache's function for adding credentials to its cache */
static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authn_cache_store = NULL;
/* Creators for per-dir and server configurations. These are called
* via the hooks in the module declaration to allocate and initialize
* the per-directory and per-server configuration data structures declared
* above. */
static void *create_authnz_external_dir_config(apr_pool_t *p, char *d)
{
authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
apr_palloc(p, sizeof(authnz_external_dir_config_rec));
dir->auth_name= apr_array_make(p,2,sizeof(const char *)); /* no default */
dir->group_name= NULL; /* no default */
dir->context= NULL; /* no default */
dir->groupsatonce= 1; /* default to on */
dir->providecache= 0; /* default to off */
return dir;
}
static void *create_authnz_external_svr_config( apr_pool_t *p, server_rec *s)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
apr_palloc(p, sizeof(authnz_external_svr_config_rec));
svr->auth_method= apr_table_make(p, 4);
svr->auth_path= apr_table_make(p, 4);
svr->group_method= apr_table_make(p, 4);
svr->group_path= apr_table_make(p, 4);
/* Note: 4 is only initial hash size - they can grow bigger) */
return (void *)svr;
}
/* Handler for a DefineExternalAuth server config line */
static const char *def_extauth(cmd_parms *cmd, void *dummy, const char *keyword,
const char *method, const char *path)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config( cmd->server->module_config,
&authnz_external_module);
apr_table_set( svr->auth_path, keyword, path );
apr_table_set( svr->auth_method, keyword, method );
return NULL;
}
/* Handler for a DefineExternalGroup server config line */
static const char *def_extgroup(cmd_parms *cmd, void *dummy,
const char *keyword, const char *method, const char *path)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config( cmd->server->module_config,
&authnz_external_module);
apr_table_set( svr->group_path, keyword, path );
apr_table_set( svr->group_method, keyword, method );
return NULL;
}
/* Handler for a AddExternalAuth server config line - add a external auth
* type to the server configuration */
static const char *add_extauth(cmd_parms *cmd, void *dummy, const char *keyword,
const char *path)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config( cmd->server->module_config,
&authnz_external_module);
apr_table_set( svr->auth_path, keyword, path );
apr_table_set( svr->auth_method, keyword, DEFAULT_METHOD );
return NULL;
}
/* Handler for a AddExternalGroup server config line - add a external group
* type to the server configuration */
static const char *add_extgroup(cmd_parms *cmd, void *dummy,
const char *keyword, const char *path)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config( cmd->server->module_config,
&authnz_external_module);
apr_table_set( svr->group_path, keyword, path );
apr_table_set( svr->group_method, keyword, DEFAULT_METHOD );
return NULL;
}
/* Handler for a SetExternalAuthMethod server config line - change an external
* auth method in the server configuration */
static const char *set_authnz_external_method(cmd_parms *cmd, void *dummy,
const char *keyword, const char *method)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config( cmd->server->module_config,
&authnz_external_module);
apr_table_set( svr->auth_method, keyword, method );
return NULL;
}
/* Handler for a SetExternalGroupMethod server config line - change an external
* group method in the server configuration */
static const char *set_extgroup_method(cmd_parms *cmd, void *dummy,
const char *keyword, const char *method)
{
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config( cmd->server->module_config,
&authnz_external_module);
apr_table_set( svr->group_method, keyword, method );
return NULL;
}
/* Append an argument to an array defined by the offset */
static const char *append_array_slot(cmd_parms *cmd, void *struct_ptr,
const char *arg)
{
int offset = (int)(long)cmd->info;
apr_array_header_t *array=
*(apr_array_header_t **)((char *)struct_ptr + offset);
*(const char **)apr_array_push(array)= apr_pstrdup(array->pool, arg);
return NULL;
}
/* Config file directives for this module */
static const command_rec authnz_external_cmds[] =
{
AP_INIT_ITERATE("AuthExternal",
append_array_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec,auth_name),
OR_AUTHCFG,
"one (or more) keywords indicating which authenticators to use"),
AP_INIT_TAKE3("DefineExternalAuth",
def_extauth,
NULL,
RSRC_CONF,
"a keyword followed by auth method and path to authentictor"),
AP_INIT_TAKE2("AddExternalAuth",
add_extauth,
NULL,
RSRC_CONF,
"a keyword followed by a path to the authenticator program"),
AP_INIT_TAKE2("SetExternalAuthMethod",
set_authnz_external_method,
NULL,
RSRC_CONF,
"a keyword followed by the method by which the data is passed"),
AP_INIT_TAKE1("GroupExternal",
ap_set_string_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec, group_name),
OR_AUTHCFG,
"a keyword indicating which group checker to use"),
AP_INIT_TAKE3("DefineExternalGroup",
def_extgroup,
NULL,
RSRC_CONF,
"a keyword followed by auth method type and path to group checker"),
AP_INIT_TAKE2("AddExternalGroup",
add_extgroup,
NULL,
RSRC_CONF,
"a keyword followed by a path to the group check program"),
AP_INIT_TAKE2("SetExternalGroupMethod",
set_extgroup_method,
NULL,
RSRC_CONF,
"a keyword followed by the method by which the data is passed"),
AP_INIT_TAKE1("AuthExternalContext",
ap_set_string_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec, context),
OR_AUTHCFG,
"An arbitrary context string to pass to the authenticator in the "
ENV_CONTEXT " environment variable"),
AP_INIT_FLAG("AuthExternalProvideCache",
ap_set_flag_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec, providecache),
OR_AUTHCFG,
"Should we forge authentication credentials for mod_authn_socache?"),
AP_INIT_FLAG("GroupExternalManyAtOnce",
ap_set_flag_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec, groupsatonce),
OR_AUTHCFG,
"Set to 'off' if group authenticator cannot handle multiple group "
"names in one invocation" ),
AP_INIT_FLAG("AuthExternalGroupsAtOnce",
ap_set_flag_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec, groupsatonce),
OR_AUTHCFG,
"Old version of 'GroupExternalManyAtOnce'" ),
{ NULL }
};
/* Called from apr_proc_create() if there are errors during launch of child
* process. Mostly just lifted from mod_cgi. */
static void extchilderr(apr_pool_t *p, apr_status_t err, const char *desc)
{
apr_file_t *stderr_log;
char errbuf[200];
apr_file_open_stderr(&stderr_log, p);
apr_file_printf(stderr_log,"%s: (%d) %s\n", ap_escape_logitem(p,desc),
err, apr_strerror(err,errbuf,sizeof(errbuf)));
}
/* Run an external authentication program using the given method for passing
* in the data. The login name is always passed in. Dataname is "GROUP" or
* "PASS" and data is the group list or password being checked. To launch
* a detached daemon, run this with extmethod=NULL.
*
* If the authenticator was run, we return the numeric code from the
* authenticator, normally 0 if the login was valid, some small positive
* number if not. If we were not able to run the authenticator, we log
* an error message and return a numeric error code:
*
* -1 Could not execute authenticator, usually a path or permission problem
* -2 The external authenticator crashed or was killed.
* -3 Could not create process attribute structure
* -4 apr_proc_wait() did not return a status code. Should never happen.
* -5 apr_proc_wait() returned before child finished. Should never happen.
*/
static int exec_external(const char *extpath, const char *extmethod,
const request_rec *r, const char *dataname, const char *data)
{
conn_rec *c= r->connection;
apr_pool_t *p= r->pool;
int isdaemon, usecheck= 0, usepipeout= 0, usepipein= 0;
apr_procattr_t *procattr;
apr_proc_t proc;
apr_status_t rc= APR_SUCCESS;
char *child_env[12];
char *child_arg[MAX_ARG+2];
const char *t;
int i, status= -4;
apr_exit_why_e why= APR_PROC_EXIT;
apr_sigfunc_t *sigchld;
/* Set various flags based on the execution method */
isdaemon= (extmethod == NULL);
if (!isdaemon)
{
usecheck= extmethod && !strcasecmp(extmethod, "checkpassword");
usepipeout= usecheck || (extmethod && !strcasecmp(extmethod, "pipes"));
usepipein= usepipeout || (extmethod && !strcasecmp(extmethod, "pipe"));
}
/* Create the environment for the child. Daemons don't get these, they
* just inherit apache's environment variables.
*/
if (!isdaemon)
{
const char *cookie, *host, *remote_host;
authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
ap_get_module_config(r->per_dir_config, &authnz_external_module);
i= 0;
if (!usepipein)
{
/* Put user name and password/group into environment */
child_env[i++]= apr_pstrcat(p, ENV_USER"=", r->user, NULL);
child_env[i++]= apr_pstrcat(p, dataname, "=", data, NULL);
}
child_env[i++]= apr_pstrcat(p, "PATH=", getenv("PATH"), NULL);
child_env[i++]= apr_pstrcat(p, "AUTHTYPE=", dataname, NULL);
remote_host= ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST,NULL);
if (remote_host != NULL)
child_env[i++]= apr_pstrcat(p, ENV_HOST"=", remote_host,NULL);
if (r->useragent_ip)
child_env[i++]= apr_pstrcat(p, ENV_IP"=", r->useragent_ip, NULL);
if (r->uri)
child_env[i++]= apr_pstrcat(p, ENV_URI"=", r->uri, NULL);
if ((host= apr_table_get(r->headers_in, "Host")) != NULL)
child_env[i++]= apr_pstrcat(p, ENV_HTTP_HOST"=", host, NULL);
if (dir->context)
child_env[i++]= apr_pstrcat(r->pool, ENV_CONTEXT"=",
dir->context, NULL);
#ifdef ENV_COOKIE
if ((cookie= apr_table_get(r->headers_in, "Cookie")) != NULL)
child_env[i++]= apr_pstrcat(p, ENV_COOKIE"=", cookie, NULL);
#endif
/* NOTE: If you add environment variables,
* remember to increase the size of the child_env[] array */
/* End of environment */
child_env[i]= NULL;
}
/* Construct argument array */
for (t= extpath, i=0; *t != '\0' && (i <= MAX_ARG + 1);
child_arg[i++]= ap_getword_white(p, &t)) {}
child_arg[i]= NULL;
/* Create the process attribute structure describing the script we
* want to run using the Thread/Process functions from the Apache
* portable runtime library. */
if (((rc= apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||
/* should we create pipes to stdin, stdout and stderr? */
((rc= apr_procattr_io_set(procattr,
(usepipein && !usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE,
usepipeout ? APR_FULL_BLOCK : APR_NO_PIPE,
(usepipein && usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE))
!= APR_SUCCESS ) ||
/* will give full path of program and make a new environment */
((rc= apr_procattr_cmdtype_set(procattr,
isdaemon ? APR_PROGRAM_ENV : APR_PROGRAM)) != APR_SUCCESS) ||
/* detach the child only if it is a daemon */
((rc= apr_procattr_detach_set(procattr, isdaemon)) != APR_SUCCESS) ||
/* function to call if child has error after fork, before exec */
((rc= apr_procattr_child_errfn_set(procattr, extchilderr)
!= APR_SUCCESS)))
{
/* Failed. Probably never happens. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
"could not set child process attributes");
return -3;
}
/* Sometimes other modules wil mess up sigchild. Need to fix it for
* the wait call to work correctly. */
sigchld= apr_signal(SIGCHLD,SIG_DFL);
/* Start the child process */
rc= apr_proc_create(&proc, child_arg[0],
(const char * const *)child_arg,
(const char * const *)child_env, procattr, p);
if (rc != APR_SUCCESS)
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
"Could not run external authenticator: %d: %s", rc,
child_arg[0]);
return -1;
}
if (isdaemon) return 0;
apr_pool_note_subprocess(p, &proc, APR_KILL_AFTER_TIMEOUT);
if (usepipein)
{
/* Select appropriate pipe to write to */
apr_file_t *pipe= (usecheck ? proc.err : proc.in);
/* Send the user */
apr_file_write_full(pipe, r->user, strlen(r->user), NULL);
apr_file_putc(usecheck ? '\0' : '\n', pipe);
/* Send the password */
apr_file_write_full(pipe, data, strlen(data), NULL);
apr_file_putc(usecheck ? '\0' : '\n', pipe);
/* Send dummy timestamp for checkpassword */
if (usecheck) apr_file_write_full(pipe, "0", 2, NULL);
/* Close the file */
apr_file_close(pipe);
}
/* Wait for the child process to terminate, and get status */
rc= apr_proc_wait(&proc,&status,&why,APR_WAIT);
/* Restore sigchild to whatever it was before we reset it */
apr_signal(SIGCHLD,sigchld);
if (!APR_STATUS_IS_CHILD_DONE(rc))
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
"Could not get status from child process");
return -5;
}
if (!APR_PROC_CHECK_EXIT(why))
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"External authenticator died on signal %d",status);
return -2;
}
return status;
}
/* Call the hardcoded function specified by the external path. Of course,
* you'll have to write the hardcoded functions yourself and insert them
* into this source file, as well as inserting a call to them into this
* routine.
*/
static int exec_hardcode(const request_rec *r, const char *extpath,
const char *password)
{
#ifdef _HARDCODE_
char *check_type; /* Pointer to HARDCODE type check */
char *config_file; /* Pointer to HARDCODE config file */
int standard_auth= 0;
/* Parse a copy of extpath into type and filename */
check_type= apr_pstrdup(r->pool, extpath);
config_file= strchr(check_type, ':');
if (config_file != NULL)
{
*config_file= '\0'; /* Mark end of type */
config_file++; /* Start of filename */
}
/* This is where you make your function call. Here is an example of
* what one looks like:
*
* if (strcmp(check_type,"RADIUS")==0)
* code= radcheck(r->user,password,config_file);
*
* Replace 'radcheck' with whatever the name of your function is.
* Replace 'RADIUS' with whatever you are using as the in:
* AddExternalAuth :
*/
if (strcmp(check_type,"EXAMPLE")==0) /* change this! */
code= example(r->user,password,config_file); /* change this! */
else
code= -5;
return code;
#else
return -4; /* If _HARDCODE_ is not defined, always fail */
#endif /* _HARDCODE_ */
}
/* Handle a group check triggered by a 'Require external-group foo bar baz'
* directive. */
static authz_status externalgroup_check_authorization(request_rec *r,
const char *require_args, const void *parsed_require_args)
{
authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
ap_get_module_config(r->per_dir_config, &authnz_external_module);
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config(r->server->module_config, &authnz_external_module);
char *user= r->user;
char *extname= dir->group_name;
const char *extpath, *extmethod;
const char *t, *w;
int code;
/* If no authenticated user, pass */
if ( !user ) return AUTHZ_DENIED_NO_USER;
/* If no external authenticator has been configured, pass */
if ( !extname ) return AUTHZ_DENIED;
/* Get the path and method associated with that external */
if (!(extpath= apr_table_get(svr->group_path, extname)) ||
!(extmethod= apr_table_get(svr->group_method,extname)))
{
errno= 0;
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"invalid GroupExternal keyword (%s)", extname);
return AUTHZ_DENIED;
}
if (dir->groupsatonce)
{
/* Pass rest of require line to authenticator */
code= exec_external(extpath, extmethod, r, ENV_GROUP, require_args);
if (code == 0) return AUTHZ_GRANTED;
}
else
{
/* Call authenticator once for each group name on line */
t= require_args;
while ((w= ap_getword_conf(r->pool, &t)) && w[0])
{
code= exec_external(extpath, extmethod, r, ENV_GROUP, w);
if (code == 0) return AUTHZ_GRANTED;
}
}
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Authorization of user %s to access %s failed. "
"User not in Required group.",
r->user, r->uri);
return AUTHZ_DENIED;
}
/* Handle a group check triggered by a 'Require external-file-group'
* directive. */
static authz_status externalfilegroup_check_authorization(request_rec *r,
const char *require_args, const void *parsed_require_args)
{
authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
ap_get_module_config(r->per_dir_config, &authnz_external_module);
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config(r->server->module_config, &authnz_external_module);
char *user= r->user;
char *extname= dir->group_name;
const char *extpath, *extmethod;
const char *filegroup= NULL;
const char *t, *w;
int code;
/* If no authenticated user, pass */
if ( !user ) return AUTHZ_DENIED_NO_USER;
/* If no external authenticator has been configured, pass */
if ( !extname ) return AUTHZ_DENIED;
/* Get the path and method associated with that external */
if (!(extpath= apr_table_get(svr->group_path, extname)) ||
!(extmethod= apr_table_get(svr->group_method,extname)))
{
errno= 0;
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"invalid GroupExternal keyword (%s)", extname);
return AUTHZ_DENIED;
}
/* Get group name for requested file from mod_authz_owner */
filegroup= authz_owner_get_file_group(r);
if (!filegroup)
/* No errog log entry, because mod_authz_owner already made one */
return AUTHZ_DENIED;
/* Pass the group to the external authenticator */
code= exec_external(extpath, extmethod, r, ENV_GROUP, filegroup);
if (code == 0) return AUTHZ_GRANTED;
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Authorization of user %s to access %s failed. "
"User not in Required file group (%s).",
r->user, r->uri, filegroup);
return AUTHZ_DENIED;
}
/* Mod_authn_socache wants us to pass it the username and the encrypted
* password from the user database to cache. But we have no access to the
* actual user database - only the external authenticator can see that -
* and chances are, the passwords there aren't encrypted in any way that
* mod_authn_socache would understand anyway. So instead, after successful
* authentications only, we take the user's plain text password, encrypt
* that using an algorithm mod_authn_socache will understand, and cache that
* as if we'd actually gotten it from a password database.
*/
void mock_turtle_cache(request_rec *r, const char *plainpw)
{
char cryptpw[120];
/* Authn_cache_store will be null if mod_authn_socache does not exist.
* If it does exist, but is not set up to cache us, then
* authn_cache_store() will do nothing, which is why we turn this off
* with "AuthExternalProvideCache Off" to avoid doing the encryption
* for no reason. */
if (authn_cache_store != NULL)
{
apr_sha1_base64(plainpw,strlen(plainpw),cryptpw);
authn_cache_store(r, "external", r->user, NULL, cryptpw);
}
}
/* Password checker for basic authentication - given a login/password,
* check if it is valid. Returns one of AUTH_DENIED, AUTH_GRANTED,
* or AUTH_GENERAL_ERROR. */
static authn_status authn_external_check_password(request_rec *r,
const char *user, const char *password)
{
const char *extname, *extpath, *extmethod;
int i;
authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
ap_get_module_config(r->per_dir_config, &authnz_external_module);
authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
ap_get_module_config(r->server->module_config,
&authnz_external_module);
int code= 1;
/* Check if we are supposed to handle this authentication */
if (dir->auth_name->nelts == 0)
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"No AuthExternal name has been set");
return AUTH_GENERAL_ERROR;
}
for (i= 0; i < dir->auth_name->nelts; i++)
{
extname= ((const char **)dir->auth_name->elts)[i];
/* Get the path associated with that external */
if (!(extpath= apr_table_get(svr->auth_path, extname)))
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Invalid AuthExternal keyword (%s)", extname);
return AUTH_GENERAL_ERROR;
}
/* Do the authentication, by the requested method */
extmethod= apr_table_get(svr->auth_method, extname);
if ( extmethod && !strcasecmp(extmethod, "function") )
code= exec_hardcode(r, extpath, password);
else
code= exec_external(extpath, extmethod, r, ENV_PASS, password);
/* If return code was zero, authentication succeeded */
if (code == 0)
{
if (dir->providecache) mock_turtle_cache(r, password);
return AUTH_GRANTED;
}
/* Log a failed authentication */
errno= 0;
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"AuthExtern %s [%s]: Failed (%d) for user %s",
extname, extpath, code, r->user);
}
/* If no authenticators succeed, refuse authentication */
return AUTH_DENIED;
}
#if 0
/* Password checker for digest authentication - given a login/password,
* check if it is valid. Returns one of AUTH_USER_FOUND, AUTH_USER_NOT_FOUND,
* or AUTH_GENERAL_ERROR. Not implemented at this time and probably not ever.
*/
auth_status *authn_external_get_realm_hash(request_rec *r, const char *user,
const char *realm, char **rethash);
{
}
#endif
/* This is called after all modules have been initialized to acquire pointers
* to some functions from other modules that we would like to use if they are
* available. */
static void opt_retr(void)
{
/* Get authn_cache_store from mod_authn_socache */
authn_cache_store=
APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store);
/* Get authz_owner_get_file_group from mod_authz_owner */
authz_owner_get_file_group=
APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
}
/* This tells mod_auth_basic and mod_auth_digest what to call for
* authentication. */
static const authn_provider authn_external_provider =
{
&authn_external_check_password,
#if 0
&authn_external_get_realm_hash
#else
NULL /* No support for digest authentication */
#endif
};
/* This tells mod_auth_basic and mod_auth_digest what to call for
* access control with 'Require external-group' directives. */
static const authz_provider authz_externalgroup_provider =
{
&externalgroup_check_authorization,
NULL,
};
/* This tells mod_auth_basic and mod_auth_digest what to call for
* access control with 'Require external-file-group' directives. */
static const authz_provider authz_externalfilegroup_provider =
{
&externalfilegroup_check_authorization,
NULL,
};
/* Register this module with Apache */
static void register_hooks(apr_pool_t *p)
{
/* Register authn provider */
ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "external",
AUTHN_PROVIDER_VERSION,
&authn_external_provider, AP_AUTH_INTERNAL_PER_CONF);
/* Register authz providers */
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "external-group",
AUTHZ_PROVIDER_VERSION,
&authz_externalgroup_provider, AP_AUTH_INTERNAL_PER_CONF);
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "external-file-group",
AUTHZ_PROVIDER_VERSION,
&authz_externalfilegroup_provider, AP_AUTH_INTERNAL_PER_CONF);
/* Ask for opt_retr() to be called after all modules have registered */
ap_hook_optional_fn_retrieve(opt_retr, NULL, NULL, APR_HOOK_MIDDLE);
}
AP_DECLARE_MODULE(authnz_external) = {
STANDARD20_MODULE_STUFF,
create_authnz_external_dir_config, /* create per-dir config */
NULL, /* merge per-dir config - dflt is override */
create_authnz_external_svr_config, /* create per-server config */
NULL, /* merge per-server config */
authnz_external_cmds, /* command apr_table_t */
register_hooks /* register hooks */
};
mod_authnz_external-3.3.2/README 0000644 0001750 0000144 00000026333 12252353504 015150 0 ustar jan users Mod_Authnz_External version 3.3.x
Original Coder: Nathan Neulinger
Previous Maintainer: Tyler Allison
Current Maintainer: Jan Wolter http://www.unixpapa.com
Apache 2.0 Port: Dave Woolaway
Sven Koch
Apache 2.2 Port: Jan Wolter http://www.unixpapa.com
Caution:
--------
Mod_Auth_External can be used to quickly construct secure, reliable
authentication systems. It can also be mis-used to quickly open gaping
holes in your security. Read the documentation, and use with extreme
caution.
Versions:
---------
Mod_authnz_external version 3.3.x is designed for use with Apache version
2.4.x. It will not work with Apache 2.2 or 2.0. For older versions of
Apache you will need older branches of mod_authnz_external:
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
This module was developed from "mod_auth_external". It has been restructured
to fit into the authn/authz structure introduce in Apache 2.1. It can be used
in any application where mod_auth_external was previously used. No changes
will be needed to the external authentication programs, but the exact Apache
configuration commands needed will be different. It is possible to use the
old "mod_auth_external-2.2" with Apache-2.2, but mod_authnz_external is
preferable. If you are upgrading from "mod_auth_external" to
"mod_authnz_external" then read the file "UPGRADE" for advice.
Introduction:
-------------
Mod_Authnz_External is an Apache module used for authentication. The Apache
HTTP Daemon can be configured to require users to supply logins and passwords
before accessing pages in some directories. Authentication is the process
of checking if the password given is correct for a user. Apache has
standard modules for authenticating out of several different kinds of
databases. Mod_Authnz_External is a flexible tool for creating authentication
systems based on other databases.
Mod_Authnz_External can be used in either of two somewhat divergent ways:
External Authentication:
When a user supplies a login and password, mod_authnz_external runs a
program you write, passing it the login and password. Your program
does whatever checking and logging it needs to, and then returns a
Accept/Reject flag to Apache.
This is slower than doing the authentication internally because it
has the overhead of launching an external program for each authentication.
However, there are at least two situations where it is very useful:
- Rapid prototyping. The external authentication program can be
a shell script or perl program. It can be written without knowing
much about building Apache modules. Bugs in it will not endanger
the overall integrity of the Apache server. Later, as performance
becomes more of an issue, you can write a custom Apache module to
do the job more efficiently (perhaps using the HARDCODE option below).
- Access restrictions. There are situations where you do not want to
make your user database readable to the user-id that Apache runs
under. In these cases the external authentication program can be
an suid program that has access to databases Apache cannot access.
For example, if you want to authentication out of a Unix shadow
password database, and you aren't foolish enough to run Apache
as root, a carefully written suid-root external authentication
program can do the job for you.
Pwauth, an external authentication program for securely authenticating
out of a Unix shadow password database available from
http://www.unixpapa.com/pwauth/ .
Hardcoded Authentication:
Some hooks have been inserted into mod_authnz_external to make it easy
to replace the call to the external authentication program with a
call to a hardcoded internal authentication routine that you write.
This is sort of a half-way measure to just writing your own Apache
module from scratch, allowing you to use some of the logic from
mod_authnz_external.
Example functions for authenticating out of a RADIUS server or Sybase
database are included in this distribution.
Compatibility:
--------------
The current version of mod_authnz_external is designed for use with Apache 2.2.
It will not work with older versions of Apache.
Mod_authnz_external has been tested on a wide variety of Unix platforms. In
theory versions after 3.2.0 should work on any non-Unix platforms supported
by Apache, but it has been tested only under Unix.
Mod_authnz_external is also compatible with authenticators using the
checkpassword interface. See http://cr.yp.to/checkpwd.html for more
information.
Authn / Authz
-------------
Users of mod_authnz_external may find it helpful understand a bit more of
it's internal structure. It is actually best thought of as two functionally
separate modules, mod_authn_external and mod_authz_external, which have
combined into a single module simply because they share a lot of code.
In any particular application, you may only be using one of these two
modules, or you may be using both.
The mod_authn_external part is an authentication provider for the
mod_auth_basic module. Mod_auth_basic handles all the negotiations with
the browser, while all mod_authn_external does is check if a password
submitted by the user is correct (which it does by running an external
program to perform the check).
The mod_authz_external part does access control. It has no relation
to mod_auth_basic. It comes into play after authentication is complete,
when a "Require group" or "Require file-group" directive is given. It
checks if the authenticated user is in the list of required groups (which
it does by running an external program to perform the check).
Digest Authentication
---------------------
The new authentication structure introduced in Apache 2.1 makes it much
easier for modules like this one to support digest authentication as an
alternative to basic authentication. Mod_Authnz_External, however, does
not yet support digest authentication.
I hope to support this in the future, but it really isn't a very attractive
alternative and I don't expect many people will want to use it. It will
not be possible to use the same external authentication programs that are
used for basic authentication - they would have to be rewritten. It will
only work if the database being accessed by the external program either has
passwords in plaintext, or has them encrypted in a very specific way. This
means it could not be used for unix password database authentication or with
most other password databases not specifically designed for this application.
And password databases specifically designed for this application might as
well be designed in a format where they could be accessed by mod_authn_file
or mod_authn_dbm.
Security Considerations:
------------------------
By default, mod_authnz_external passes the user's login and password to the
external authentication program by sending them through a pipe. This is
very secure.
In older versions of mod_auth_external, the login and password were by
default passed in environment variables called USER and PASS. This is
still an option, but we do NOT recommend using option.
On some versions of Unix (including SunOS and IRIX) any user logged onto
the server can see these values by doing a "ps -e" command. This would
obviously be a problem if there are ever untrusted users on your server.
Other versions of Unix (including Linux) restrict "ps -e" so you can only
see your own processes, but this may still be a problem if untrusted people
can put CGI programs on your server, since those may run as the same user
as your authentication program does. Some versions of Unix don't seem to
have a "ps -e" command at all, but even then it is best to be careful.
Although the default "ps" command on Solaris won't display environment
variables, the backwards compatible "/usr/ucb/ps" command does. Are you
sure there isn't and won't be an old-style ps command installed on your
system?
Use of this module requires development of an external authentication program
or a hardcoded internal function. These are typically very simple programs,
but there are more ways to screw up your security by doing them badly than
we could possibly list. See the file AUTHENTICATORS for more information
on implementing authenticators.
Example Authentication Routines in this Distribution:
-----------------------------------------------------
test/
Several small dummy external authentication programs written in Perl
(there is also a PHP version of one of them). These are meant only for
testing of mod_authnz_external. They accept any user whose password
and login name are identical. They write lots of debugging info to
the error_log file.
Author and Maintainer: Jan Wolter http://unixpapa.com/
Author of PHP Version: Claus Andersen
Example Authentication Routines Formerly Included in this Distribution:
-----------------------------------------------------------------------
In the interest of cleaning up the distribution, several other examples
that were formerly distributed with this module are now only available
separately.
pwauth
A C program for authenticating out of unix shadow password files or
PAM.
Author and Maintainer: Jan Wolter http://unixpapa.com/
Available from: http://code.google.com/p/pwauth/
MYSQL-auth
A Perl program for authenticating out of a MySQL database. This is
written in Perl using the DBI interface, so it could be trivially adapted
to work with any other SQL database server that has a DBI interface
(that is to say all of them).
Author and Maintainer: Anders Nordby
Available From: http://anders.fix.no/software/#unix
sybase-internal-auth
An example of a hardcoded internal authentication function for use with
mod_auth_external or mod_authnz_external. It's designed for doing
authentication out of a sybase database, which these days would be better
done using mod_authn_dbd.
Author:
Available From: http://code.google.com/p/mod-auth-external/downloads
mae-radius
Another example or a hardcoded internal authentication function.
This does radius authentication. It may not be fully open source.
Available From: http://unixpapa.com/software/mae_radius.tar.gz
Checkpassword Authenticators
----------------------------
There are various "checkpassword" compatible authenticators available on the
net which can be used with mod_authnz_external. These authenticators are most
commonly used with qmail pop servers but it is sometimes useful to be able
to use the same authentication system for some web pages. I've listed some
of the ones that look useful for mod_authnz_external, but I've tested only
'checkpassword'.
checkpassword
http://cr.yp.to/checkpwd.html
Dan J. Bernstein
Authentication from a Unix shadow password file, similar to the
the pwauth program.
radcheckpassword
http://www.tic.ch/e-image/andrew/software/radcheckpassword/
Andrew Richards
Radius authentication.
mod_authnz_external-3.3.2/test/ 0000755 0001750 0000144 00000000000 12252354114 015236 5 ustar jan users mod_authnz_external-3.3.2/test/test.env 0000755 0001750 0000144 00000001721 11205135453 016733 0 ustar jan users #!/usr/bin/perl
# Test authenticator using environment method. Logins will be accepted if
# the login and the password are identical, and will be rejected otherwise.
#
# Generally the environment method is not recommended. Use the pipe method
# instead.
#
# This authenticator does copious logging by writing all sorts of stuff to
# STDERR. A production authenticator would not normally do this, and it
# *especially* would not write the plain text password out to the log file.
# Get the name of this program
$prog= join ' ',$0,@ARGV;
# Get the user name
$user= $ENV{USER};
# Get the password name
$pass= $ENV{PASS};
# Dump the environment to the error_log file
foreach $env (keys(%ENV))
{
print STDERR "$prog: $env=$ENV{$env}\n";
}
# Accept the login if the user name matchs the password
if ($user eq $pass)
{
print STDERR "$prog: login matches password - Accepted\n";
exit 0;
}
else
{
print STDERR "$prog: login doesn't match password - Rejected\n";
exit 1;
}
mod_authnz_external-3.3.2/test/README 0000644 0001750 0000144 00000002502 12060414337 016116 0 ustar jan users These are dummy external authenticator programs used for testing
mod_auth_external or mod_authnz_external.
They are mostly Perl scripts, and one PHP script. Before using them, make
sure that the directives on the first lines of each file:
#!/usr/bin/perl
#!/usr/bin/php
give the correct pathname for the Perl and/or PHP interpretors on your system.
The files are:
test.pipe Dummy user authentication program using pipe method
test.env Dummy user authentication program using environment method
testgroup.pipe Dummy group check program using pipe method
testgroup.env Dummy group check program using environment method
test.pipe.php PHP version of test.pipe
The user authentication programs will accept a login if the user name
matches the password, and will reject all others.
The group check programs will accept a login if the user name matches the
group name, and will reject all others.
All programs print lots of stuff to stderr. All this output should get
logged in Apache's "error_log" file, so do a "tail -f" on that file to
see what happens when you try an authentication.
(Obviously you wouldn't want to log plain-text passwords in a real
authentication program).
Author & Maintainer for Perl Versions: Jan Wolter http://www.unixpapa.com
Author of PHP Version: Claus Andersen
mod_authnz_external-3.3.2/test/test.pipe 0000755 0001750 0000144 00000001734 11205135453 017104 0 ustar jan users #!/usr/bin/perl
# Test authenticator using pipe method. Logins will be accepted if the
# login and the password are identical, and will be rejected otherwise.
#
# This authenticator does copious logging by writing all sorts of stuff to
# STDERR. A production authenticator would not normally do this, and it
# *especially* would not write the plain text password out to the log file.
# Get the name of this program
$prog= join ' ',$0,@ARGV;
# Get the user name
$user= ;
chomp $user;
# Get the password name
$pass= ;
chomp $pass;
# Print them to the error_log file
print STDERR "$prog: user='$user' pass='$pass'\n";
# Dump the environment to the error_log file
foreach $env (keys(%ENV))
{
print STDERR "$prog: $env=$ENV{$env}\n";
}
# Accept the login if the user name matchs the password
if ($user eq $pass)
{
print STDERR "$prog: login matches password - Accepted\n";
exit 0;
}
else
{
print STDERR "$prog: login doesn't match password - Rejected\n";
exit 1;
}
mod_authnz_external-3.3.2/test/test.pipe.php 0000755 0001750 0000144 00000001746 12060413563 017676 0 ustar jan users #!/usr/bin/php
$v)
{
fwrite(STDERR, $prog . ': ' . $k . '=' . $v . "\n");
}
// Accept the login if the user name matchs the password
if ($user == $pass)
{
fwrite(STDERR, $prog . ": login matches password - Accepted\n");
exit(0);
}
else
{
fwrite(STDERR, $prog . ": login doesn't match password - Rejected\n");
exit(1);
}
?>
mod_authnz_external-3.3.2/test/testgroup.env 0000755 0001750 0000144 00000001603 11205135453 020007 0 ustar jan users #!/usr/bin/perl
# Test group checker using environment method. Access will be granted if
# the login and the group name are identical, and will be rejected otherwise.
#
# This authenticator does copious logging by writing all sorts of stuff to
# STDERR. A production authenticator would not normally do this.
# Get the name of this program
$prog= join ' ',$0,@ARGV;
# Get the user name
$user= $ENV{USER};
# Get the group names
$groups= $ENV{GROUP};
# Dump the environment to the error_log file
foreach $env (keys(%ENV))
{
print STDERR "$prog: $env=$ENV{$env}\n";
}
# Loop through groups
foreach $group (split ' ', $groups)
{
# Accept the login if the user name matchs the group name
if ($user eq $group)
{
print STDERR "$prog: login name matches group name - Accepted\n";
exit 0;
}
}
print STDERR "$prog: login name doesn't match any group name - Rejected\n";
exit 1;
mod_authnz_external-3.3.2/test/testgroup.pipe 0000755 0001750 0000144 00000002074 11205135453 020157 0 ustar jan users #!/usr/bin/perl
# Test group checker using pipe method. Logins will be accepted if the
# login and the group name are identical, and will be rejected otherwise.
#
# This authenticator does copious logging by writing all sorts of stuff to
# STDERR. A production authenticator would not normally do this, and it
# *especially* would not write the plain text password out to the log file.
# Get the name of this program
$prog= join ' ',$0,@ARGV;
# Get the user name
$user= ;
chomp $user;
# Get the group name
$groups= ;
chomp $groups;
# Print them to the error_log file
print STDERR "$prog: user='$user' groups='$groups'\n";
# Dump the environment to the error_log file
foreach $env (keys(%ENV))
{
print STDERR "$prog: $env=$ENV{$env}\n";
}
# Loop through groups
foreach $group (split ' ', $groups)
{
# Accept the login if the user name matchs the group name
if ($user eq $group)
{
print STDERR "$prog: login name matches group name - Accepted\n";
exit 0;
}
}
print STDERR "$prog: login name doesn't match any group name - Rejected\n";
exit 1;
mod_authnz_external-3.3.2/INSTALL.HARDCODE 0000644 0001750 0000144 00000005231 11205135454 016462 0 ustar jan users If you want to use mod_authnz_external.c with a hardcoded internal function,
then you first have to hardcode an internal function (who wudda thunk?).
-----------------------------------------------------------------------------
Step 1:
Edit "mod_authnz_external.c"
Step 2:
Uncomment the _HARDCODE_ #define.
Step 3:
Uncomment the line:
/* #include "your_function_here.c" */
Replace "your_function_here.c" with the path/name of your function.
(Actually, I think it might be better to imbed the function itself
directly in this file instead of including it. Modules work better
if they are implemented in a single source file.)
Your function should start something like:
int
function_name (char *user_name,char *user_passwd,char *config_path)
It should return 0 if the password is correct for the given user,
and other values if it is not, pretty much just like external
authentication programs do.
You'll want to code this very carefully. A crash will crash not just
your program but the entire httpd.
** BIG NOTE TO PROGRAMMERS **
-DO NOT- use exit() or other such calls that will cause your
function to exit abnormally or dump core. It will take the entire
httpd with it and display a message to your browser saying "no data".
Use "return" instead of exit().
Step 4:
Choose a for your function. ie: 'RADIUS' or 'SYBASE'
This will be used for telling mod_authnz_external which hard coded
function you want to call.
Step 5:
Find the exec_hardcode() function inside mod_authnz_external.c.
Find the big commented section there. Replace the example call
to example() with a call to your function. Also change the name
"EXAMPLE" to the name you chose for your function.
The function call in exec_hardcode() should look something like:
if (strcmp(check_type,"")==0) {
code = function_name(c->user,sent_pw,config_file);
}
Here, we replace "" with the name you chose in step 4.
function_name(), of course, should be whatever you called your function
in step 3.
Step 6:
Save your work. Also save some whales.
Step 7:
Compile and configure mod_authnz_external as described in the
INSTALL file.
The AddExternalAuth command in your httpd.conf file might look
something like
AddExternalAuth whatever EXAMPLE:/usr/local/data/configfile
Here 'whatever' is the name you will use to invoke this authenticator
in the AuthExternal commands in your .htaccess files. 'EXAMPLE'
is the name you choose in step 4 and inserted into the "if" statement
in step 5. Any data after the colon will be passed into your function.
It might be a config file path or something else.
mod_authnz_external-3.3.2/UPGRADE 0000644 0001750 0000144 00000012012 11643333402 015265 0 ustar jan users How to upgrade from mod_auth_external to mod_authnz_external:
(0) Read the section entitled "Authn / Authz" in the README file. This will
probably make understanding this new version of the module easier.
(1) Make sure mod_auth_external is no longer being loaded. You cannot load
both mod_auth_external and mod_authnz_external without problems. This
means ensuring that there is no "LoadModule" or "AddModule" line for
mod_auth_external. You could also remove the mod_auth_external.so file
from the Apache 'modules' directory.
(2) Install mod_authnz_external as described in the INSTALL file.
(3) The server-level configuration directives in the httpd.conf file are the
same as before. There has been no change to the way "AddExternalAuth",
"AddExternalGroup", "AddExternalAuthMethod", and "AddExternalGroupMethod"
work.
(4) In the per-directory configurations (either in .htaccess files or in a
block in httpd.conf) need to include a new directive to tell
mod_auth_basic to use mod_authnz_external for authentication. For
mod_auth_external, the per-directory configurations normally looked
something this:
AuthType Basic
AuthName
AuthExternal
require valid-user
For mod_authnz_external, you need to add the "AuthBasicProvider" directive.
AuthType Basic
AuthName
AuthBasicProvider external
AuthExternal
require valid-user
The directive "AuthType Basic" tells apache that you want to use the
mod_auth_basic module to do "basic authentiation". The directive
"AuthBasicProvider external" tells mod_auth_basic to use
mod_authnz_external to check the correctness of passwords.
Note that the "AuthBasicProvider" directive is only needed if you are
using mod_authnz_external for password checking. If you are using it
only for group checking, then this is not needed.
(5) If you were using mod_auth_external in a non-authoritative mode, then
your per-directory configuration probably included the directive:
AuthExternalAuthoritative off
This command will no longer work. If upgrading to Apache 2.2, you
should use one or both of the following commands:
AuthBasicAuthoritative off
GroupExternalAuthoritative off
The "AuthBasicAuthoritative" directive effects password checking, which
is done through mod_auth_basic.
The "GroupExternalAuthoritative" effects only group checking. That is
if you had both "GroupExternal" directive setting up an external program
for group checking, and an "AuthGroupFile" directive setting up a group
file, then it would control whether the first module to process a
"Require group admin" directive was the only one to run, or whether each
group checker was given a chance to decide if the user was in that group
based on it's group database.
In Apache 2.4, all of this is handled quite differently. I need to
document this.
(6) If you were using multiple Require directives, the behavior may change
under Apache 2.2. Suppose you wanted to allow access to user "pete" and
members of the group "admins". You might have do:
Require group admin
Require user pete
Under Apache 2.0, both of these directives would have been checked by
mod_auth_external, and it would have correctly allowed access if either
of the two conditions were satisfied. In Apache 2.2, however, only
"Require group" and "Require file-group" directives are checked by
mod_authnz_external. "Require user" and "Require valid-user" are checked
by mod_authz_user, a standard module that comes with Apache. How the
two directives interact depends on whether they are authoritative or
not. mod_authz_user is Authoritative by default, so to get the old
behavior, you will need to do
GroupUserAuthoritative off
Again, in Apache 2.4, all of this is handled quite differently, and this
document needs updating.
(7) Note that a new type of functionality is available under Apache 2.2 with
mod_authnz_external. Thanks to mod_authz_owner, you can now do:
Require file-owner
or
Require file-group
The first checks if the name of the authenticated user matches the
name of the unix account that owns the file. The second checks if,
according to whatever group database has been configured for the
current directory, the currently authenticated user is in a group
with the same name as the Unix group that owns the file.
Normally these are rather strange directives, because normally unix
accounts have no relationship to accounts in whatever database is
being used for http authentication, but for people using 'pwauth'
with mod_authnz_external, these really check if the user has been
authenticated as the unix user who owns the file.
In Apache 2.4, this is the same, except the latter of the two becomes:
Require external-file-group
mod_authnz_external-3.3.2/CHANGES 0000644 0001750 0000144 00000036627 12252345737 015303 0 ustar jan users v3.3.2 (Jan Wolter - Dec 12, 2013)
----------------------------------------------
* Replaced reference to remote_ip field of the connection record with
useragent_ip, due to the elimination of remote_ip in Apache 2.4.1. Thanks
to davidsansome and cjwatson for pointing out the need for this.
* Fixed a bug with setting of GROUP environment variable. Thanks to
ddarbyson for reporting this, and Guoan Hu for posting the fix.
* Added test/test.pipe.php, a PHP version of test/test.pipe contributed
by Claus Andersen.
v3.3.1 (Jan Wolter - Oct 12, 2011)
----------------------------------------------
* Deleted most of the sample authenticators from the distribution. They
are mostly old and crufty or available elsewhere. No need to clutter
the main distribution with them.
* Added code to support caching authentications with mod_authn_socache.
This is enabled by the "AuthExternalProvideCache On" directive. This
feature should be considered experimental, since mod_authn_socache still
seems buggy and it's interface may not have been finalized.
v3.3.0 (Jan Wolter - Oct 6, 2011)
----------------------------------------------
* Revised to work with Apache 2.3 / 2.4. Will not work with previous Apache
versions.
* Deleted 'GroupExternalAuthoritative' and 'AuthzExternalAuthoritative'
directives which are obsolete.
* Deleted 'GroupExternalError' directive which is superceded by Apache's
'AuthzSendForbiddenOnFailure' directive.
v3.2.6 (Jan Wolter - Oct 6, 2011)
-----------------------------------------------
* Modified parsing of "Require groups" line so that you can have group
names that include spaces by enclosing them in quotes. This change
suggested by David Homborg.
* Default action of Makefile changed to "build" not "install".
* Corrected an exploitable SQL injection flaw in the sample mysql
authenticator.
* Add references to version 3.3.x to documentation.
v3.2.5 (Jan Wolter - Oct 29, 2009)
-----------------------------------------------
* Fixed a bug introduced in 3.2.0 in which data for checkpassword-type
authenticators is written to the authenticator's stdin instead of stderr.
v3.2.4 (Jan Wolter - May 20, 2009)
-----------------------------------------------
* Dropped the radius code from the distribution, because of possible problems
with it's license. Thanks to Hai Zaar for pointing out this problem.
* Modified AuthExternal directive to be able to take more than one
authenticator name. If more than one is defined, then each authenticator
is run in turn, until one succeeds or all have failed. Probably a similar
change should be made to GroupExternal, but it hasn't been done yet because
it's a more complex change and nobody has asked for it. Thanks to Andreas
Ntaflos for suggesting this change.
* Inserted code to restore SIGCHLD to default before running the
authenticator. Sometime other modules (like php built with the
--enable-sigchild option) leave SIGCHLD messed up, which would cause
problems with getting the return code back from authenticators. We
restore SIGCHLD to whatever state it was in originally after the
authenticator terminates. Thanks to Stefan Mehlhorn for reporting this
problem and providing the help needed to diagnose it.
* Clean-up of handling of return codes from apr_proc_wait() to be more
formally correct.
v3.2.3 (Jan Wolter - Feb 26, 2009)
-----------------------------------------------
* Added GroupExternalError directive, which allows you to specify the
HTTP error code to be returned if the group access check fails.
Defaut is 401, but you may want to return 403 if you want to show the
user an error page instead of asking him to login again. Thanks to
Peter Crawshaw for this patch.
* In hopes of getting to a more consistantly named set of directives,
added new aliases for two old directives:
GroupExternalAuthoritative alias for AuthzExternalAuthoritative
GroupExternalManyAtOnce alias for AuthExternalGroupsAtOnce
Documentation updated to refer primarily to the new names.
v3.2.2 (Jan Wolter - Dec 1, 2008)
-----------------------------------------------
THIS RELEASE UPDATES DOCUMENTATION ONLY!
* Improved documentation of AuthExternalContext directive in the INSTALL
file.
* Added documentation to the UPGRADE file on interactions between multiple
Require directives.
v3.2.1 (Jan Wolter - Jul 31, 2008)
-----------------------------------------------
* Added AuthExternalContext directive, which defines a string that will be
passed to the authenticator in the CONTEXT environment variable. This can
be set from the .htaccess file or the block to give slightly
different behavior from the same authenticator in different directories.
Thanks to Olivier Thauvin for this patch.
v3.2.0 (Jan Wolter - Jan 7, 2007)
-----------------------------------------------
* Rewrite external authenticator launching code to use Apache's cross-OS
process/thread library instead of directly calling Unix functions.
Theoretically this should get us much closer to being usable on non-
Unix platforms.
* Support alternate syntax for configuration, using DefineAuthExternal and
DefineAuthGroup commands.
* More detailed error logging.
* Much cleanup of documentation.
v3.1.0 (Jan Wolter - Feb 17, 2006)
-----------------------------------------------
* New authn/authz version for Apache 2.2.
* Renamed from "mod_auth_external" to "mod_authnz_external" to agree
with new module naming conventions.
* The more secure "pipe" method is now the default, instead of the old
insecure "environment" method.
* Eliminated "AuthExternalAuthoritative" directive. Instead use
"AuthBasicAuthoritative" for authentication and "AuthzExternalAuthoritative"
for access control.
* Substantially rewritten to function as an authentication provider for
mod_auth_basic instead of a stand-alone authentication module.
* Eliminated duplication of documentation inside mod_authnz_external.c file.
* Addition of UPGRADE document, and update of all other documentation.
* Normalization of many variable names and other clean up of code.
v2.2.10 (Jan Wolter - Sep 29, 2005)
-----------------------------------------------
* Renamed module from "external_auth_module" to "auth_external_module". This
seems to be what is wanted for static linking.
v2.2.9 (Jan Wolter - Sep 25, 2004)
-----------------------------------------------
* Small corrections to 2.0 defines, thanks to Guenter Knauf .
* Pwauth removed from this package. It is now distributed separately.
v2.2.8 (Jan Wolter - Jun 30, 2004)
-----------------------------------------------
* Trivial documentation improvement.
* Clarification of docomentation on use of pwauth options UNIX_LASTLOG,
FAILLOG_JFH, and MIN_UNIX_UID with PAM.
v2.2.7 (Jan Wolter - Oct 23, 2003)
-----------------------------------------------
* Pwauth gains IGNORE_CASE and DOMAIN_AWARE options, both aimed at making
work more easily for those used to authentication in Microsoft environments.
Thanks to Peter Eggimann for these enhancemen
* Fix one bit of remaining Apache 1.3 api inside HARDCODE block.
* Grammar corrections in AUTHENTICATORS file.
v2.2.6 (Jan Wolter - Aug 14, 2003)
-----------------------------------------------
* Minor improvements to debugging notes in the INSTALL document.
v2.2.5 (Jan Wolter - Jul 11, 2003)
-----------------------------------------------
* Pass local hostname (or virtual hostname) to authenticator in HTTP_HOST
environment variable. Thanks to Steve Horan for
submitting this modification.
v2.2.4 (Jan Wolter - Jan 12, 2003)
-----------------------------------------------
* Documentation updates for OpenBSD and minor OpenBSD portability fixes to
pwauth.
v2.2.3 (Jan Wolter - Oct 21, 2002)
-----------------------------------------------
* More update of installation instructions. Thanks to Sven Koch
and Joshua Polterock .
v2.2.2 (Jan Wolter - Oct 14, 2002)
-----------------------------------------------
* Partial update of installation instructions.
v2.2.1 (Jan Wolter - Jun 24, 2002)
-----------------------------------------------
* Corrected undefined symbol in _HARDCODE_ option. Thanks to Phil
Benchoff .
v2.2.0 (Dave Woolaway, Sven Koch & Jan Wolter - Jun 22, 2002)
--------------------------------------------------------------
* Ported to work with Apache 2.0.28 by Dave Woolaway
* Independently ported to work with Apache 2.0.39 by Sven Koch
* Version merger and insufficient documentation updates by Jan Wolter.
v2.1.15 (Jan Wolter - Jan 22, 2002)
-----------------------------------
* Added MySQL-auth to distribution. Contributed by Anders Nordby
.
v2.1.14 (Jan Wolter - Jan 1, 2002)
-----------------------------------
* Minor clarification to documentation on virtual hosts.
* Minor update of description of pwauth in README file.
* Correction of AIX compilation instructions. Thanks to Mathieu Legare
for this.
* Fixed name of GROUP environment variable in pwauth/unixgroup script. Thanks
to Jeroen Roodnat for pointing this out.
v2.1.13 (Jan Wolter - Jul 31, 2001)
-----------------------------------
* Pass AUTHTYPE environment variable to external authenticator. This is
PASS if we are doing password authentication, GROUP if we are doing group
authentication, so the same authentication program can easily be used to
do both. Thanks to Dan Thibadeau for this.
* pwauth can now be configured to work for more than one UID.
* pwauth/FORM_AUTH updated to discuss suExec.
v2.1.12 (Jan Wolter - Jul 9, 2001)
-----------------------------------
* Fixed erroneous variable names in _HARDCODE_ stuff. Thanks to Phil
Benchoff for this fix.
* Added pwauth/unixgroup, a simple perl unix group authenticator. Hope to
replace this with a better solution someday.
v2.1.11 (Jan Wolter - Apr 25, 2001)
-----------------------------------
* Arguments may now be specified for authenticators on the AddAuthExternal
command. The whole command must be in quotes, no shell meta characters
may be used, and there is a limit of 32 arguments.
* Support for the checkpassword protocol, allowing use of checkpassword
compatible authenticators. Thanks go to Matthew Kirkwood
for submitting patches for this.
* Mod_auth_external now passes the URI environment variable to all
authenticators, giving the URL of the requested page minus hostname,
and CGI arguments. Thanks to Charles Clancy
and Niall Daley for independently submitting similar
patches for this.
* Fixed a possible buffer overflow problem in the HARDCODE section. This
is unlikely to have been an exploitable security problem but could
cause a crash in rare circumstances. Thanks go to Bradley S. Huffman
for pointing this out.
* Example programs in test directory log command-line arguments.
v2.1.10 (Jan Wolter - Jan 9, 2001)
----------------------------------
* Fix a pwauth bug that could cause segmentation faults when compiled with
the ENV_METHOD option.
* Add documentation on how to use pwauth for form authentication.
* Clarify documentation on configuration for SSL servers.
v2.1.9 (Jan Wolter - Jul 7, 2000)
----------------------------------
* Correct documentation to reflect the fact that Solaris *does* have a ps
command that displays environment variables. Thanks to Piotr Klaban
for pointing this out.
v2.1.8 (Jan Wolter - May 3, 2000)
----------------------------------
* By default, pass all group names at once to group authenticators. To get
old one-group-at-a-time behavior back, use the new directive
"AuthExternalGroupsAtOnce off". This modification contributed by
Rudi Heitbaum . Thanks.
v2.1.7 (Jan Wolter - Apr 3, 2000)
----------------------------------
* Pass COOKIE environment variable to authenticator with cookies from current
request. Is this a good idea?
* Added rather dubious HP-UX support to pwauth. Untested.
v2.1.6 (Jan Wolter - Mar 23, 2000)
----------------------------------
* Added documentation about installing as a dynamically loaded module.
* Added documentation about "AddModule" command for RedHat installs.
* Lots of other small documentation improvements.
v2.1.5 (Jan Wolter - Jan 6, 2000)
----------------------------------
* Improved documentation on writing authenticators.
v2.1.4 (Jan Wolter - Jan 4, 2000)
----------------------------------
* Oops, PAM support in v2.1.3 didn't work after all. Many fixes, including
Work-around for Solaris 2.6 appdata_ptr=NULL bug. Huge thanks again to
Peter Arnold for help with testing.
* Generate compile-time error if Apache version is older than 1.3.1
* Better code to get lastlog path for pwauth.
v2.1.3 (Jan Wolter - Dec 17, 1999)
----------------------------------
* AuthExternalAuthoritative directive added. This code contributed by Mike
Burns (burns@cac.psu.edu).
* Testing of PAM support in pwauth under Solaris 2.6 by Peter Arnold
.
* Many clarifications to install manual and other documentation.
v2.1.2 beta (Jan Wolter - Jun 28, 1999)
----------------------------------
PAM support and minor bug fixes. PAM support in pwauth is based on code
contributed by Karyl Stein (xenon313@arbornet.org). Not been fully tested.
v2.1.1 (Jan Wolter - Mar 10, 1999)
----------------------------------
Various small enhancements making better use of Apache API.
* Better memory management, eliminating all use of fixed sized arrays.
* Child process calls ap_cleanup_for_exec() to close any resources (file
descriptors, etc) left open in the pools.
* Cleanup of error messages.
v2.1.0 (Jan Wolter - Mar 5, 1999)
---------------------------------
Significant rewrite, rolling in changes from various divergent versions
and a number of bug fixes, and small enhancements. Changes include:
* Better checking against overflow of various fixed sized arrays. (There was
already some protection, so there probably wasn't a big security problem
here.)
* Set environment variables in child process, not parent process. This
prevents them from being inherited by future spawned children.
* Check WIFEXITED before acceping WEXITSTATUS.
* Elimination of memory leak in strdup() calls.
* Check return code from pipe().
* Don't close standard output on child process, instead direct it to error
log file, just like stderr.
* Don't use system() calls. Instead do direct execl() for faster launch
and better security.
* In pipe method, the "user=" and "pass=" tags are no longer given on the
login and password line.
* Pipe method is supported for group authenticators as well as user
authenticators.
* ip-address and host-name are made available to authenticator in IP and HOST
environment variables.
* Updated and expanded comments up front.
v2.0.1 (Tyler Allison)
----------------------
I received a patch update to mod_auth_external v2.0 that supposedly fixes some
pipe related bugs. I do not have a program that uses pipes so I can not test
it myself. I have included the original v2.0 with no patch applied that you
should use if you run into problems and you DO NOT need pipe support.
mod_authnz_external-3.3.2/INSTALL 0000644 0001750 0000144 00000071516 12252352632 015325 0 ustar jan users 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 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
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 .
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 block. The declarations must be *inside*
the 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 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
Old-Style Syntax:
AddExternalAuth
SetExternalAuthMethod
is some name you choose. You can configure multiple
different external authenticators by using different keywords for them.
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.
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:
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:
is a string like ":". The part
is a string that can be used to select from multiple internal
functions. is a string passed to that function and is
typically used as config file path. The ":" is required even if
the 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
Old-Style Syntax:
AddExternalGroup
SetExternalGroupMethod
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
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 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 block:
AuthType Basic
AuthName
AuthBasicProvider external
AuthExternal
Require valid-user
Here identifies what we are authenticating for - it usually
appears in the browser's pop-up login window. 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 ...
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 ...
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
AuthBasicProvider external
AuthExternal
GroupExternal
Require external-group ...
Here 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
This will simply pass whatever 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.
* 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 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 ).
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.
mod_authnz_external-3.3.2/Makefile 0000644 0001750 0000144 00000001136 12252345142 015721 0 ustar jan users # Location of apxs command:
#APXS=apxs2
APXS=apxs
TAR= README INSTALL INSTALL.HARDCODE CHANGES AUTHENTICATORS UPGRADE TODO \
mod_authnz_external.c test/* Makefile
.DEFAULT_GOAL:= build
.PHONY: install build clean
install: mod_authnz_external.la
$(APXS) -i -a mod_authnz_external.la
build: mod_authnz_external.la
mod_authnz_external.la: mod_authnz_external.c
$(APXS) -c mod_authnz_external.c
clean:
rm -rf mod_authnz_external.so mod_authnz_external.o \
mod_authnz_external.la mod_authnz_external.slo \
mod_authnz_external.lo .libs
-ls -a .*.swp
mae.tar: $(TAR)
tar cvf mae.tar $(TAR)
mod_authnz_external-3.3.2/AUTHENTICATORS 0000644 0001750 0000144 00000031147 12252136771 016354 0 ustar jan users How To Implementation External Authentication Programs
for mod_authnz_external or mod_auth_external
Version 3.3.x
LANGUAGES
External authenticators can be written in almost any language. The sample
authenticators in the 'test' directory are in Perl and PHP. The 'pwauth'
authenticator is in ANSI C. The example code fragments in this document
are in C.
If the authenticator is a script rather than a compiled program, it normally
has to start with a "#!/bin/sh" or "#!/usr/bin/perl" type directive. Scripts
without such directives may get interpreted by the shell, or may just not
work, depending on your installation.
SECURITY
The authenticator program should be written with great care because it runs
as a privileged user and handles privileged data. A poorly written
authenticator could substantially compromise the security of your system.
You get points for paranoia. Some notes:
- Don't make any assumptions about the length of the login names and
passwords given by the user. I *think* Apache will never pass you ones
that are longer than 8192 characters, but don't depend this. Check very
carefully for buffer overflows.
- Think about locking. It is possible to get lots of hits at your website
very fast, so there may be many programs simultaneously reading your
authentication database, plus updates may be going on at the same time.
Probably some form of locking is needed to make all this work right.
- Think about core dumps. On some systems core dump files can be publically
readable. A core dump from your authenticator is likely to contain the
user's plain text password, and may include large chunks of your password
database that may have been in buffers. For C programs on most versions of
Unix, it is possible to disable core dumps by doing something like:
rlim.rlim_cur = rlim.rlim_max = 0;
(void)setrlimit(RLIMIT_CORE, &rlim);
Actually, core dumps seem to be mostly a thing of the past. Most modern
Unixes don't seem to generate them.
It may not hurt to spend a little time looking at the features of the pwauth
authenticator, which is the most secure external authenticator that I have
written.
PASSWORD AUTHENTICATORS
Authenticators communicate their result by the exit status code they return.
A value of 0 indicates that the password is correct. Other values indicate
that the password is incorrect, or something else is wrong. It can be
useful to return different error codes for different kinds of errors. These
will be logged in the Apache error log file, and can be helpful in diagnosing
problems. This version of mod_authnz_external does not have any provision for
returning textual error messages from the external authenticator. You might
be able to use syslog() for this. This might be improved in future releases.
Returned error codes should not be negative. Negative values are used
internally to mod_authnz_external to indicate problems launching your program.
How the external authentication program gets its arguments depends on
the method used. The method used is determined by the 'SetExternalAuthMethod'
command in your Apache configuration file. You need implement only the
method that you plan to use in your configuration.
PIPE METHOD
In the "pipe" method, the arguments are read from standard input. The
user name will be on the first line, and the password will be on the
second. Here's a typical chunk of C code to read that:
main()
{
char user[100], password[100], *p;
if (fgets(user, sizeof(user), stdin) == NULL) exit(2);
if ((p= strchr(user, '\n')) == NULL) exit(4)
*p= '\0';
if (fgets(password, sizeof(password), stdin) == NULL) exit(3);
if ((p= strchr(password, '\n')) == NULL) exit(5)
*p= '\0';
if (check_password(user, password) == OK)
exit(0); /* Good Password */
else
exit(1); /* Incorrect Password */
}
Here we simply read two lines from stdin, being careful not to allow
buffer overflows and stripping off trailing newlines.
We assume "check_password()" is some function that checks the validity of a
password and returns 'OK' if it is good.
Note that we exit with different non-zero error codes in different error
cases. This will be helpful for debugging, as those values will be logged
when authentication fails, giving you some clue as to what went wrong.
It'd really be better for check_password() to return more detailed error
codes, but I wanted to keep the example simple.
CHECKPASSWORD METHOD
The "checkpassword" method is identical to the "pipe" method, except
that the user name and password are terminated by NUL ('\0') characters
instead of newline characters, and they must be read from file descriptor
3 instead of standard input. Documentation for the checkpassword
interface is at http://cr.yp.to/checkpwd.html.
ENVIRONMENT METHOD
In the "environment" method, the arguments are passed in environment
variables. The user id and the clear-text password are passed in the
USER and PASS environment variables respectively.
Note that the environment method has fundamental security weaknesses,
and should probably not be used unless you have cause to believe it is
safe on your system. I wouldn't be surprised if it is marginally faster
than the pipe method. Most applications should use the pipe method instead.
A typical chunk of C code to authenticate with the environment method
might be like:
main()
{
char *user, *password;
if ((user= getenv("USER")) == NULL) exit(2);
if ((password= getenv("PASS")) == NULL) exit(3);
if (check_password(user, password) == OK)
exit(0); /* Good Password */
else
exit(1); /* Incorrect Password */
}
GROUP AUTHENTICATORS
Security is generally less of a issue with group authenicators, since they
are not handling any data as sensitive as clear-text passwords. They are
only passed a user name (presumably already authenticated), and a list of
group names. They exit with status code 0 if that user is in one of those
groups, and a non-zero code otherwise.
In versions of mod_auth_external before 2.1.8, external authenticators were
always passed just one group name. If the Apache "require group" directive
listed more than one group, then the external authenticator would be called
once with each group name, which could be inefficient if you have a large
number of groups. Mod_auth_external will still behave this way if you
issue the "GroupExternalManyAtOnce off" directive.
Newer versions of mod_auth_external and mod_authnz_external will pass all
group names, separated by spaces. There will only be multiple calls if more
than one "require group" directive applies to the same program (e.g., if
different parent directories contain such directives in their .htaccess
files - for efficiency, this should be avoided). The list of group names
is passed in exactly as they appear on the "require group" directive - if
your program can't handle multiple spaces between group names, don't put
them there.
Arguments are passed in a manner similar to password authenticators. The
method used is determined by the 'SetExternalGroupMethod' command in your
Apache configuration file.
ENVIRONMENT METHOD
In the "environment" method, the arguments are passed in environment
variables. The user id and the group names are passed in the USER and
GROUP environment variables respectively. A typical chunk of C code to
fetch the arguments and check each group might be like:
main()
{
char *user, *groups, *group;
if ((user= getenv("USER")) == NULL) exit(2);
if ((groups= getenv("GROUP")) == NULL) exit(3);
group= strtok(groups, " ");
while (group != NULL)
{
if (check_group(user, group) == OK)
exit(0); /* User is in group */
group= strtok(NULL, " ");
}
exit(1); /* User is not in any group */
}
Here "check_group()" is some function that looks in your database to see if
user is in group and returns 'OK' if he is.
PIPE METHOD
In the "pipe" method, the arguments are read from standard input. The
user name will be on the first line, and the group name will be on the
second. Here's a typical chunk of C code to read that:
main()
{
char user[100], groups[100], *group, *p;
if (fgets(user, sizeof(user), stdin) == NULL) exit(2);
if ((p= strchr(user, '\n')) == NULL) exit(4)
*p= '\0';
if (fgets(groups, sizeof(groups), stdin) == NULL) exit(3);
if ((p= strchr(groups, '\n')) == NULL) exit(5)
*p= '\0';
group= strtok(groups, " ");
while (group != NULL)
{
if (check_group(user, group) == OK)
exit(0); /* User is in group */
group= strtok(NULL, " ");
}
exit(1); /* User is not in any group */
}
Here we simply read two lines from stdin, being careful not to allow
buffer overflows and stripping off trailing newlines. We loop through
all groups, checking each.
CHECKPASSWORD METHOD
Mod_auth_external will happily try to do group authentication via the
checkpassword method, piping NUL terminated user and group names to
the child process's file descriptor 3, but this isn't actually allowed
for in the checkpassword protocol specification, so I don't recommend it.
OTHER ENVIRONMENT VARIABLES
In all cases (pipe or environment method, password or group authentication),
the following additional environment variables will be supplied to the
authenticator:
AUTHTYPE either "PASS" or "GROUP" depending on whether we are doing
password or group authentication. This is handy if you are
using one program to do both.
CONTEXT a string whose value is set by an "AuthExternalContext"
directive in the .htaccess file or "" block for
the directory. This can be used to select different
authentication behaviors in different directories. It is
undefined if there is no "AuthExternalContext" directive.
IP the client's ip-address.
HOST the host name corresponding to IP, if Apache has
"HostnameLookups On".
PATH the httpd's path environment variable.
COOKIE all cookie values passed in by the client.
HTTP_HOST the server's host name, as given in the HTTP request. May
be useful if you have multiple virtual hosts sharing an
authenticator.
URI the document requested. This is the URL including any extra
path information, but not including the hostname or any CGI
arguments.
These may be useful for logging, or you may want to accept logins from
certain users only if they are connecting from certain locations or requesting
certain documents.
Note that if you have configured Apache with "HostnameLookups Off" then HOST
will usually not be set. If you really want hostnames, either turn on
HostnameLookups or do your own gethostbyaddr() calls from the authenticator
when HOST is not defined. Note that if the user is coming from an
unresolvable IP, then hostname lookups can be very slow.
Note that using IP addresses to track a user through your site is not
reliable. Users of services like AOL and WebTV use proxy servers, so that
their IP addresses appear to change constantly since each request may come
through a different proxy. A single user's requests for successive pages,
or for different images on the same page may all come from different IP
addresses.
The PATH environment variable passed to the authenticator is just whatever
PATH was in effect when Apache was launched, and may differ if the server
was launched automatically during a reboot or manually by an admin.
Probably your program should set its own PATH if it needs one.
The COOKIE environment variable contains all cookies set in the current
request. This has the same format as the HTTP_COOKIES ("key=val;key=val")
passed to a CGI program. This should be used with caution. Cookies come
from the user's computer and might have been created, editted or deleted
by the user rather than your website. This severely limits their use for
authentication. It is not possible to set cookies from an authentication
module.
The URI variable is there because various people want it. Mostly it
is useful not for authentication ("who is this person?") but for access
control ("is this person permitted to do this?"), and good design usually
dictates separating those functions. Strictly speaking, an authenticator
is not the right place to be doing access control. However,
mod_authnz_external is 50% a kludge-builder's tool, so we won't fuss if you
want to break the rules.