From 6f91fe5dbc58ea1b13812cb856925fba1b0057b6 Mon Sep 17 00:00:00 2001
From: Graham Leggett 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. 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.
$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 569b6050d6..39999f07c2 100644 --- a/modules/aaa/mod_auth_basic.c +++ b/modules/aaa/mod_auth_basic.c @@ -28,26 +28,51 @@ #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; + + return newconf; +} + static const char *add_authn_provider(cmd_parms *cmd, void *config, const char *arg) { @@ -93,15 +118,50 @@ 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; + + 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_TAKE2("AuthBasicFake", add_basic_fake, NULL, OR_AUTHCFG, + "Fake basic authentication using the given expressions for " + "username and password"), {NULL} }; @@ -294,10 +354,62 @@ 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->fake_set) { + 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); + 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); + 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); } @@ -306,7 +418,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 */ -- 2.40.0