mirror of
https://github.com/apache/httpd.git
synced 2025-08-10 02:56:11 +00:00
Add AuthBasicUseDigestAlgorithm directive to allow migration of
passwords from digest to basic authentication. Proposed by: chrisd Reviewed by: jim, rjung Backport of r1514064 from trunk. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1528957 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
4
CHANGES
4
CHANGES
@ -2,6 +2,10 @@
|
||||
|
||||
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>]
|
||||
|
7
STATUS
7
STATUS
@ -97,13 +97,6 @@ RELEASE SHOWSTOPPERS:
|
||||
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
|
||||
|
@ -181,4 +181,80 @@ username and password</description>
|
||||
</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>
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "http_log.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_request.h"
|
||||
#include "util_md5.h"
|
||||
#include "ap_provider.h"
|
||||
#include "ap_expr.h"
|
||||
|
||||
@ -38,7 +39,9 @@ typedef struct {
|
||||
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;
|
||||
|
||||
@ -70,6 +73,12 @@ static void *merge_auth_basic_dir_config(apr_pool_t *p, void *basev, void *overr
|
||||
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;
|
||||
@ -175,6 +184,23 @@ static const char *add_basic_fake(cmd_parms * cmd, void *config,
|
||||
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,
|
||||
@ -186,6 +212,10 @@ static const command_rec auth_basic_cmds[] =
|
||||
"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}
|
||||
};
|
||||
|
||||
@ -271,6 +301,8 @@ static int authenticate_basic_user(request_rec *r)
|
||||
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;
|
||||
@ -295,6 +327,15 @@ static int authenticate_basic_user(request_rec *r)
|
||||
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;
|
||||
@ -320,8 +361,27 @@ static int authenticate_basic_user(request_rec *r)
|
||||
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);
|
||||
|
||||
|
Reference in New Issue
Block a user