Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Apache: Dev

RequireAll: seems to evaluate require lines unnecessarily

 

 

Apache dev RSS feed   Index | Next | Previous | View Threaded


minfrin at sharp

Aug 2, 2012, 2:49 PM

Post #1 of 8 (1008 views)
Permalink
RequireAll: seems to evaluate require lines unnecessarily

Hi all,

I have a config like this using httpd v2.4, in an effort to password protect each person's userdir:

<RequireAll>
Require valid-user
Require expr %{note:mod_userdir_user} == %{REMOTE_USER}
</RequireAll>

Hit it with a browser, and instead of 401 Unauthorized I'm getting 403 Forbidden instead, which prevents the basic authentication from kicking in and the user is denied.

The log however shows something odd - despite the RequireAll directive being used, which implies AND behaviour, which in turn implies that require lines should be parsed until the first one fails and then the parsing should stop, both require lines are being evaluated even though the first line failed, and the result of the second require line is being sent instead.

[Thu Aug 02 23:35:08.874887 2012] [authz_core:debug] [pid 19527:tid 1100466496] mod_authz_core.c(783): [client 127.0.0.1:50635] AH01626: authorization result of Require valid-user : denied (no authenticated user yet)
[Thu Aug 02 23:35:08.875130 2012] [authz_core:debug] [pid 19527:tid 1100466496] mod_authz_core.c(783): [client 127.0.0.1:50635] AH01626: authorization result of Require expr %{note:mod_userdir_user} == %{REMOTE_USER}: denied
[Thu Aug 02 23:35:08.875153 2012] [authz_core:debug] [pid 19527:tid 1100466496] mod_authz_core.c(783): [client 127.0.0.1:50635] AH01626: authorization result of <RequireAll>: denied

In theory, in the RequireAll situation, require directives should be parsed until one fails, and the result of that failure returned to the client. All further require lines should be ignored as is standard behaviour for AND implementations. In the example above, the "authorization result of Require valid-user : denied (no authenticated user yet)" part should prevent the "authorization result of Require expr %{note:mod_userdir_user} == %{REMOTE_USER}: denied" part from being attempted at all.

Can someone check whether my thinking is correct?

Regards,
Graham
--
Attachments: smime.p7s (4.26 KB)


rpluem at apache

Aug 2, 2012, 11:47 PM

Post #2 of 8 (994 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

Graham Leggett wrote:
> Hi all,
>
> I have a config like this using httpd v2.4, in an effort to password protect each person's userdir:
>
> <RequireAll>
> Require valid-user
> Require expr %{note:mod_userdir_user} == %{REMOTE_USER}
> </RequireAll>
>
> Hit it with a browser, and instead of 401 Unauthorized I'm getting 403 Forbidden instead, which prevents the basic authentication from kicking in and the user is denied.
>
> The log however shows something odd - despite the RequireAll directive being used, which implies AND behaviour, which in turn implies that require lines should be parsed until the first one fails and then the parsing should stop, both require lines are being evaluated even though the first line failed, and the result of the second require line is being sent instead.
>
> [Thu Aug 02 23:35:08.874887 2012] [authz_core:debug] [pid 19527:tid 1100466496] mod_authz_core.c(783): [client 127.0.0.1:50635] AH01626: authorization result of Require valid-user : denied (no authenticated user yet)
> [Thu Aug 02 23:35:08.875130 2012] [authz_core:debug] [pid 19527:tid 1100466496] mod_authz_core.c(783): [client 127.0.0.1:50635] AH01626: authorization result of Require expr %{note:mod_userdir_user} == %{REMOTE_USER}: denied
> [Thu Aug 02 23:35:08.875153 2012] [authz_core:debug] [pid 19527:tid 1100466496] mod_authz_core.c(783): [client 127.0.0.1:50635] AH01626: authorization result of <RequireAll>: denied
>
> In theory, in the RequireAll situation, require directives should be parsed until one fails, and the result of that failure returned to the client. All further require lines should be ignored as is standard behaviour for AND implementations. In the example above, the "authorization result of Require valid-user : denied (no authenticated user yet)" part should prevent the "authorization result of Require expr %{note:mod_userdir_user} == %{REMOTE_USER}: denied" part from being attempted at all.
>
> Can someone check whether my thinking is correct?

