Changes with Apache 2.4.7
+ *) mod_auth_basic: Add AuthBasicUseDigestAlgorithm directive to
+ allow migration of passwords from digest to basic authentication.
+ [Chris Darroch]
+
*) ab: Add a new -l parameter in order not to check the length of the responses.
This can be usefull with dynamic pages.
PR9945, PR27888, PR42040 [<ccikrs1 cranbrook edu>]
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- * mod_auth_basic: Add AuthBasicUseDigestAlgorithm directive to allow
- migration of passwords from digest to basic authentication.
- trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1514064
- 2.4.x patch: trunk patch works, modulo CHANGES, next-number, and
- doc compatibility version note
- +1: chrisd, jim, rjung
-
* core: name-based vhosts printed twice in apachectl -S since
dropping NameVirtualHost directive.
trunk patch: http://svn.apache.org/r1485675 , http://svn.apache.org/r1525000
</usage>
</directivesynopsis>
+<directivesynopsis>
+<name>AuthBasicUseDigestAlgorithm</name>
+<description>Check passwords against the authentication providers as if
+Digest Authentication was in force instead of Basic Authentication.
+</description>
+<syntax>AuthBasicUseDigestAlgorithm MD5|Off</syntax>
+<default>AuthBasicUseDigestAlgorithm Off</default>
+<contextlist><context>directory</context><context>.htaccess</context>
+</contextlist>
+<override>AuthConfig</override>
+<compatibility>Apache HTTP Server 2.4.7 and later</compatibility>
+
+<usage>
+ <p>Normally, when using Basic Authentication, the providers listed in
+ <directive module="mod_auth_basic">AuthBasicProvider</directive>
+ attempt to verify a user by checking their data stores for
+ a matching username and associated password. The stored passwords
+ are usually encrypted, but not necessarily so; each provider may
+ choose its own storage scheme for passwords.</p>
+
+ <p>When using <directive
+ module="mod_auth_digest">AuthDigestProvider</directive> and Digest
+ Authentication, providers perform a similar check to find a matching
+ username in their data stores. However, unlike in the Basic
+ Authentication case, the value associated with each stored username
+ must be an encrypted string composed from the username, realm name,
+ and password. (See
+ <a href="http://tools.ietf.org/html/rfc2617#section-3.2.2.2">
+ RFC 2617, Section 3.2.2.2</a> for more details on the format used
+ for this encrypted string.)</p>
+
+ <p>As a consequence of the difference in the stored values between
+ Basic and Digest Authentication, converting from Digest
+ Authentication to Basic Authentication generally requires that all
+ users be assigned new passwords, as their existing passwords cannot
+ be recovered from the password storage scheme imposed on those
+ providers which support Digest Authentication.</p>
+
+ <p>Setting the <directive
+ module="mod_auth_basic">AuthBasicUseDigestAlgorithm</directive> directive
+ to <code>MD5</code> will cause the user's Basic Authentication password
+ to be checked using the same encrypted format as for Digest
+ Authentication. First a string composed from the username, realm name,
+ and password is hashed with MD5; then the username and this encrypted
+ string are passed to the providers listed in
+ <directive module="mod_auth_basic">AuthBasicProvider</directive>
+ as if
+ <directive module="mod_authn_core">AuthType</directive>
+ was set to <code>Digest</code> and Digest Authentication was in force.
+ </p>
+
+ <p>Through the use of <directive
+ module="mod_auth_basic">AuthBasicUseDigestAlgorithm</directive>
+ a site may switch from Digest to Basic Authentication without
+ requiring users to be assigned new passwords.</p>
+
+ <note>
+ The inverse process of switching from Basic to Digest
+ Authentication without assigning new passwords is generally
+ not possible. Only if the Basic Authentication passwords
+ have been stored in plain text or with a reversable encryption
+ scheme will it be possible to recover them and generate a
+ new data store following the Digest Authentication password
+ storage scheme.
+ </note>
+
+ <note>
+ Only providers which support Digest Authentication will be able
+ to authenticate users when <directive
+ module="mod_auth_basic">AuthBasicUseDigestAlgorithm</directive>
+ is set to <code>MD5</code>. Use of other providers will result
+ in an error response and the client will be denied access.
+ </note>
+</usage>
+</directivesynopsis>
+
</modulesynopsis>
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
+#include "util_md5.h"
#include "ap_provider.h"
#include "ap_expr.h"
int authoritative;
ap_expr_info_t *fakeuser;
ap_expr_info_t *fakepass;
+ const char *use_digest_algorithm;
int fake_set:1;
+ int use_digest_algorithm_set:1;
int authoritative_set:1;
} auth_basic_config_rec;
overrides->fake_set ? overrides->fakepass : base->fakepass;
newconf->fake_set = overrides->fake_set || base->fake_set;
+ newconf->use_digest_algorithm =
+ overrides->use_digest_algorithm_set ? overrides->use_digest_algorithm
+ : base->use_digest_algorithm;
+ newconf->use_digest_algorithm_set =
+ overrides->use_digest_algorithm_set || base->use_digest_algorithm_set;
+
newconf->providers = overrides->providers ? overrides->providers : base->providers;
return newconf;
return NULL;
}
+static const char *set_use_digest_algorithm(cmd_parms *cmd, void *config,
+ const char *alg)
+{
+ auth_basic_config_rec *conf = (auth_basic_config_rec *)config;
+
+ if (strcasecmp(alg, "Off") && strcasecmp(alg, "MD5")) {
+ return apr_pstrcat(cmd->pool,
+ "Invalid algorithm in "
+ "AuthBasicUseDigestAlgorithm: ", alg, NULL);
+ }
+
+ conf->use_digest_algorithm = apr_pstrdup(cmd->pool, alg);
+ conf->use_digest_algorithm_set = 1;
+
+ return NULL;
+}
+
static const command_rec auth_basic_cmds[] =
{
AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG,
"Fake basic authentication using the given expressions for "
"username and password, 'off' to disable. Password defaults "
"to 'password' if missing."),
+ AP_INIT_TAKE1("AuthBasicUseDigestAlgorithm", set_use_digest_algorithm,
+ NULL, OR_AUTHCFG,
+ "Set to 'MD5' to use the auth provider's authentication "
+ "check for digest auth, using a hash of 'user:realm:pass'"),
{NULL}
};
auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config,
&auth_basic_module);
const char *sent_user, *sent_pw, *current_auth;
+ const char *realm = NULL;
+ const char *digest = NULL;
int res;
authn_status auth_result;
authn_provider_list *current_provider;
return res;
}
+ if (conf->use_digest_algorithm
+ && !strcasecmp(conf->use_digest_algorithm, "MD5")) {
+ realm = ap_auth_name(r);
+ digest = ap_md5(r->pool,
+ (unsigned char *)apr_pstrcat(r->pool, sent_user, ":",
+ realm, ":",
+ sent_pw, NULL));
+ }
+
current_provider = conf->providers;
do {
const authn_provider *provider;
apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name);
}
+ if (digest) {
+ char *password;
- auth_result = provider->check_password(r, sent_user, sent_pw);
+ if (!provider->get_realm_hash) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02493)
+ "Authn provider does not support "
+ "AuthBasicUseDigestAlgorithm");
+ auth_result = AUTH_GENERAL_ERROR;
+ break;
+ }
+ /* We expect the password to be hash of user:realm:password */
+ auth_result = provider->get_realm_hash(r, sent_user, realm,
+ &password);
+ if (auth_result == AUTH_USER_FOUND) {
+ auth_result = strcmp(digest, password) ? AUTH_DENIED
+ : AUTH_GRANTED;
+ }
+ }
+ else {
+ auth_result = provider->check_password(r, sent_user, sent_pw);
+ }
apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);