httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy T. Fielding" <>
Subject Re: AuthzMergeRules blocks everything in default configuration
Date Mon, 01 Dec 2008 20:12:15 GMT
IIRC, trunk contains (or contained) a security problem with regard to
backward compatibility with 2.x configs.  I won't consider it releasable
until that has been fixed one way or another, and I can't tell from this
mail thread whether the actual fix was committed or not.  I thought that
Chris committed the patches indicated below, but there is no  
config directive in trunk and

   AuthzMergeRules Off

still appears in docs/conf/httpd.conf:162-167 even though it doesn't
appear to be a valid config directive either.  Note that the global
(unconfigured) default must be Off in order to stay in 2.x.

The docs seem to indicate this is now MergeAuthz Off and is off by
default?  Is that true in the code?  The code seems to confirm that

     conf->op = AUTHZ_LOGIC_OFF;

is the default until one of the Match* containers is used (why those
directive names are Match* instead of AuthMatch* boggles my mind).

What is the conclusion to this thread?  Why are all the Authz
directives given random names?  Am I the only one that finds this
feature set impossible to follow?


On Oct 29, 2008, at 3:17 PM, Chris Darroch wrote:

> Dan Poirier wrote:
>> I like the idea of replacing ON with AND and OR.  It would not
>> only provide more control, but make it explicit what kind of merging
>> was going to happen.
>> I have mixed thoughts about changing the default to OFF.  Cons:  
>> That would mean every container directive would have to specify
>> some sort of access control (or at least AuthzMergeRules AND) or it'd
>> be wide open, right?
>   I don't think so; at least, that's not what I was intending.
> Rather, something much like 2.2's behaviour: containers that don't
> specify any authz are simply protected by the "nearest" container
> merged ahead of them that does specify authz.
>   I'm hoping to put this thread to bed shortly with the patches
> available here:
>   My intent is to finish up the necessary documentation changes
> and get everything committed to trunk in the next few days.  (Fingers
> crossed!)
>   In the meantime, an overview follows.  Many, many thanks are
> due to Brad Nicholes, whose massive refactoring of the authn/z
> system makes all of this work possible.
> 1) <Limit> and <LimitExcept> are made nestable, with an error in
>   the case where all methods are configured out.  There are also some
>   tuneups related to <Limit>/<LimitExcept> being intended to contain
>   authz configurations only and to not be functional outside  
> <Directory>/
>   <Location>/etc.
> 2) A setting of "AuthType None" is allowed, which sets ap_auth_type 
> () to
>   NULL and thus provides a way to turn off authentication for a
>   sub-directory.  This corresponds to several convenient ways in  
> 2.4 to
>   turn off authorization, including "Require all granted" (and, at a
>   deeper level, the new "SatisfySections Off").
> 3) The mod_authz_core.c module is rewritten to attempt to deal with  
> the
>   issues discussed on this thread and the previous one, as well as
>   those described at the end of this email.  The authz_provider_list
>   two-pronged linked lists are replaced by a tree structure that  
> mirrors
>   what is configured via <SatisfyAll> and <SatisfyAny>.
>   A pair of negative authz containers are introduced, <SatisfyNotAll>
>   and <SatisfyNotAny>, which negate their operands in the same
>   manner as Reject.  Thus we have the following table:
>      Require			A
>      Reject			!A
>      <SatisfyAll>		(A && B && ...)
>      <SatisfyAny>              (A || B || ...)
>      <SatisfyNotAll>           !(A && B && ...)
>      <SatisfyNotAny>           !(A || B || ...)
>   The <SatisfyAny> directive is renamed from <SatisfyOne> so as not
>   to imply XOR-like functionality (requiring exactly one successful
>   operand).
>   A number of configuration-time checks are implemented to warn
>   administrators regarding redundant or non-functional authz
>   configurations. In particular, since the negative authz directives
>   can not contribute meaningfully to OR-like blocks, as they
>   can only supply neutral (AUTHZ_NEUTRAL) or false (AUTHZ_DENIED)
>   values, they are simply not allowed in these containers.  (The
>   code should support them, though, if this check is ever removed.)
>   Similarly, AND-like blocks without only negative authz directives
>   also produce a configuration-time error.
>   The MergeAuthzRules directive is renamed SatisfySections and
>   take three possible values, Off, All, and And.  The default is Off,
>   meaning that as directory configuration sections are merged,
>   new authz configurations replace previously merged ones.  However,
>   a directory section may specify "SatisfySections All" to force
>   its predecessor's authz to be successful as well as its own.
>   The "SatisfySections Any" option permits either the predecessor
>   or current section's authz to grant the user access.  Note that
>   the setting of SatisfySections continues to be local only to
>   the directory section it appears in; it is not inherited to
>   subsequent sections as they are merged.
>   The default setting of SatisfySections is Off, corresponding to
>   traditional pre-2.4 authz logic.  Within a directory section,
>   the default logic corresponds to an AND-like block (i.e.,  
> <SatisfyAll>),
>   which differs from the pre-2.4 logic whereby the first Require
>   statement to succeed authorized the request.
>   Legacy 2.2 configurations should, I hope, work with few or no
>   changes as a result of these revisions.  Few administrators, I hope,
>   have configurations with multiple Require directives in a  
> section; e.g.:
>      <Directory /foo>
>          Require group shirt
>          Require group shoes
>      </Directory>
>   If they do, these would need to be revised to either place all the
>   items in a single Require directive (e.g., Require group shirt  
> shoes)
>   or to use a <SatisfyAny> section.  I feel this makes the overall
>   intent of the configuration directives clearer, since it is not
>   apparent that the example above grants access to members of either
>   group, not just those who are members of both.
>   It also means that the following 2.4-style configuration makes
>   intuitive sense, because the negative Reject directive only has
>   meaning in an AND-like context:
>      <Directory /foo>
>          Require group shirt
>          Reject user noshoes
>      </Directory>
>   However, if this proves to be a point of considerable difficulty
>   for people upgrading to 2.4, it is straightforward to make the
>   default logic of a section be OR-like by editing the
>   create_default_section() function in mod_authz_core.c.
>   The legacy Satisfy directive's logic is already largely handled in
>   request.c in 2.4, so mod_access_compat.c could be simplified  
> slightly.
>   The <Limit> and <LimitExcept> directives are handled by
>   tracking the currently applicable set of methods for all Require/ 
> Reject
>   directives within a section and its sub-sections.  When the
>   request's method does not apply to an authz section, we can then
>   immediately return either AUTHZ_GRANTED or AUTHZ_NEUTRAL, depending
>   on whether we are in an AND-like or OR-like context, respectively.
> 4) The mod_authn_default.c and mod_authz_default.c modules are  
> removed,
>   shifting the small amount of remaining functionality they provide  
> into
>   mod_authn_core.c and mod_authz_core.c.  The existence of both "core"
>   and "default" authn/z modules appeared likely to be a source of some
>   confusion (especially since they can all be made optional at  
> runtime).
>   The mod_authz_default.c module, in particular, was also almost
>   entirely obviated by the mod_authz_core.c rewrite, and removing
>   it clarified the code paths in many cases where administrators
>   likely failed to create a sensible configuration, e.g., by engaging
>   authentication with an AuthType directive but configuring not
>   authorization to match.
>   That's about it for now; comments welcome.  Just for historical
> purposes, some things I ran into with the authz_provider_list
> two-pronged linked lists with prompted the rewrite:
>   First, there were some configurations which could send the
> check_provider_list() function into an infinite loop.  For example,  
> with
> the following configuration, if one authenticated as user "foo" (i.e.,
> a user not in any of the Require directives), the function recursed  
> until
> it reached the end of the list(s), received AUTHZ_DENIED from the last
> invocation, and then the second-last invocation would loop on the goto
> one_next statement.  Since nothing had changed, it just repeated  
> the final
> invocation over and over.
> AuthzMergeRules Off
> <SatisfyOne>
>  Require user who
>  <SatisfyOne>
>    Require user tar
>  </SatisfyOne>
>  Require user dis
> </SatisfyOne>
>   Second, the two-pronged authz_provider_list lists seemed to lead to
> incorrect authorization behaviour when directives were moved around in
> the configuration file in innocuous ways.  For example, with the  
> following
> configuration, logging in as user "foo" would succeed:
> Require valid-user
> <SatisfyOne>
> Require user who
> Require user foo
> </SatisfyOne>
>   Moving the first statement to the end of the configuration caused
> the user to be rejected, though:
> <SatisfyOne>
> Require user who
> Require user foo
> </SatisfyOne>
> Require valid-user
>   The difference was that in the first case, the linked lists looked
> roughly like this:
> "Require valid-user"
>  req_state =  AUTHZ_REQSTATE_ALL
>  all_next  -> "Require user who"
>                 req_state =  AUTHZ_REQSTATE_ONE
>                 one_next  -> "Require user foo"
>                                req_state = AUTHZ_REQSTATE_ONE
> while in the second case, they looked like this:
> "Require user who"
>  req_state =  AUTHZ_REQSTATE_ONE
>  all_next  -> "Require valid-user"
>                 req_state =  AUTHZ_REQSTATE_ALL
>                 all_next  -> "Require user foo"
>                                req_state = AUTHZ_REQSTATE_ONE
>   When check_provider_list() received AUTHZ_DENIED after testing
> user "foo" against "Require user who", it found a NULL one_next
> pointer and just returned AUTHZ_DENIED, rather than proceeding
> any further.
> Chris.
> -- 
> GPG Key ID: 366A375B
> GPG Key Fingerprint: 485E 5041 17E1 E2BB C263  E4DE C8E3 FA36 366A  
> 375B

View raw message