Sounds correct.

Regards

Rüdiger


sf at sfritsch

Aug 3, 2012, 12:25 AM

Post #3 of 8 (986 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

On Thursday 02 August 2012, Graham Leggett wrote:
> I have a config like this using httpd v2.4, in an effort to
> password protect each person's userdir:
>
> <RequireAll>
> Require valid-user
> Require expr %{note:mod_userdir_user} == %{REMOTE_USER}
> </RequireAll>
>
> Hit it with a browser, and instead of 401 Unauthorized I'm getting
> 403 Forbidden instead, which prevents the basic authentication
> from kicking in and the user is denied.
>
> The log however shows something odd - despite the RequireAll
> directive being used, which implies AND behaviour, which in turn
> implies that require lines should be parsed until the first one
> fails and then the parsing should stop, both require lines are
> being evaluated even though the first line failed, and the result
> of the second require line is being sent instead.

This works as designed. Authentication will only be triggered if the
end result depends on a valid user being present. The reason is to
avoid a password dialogue if the access will be denied anyway.

> In theory, in the RequireAll situation, require directives should
> be parsed until one fails, and the result of that failure returned
> to the client. All further require lines should be ignored as is
> standard behaviour for AND implementations. In the example above,
> the "authorization result of Require valid-user : denied (no
> authenticated user yet)" part should prevent the "authorization
> result of Require expr %{note:mod_userdir_user} == %{REMOTE_USER}:
> denied" part from being attempted at all.
>
> Can someone check whether my thinking is correct?

I guess your approach would have been valid, too. But it causes other
problems since the user cannot influence the order in which require
directives are evaluated if AuthMerging is "or" or "and". One could
have solved that with some additional directives like "AuthMerging or
prepend", etc., but that would get rather complex if one wants to keep
the full flexibility. I could imagine cases where additional require
lines would need to be evaluated in the middle of the inherited lines.

For 2.4.x, we are now stuck with the current behavior. For 2.6/3.0, we
may of course consider to change it, if the alternative is better.

2.4.3 will give "require expr" some special casing for REMOTE_USER
that makes your use case work (see r1364266). PR 52892 has a
workaround that works with 2.4.2, too.

If the special case for REMOTE_USER is not enough, one could add a
trigger_authn function that allows the same behavior for arbitrary
variables. E.g.

Require expr %{note:mod_userdir_user} ==
trigger_authn(%{AUTHZ_VAR_FOO})


minfrin at sharp

Aug 5, 2012, 11:56 AM

Post #4 of 8 (981 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

On 03 Aug 2012, at 9:25 AM, Stefan Fritsch wrote:

>> I have a config like this using httpd v2.4, in an effort to
>> password protect each person's userdir:
>>
>> <RequireAll>
>> Require valid-user
>> Require expr %{note:mod_userdir_user} == %{REMOTE_USER}
>> </RequireAll>
>>
>> Hit it with a browser, and instead of 401 Unauthorized I'm getting
>> 403 Forbidden instead, which prevents the basic authentication
>> from kicking in and the user is denied.
>>
>> The log however shows something odd - despite the RequireAll
>> directive being used, which implies AND behaviour, which in turn
>> implies that require lines should be parsed until the first one
>> fails and then the parsing should stop, both require lines are
>> being evaluated even though the first line failed, and the result
>> of the second require line is being sent instead.
>
> This works as designed. Authentication will only be triggered if the
> end result depends on a valid user being present. The reason is to
> avoid a password dialogue if the access will be denied anyway.

This breaks basic authentication though, because basic auth relies on that initial 401 Unauthorized to tell the client that a password is required. In this case, access would have been approved, not denied, but the client never got the opportunity to try log in as it was forbidden from the outset.

Right now, I cannot get aaa to work in either a browser or in the webdav client for MacOSX with two require lines. In both cases, the user is forbidden immediately with no opportunity to log in.

