From: Jim Jagielski The username and password specified are combined into an
+ Authorization header, which is passed to the server or service
+ behind the webserver. Both the username and password fields are
+ interpreted using the expression parser,
+ which allows both the username and password to be set based on
+ request parameters. If the password is not specified, the default value "password"
+ will be used. To disable fake basic authentication for an URL
+ space, specify "AuthBasicFake off". In this example, we pass a fixed username and password to a
+ backend server. In this example, we pass the email address extracted from a client
+ certificate, extending the functionality of the FakeBasicAuth option
+ within the Extending the above example, we generate a password by hashing the
+ email address with a fixed passphrase, and passing the hash to the
+ backend server. This can be used to gate into legacy systems that do
+ not support client certificates.
password
''. Those who live under MD5-based encryption
(for instance under FreeBSD or BSD/OS, etc.) should use the following MD5
hash of the same word: ``$1$OXLyS...$Owx8s2/m9/gfkcRVXzgoE/
''.
+
+ Note that the
StrictRequire
diff --git a/modules/aaa/mod_auth_basic.c b/modules/aaa/mod_auth_basic.c index cadeb5bda9..19cce78c42 100644 --- a/modules/aaa/mod_auth_basic.c +++ b/modules/aaa/mod_auth_basic.c @@ -29,26 +29,53 @@ #include "http_protocol.h" #include "http_request.h" #include "ap_provider.h" +#include "ap_expr.h" #include "mod_auth.h" typedef struct { authn_provider_list *providers; - char *dir; + char *dir; /* unused variable */ int authoritative; + ap_expr_info_t *fakeuser; + ap_expr_info_t *fakepass; + int fake_set:1; + int authoritative_set:1; } auth_basic_config_rec; static void *create_auth_basic_dir_config(apr_pool_t *p, char *d) { auth_basic_config_rec *conf = apr_pcalloc(p, sizeof(*conf)); - conf->dir = d; /* Any failures are fatal. */ conf->authoritative = 1; return conf; } +static void *merge_auth_basic_dir_config(apr_pool_t *p, void *basev, void *overridesv) +{ + auth_basic_config_rec *newconf = apr_pcalloc(p, sizeof(*newconf)); + auth_basic_config_rec *base = basev; + auth_basic_config_rec *overrides = overridesv; + + newconf->authoritative = + overrides->authoritative_set ? overrides->authoritative : + base->authoritative; + newconf->authoritative_set = overrides->authoritative_set + || base->authoritative_set; + + newconf->fakeuser = + overrides->fake_set ? overrides->fakeuser : base->fakeuser; + newconf->fakepass = + overrides->fake_set ? overrides->fakepass : base->fakepass; + newconf->fake_set = overrides->fake_set || base->fake_set; + + newconf->providers = overrides->providers ? overrides->providers : base->providers; + + return newconf; +} + static const char *add_authn_provider(cmd_parms *cmd, void *config, const char *arg) { @@ -94,15 +121,72 @@ static const char *add_authn_provider(cmd_parms *cmd, void *config, return NULL; } +static const char *set_authoritative(cmd_parms * cmd, void *config, int flag) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec *) config; + + conf->authoritative = flag; + conf->authoritative_set = 1; + + return NULL; +} + +static const char *add_basic_fake(cmd_parms * cmd, void *config, + const char *user, const char *pass) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec *) config; + const char *err; + + if (!strcasecmp(user, "off")) { + + conf->fakeuser = NULL; + conf->fakepass = NULL; + conf->fake_set = 1; + + } + else { + + /* if password is unspecified, set it to the fixed string "password" to + * be compatible with the behaviour of mod_ssl. + */ + if (!pass) { + pass = "password"; + } + + conf->fakeuser = + ap_expr_parse_cmd(cmd, user, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse fake username expression '%s': %s", user, + err); + } + conf->fakepass = + ap_expr_parse_cmd(cmd, pass, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse fake password expression '%s': %s", user, + err); + } + conf->fake_set = 1; + + } + + return NULL; +} + static const command_rec auth_basic_cmds[] = { AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG, "specify the auth providers for a directory or location"), - AP_INIT_FLAG("AuthBasicAuthoritative", ap_set_flag_slot, - (void *)APR_OFFSETOF(auth_basic_config_rec, authoritative), - OR_AUTHCFG, + AP_INIT_FLAG("AuthBasicAuthoritative", set_authoritative, NULL, OR_AUTHCFG, "Set to 'Off' to allow access control to be passed along to " "lower modules if the UserID is not known to this module"), + AP_INIT_TAKE12("AuthBasicFake", add_basic_fake, NULL, OR_AUTHCFG, + "Fake basic authentication using the given expressions for " + "username and password, 'off' to disable. Password defaults " + "to 'password' if missing."), {NULL} }; @@ -295,10 +379,68 @@ static int authenticate_basic_user(request_rec *r) return OK; } +/* If requested, create a fake basic authentication header for the benefit + * of a proxy or application running behind this server. + */ +static int authenticate_basic_fake(request_rec *r) +{ + const char *auth_line, *user, *pass, *err; + auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config, + &auth_basic_module); + + if (!conf->fakeuser) { + return DECLINED; + } + + user = ap_expr_str_exec(r, conf->fakeuser, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02455) + "AuthBasicFake: could not evaluate user expression for URI '%s': %s", r->uri, err); + return HTTP_INTERNAL_SERVER_ERROR; + } + if (!user || !*user) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02458) + "AuthBasicFake: empty username expression for URI '%s', ignoring", r->uri); + + apr_table_unset(r->headers_in, "Authorization"); + + return DECLINED; + } + + pass = ap_expr_str_exec(r, conf->fakepass, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02456) + "AuthBasicFake: could not evaluate password expression for URI '%s': %s", r->uri, err); + return HTTP_INTERNAL_SERVER_ERROR; + } + if (!pass || !*pass) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02459) + "AuthBasicFake: empty password expression for URI '%s', ignoring", r->uri); + + apr_table_unset(r->headers_in, "Authorization"); + + return DECLINED; + } + + auth_line = apr_pstrcat(r->pool, "Basic ", + ap_pbase64encode(r->pool, + apr_pstrcat(r->pool, user, + ":", pass, NULL)), + NULL); + apr_table_setn(r->headers_in, "Authorization", auth_line); + + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02457) + "AuthBasicFake: \"Authorization: %s\"", + auth_line); + + return OK; +} + static void register_hooks(apr_pool_t *p) { ap_hook_check_authn(authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF); + ap_hook_fixups(authenticate_basic_fake, NULL, NULL, APR_HOOK_LAST); ap_hook_note_auth_failure(hook_note_basic_auth_failure, NULL, NULL, APR_HOOK_MIDDLE); } @@ -307,7 +449,7 @@ AP_DECLARE_MODULE(auth_basic) = { STANDARD20_MODULE_STUFF, create_auth_basic_dir_config, /* dir config creater */ - NULL, /* dir merger --- default is to override */ + merge_auth_basic_dir_config, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ auth_basic_cmds, /* command apr_table_t */