Require valid-user
Here <authname> identifies what we are authenticating for - it usually
- appears in the browser's pop-up login windown. <keyword> matches a
+ appears in the browser's pop-up login window. <keyword> matches a
keyword you defined with DefineExternalAuth or AddExternalAuth in step 2.
If you only want some users to have access to the directory, as opposed
Require file-owner
+ It is possible to list more than one authenticator on the AuthExternal
+ command:
+
+ AuthExternal <keyword1> <keyword2>...
+
+ Here each keyword should match an authenticator defined with the
+ DefineExternalAuth command. If the first authenticator fails, then
+ the second one will be run, and so on, until either one authenticator
+ accepts the user's login/password combination or all reject it.
+
* EXTERNAL GROUP CHECKING:
If you want to use the external group check program to allow only
Require file-group
+ The GroupExternal cannot (yet?) be used with multiple external
+ authenticators.
+
* PASSING CONTEXT INFORMATION INTO AUTHENTICATORS:
If you want the authentication to work slightly differently in
- Miscellaneous odd behaviors.
- Did you restart the httpd after the last time you editted the
+ 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.
typedef struct
{
- char *auth_name; /* Auth keyword for current dir */
+ 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 authoritative; /* Are we authoritative in current dir? */
authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
apr_palloc(p, sizeof(authnz_external_dir_config_rec));
- dir->auth_name= NULL; /* no default */
+ 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->authoritative= 1; /* strong by default */
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 commands that this module can handle
static const command_rec authnz_external_cmds[] =
{
- AP_INIT_TAKE1("AuthExternal",
- ap_set_string_slot,
+ AP_INIT_ITERATE("AuthExternal",
+ append_array_slot,
(void *)APR_OFFSETOF(authnz_external_dir_config_rec,auth_name),
OR_AUTHCFG,
- "a keyword indicating which authenticator to use"),
+ "one (or more) keywords indicating which authenticators to use"),
AP_INIT_TAKE3("DefineExternalAuth",
def_extauth,
static authn_status authn_external_check_password(request_rec *r,
const char *user, const char *password)
{
- const char *extpath, *extmethod;
+ 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);
- const char *extname= dir->auth_name;
int code= 1;
/* Check if we are supposed to handle this authentication */
- if ( extname == NULL )
+ 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;
}
- /* Get the path associated with that external */
- if (!(extpath= apr_table_get(svr->auth_path, extname)))
+ for (i= 0; i < dir->auth_name->nelts; i++)
{
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid AuthExternal keyword (%s)", extname);
- return AUTH_GENERAL_ERROR;
- }
+ extname= ((const char **)dir->auth_name->elts)[i];
- /* 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);
+ /* 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;
+ }
- /* If return code was zero, authentication succeeded */
- if (code == 0) return AUTH_GRANTED;
+ /* 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);
- /* Otherwise it failed */
- 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 return code was zero, authentication succeeded */
+ if (code == 0) 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;
}