>> In theory, in the RequireAll situation, require directives should
>> be parsed until one fails, and the result of that failure returned
>> to the client. All further require lines should be ignored as is
>> standard behaviour for AND implementations. In the example above,
>> the "authorization result of Require valid-user : denied (no
>> authenticated user yet)" part should prevent the "authorization
>> result of Require expr %{note:mod_userdir_user} == %{REMOTE_USER}:
>> denied" part from being attempted at all.
>>
>> Can someone check whether my thinking is correct?
>
> I guess your approach would have been valid, too. But it causes other
> problems since the user cannot influence the order in which require
> directives are evaluated if AuthMerging is "or" or "and".

In theory the evaluation should be done in the order that the directives appear in the config file.

> One could
> have solved that with some additional directives like "AuthMerging or
> prepend", etc., but that would get rather complex if one wants to keep
> the full flexibility. I could imagine cases where additional require
> lines would need to be evaluated in the middle of the inherited lines.

How does inheritance work now?

> For 2.4.x, we are now stuck with the current behavior. For 2.6/3.0, we
> may of course consider to change it, if the alternative is better.

Right now from what I can see the RequireAll directive isn't working at all, so to fix it in v2.4 would just be a bugfix.

> 2.4.3 will give "require expr" some special casing for REMOTE_USER
> that makes your use case work (see r1364266). PR 52892 has a
> workaround that works with 2.4.2, too.
>
> If the special case for REMOTE_USER is not enough, one could add a
> trigger_authn function that allows the same behavior for arbitrary
> variables. E.g.
>
> Require expr %{note:mod_userdir_user} ==
> trigger_authn(%{AUTHZ_VAR_FOO})

I'm not convinced. Both AND and OR have behaviour dictated by the principle of least astonishment, and I think it would be better for end users for the behaviour to match what they expect, rather than try to second guess what the end user wants with special cases.

Regards,
Graham
--
Attachments: smime.p7s (4.26 KB)


sf at sfritsch

Aug 5, 2012, 1:39 PM

Post #5 of 8 (995 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

On Sun, 5 Aug 2012, Graham Leggett wrote:
>> This works as designed. Authentication will only be triggered if the
>> end result depends on a valid user being present. The reason is to
>> avoid a password dialogue if the access will be denied anyway.
>
> This breaks basic authentication though, because basic auth relies on
> that initial 401 Unauthorized to tell the client that a password is
> required. In this case, access would have been approved, not denied, but
> the client never got the opportunity to try log in as it was forbidden
> from the outset.
>
> Right now, I cannot get aaa to work in either a browser or in the webdav
> client for MacOSX with two require lines. In both cases, the user is
> forbidden immediately with no opportunity to log in.

You mean you can't get "Require expr" to work. All other providers should
work ok. Or do you have an example that does not involve "Require expr"?

>> I guess your approach would have been valid, too. But it causes other
>> problems since the user cannot influence the order in which require
>> directives are evaluated if AuthMerging is "or" or "and".
>
> In theory the evaluation should be done in the order that the directives appear in the config file.
>
>> One could
>> have solved that with some additional directives like "AuthMerging or
>> prepend", etc., but that would get rather complex if one wants to keep
>> the full flexibility. I could imagine cases where additional require
>> lines would need to be evaluated in the middle of the inherited lines.
>
> How does inheritance work now?

The Require lines are evaluated in normal config merge order. This
means that Require lines from <Directory> blocks are always evaluated
before <Location>, etc.

>
>> For 2.4.x, we are now stuck with the current behavior. For 2.6/3.0, we
>> may of course consider to change it, if the alternative is better.
>
> Right now from what I can see the RequireAll directive isn't working at all, so to fix it in v2.4 would just be a bugfix.

I disagree. It works except for "Require expr". And fixing it your way
would cause behavior changes in many cases, not just for "Require expr".

