Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 16 additions & 139 deletions modules/aaa/mod_auth_digest.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@
typedef struct digest_config_struct {
const char *dir_name;
authn_provider_list *providers;
apr_array_header_t *qop_list;
apr_sha1_ctx_t nonce_ctx;
apr_time_t nonce_lifetime;
int check_nc;
const char *algorithm;
Expand Down Expand Up @@ -472,7 +470,6 @@ static void *create_digest_dir_config(apr_pool_t *p, char *dir)

conf = (digest_config_rec *) apr_pcalloc(p, sizeof(digest_config_rec));
if (conf) {
conf->qop_list = apr_array_make(p, 2, sizeof(char *));
conf->nonce_lifetime = DFLT_NONCE_LIFE;
conf->dir_name = apr_pstrdup(p, dir);
conf->algorithm = DFLT_ALGORITHM;
Expand All @@ -481,36 +478,6 @@ static void *create_digest_dir_config(apr_pool_t *p, char *dir)
return conf;
}


/*
* The realm is no longer precomputed because it may be an expression, which
* makes this hooking of AuthName quite weird.
*/
static const char *set_realm(cmd_parms *cmd, void *config, const char *realm)
{
digest_config_rec *conf = (digest_config_rec *) config;
#ifdef AP_DEBUG
int i;

/* check that we got random numbers */
for (i = 0; i < SECRET_LEN; i++) {
if (secret[i] != 0)
break;
}
ap_assert(i < SECRET_LEN);
#endif

/* we precompute the part of the nonce hash that is constant (well,
* the host:port would be too, but that varies for .htaccess files
* and directives outside a virtual host section)
*/
apr_sha1_init(&conf->nonce_ctx);
apr_sha1_update_binary(&conf->nonce_ctx, secret, SECRET_LEN);


return DECLINE_CMD;
}

static const char *add_authn_provider(cmd_parms *cmd, void *config,
const char *arg)
{
Expand Down Expand Up @@ -558,23 +525,10 @@ static const char *add_authn_provider(cmd_parms *cmd, void *config,

static const char *set_qop(cmd_parms *cmd, void *config, const char *op)
{
digest_config_rec *conf = (digest_config_rec *) config;

if (!ap_cstr_casecmp(op, "none")) {
apr_array_clear(conf->qop_list);
*(const char **)apr_array_push(conf->qop_list) = "none";
return NULL;
if (!ap_cstr_casecmp(op, "auth")) {
return "AuthDigestQop is deprecated: only 'auth' is supported";
}

if (!ap_cstr_casecmp(op, "auth-int")) {
return "AuthDigestQop auth-int is not implemented";
}
else if (ap_cstr_casecmp(op, "auth")) {
return apr_pstrcat(cmd->pool, "Unrecognized qop: ", op, NULL);
}

*(const char **)apr_array_push(conf->qop_list) = op;

return NULL;
}

Expand Down Expand Up @@ -679,8 +633,6 @@ static const char *set_shmem_size(cmd_parms *cmd, void *config,

static const command_rec digest_cmds[] =
{
AP_INIT_TAKE1("AuthName", set_realm, NULL, OR_AUTHCFG,
"The authentication realm (e.g. \"Members Only\")"),
AP_INIT_ITERATE("AuthDigestProvider", add_authn_provider, NULL, OR_AUTHCFG,
"specify the auth providers for a directory or location"),
AP_INIT_ITERATE("AuthDigestQop", set_qop, NULL, OR_AUTHCFG,
Expand Down Expand Up @@ -1076,14 +1028,8 @@ static void gen_nonce_hash(char hash[NONCE_HASH_LEN+1], const char *timestr, con
unsigned char sha1[APR_SHA1_DIGESTSIZE];
apr_sha1_ctx_t ctx;

memcpy(&ctx, &conf->nonce_ctx, sizeof(ctx));
/*
apr_sha1_update_binary(&ctx, (const unsigned char *) server->server_hostname,
strlen(server->server_hostname));
apr_sha1_update_binary(&ctx, (const unsigned char *) &server->port,
sizeof(server->port));
*/

apr_sha1_init(&ctx);
apr_sha1_update_binary(&ctx, secret, SECRET_LEN);
apr_sha1_update_binary(&ctx, (const unsigned char *) realm, strlen(realm));

apr_sha1_update_binary(&ctx, (const unsigned char *) timestr, strlen(timestr));
Expand Down Expand Up @@ -1179,18 +1125,7 @@ static void note_digest_auth_failure(request_rec *r,
const char *qop, *opaque, *opaque_param, *domain, *nonce;

/* Setup qop */
if (apr_is_empty_array(conf->qop_list)) {
qop = ", qop=\"auth\"";
}
else if (!ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none")) {
qop = "";
}
else {
qop = apr_pstrcat(r->pool, ", qop=\"",
apr_array_pstrcat(r->pool, conf->qop_list, ','),
"\"",
NULL);
}
qop = ", qop=\"auth\"";

/* Setup opaque */

Expand Down Expand Up @@ -1380,19 +1315,6 @@ static int check_nc(const request_rec *r, const digest_header_rec *resp,
return OK;
}

if (!apr_is_empty_array(conf->qop_list) &&
!ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none")) {
/* qop is none, client must not send a nonce count */
if (snc != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01772)
"invalid nc %s received - no nonce count allowed when qop=none",
snc);
return !OK;
}
/* qop is none, cannot check nonce count */
return OK;
}

nc = strtol(snc, &endptr, 16);
if (endptr < (snc+strlen(snc)) && !apr_isspace(*endptr)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01773)
Expand Down Expand Up @@ -1473,19 +1395,6 @@ static int check_nonce(request_rec *r, digest_header_rec *resp,

/* The actual MD5 code... whee */

/* RFC-2069 */
static const char *old_digest(const request_rec *r,
const digest_header_rec *resp)
{
const char *ha2;

ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":",
resp->uri, NULL));
return ap_md5(r->pool,
(unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":",
resp->nonce, ":", ha2, NULL));
}

/* RFC-2617 */
static const char *new_digest(const request_rec *r,
digest_header_rec *resp)
Expand Down Expand Up @@ -1758,39 +1667,18 @@ static int authenticate_digest_user(request_rec *r)
return HTTP_INTERNAL_SERVER_ERROR;
}

if (resp->message_qop == NULL) {
/* old (rfc-2069) style digest */
if (!ap_memeq_timingsafe(old_digest(r, resp), resp->digest, MD5_DIGEST_LEN)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792)
"user %s: password mismatch: %s", r->user,
r->uri);
note_digest_auth_failure(r, conf, resp, 0);
return HTTP_UNAUTHORIZED;
}
if (resp->message_qop == NULL
|| !ap_cstr_casecmp(resp->message_qop, "auth")) {
/* RFC 2069-style Digest is no longer supported. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10560)
"invalid or missing qop value '%s', RFC 2069 is "
"no longer supported: %s", resp->message_qop, r->uri);
note_digest_auth_failure(r, conf, resp, 0);
return HTTP_UNAUTHORIZED;
}
else {
const char *exp_digest;
int match = 0, idx;
const char **tmp = (const char **)(conf->qop_list->elts);
for (idx = 0; idx < conf->qop_list->nelts; idx++) {
if (!ap_cstr_casecmp(*tmp, resp->message_qop)) {
match = 1;
break;
}
++tmp;
}

if (!match
&& !(apr_is_empty_array(conf->qop_list)
&& !ap_cstr_casecmp(resp->message_qop, "auth"))) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01793)
"invalid qop `%s' received: %s",
resp->message_qop, r->uri);
note_digest_auth_failure(r, conf, resp, 0);
return HTTP_UNAUTHORIZED;
}

exp_digest = new_digest(r, resp);
/* RFC 2617 (or 7616)-style Digest hash calculation. */
const char *exp_digest = new_digest(r, resp);
if (!exp_digest) {
/* we failed to allocate a client struct */
return HTTP_INTERNAL_SERVER_ERROR;
Expand Down Expand Up @@ -1836,9 +1724,6 @@ static int add_auth_info(request_rec *r)
return OK;
}

/* 2069-style entity-digest is not supported (it's too hard, and
* there are no clients which support 2069 but not 2617). */

/* setup nextnonce
*/
if (conf->nonce_lifetime > 0) {
Expand All @@ -1861,15 +1746,7 @@ static int add_auth_info(request_rec *r)
/* else nonce never expires, hence no nextnonce */


/* do rfc-2069 digest
*/
if (!apr_is_empty_array(conf->qop_list) &&
!ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none")
&& resp->message_qop == NULL) {
/* use only RFC-2069 format */
ai = nextnonce;
}
else {
{
const char *resp_dig, *ha1, *a2, *ha2;

/* calculate rspauth attribute
Expand Down
Loading