From 4900889e23514c33a7fa8edea5b4599f5f8205f8 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Tue, 2 Jun 2026 17:41:08 +0100 Subject: [PATCH 1/8] mod_auth_digest: Drop RFC 2069 and configurable qop support. (RFC 2617, which replaced 2069, is now 26 years old) * modules/aaa/mod_auth_digest.c (digest_config_rec): Remove qop_list field. (create_digest_dir_config): Remove qop_list initialization. (set_qop): Deprecate AuthDigestQop, only "auth" is supported. (note_digest_auth_failure): Always send qop="auth". (check_nc): Remove handling for qop=none. (old_digest): Remove function. (authenticate_digest_user): Reject requests with missing or non-"auth" qop value rather than falling back to RFC 2069. Co-Authored-By: Claude Opus 4.6 --- modules/aaa/mod_auth_digest.c | 114 +++++----------------------------- 1 file changed, 15 insertions(+), 99 deletions(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 2edbc4d3601..fe749df1a01 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -85,8 +85,7 @@ 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_sha1_ctx_t nonce_ctx; apr_time_t nonce_lifetime; int check_nc; const char *algorithm; @@ -472,7 +471,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; @@ -558,22 +556,9 @@ 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-int")) { - return "AuthDigestQop auth-int is not implemented"; + if (ap_cstr_casecmp(op, "auth")) { + return "AuthDigestQop is deprecated: only 'auth' is supported"; } - 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; } @@ -1179,18 +1164,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 */ @@ -1380,19 +1354,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) @@ -1473,19 +1434,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) @@ -1758,39 +1706,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; @@ -1836,9 +1763,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) { @@ -1861,15 +1785,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 From b23d7c2a1c60c9ba6dd35c317e8145430a9a33da Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Tue, 2 Jun 2026 17:01:45 +0100 Subject: [PATCH 2/8] * modules/aaa/mod_auth_digest.c: Remove "weird" override of AuthName directive, which adds complexity for little benefit (avoids putting 20 bytes through SHA1 for each auth attempt). (set_realm): Remove function. (gen_nonce_hash): Create the nonce hash here from scratch. (create_digest_dir_config): Always allocate a config struct. Remove unused dir_name field from digest_config_rec. Co-Authored-By: Claude Opus 4.6 --- modules/aaa/mod_auth_digest.c | 58 +++-------------------------------- 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index fe749df1a01..320919331eb 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -83,9 +83,7 @@ /* struct to hold the configuration info */ typedef struct digest_config_struct { - const char *dir_name; authn_provider_list *providers; - apr_sha1_ctx_t nonce_ctx; apr_time_t nonce_lifetime; int check_nc; const char *algorithm; @@ -463,52 +461,14 @@ static void initialize_child(apr_pool_t *p, server_rec *s) static void *create_digest_dir_config(apr_pool_t *p, char *dir) { - digest_config_rec *conf; - - if (dir == NULL) { - return NULL; - } + digest_config_rec *conf = apr_pcalloc(p, sizeof *conf); - conf = (digest_config_rec *) apr_pcalloc(p, sizeof(digest_config_rec)); - if (conf) { - conf->nonce_lifetime = DFLT_NONCE_LIFE; - conf->dir_name = apr_pstrdup(p, dir); - conf->algorithm = DFLT_ALGORITHM; - } + conf->nonce_lifetime = DFLT_NONCE_LIFE; + conf->algorithm = DFLT_ALGORITHM; 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) { @@ -664,8 +624,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, @@ -1061,14 +1019,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)); From 73e08918e10533c204e8ebe217b54eb4fc8d797e Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 11 Jun 2026 16:23:35 +0100 Subject: [PATCH 3/8] * modules/aaa/mod_auth_digest.c (set_algorithm): Note that conf->algorithm is a constant ("MD5") so there is no point in overriding it at runtime. Simplify error case. --- modules/aaa/mod_auth_digest.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 320919331eb..61f3b7f02cb 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -86,7 +86,7 @@ typedef struct digest_config_struct { authn_provider_list *providers; apr_time_t nonce_lifetime; int check_nc; - const char *algorithm; + const char *algorithm; /* currently a constant (MD5). */ char *uri_list; } digest_config_rec; @@ -556,15 +556,11 @@ static const char *set_nc_check(cmd_parms *cmd, void *config, int flag) static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg) { - if (!ap_cstr_casecmp(alg, "MD5-sess")) { - return "AuthDigestAlgorithm: ERROR: algorithm `MD5-sess' " - "is not implemented"; - } - else if (ap_cstr_casecmp(alg, "MD5")) { - return apr_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL); + if (ap_cstr_casecmp(alg, "MD5")) { + return apr_pstrcat(cmd->pool, "Unsupported algorithm in AuthDigestAlgorithm: ", alg, NULL); } - ((digest_config_rec *) config)->algorithm = alg; + /* conf->algorithm remains the constant, "MD5". */ return NULL; } From 9f8494577c1ef28f870716fd7cbcef15355cfb59 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Sun, 21 Jun 2026 20:54:02 +0100 Subject: [PATCH 4/8] * modules/aaa/config.m4, modules/aaa/mod_auth_digest.c (pre_init, initialize_module): Prevent using mod_auth_digest without APR_HAS_SHARED_MEMORY. --- modules/aaa/config.m4 | 6 +++--- modules/aaa/mod_auth_digest.c | 25 +++++++------------------ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/modules/aaa/config.m4 b/modules/aaa/config.m4 index 1b59f99f492..c71f186ec3d 100644 --- a/modules/aaa/config.m4 +++ b/modules/aaa/config.m4 @@ -81,9 +81,9 @@ APACHE_MODULE(auth_bearer, bearer authentication, , , yes) APACHE_MODULE(auth_form, form authentication, , , most) APACHE_MODULE(auth_digest, RFC2617 Digest authentication, , , most, [ APR_CHECK_APR_DEFINE(APR_HAS_RANDOM) - if test $ac_cv_define_APR_HAS_RANDOM = "no"; then - echo "You need APR random support to use mod_auth_digest." - echo "Look at APR configure options --with-egd and --with-devrandom." + APR_CHECK_APR_DEFINE(APR_HAS_SHARED_MEMORY) + if test "${ac_cv_define_APR_HAS_RANDOM}X${ac_cv_define_APR_HAS_SHARED_MEMORY}" != "yesXyes"; then + AC_MSG_NOTICE([mod_auth_digest requires APR with random and shared memory support]) enable_auth_digest="no" fi ]) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 61f3b7f02cb..fc4135afe26 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -254,8 +254,6 @@ static apr_status_t rmm_free(apr_rmm_t *rmm, void *alloc) return apr_rmm_free(rmm, offset); } -#if APR_HAS_SHARED_MEMORY - static int initialize_tables(server_rec *s, apr_pool_t *ctx) { unsigned long idx; @@ -360,13 +358,17 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) return OK; } -#endif /* APR_HAS_SHARED_MEMORY */ - static int pre_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) { apr_status_t rv; void *retained; + if (!APR_HAS_SHARED_MEMORY) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO() + "mod_auth_digest cannot be used on platforms without shared memory support"); + return !OK; + } + rv = ap_mutex_register(pconf, client_mutex_type, NULL, APR_LOCK_DEFAULT, 0); if (rv != APR_SUCCESS) return !OK; @@ -403,7 +405,6 @@ static int initialize_module(apr_pool_t *p, apr_pool_t *plog, if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) return OK; -#if APR_HAS_SHARED_MEMORY /* Note: this stuff is currently fixed for the lifetime of the server, * i.e. even across restarts. This means that A) any shmem-size * configuration changes are ignored, and B) certain optimizations, @@ -414,11 +415,7 @@ static int initialize_module(apr_pool_t *p, apr_pool_t *plog, * last child dies. Therefore we can never clean up the old stuff, * creating a creeping memory leak. */ - if (initialize_tables(s, p) != OK) { - return !OK; - } -#endif /* APR_HAS_SHARED_MEMORY */ - return OK; + return initialize_tables(s, p); } static void initialize_child(apr_pool_t *p, server_rec *s) @@ -542,14 +539,6 @@ static const char *set_nonce_lifetime(cmd_parms *cmd, void *config, static const char *set_nc_check(cmd_parms *cmd, void *config, int flag) { -#if !APR_HAS_SHARED_MEMORY - if (flag) { - return "AuthDigestNcCheck: ERROR: nonce-count checking " - "is not supported on platforms without shared-memory " - "support"; - } -#endif - ((digest_config_rec *) config)->check_nc = flag; return NULL; } From 2580a49d8275752e12736109bea11d63e4b0cf8b Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Sun, 21 Jun 2026 20:59:26 +0100 Subject: [PATCH 5/8] * modules/aaa/mod_auth_digest.c: Use apr_uint32_t for the one-time-nonce counter. (gen_nonce): Drop the fallback case for non-shmem builds where otn_counter could be NULL previously. Use atomics to increment the counter. --- modules/aaa/mod_auth_digest.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index fc4135afe26..ede70a674fd 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -56,6 +56,7 @@ #include "apr_errno.h" #include "apr_global_mutex.h" #include "apr_strings.h" +#include "apr_atomic.h" #define APR_WANT_STRFUNC #include "apr_want.h" @@ -174,7 +175,7 @@ static unsigned char *secret; static apr_shm_t *client_shm = NULL; static apr_rmm_t *client_rmm = NULL; static unsigned long *opaque_cntr; -static apr_time_t *otn_counter; /* one-time-nonce counter */ +static volatile apr_uint32_t *otn_counter; /* one-time-nonce counter */ static apr_global_mutex_t *client_lock = NULL; static apr_global_mutex_t *opaque_lock = NULL; static const char *client_mutex_type = "authdigest-client"; @@ -1032,15 +1033,8 @@ static const char *gen_nonce(apr_pool_t *p, apr_time_t now, const char *opaque, if (conf->nonce_lifetime != 0) { t.time = now; } - else if (otn_counter) { - /* this counter is not synch'd, because it doesn't really matter - * if it counts exactly. - */ - t.time = (*otn_counter)++; - } else { - /* XXX: WHAT IS THIS CONSTANT? */ - t.time = 42; + t.time = apr_atomic_inc32(otn_counter); } apr_base64_encode_binary(nonce, t.arr, sizeof(t.arr)); gen_nonce_hash(nonce+NONCE_TIME_LEN, nonce, opaque, server, conf, realm); From 4798f529129c6533dea4ac68fb1b20e4d0ad42c0 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Sun, 21 Jun 2026 21:43:26 +0100 Subject: [PATCH 6/8] * modules/aaa/mod_auth_digest.c (get_digest_rec): Parse opaque more strictly. --- modules/aaa/mod_auth_digest.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index ede70a674fd..3a20a3a2353 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -950,7 +950,13 @@ static int get_digest_rec(request_rec *r, digest_header_rec *resp) } if (resp->opaque) { - resp->opaque_num = (unsigned long) strtol(resp->opaque, NULL, 16); + char *endptr; + long num; + + errno = 0; + num = strtol(resp->opaque, &endptr, 16); + if (errno == 0 && *endptr == '\0' && num > 0) + resp->opaque_num = (unsigned long)num; } resp->auth_hdr_sts = VALID; From c6cb380f0b9eb0b5ae5de487300a6d4f57dbbb54 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Sun, 21 Jun 2026 21:51:40 +0100 Subject: [PATCH 7/8] * modules/aaa/mod_auth_digest.c (cleanup_tables, initialize_tables, initialize_child, gen_client): Replace mutex-protected opaque_cntr with opaque_counter, incremented via atomics. --- modules/aaa/mod_auth_digest.c | 40 +++++------------------------------ 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 3a20a3a2353..b35d61be4fc 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -174,10 +174,9 @@ static unsigned char *secret; static apr_shm_t *client_shm = NULL; static apr_rmm_t *client_rmm = NULL; -static unsigned long *opaque_cntr; +static volatile apr_uint32_t *opaque_counter; static volatile apr_uint32_t *otn_counter; /* one-time-nonce counter */ static apr_global_mutex_t *client_lock = NULL; -static apr_global_mutex_t *opaque_lock = NULL; static const char *client_mutex_type = "authdigest-client"; static const char *opaque_mutex_type = "authdigest-opaque"; static const char *client_shm_filename; @@ -216,11 +215,6 @@ static apr_status_t cleanup_tables(void *not_used) client_lock = NULL; } - if (opaque_lock) { - apr_global_mutex_destroy(opaque_lock); - opaque_lock = NULL; - } - client_list = NULL; return APR_SUCCESS; @@ -267,7 +261,6 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) client_shm = NULL; client_rmm = NULL; client_lock = NULL; - opaque_lock = NULL; client_list = NULL; /* @@ -329,20 +322,12 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) /* setup opaque */ - opaque_cntr = rmm_malloc(client_rmm, sizeof(*opaque_cntr)); - if (opaque_cntr == NULL) { + opaque_counter = rmm_malloc(client_rmm, sizeof *opaque_counter); + if (opaque_counter == NULL) { log_error_and_cleanup("failed to allocate shared memory", -1, s); return !OK; } - *opaque_cntr = 1UL; - - sts = ap_global_mutex_create(&opaque_lock, NULL, opaque_mutex_type, NULL, - s, ctx, 0); - if (sts != APR_SUCCESS) { - log_error_and_cleanup("failed to create lock (opaque_lock)", sts, s); - return !OK; - } - + *opaque_counter = 1; /* setup one-time-nonce counter */ @@ -444,13 +429,6 @@ static void initialize_child(apr_pool_t *p, server_rec *s) log_error_and_cleanup("failed to create lock (client_lock)", sts, s); return; } - sts = apr_global_mutex_child_init(&opaque_lock, - apr_global_mutex_lockfile(opaque_lock), - p); - if (sts != APR_SUCCESS) { - log_error_and_cleanup("failed to create lock (opaque_lock)", sts, s); - return; - } } /* @@ -1059,17 +1037,9 @@ static const char *gen_nonce(apr_pool_t *p, apr_time_t now, const char *opaque, */ static client_entry *gen_client(const request_rec *r) { - unsigned long op; + apr_uint32_t op = apr_atomic_inc32(opaque_counter); client_entry new_entry = { 0, NULL, 0, "" }, *entry; - if (!opaque_cntr) { - return NULL; - } - - apr_global_mutex_lock(opaque_lock); - op = (*opaque_cntr)++; - apr_global_mutex_unlock(opaque_lock); - if (!(entry = add_client(op, &new_entry, r->server))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01769) "failed to allocate client entry - ignoring client"); From cd10a3ceececdd34b80b0b98c5c8f7e20f5b499b Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Sun, 21 Jun 2026 21:59:04 +0100 Subject: [PATCH 8/8] * modules/aaa/mod_auth_digest.c (pre_init): Don't register now-unused "authdigest-opaque" mutex type. --- modules/aaa/mod_auth_digest.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index b35d61be4fc..d0154df2397 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -178,7 +178,6 @@ static volatile apr_uint32_t *opaque_counter; static volatile apr_uint32_t *otn_counter; /* one-time-nonce counter */ static apr_global_mutex_t *client_lock = NULL; static const char *client_mutex_type = "authdigest-client"; -static const char *opaque_mutex_type = "authdigest-opaque"; static const char *client_shm_filename; #define DEF_SHMEM_SIZE 1000L /* ~ 12 entries */ @@ -356,9 +355,6 @@ static int pre_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) } rv = ap_mutex_register(pconf, client_mutex_type, NULL, APR_LOCK_DEFAULT, 0); - if (rv != APR_SUCCESS) - return !OK; - rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT, 0); if (rv != APR_SUCCESS) return !OK;