>> 2.4.3 will give "require expr" some special casing for REMOTE_USER
>> that makes your use case work (see r1364266). PR 52892 has a
>> workaround that works with 2.4.2, too.
>>
>> If the special case for REMOTE_USER is not enough, one could add a
>> trigger_authn function that allows the same behavior for arbitrary
>> variables. E.g.
>>
>> Require expr %{note:mod_userdir_user} ==
>> trigger_authn(%{AUTHZ_VAR_FOO})
>
> I'm not convinced. Both AND and OR have behaviour dictated by the
> principle of least astonishment, and I think it would be better for end
> users for the behaviour to match what they expect, rather than try to
> second guess what the end user wants with special cases.

If the interpretation of Require lines depends on the order, but you
cannot influence the order in case of inheritance, then inheritance gets
mostly useless. This is not the kind of change to make in a stable
release.


minfrin at sharp

Aug 5, 2012, 2:52 PM

Post #6 of 8 (984 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

On 05 Aug 2012, at 10:39 PM, Stefan Fritsch wrote:

>>> This works as designed. Authentication will only be triggered if the
>>> end result depends on a valid user being present. The reason is to
>>> avoid a password dialogue if the access will be denied anyway.
>>
>> This breaks basic authentication though, because basic auth relies on that initial 401 Unauthorized to tell the client that a password is required. In this case, access would have been approved, not denied, but the client never got the opportunity to try log in as it was forbidden from the outset.
>>
>> Right now, I cannot get aaa to work in either a browser or in the webdav client for MacOSX with two require lines. In both cases, the user is forbidden immediately with no opportunity to log in.
>
> You mean you can't get "Require expr" to work. All other providers should work ok. Or do you have an example that does not involve "Require expr"?

Most specifically, as per my original mail, I can't get the following to work:

<RequireAll>
Require valid-user
Require expr %{note:mod_userdir_user} == %{REMOTE_USER}
</RequireAll>

Can you clarify what is special about the expr specifically that triggers forbidden instead of unauthorized?

Perhaps this is a bug inside the expr code.

Regards,
Graham
--
Attachments: smime.p7s (4.26 KB)


sf at sfritsch

Aug 5, 2012, 3:01 PM

Post #7 of 8 (982 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

On Sunday 05 August 2012, Graham Leggett wrote:
> > You mean you can't get "Require expr" to work. All other
> > providers should work ok. Or do you have an example that does
> > not involve "Require expr"?
>
> Most specifically, as per my original mail, I can't get the
> following to work:
>
> <RequireAll>
> Require valid-user
> Require expr %{note:mod_userdir_user} == %{REMOTE_USER}
> </RequireAll>
>
> Can you clarify what is special about the expr specifically that
> triggers forbidden instead of unauthorized?
>
> Perhaps this is a bug inside the expr code.

The API is currently such that an authz provider must return
AUTHZ_DENIED_NO_USER instead of AUTHZ_DENIED if its result may change
after authentication. Require expr in 2.4.2 does not do that. But it
will be fixed in 2.4.3 with

http://svn.apache.org/viewvc?view=revision&revision=1364266


minfrin at sharp

Aug 6, 2012, 10:05 AM

Post #8 of 8 (978 views)
Permalink
Re: RequireAll: seems to evaluate require lines unnecessarily [In reply to]

On 06 Aug 2012, at 12:01 AM, Stefan Fritsch wrote:

> The API is currently such that an authz provider must return
> AUTHZ_DENIED_NO_USER instead of AUTHZ_DENIED if its result may change
> after authentication. Require expr in 2.4.2 does not do that. But it
> will be fixed in 2.4.3 with
>
> http://svn.apache.org/viewvc?view=revision&revision=1364266

I'm away for part of this week, I'll try this out when I get back.

My concern at the API is that it seems that some of the Require lines are AUTHN related, while others are AUTHZ. In theory, if a single Require check fails AUTHN, it nullifies AUTHZ - you cannot know if the AUTHZ would have succeeded or failed until AUTHN has occurred successfully. This in turn means that if a line like "Require valid-user" fails, you can draw no conclusion about any of the AUTHZ lines, they might have succeeded, they might have failed, impossible to know with the information at hand.

Regards,
Graham
--
Attachments: smime.p7s (4.26 KB)

Apache dev RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.