Repository navigation
Conversation
construct_key() built the key from the server hostname, the URI truncated at the last slash, and the username, so distinct credential sources in one directory (for example <Files> sections with different AuthUserFile settings) silently shared cache entries under the default AuthnCacheContext directory. The key now includes the full request URI and port for the directory and server contexts, the name of the provider that produced the entry, and the realm (for Basic auth, the AuthName protection space, as Digest already used the realm). Lookups try the key of each provider named in AuthnCacheProvideFor. Update the AuthnCacheContext documentation accordingly, including when a shared custom context is and is not safe.
|
I wonder if the directory aspect could remain now that the AuthName is mixed in? Along with a caveat in the docs that the default requires unique directory-like URL paths, authnames, or a custom AuthnCacheContext to differentiate between different backend provider results. |
|
Could really use some coverage in the pyhttpd / modules/ suite for this module, current coding assistants are really good at deriving from what's there. |
Per review: with the provider and the realm (AuthName) now mixed into the key, the directory context no longer needs the full request URI to separate authentication domains. Restore the directory of the URI as the context component (the server name keeps the port added in the previous commit), and state the resulting limit in the AuthnCacheContext documentation: the default separates backend provider results only where the directory-like URL path, the provider, or the AuthName differs, so a configuration that varies the credential source within one directory and AuthName must use distinct AuthName values or a custom AuthnCacheContext per source.
test_020_authn_socache covers the cache-key separation of one directory whose two files are backed by different htpasswd files: separated by AuthName, separated by a custom AuthnCacheContext, and shared when neither differentiates the sources, as the manual now documents. The aaa suite gains the auth_basic, authn_socache and socache_shmcb modules and two Basic htpasswd files for this.
|
Thanks for the review — both points are addressed in two new commits. Directory aspect. Restored. The caveat is now in the AuthnCacheContext documentation, in the terms you put it: the default separates backend provider results only where the directory-like URL path, the provider, or the AuthName differs. A configuration that varies the credential source within one directory and one AuthName — the I re-ran the lab differential against the revised code, with the report's geometry (one directory, per-file AuthUserFile, AuthnCacheTimeout 600):
Test coverage. New |
mod_authn_socache: bind cache keys to the authentication domain
Background
This follows up a report I sent to security@apache.org about
mod_authn_socache. Eric Covener classified it as hardening rather than
a vulnerability and suggested opening a public PR for the docs or
implementation; this is that PR, for the implementation half.
The problem
construct_key()built the cache key from the server hostname, therequest URI truncated at the last slash, and the username. Nothing in
the key identified the authentication domain that produced the entry:
not the provider, not the credential source, not the realm (for Basic
auth), not the port.
With the default
AuthnCacheContext directory, two<Files>sectionsin one directory that use different
AuthUserFiles therefore sharecache entries. Reproduction (two password files in one directory,
alice/lowpassin the first,alice/highpassin the second,AuthBasicProvider socache file):The third line is a consequence of the same key: the cached foreign
hash is authoritative, and every successful login on the first file
re-stores it with a fresh expiry, so the lockout does not end with
AuthnCacheTimeoutwhile the colliding domain stays in use.The change (mod_authn_socache only, no API changes)
construct_key()now binds an entry to its authentication domain:directorycontext identifies an entry by server (hostname andport) and the full request URI instead of the URI truncated at
the last slash, so per-resource credential sources (such as
<Files>sections) no longer merge;servercontext gains the port;(the value providers already pass to
ap_authn_cache_store);the lookup paths try the key of each provider named in
AuthnCacheProvideFor;AuthName),as it already did the realm for Digest auth.
A custom literal
AuthnCacheContextis unchanged: an administratorwho deliberately sets one still chooses how widely entries are shared,
and the documentation now says when that is and is not safe.
Existing caches are not migrated: old entries simply miss under the
new keys and expire within
AuthnCacheTimeout, as they would on anyrestart. No configuration change is required.
The documentation for
AuthnCacheContextis updated to describe whatthe default context now binds, and to warn that a shared custom
context is only safe where the whole scope uses a single credential
source.
Testing
Built the patched module against 2.4.69 and ran it in a local lab
(the 2.4.69
mod_authn_socache.cis identical to trunk's):200 / 401 / 200 / 401 with a fresh cache, and stays correct with
a warm cache;
AuthnCacheTimeout, a password rotationin the file does not take effect until the entry expires (the
documented behaviour), for both the previously colliding resources;
AuthNameauthenticatesindependently;
AuthDigestProvider socache fileworks,including the socache-served second request, and a wrong password
still returns 401.
Not in this PR
On a cached-hash mismatch the module still returns
AUTH_DENIEDwithout falling through to the real provider. Within
AuthnCacheTimeoutthat behaviour is the documented stalenesstrade-off, and this PR does not change it; binding the key removes
the cross-domain lockout described above, which was the part not
covered by the documentation.