From: Justin Erenkrantz Date: Wed, 18 Sep 2002 01:05:25 +0000 (+0000) Subject: Add ability to use multiple providers for basic and digest authentication. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=68d023bbb700ad6dff4ff0ab06ab5aceebcfd23f;p=apache Add ability to use multiple providers for basic and digest authentication. The syntax is: AuthBasicProvider file dbm AuthUserFile conf/basic-user AuthDBMUserFile conf/basic-user-dbm git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@96869 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/aaa/mod_auth.h b/modules/aaa/mod_auth.h index f7fe064c1f..f0f4fbf4cc 100644 --- a/modules/aaa/mod_auth.h +++ b/modules/aaa/mod_auth.h @@ -106,6 +106,15 @@ typedef struct { const char *realm, char **rethash); } authn_provider; +/* A linked-list of authn providers. */ +typedef struct authn_provider_list authn_provider_list; + +struct authn_provider_list { + const char *provider_name; + const authn_provider *provider; + authn_provider_list *next; +}; + AAA_DECLARE(void) authn_register_provider(apr_pool_t *p, const char *name, const authn_provider *provider); AAA_DECLARE(const authn_provider *) authn_lookup_provider(const char *name); diff --git a/modules/aaa/mod_auth_basic.c b/modules/aaa/mod_auth_basic.c index 3f76418a36..c4b390ff87 100644 --- a/modules/aaa/mod_auth_basic.c +++ b/modules/aaa/mod_auth_basic.c @@ -74,8 +74,7 @@ #include "mod_auth.h" typedef struct { - const char *provider_name; - const authn_provider *provider; + authn_provider_list *providers; char *dir; int authoritative; } auth_basic_config_rec; @@ -95,29 +94,46 @@ static const char *add_authn_provider(cmd_parms *cmd, void *config, const char *arg) { auth_basic_config_rec *conf = (auth_basic_config_rec*)config; + authn_provider_list *newp; + const char *provider_name; if (strcasecmp(arg, "on") == 0) { - conf->provider_name = AUTHN_DEFAULT_PROVIDER; + provider_name = AUTHN_DEFAULT_PROVIDER; } else if (strcasecmp(arg, "off") == 0) { - conf->provider_name = NULL; - conf->provider = NULL; + /* Clear all configured providers and return. */ + conf->providers = NULL; + return NULL; } else { - conf->provider_name = apr_pstrdup(cmd->pool, arg); + provider_name = apr_pstrdup(cmd->pool, arg); + } + + newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); + newp->provider_name = provider_name; + + /* lookup and cache the actual provider now */ + newp->provider = authn_lookup_provider(newp->provider_name); + + if (newp->provider == NULL) { + /* by the time they use it, the provider should be loaded and + registered with us. */ + return apr_psprintf(cmd->pool, + "Unknown Authn provider: %s", + newp->provider_name); } - if (conf->provider_name != NULL) { - /* lookup and cache the actual provider now */ - conf->provider = authn_lookup_provider(conf->provider_name); + /* Add it to the list now. */ + if (!conf->providers) { + conf->providers = newp; + } + else { + authn_provider_list *last = conf->providers; - if (conf->provider == NULL) { - /* by the time they use it, the provider should be loaded and - registered with us. */ - return apr_psprintf(cmd->pool, - "Unknown Authn provider: %s", - conf->provider_name); + while (last->next) { + last = last->next; } + last->next = newp; } return NULL; @@ -207,6 +223,7 @@ static int authenticate_basic_user(request_rec *r) const char *sent_user, *sent_pw, *current_auth; int res; authn_status auth_result; + authn_provider_list *current_provider; /* Are we configured to be Basic auth? */ current_auth = ap_auth_type(r); @@ -228,15 +245,35 @@ static int authenticate_basic_user(request_rec *r) return res; } - /* For now, if a provider isn't set, we'll be nice and use the file - * provider. - */ - if (!conf->provider) { - conf->provider = authn_lookup_provider(AUTHN_DEFAULT_PROVIDER); - } + current_provider = conf->providers; + do { + const authn_provider *provider; - auth_result = conf->provider->check_password(r, sent_user, sent_pw); + /* For now, if a provider isn't set, we'll be nice and use the file + * provider. + */ + if (!current_provider) { + provider = authn_lookup_provider(AUTHN_DEFAULT_PROVIDER); + } + else { + provider = current_provider->provider; + } + + auth_result = provider->check_password(r, sent_user, sent_pw); + + /* Access is granted. Stop checking. */ + if (auth_result == AUTH_GRANTED) { + break; + } + + /* If we're not really configured for providers, stop now. */ + if (!conf->providers) { + break; + } + current_provider = current_provider->next; + } while (current_provider); + if (auth_result != AUTH_GRANTED) { int return_code; diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 4dbe89c5ce..4058c93b4c 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -131,8 +131,7 @@ typedef struct digest_config_struct { const char *dir_name; - const char *provider_name; - const authn_provider *provider; + authn_provider_list *providers; const char *realm; char **qop_list; apr_sha1_ctx_t nonce_ctx; @@ -486,29 +485,46 @@ static const char *add_authn_provider(cmd_parms *cmd, void *config, const char *arg) { digest_config_rec *conf = (digest_config_rec*)config; - + authn_provider_list *newp; + const char *provider_name; + if (strcasecmp(arg, "on") == 0) { - conf->provider_name = AUTHN_DEFAULT_PROVIDER; + provider_name = AUTHN_DEFAULT_PROVIDER; } else if (strcasecmp(arg, "off") == 0) { - conf->provider_name = NULL; - conf->provider = NULL; + /* Clear all configured providers and return. */ + conf->providers = NULL; + return NULL; } else { - conf->provider_name = apr_pstrdup(cmd->pool, arg); + provider_name = apr_pstrdup(cmd->pool, arg); } - if (conf->provider_name != NULL) { - /* lookup and cache the actual provider now */ - conf->provider = authn_lookup_provider(conf->provider_name); + newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); + newp->provider_name = provider_name; + + /* lookup and cache the actual provider now */ + newp->provider = authn_lookup_provider(newp->provider_name); + + if (newp->provider == NULL) { + /* by the time they use it, the provider should be loaded and + registered with us. */ + return apr_psprintf(cmd->pool, + "Unknown Authn provider: %s", + newp->provider_name); + } - if (conf->provider == NULL) { - /* by the time they use it, the provider should be loaded and - registered with us. */ - return apr_psprintf(cmd->pool, - "Unknown Authn provider: %s", - conf->provider_name); + /* Add it to the list now. */ + if (!conf->providers) { + conf->providers = newp; + } + else { + authn_provider_list *last = conf->providers; + + while (last->next) { + last = last->next; } + last->next = newp; } return NULL; @@ -1447,23 +1463,45 @@ static const char *get_hash(request_rec *r, const char *user, { authn_status auth_result; char *password; + authn_provider_list *current_provider; - /* To be nice, if we make it this far and we don't have a provider set, - * we'll use the default provider. - */ - if (!conf->provider) { - conf->provider = authn_lookup_provider(AUTHN_DEFAULT_PROVIDER); - } + current_provider = conf->providers; + do { + const authn_provider *provider; - /* We expect the password to be md5 hash of user:realm:password */ - auth_result = conf->provider->get_realm_hash(r, user, conf->realm, - &password); + /* For now, if a provider isn't set, we'll be nice and use the file + * provider. + */ + if (!current_provider) { + provider = authn_lookup_provider(AUTHN_DEFAULT_PROVIDER); + } + else { + provider = current_provider->provider; + } + + /* We expect the password to be md5 hash of user:realm:password */ + auth_result = provider->get_realm_hash(r, user, conf->realm, + &password); + + /* User is found. Stop checking. */ + if (auth_result == AUTH_USER_FOUND) { + break; + } + + /* If we're not really configured for providers, stop now. */ + if (!conf->providers) { + break; + } + + current_provider = current_provider->next; + } while (current_provider); if (auth_result != AUTH_USER_FOUND) { return NULL; } - - return password; + else { + return password; + } } static int check_nc(const request_rec *r, const digest_header_rec *resp, @@ -1822,10 +1860,6 @@ static int authenticate_digest_user(request_rec *r) return HTTP_UNAUTHORIZED; } - if (!conf->provider) { - return DECLINED; - } - if (!(conf->ha1 = get_hash(r, r->user, conf))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Digest: user `%s' in realm `%s' not found: %s",