</usage>
</directivesynopsis>
+<directivesynopsis>
+<name>AuthBasicFake</name>
+<description>Fake basic authentication using the given expressions for
+username and password</description>
+<syntax>AuthBasicFake username password</syntax>
+<default>none</default>
+<contextlist><context>directory</context><context>.htaccess</context>
+</contextlist>
+<override>AuthConfig</override>
+
+<usage>
+ <p>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 <a href="../expr.html">expression parser</a>,
+ which allows both the username and password to be set based on
+ request parameters.</p>
+
+ <p>In this example, we pass a fixed username and password to a
+ backend server.</p>
+
+ <example><title>Fixed Example</title>
+ <highlight language="config">
+<Location /demo>
+ AuthBasicFake demo demopass
+</Location>
+ </highlight>
+ </example>
+
+ <p>In this example, we pass the email address extracted from a client
+ certificate, extending the functionality of the FakeBasicAuth option
+ within the <directive module="mod_ssl">SSLOptions</directive>
+ directive. Like the FakeBasicAuth option, the password is set to the
+ fixed string "password".</p>
+
+ <example><title>Certificate Example</title>
+ <highlight language="config">
+<Location /secure>
+ AuthBasicFake %{SSL_CLIENT_S_DN_Email} password
+</Location>
+ </highlight>
+ </example>
+
+ <p>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.</p>
+
+ <example><title>Password Example</title>
+ <highlight language="config">
+<Location /secure>
+ AuthBasicFake %{SSL_CLIENT_S_DN_Email} %{sha1:passphrase-%{SSL_CLIENT_S_DN_Email}}
+</Location>
+ </highlight>
+ </example>
+
+</usage>
+</directivesynopsis>
+
</modulesynopsis>
#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)
{
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}
};
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);
}
{
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 */