You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@httpd.apache.org by Mike Schlottman <ms...@spe.org> on 2017/02/20 17:17:34 UTC

[users@httpd] Problem when using nested if statements in apache 2.4

I'm trying to configure apache 2.4 to show nice error pages to external users of our web site, while allowing staff to see the real error.   The idea is to prevent exposing privileged information to the general public while allowing our staff to more easily debug issues on our production web site.   To accomplish this I am using a combination of ErrorDocument within an If statement that evaluates the header X-Real-IP which is the IP address of the client on my server.

This seems to work, until I nest the If statements to catch all the IP ranges that I am interested in.

For example...
<If  "! %{HTTP:X-Real-IP}  -ipmatch '172.28.1.84/32' ">
  ErrorDocument 404 /errors/404
</If>
will correctly show the nice 404 page for a user coming from 172.28.1.84.

Using this, the same user coming from 172.28.1.84 sees the nice error page.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
  ErrorDocument 404 /errors/404
</If>

Simmilarly the same user gets the nice error page when this code is used.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
  ErrorDocument 404 /errors/404
</If>

The problem comes when I combine these 2 so that all users except those coming from 127.*.*.* or 192.168.*.* see the nice error page.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
  <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
    ErrorDocument 404 /errors/404
  </If>
</If>
The user from 172.28.1.84 does not get the nice 404 page, but the default 404 page.   The IP does not match either of the ranges as observed when using the ranges individually, but when combined in this way it does not work as expected.

Any ideas why this is?

Mike Schlottman
Sr. Infrastructure Architect
Society of Petroleum Engineers
222 Palisades Creek Drive
Richardson, TX 75080


Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-03-28 17:28 GMT+02:00 Luca Toscano <to...@gmail.com>:

>
>
> 2017-02-21 18:45 GMT+01:00 Luca Toscano <to...@gmail.com>:
>
>> Hi Mike,
>>
>> 2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:
>>
>>> I’m trying to configure apache 2.4 to show nice error pages to external
>>> users of our web site, while allowing staff to see the real error.   The
>>> idea is to prevent exposing privileged information to the general public
>>> while allowing our staff to more easily debug issues on our production web
>>> site.   To accomplish this I am using a combination of ErrorDocument within
>>> an If statement that evaluates the header X-Real-IP which is the IP address
>>> of the client on my server.
>>>
>>>
>>>
>>> This seems to work, until I nest the If statements to catch all the IP
>>> ranges that I am interested in.
>>>
>>>
>>>
>>> For example…
>>>
>>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '172.28.1.84/32' ">
>>>
>>>   ErrorDocument 404 /errors/404
>>>
>>> </If>
>>>
>>> will correctly show the nice 404 page for a user coming from 172.28.1.84.
>>>
>>>
>>>
>>> Using this, the same user coming from 172.28.1.84 sees the nice error
>>> page.
>>>
>>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>>
>>>   ErrorDocument 404 /errors/404
>>>
>>> </If>
>>>
>>>
>>>
>>> Simmilarly the same user gets the nice error page when this code is used.
>>>
>>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>>
>>>   ErrorDocument 404 /errors/404
>>>
>>> </If>
>>>
>>>
>>>
>>> The problem comes when I combine these 2 so that all users except those
>>> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>>>
>>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>>
>>>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>>
>>>     ErrorDocument 404 /errors/404
>>>
>>>   </If>
>>>
>>> </If>
>>>
>>> The user from 172.28.1.84 does not get the nice 404 page, but the
>>> default 404 page.   The IP does not match either of the ranges as observed
>>> when using the ranges individually, but when combined in this way it does
>>> not work as expected.
>>>
>>>
>>>
>>> Any ideas why this is?
>>>
>>>
>>>
>>
>> I reproduced your use case and from the error_log (trace8) I can see that
>> with nested <If>s the second one seems not evaluated (or more precisely,
>> its expression is not). In the beginning I thought it was a peculiarity of
>> how the ErrorDocument core directive settings are merged between sections,
>> but it seems not the case.
>>
>> From my point of view, a container like <If> should be used like other
>> similar directives like <Directory> and <Location>, where this use case
>> would look a bit weird. The <If> naming brings up conventions that we use
>> in traditional programming languages, so this might be the source of the
>> confusion.
>>
>> For your specific use case, I'd have done something like the following:
>>
>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16'  || !
>> %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>     ErrorDocument 404 "My awesome error"
>> </If>
>>
>> or maybe using <ElseIf>/<Else>.
>>
>> http://httpd.apache.org/docs/current/sections.html shows a little
>> paragraph about "Nesting of sections", but I don't see any reference of
>> your use case. I'll dig a bit more during the next days to find a better
>> explanation if nobody will come up with a better solution :)
>>
>>
>
> It took me a while (and I forgot to update the list) but I double checked
> and currently httpd does not allow nested <If> sections. I updated the
> following doc pages to warn users:
>
> http://httpd.apache.org/docs/current/sections.html
> https://httpd.apache.org/docs/2.4/mod/core.html#if ("Not a scripting
> language")
>
> I am currently investigating if http://home.apache.org/~
> elukey/httpd-trunk-core-nested_if_blocks.patch solves the problem; if
> anybody wants to help testing please let me know :) (you can apply the
> patch to the latest 2.4.x branch cleanly and recompile).
>

Too soon, I found some corner cases that require more work to get fixed.
Will update the list once done for anybody interested :)

Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-02-21 18:45 GMT+01:00 Luca Toscano <to...@gmail.com>:

> Hi Mike,
>
> 2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:
>
>> I’m trying to configure apache 2.4 to show nice error pages to external
>> users of our web site, while allowing staff to see the real error.   The
>> idea is to prevent exposing privileged information to the general public
>> while allowing our staff to more easily debug issues on our production web
>> site.   To accomplish this I am using a combination of ErrorDocument within
>> an If statement that evaluates the header X-Real-IP which is the IP address
>> of the client on my server.
>>
>>
>>
>> This seems to work, until I nest the If statements to catch all the IP
>> ranges that I am interested in.
>>
>>
>>
>> For example…
>>
>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '172.28.1.84/32' ">
>>
>>   ErrorDocument 404 /errors/404
>>
>> </If>
>>
>> will correctly show the nice 404 page for a user coming from 172.28.1.84.
>>
>>
>>
>> Using this, the same user coming from 172.28.1.84 sees the nice error
>> page.
>>
>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>
>>   ErrorDocument 404 /errors/404
>>
>> </If>
>>
>>
>>
>> Simmilarly the same user gets the nice error page when this code is used.
>>
>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>
>>   ErrorDocument 404 /errors/404
>>
>> </If>
>>
>>
>>
>> The problem comes when I combine these 2 so that all users except those
>> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>>
>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>
>>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>
>>     ErrorDocument 404 /errors/404
>>
>>   </If>
>>
>> </If>
>>
>> The user from 172.28.1.84 does not get the nice 404 page, but the default
>> 404 page.   The IP does not match either of the ranges as observed when
>> using the ranges individually, but when combined in this way it does not
>> work as expected.
>>
>>
>>
>> Any ideas why this is?
>>
>>
>>
>
> I reproduced your use case and from the error_log (trace8) I can see that
> with nested <If>s the second one seems not evaluated (or more precisely,
> its expression is not). In the beginning I thought it was a peculiarity of
> how the ErrorDocument core directive settings are merged between sections,
> but it seems not the case.
>
> From my point of view, a container like <If> should be used like other
> similar directives like <Directory> and <Location>, where this use case
> would look a bit weird. The <If> naming brings up conventions that we use
> in traditional programming languages, so this might be the source of the
> confusion.
>
> For your specific use case, I'd have done something like the following:
>
> <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16'  || !
> %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>     ErrorDocument 404 "My awesome error"
> </If>
>
> or maybe using <ElseIf>/<Else>.
>
> http://httpd.apache.org/docs/current/sections.html shows a little
> paragraph about "Nesting of sections", but I don't see any reference of
> your use case. I'll dig a bit more during the next days to find a better
> explanation if nobody will come up with a better solution :)
>
>

It took me a while (and I forgot to update the list) but I double checked
and currently httpd does not allow nested <If> sections. I updated the
following doc pages to warn users:

http://httpd.apache.org/docs/current/sections.html
https://httpd.apache.org/docs/2.4/mod/core.html#if ("Not a scripting
language")

I am currently investigating if
http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks.patch
solves the problem; if anybody wants to help testing please let me know :)
(you can apply the patch to the latest 2.4.x branch cleanly and recompile).

Thanks!

Luca

RE: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Mike Schlottman <ms...@spe.org>.
Thanks Luca.   This all makes sense with what I was seeing.   I ended up using something similar to what you suggested.   Here it is in case it ever helps someone.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '10.0.0.0/8' && \
! %{HTTP:X-Real-IP}  -ipmatch '172.16.0.0/12' && \
! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' && \
! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
  ErrorDocument 400 /errors/400
  ErrorDocument 401 /errors/401
  ErrorDocument 402 /errors/402
  ErrorDocument 403 /errors/403
  ErrorDocument 404 /errors/404
  ErrorDocument 405 /errors/405
  ErrorDocument 500 /errors/500
  ErrorDocument 501 /errors/501
  ErrorDocument 502 /errors/502
  ErrorDocument 503 /errors/503
  ErrorDocument 504 /errors/504
  ErrorDocument 505 /errors/505
</If>



From: Luca Toscano [mailto:toscano.luca@gmail.com]
Sent: Tuesday, February 21, 2017 11:46 AM
To: users@httpd.apache.org
Subject: Re: [users@httpd] Problem when using nested if statements in apache 2.4

Hi Mike,

2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>>:
I’m trying to configure apache 2.4 to show nice error pages to external users of our web site, while allowing staff to see the real error.   The idea is to prevent exposing privileged information to the general public while allowing our staff to more easily debug issues on our production web site.   To accomplish this I am using a combination of ErrorDocument within an If statement that evaluates the header X-Real-IP which is the IP address of the client on my server.

This seems to work, until I nest the If statements to catch all the IP ranges that I am interested in.

For example…
<If  "! %{HTTP:X-Real-IP}  -ipmatch '172.28.1.84/32<http://172.28.1.84/32>' ">
  ErrorDocument 404 /errors/404
</If>
will correctly show the nice 404 page for a user coming from 172.28.1.84.

Using this, the same user coming from 172.28.1.84 sees the nice error page.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8<http://127.0.0.0/8>' ">
  ErrorDocument 404 /errors/404
</If>

Simmilarly the same user gets the nice error page when this code is used.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>' ">
  ErrorDocument 404 /errors/404
</If>

The problem comes when I combine these 2 so that all users except those coming from 127.*.*.* or 192.168.*.* see the nice error page.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8<http://127.0.0.0/8>' ">
  <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>' ">
    ErrorDocument 404 /errors/404
  </If>
</If>
The user from 172.28.1.84 does not get the nice 404 page, but the default 404 page.   The IP does not match either of the ranges as observed when using the ranges individually, but when combined in this way it does not work as expected.

Any ideas why this is?


I reproduced your use case and from the error_log (trace8) I can see that with nested <If>s the second one seems not evaluated (or more precisely, its expression is not). In the beginning I thought it was a peculiarity of how the ErrorDocument core directive settings are merged between sections, but it seems not the case.

From my point of view, a container like <If> should be used like other similar directives like <Directory> and <Location>, where this use case would look a bit weird. The <If> naming brings up conventions that we use in traditional programming languages, so this might be the source of the confusion.

For your specific use case, I'd have done something like the following:

<If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>'  || ! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>' ">
    ErrorDocument 404 "My awesome error"
</If>

or maybe using <ElseIf>/<Else>.

http://httpd.apache.org/docs/current/sections.html shows a little paragraph about "Nesting of sections", but I don't see any reference of your use case. I'll dig a bit more during the next days to find a better explanation if nobody will come up with a better solution :)


Luca



Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
Hi Mike,

2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:

> I’m trying to configure apache 2.4 to show nice error pages to external
> users of our web site, while allowing staff to see the real error.   The
> idea is to prevent exposing privileged information to the general public
> while allowing our staff to more easily debug issues on our production web
> site.   To accomplish this I am using a combination of ErrorDocument within
> an If statement that evaluates the header X-Real-IP which is the IP address
> of the client on my server.
>
>
>
> This seems to work, until I nest the If statements to catch all the IP
> ranges that I am interested in.
>
>
>
> For example…
>
> <If  "! %{HTTP:X-Real-IP}  -ipmatch '172.28.1.84/32' ">
>
>   ErrorDocument 404 /errors/404
>
> </If>
>
> will correctly show the nice 404 page for a user coming from 172.28.1.84.
>
>
>
> Using this, the same user coming from 172.28.1.84 sees the nice error
> page.
>
> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>
>   ErrorDocument 404 /errors/404
>
> </If>
>
>
>
> Simmilarly the same user gets the nice error page when this code is used.
>
> <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>
>   ErrorDocument 404 /errors/404
>
> </If>
>
>
>
> The problem comes when I combine these 2 so that all users except those
> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>
> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>
>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>
>     ErrorDocument 404 /errors/404
>
>   </If>
>
> </If>
>
> The user from 172.28.1.84 does not get the nice 404 page, but the default
> 404 page.   The IP does not match either of the ranges as observed when
> using the ranges individually, but when combined in this way it does not
> work as expected.
>
>
>
> Any ideas why this is?
>
>
>

I reproduced your use case and from the error_log (trace8) I can see that
with nested <If>s the second one seems not evaluated (or more precisely,
its expression is not). In the beginning I thought it was a peculiarity of
how the ErrorDocument core directive settings are merged between sections,
but it seems not the case.

From my point of view, a container like <If> should be used like other
similar directives like <Directory> and <Location>, where this use case
would look a bit weird. The <If> naming brings up conventions that we use
in traditional programming languages, so this might be the source of the
confusion.

For your specific use case, I'd have done something like the following:

<If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16'  || !
%{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
    ErrorDocument 404 "My awesome error"
</If>

or maybe using <ElseIf>/<Else>.

http://httpd.apache.org/docs/current/sections.html shows a little paragraph
about "Nesting of sections", but I don't see any reference of your use
case. I'll dig a bit more during the next days to find a better explanation
if nobody will come up with a better solution :)


Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-04-19 10:05 GMT+02:00 Luca Toscano <to...@gmail.com>:

>
>
> 2017-03-27 19:09 GMT+02:00 Luca Toscano <to...@gmail.com>:
>
>> Hi Yann,
>>
>> 2017-03-27 8:56 GMT+02:00 Yann Ylavic <yl...@gmail.com>:
>>
>>> Hi Luca,
>>>
>>> On Mon, Mar 20, 2017 at 1:25 PM, Luca Toscano <to...@gmail.com>
>>> wrote:
>>> >
>>> > Documentation updated with the current status, plus the following patch
>>> > seems to allow nested if blocks (probably not the best one but it is a
>>> pof):
>>> >
>>> > http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks.patch
>>>
>>> LGTM (nit: ap_if_walk_sub() needs not be AP_DECLARE()d since it's a
>>> local helper only).
>>>
>>
>> Thanks a lot for the feedback, I modified the patch to include your
>> suggestion and another one from Jim (checking whether or not the
>> ap_if_walk_sub calls return something different than OK, hope that the
>> implementation is what was expected). Ran also the test suite in trunk, no
>> failure registered (Jacob: make check is really awesome).
>>
>> I'd like to perform some performance tests before proceeding, this code
>> adds a (probably negligible in 90% of the use case) overhead to each
>> ap_if_walk call (running twice for each request afaics).
>>
>> Any other comment/review will be really appreciated :)
>>
>>
> Updates:
>
> - the original patch evolved up to http://home.apache.org/~elukey
> /httpd-trunk-core-nested_if_blocks.patch but it was a bit too hacky.
>
> - Jacob reviewed the code and suggested to investigate the use of
> now_merged to clean up the code, and a new patch came to life:
> http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks_v2.patch
>
> - Added some tests to the suite in http://home.apache.org/~elukey
> /httpd-framework-nested-ifs.patch, everything seems to work fine. My
> understanding is that the tests are leveraging the "Header merge" feature
> to simulate the order of merging with different <If> condition evaluations.
> I added the same block of nested <If>/ElseIf/Else to
> Directory/Location/Files and the result looks consistent.
>
> Comments welcome, I think the work is almost done but I might have missed
> something..
>


For the records the trunk patch has been committed in r1792589 and the
related tests in r1793187.

Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-03-27 19:09 GMT+02:00 Luca Toscano <to...@gmail.com>:

> Hi Yann,
>
> 2017-03-27 8:56 GMT+02:00 Yann Ylavic <yl...@gmail.com>:
>
>> Hi Luca,
>>
>> On Mon, Mar 20, 2017 at 1:25 PM, Luca Toscano <to...@gmail.com>
>> wrote:
>> >
>> > Documentation updated with the current status, plus the following patch
>> > seems to allow nested if blocks (probably not the best one but it is a
>> pof):
>> >
>> > http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks.patch
>>
>> LGTM (nit: ap_if_walk_sub() needs not be AP_DECLARE()d since it's a
>> local helper only).
>>
>
> Thanks a lot for the feedback, I modified the patch to include your
> suggestion and another one from Jim (checking whether or not the
> ap_if_walk_sub calls return something different than OK, hope that the
> implementation is what was expected). Ran also the test suite in trunk, no
> failure registered (Jacob: make check is really awesome).
>
> I'd like to perform some performance tests before proceeding, this code
> adds a (probably negligible in 90% of the use case) overhead to each
> ap_if_walk call (running twice for each request afaics).
>
> Any other comment/review will be really appreciated :)
>
>
Updates:

- the original patch evolved up to http://home.apache.org/~
elukey/httpd-trunk-core-nested_if_blocks.patch but it was a bit too hacky.

- Jacob reviewed the code and suggested to investigate the use of
now_merged to clean up the code, and a new patch came to life:
http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks_v2.patch

- Added some tests to the suite in http://home.apache.org/~
elukey/httpd-framework-nested-ifs.patch, everything seems to work fine. My
understanding is that the tests are leveraging the "Header merge" feature
to simulate the order of merging with different <If> condition evaluations.
I added the same block of nested <If>/ElseIf/Else to
Directory/Location/Files and the result looks consistent.

Comments welcome, I think the work is almost done but I might have missed
something..

Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
Hi Yann,

2017-03-27 8:56 GMT+02:00 Yann Ylavic <yl...@gmail.com>:

> Hi Luca,
>
> On Mon, Mar 20, 2017 at 1:25 PM, Luca Toscano <to...@gmail.com>
> wrote:
> >
> > Documentation updated with the current status, plus the following patch
> > seems to allow nested if blocks (probably not the best one but it is a
> pof):
> >
> > http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks.patch
>
> LGTM (nit: ap_if_walk_sub() needs not be AP_DECLARE()d since it's a
> local helper only).
>

Thanks a lot for the feedback, I modified the patch to include your
suggestion and another one from Jim (checking whether or not the
ap_if_walk_sub calls return something different than OK, hope that the
implementation is what was expected). Ran also the test suite in trunk, no
failure registered (Jacob: make check is really awesome).

I'd like to perform some performance tests before proceeding, this code
adds a (probably negligible in 90% of the use case) overhead to each
ap_if_walk call (running twice for each request afaics).

Any other comment/review will be really appreciated :)

Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Yann Ylavic <yl...@gmail.com>.
Hi Luca,

On Mon, Mar 20, 2017 at 1:25 PM, Luca Toscano <to...@gmail.com> wrote:
>
> Documentation updated with the current status, plus the following patch
> seems to allow nested if blocks (probably not the best one but it is a pof):
>
> http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks.patch

LGTM (nit: ap_if_walk_sub() needs not be AP_DECLARE()d since it's a
local helper only).

Thanks for this work.

Regards,
Yann.

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-03-17 22:33 GMT+01:00 Luca Toscano <to...@gmail.com>:

>
>
> 2017-03-09 22:47 GMT+01:00 Luca Toscano <to...@gmail.com>:
>
>>
>>
>> 2017-02-24 23:27 GMT+01:00 Luca Toscano <to...@gmail.com>:
>>
>>> Hi everybody,
>>>
>>> the following users@ question is interesting in my opinion:
>>>
>>> 2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:
>>>
>>>>
>>>> The problem comes when I combine these 2 so that all users except those
>>>> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>>>>
>>>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>>>
>>>>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>>>
>>>>     ErrorDocument 404 /errors/404
>>>>
>>>>   </If>
>>>>
>>>> </If>
>>>>
>>>> The user from 172.28.1.84 does not get the nice 404 page, but the
>>>> default 404 page.   The IP does not match either of the ranges as observed
>>>> when using the ranges individually, but when combined in this way it does
>>>> not work as expected.
>>>>
>>>>
>>>>
>>>> Any ideas why this is?
>>>>
>>>>
>>>>
>>>
>>> He ended up using a single if with an expression composed by the two
>>> conditions in && to solve the problem, but I started to wonder why this
>>> configuration does not work. I tested the "nested ifs" config with trace8
>>> logging and it seem that only the outermost <If> expression gets evaluated.
>>>
>>> Is there a specific reason why this happens? I'd expect two possible
>>> outcomes from this configuration, namely either a syntax error while
>>> parsing the config (preferred imho) or a context merge, but not a no-op.
>>>
>>> Any pointers/suggestions about where to look?
>>>
>>>
>> I tried to investigate a bit the problem to write a good explanation in
>> the docs (and also to better understand the httpd internals for fun) but I
>> am still far from a satisfactory result.
>>
>> I tried the following config (inside other containers like Location too):
>>
>> <If  "true">
>>     ErrorDocument 503 "This is a custom 503 inside the outer IF!"
>>     <If "true">
>>        ErrorDocument 503 "This is a custom 503 inside the inner IF!"
>>     </If>
>> </If>
>>
>> Each time that 503 is generated, I get the "outer IF" 503 response, never
>> the inner one.
>>
>> With gdb it is easy to see that when ap_if_walk is executed,
>> dconf->sec_if->nelts is 1, so only one of the Ifs is evaluated.
>>
>> So I checked how the if sections are parsed and built
>> with ap_process_config_tree->ap_walk_config->ap_walk_config_sub->invoke_cmd->ifsection
>> and eventually ap_add_if, but I only got that the parent/child relationship
>> is set up correctly.
>>
>> My only goal is to figure out if nested Ifs are not evaluated on purpose
>> and if so why they are allowed by the syntax checker. Eventually it would
>> be really great to update the docs (regular user docs and also
>> https://httpd.apache.org/docs/trunk/developer/request.html).
>>
>>
> This time (hopefully) I think I found what I was looking for, namely why
> nested <If> blocks are definitely not going to work.
>
> The ap_if_walk (request.c) function gets the core_dir_config settings
> via ap_get_core_module_config(r->per_dir_config), retrieving all the <If>
> containers using the sec_if field, and then iterating through them to
> evaluate their (apr_expr) conditions.
>
> In order to be able to use nested <If> blocks ap_if_walk would need to
> check, for each sec_if->elts element of the core's r->per_dir_config, if it
> contains a sec_if blocks too (and restart the process of checking its
> condition etc..). Something like:
>
> AP_DECLARE(int) ap_if_walk(request_rec *r) {
> [..]
>     /* Go through the if entries, and check for matches  */
>     for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
>         core_dir_config *entry_core;
>         entry_core = ap_get_core_module_config(sec_ent[sec_idx]);
>         if(entry_core->sec_if->nelts > 0) { .. /* handling nested <If>s */
> .. }
> [..]
>
> In this way we would allow arbitrary nesting of <If> blocks in the httpd
> config. I am not advocating for this solution but we should either allow
> nested <If> blocks or explicitly warn the users when httpd checks its
> config that a nested configuration will be silently ignored (emitting an
> explicit configuration error while parsing the config would be even better
> but probably too invasive for 2.4.x releases).
>

Documentation updated with the current status, plus the following patch
seems to allow nested if blocks (probably not the best one but it is a pof):

http://home.apache.org/~elukey/httpd-trunk-core-nested_if_blocks.patch

 Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-03-09 22:47 GMT+01:00 Luca Toscano <to...@gmail.com>:

>
>
> 2017-02-24 23:27 GMT+01:00 Luca Toscano <to...@gmail.com>:
>
>> Hi everybody,
>>
>> the following users@ question is interesting in my opinion:
>>
>> 2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:
>>
>>>
>>> The problem comes when I combine these 2 so that all users except those
>>> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>>>
>>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>>
>>>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>>
>>>     ErrorDocument 404 /errors/404
>>>
>>>   </If>
>>>
>>> </If>
>>>
>>> The user from 172.28.1.84 does not get the nice 404 page, but the
>>> default 404 page.   The IP does not match either of the ranges as observed
>>> when using the ranges individually, but when combined in this way it does
>>> not work as expected.
>>>
>>>
>>>
>>> Any ideas why this is?
>>>
>>>
>>>
>>
>> He ended up using a single if with an expression composed by the two
>> conditions in && to solve the problem, but I started to wonder why this
>> configuration does not work. I tested the "nested ifs" config with trace8
>> logging and it seem that only the outermost <If> expression gets evaluated.
>>
>> Is there a specific reason why this happens? I'd expect two possible
>> outcomes from this configuration, namely either a syntax error while
>> parsing the config (preferred imho) or a context merge, but not a no-op.
>>
>> Any pointers/suggestions about where to look?
>>
>>
> I tried to investigate a bit the problem to write a good explanation in
> the docs (and also to better understand the httpd internals for fun) but I
> am still far from a satisfactory result.
>
> I tried the following config (inside other containers like Location too):
>
> <If  "true">
>     ErrorDocument 503 "This is a custom 503 inside the outer IF!"
>     <If "true">
>        ErrorDocument 503 "This is a custom 503 inside the inner IF!"
>     </If>
> </If>
>
> Each time that 503 is generated, I get the "outer IF" 503 response, never
> the inner one.
>
> With gdb it is easy to see that when ap_if_walk is executed,
> dconf->sec_if->nelts is 1, so only one of the Ifs is evaluated.
>
> So I checked how the if sections are parsed and built
> with ap_process_config_tree->ap_walk_config->ap_walk_config_sub->invoke_cmd->ifsection
> and eventually ap_add_if, but I only got that the parent/child relationship
> is set up correctly.
>
> My only goal is to figure out if nested Ifs are not evaluated on purpose
> and if so why they are allowed by the syntax checker. Eventually it would
> be really great to update the docs (regular user docs and also
> https://httpd.apache.org/docs/trunk/developer/request.html).
>
>
This time (hopefully) I think I found what I was looking for, namely why
nested <If> blocks are definitely not going to work.

The ap_if_walk (request.c) function gets the core_dir_config settings
via ap_get_core_module_config(r->per_dir_config), retrieving all the <If>
containers using the sec_if field, and then iterating through them to
evaluate their (apr_expr) conditions.

In order to be able to use nested <If> blocks ap_if_walk would need to
check, for each sec_if->elts element of the core's r->per_dir_config, if it
contains a sec_if blocks too (and restart the process of checking its
condition etc..). Something like:

AP_DECLARE(int) ap_if_walk(request_rec *r) {
[..]
    /* Go through the if entries, and check for matches  */
    for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
        core_dir_config *entry_core;
        entry_core = ap_get_core_module_config(sec_ent[sec_idx]);
        if(entry_core->sec_if->nelts > 0) { .. /* handling nested <If>s */
.. }
[..]

In this way we would allow arbitrary nesting of <If> blocks in the httpd
config. I am not advocating for this solution but we should either allow
nested <If> blocks or explicitly warn the users when httpd checks its
config that a nested configuration will be silently ignored (emitting an
explicit configuration error while parsing the config would be even better
but probably too invasive for 2.4.x releases).

Thoughts?

Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
2017-02-24 23:27 GMT+01:00 Luca Toscano <to...@gmail.com>:

> Hi everybody,
>
> the following users@ question is interesting in my opinion:
>
> 2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:
>
>>
>> The problem comes when I combine these 2 so that all users except those
>> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>>
>> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>>
>>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>>
>>     ErrorDocument 404 /errors/404
>>
>>   </If>
>>
>> </If>
>>
>> The user from 172.28.1.84 does not get the nice 404 page, but the default
>> 404 page.   The IP does not match either of the ranges as observed when
>> using the ranges individually, but when combined in this way it does not
>> work as expected.
>>
>>
>>
>> Any ideas why this is?
>>
>>
>>
>
> He ended up using a single if with an expression composed by the two
> conditions in && to solve the problem, but I started to wonder why this
> configuration does not work. I tested the "nested ifs" config with trace8
> logging and it seem that only the outermost <If> expression gets evaluated.
>
> Is there a specific reason why this happens? I'd expect two possible
> outcomes from this configuration, namely either a syntax error while
> parsing the config (preferred imho) or a context merge, but not a no-op.
>
> Any pointers/suggestions about where to look?
>
>
I tried to investigate a bit the problem to write a good explanation in the
docs (and also to better understand the httpd internals for fun) but I am
still far from a satisfactory result.

I tried the following config (inside other containers like Location too):

<If  "true">
    ErrorDocument 503 "This is a custom 503 inside the outer IF!"
    <If "true">
       ErrorDocument 503 "This is a custom 503 inside the inner IF!"
    </If>
</If>

Each time that 503 is generated, I get the "outer IF" 503 response, never
the inner one.

With gdb it is easy to see that when ap_if_walk is executed,
dconf->sec_if->nelts is 1, so only one of the Ifs is evaluated.

So I checked how the if sections are parsed and built
with ap_process_config_tree->ap_walk_config->ap_walk_config_sub->invoke_cmd->ifsection
and eventually ap_add_if, but I only got that the parent/child relationship
is set up correctly.

My only goal is to figure out if nested Ifs are not evaluated on purpose
and if so why they are allowed by the syntax checker. Eventually it would
be really great to update the docs (regular user docs and also
https://httpd.apache.org/docs/trunk/developer/request.html).

Any hints would really be appreciated :)

Thanks in advance!

Luca

Re: [users@httpd] Problem when using nested if statements in apache 2.4

Posted by Luca Toscano <to...@gmail.com>.
Hi everybody,

the following users@ question is interesting in my opinion:

2017-02-20 18:17 GMT+01:00 Mike Schlottman <ms...@spe.org>:

>
> The problem comes when I combine these 2 so that all users except those
> coming from 127.*.*.* or 192.168.*.* see the nice error page.
>
> <If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
>
>   <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' ">
>
>     ErrorDocument 404 /errors/404
>
>   </If>
>
> </If>
>
> The user from 172.28.1.84 does not get the nice 404 page, but the default
> 404 page.   The IP does not match either of the ranges as observed when
> using the ranges individually, but when combined in this way it does not
> work as expected.
>
>
>
> Any ideas why this is?
>
>
>

He ended up using a single if with an expression composed by the two
conditions in && to solve the problem, but I started to wonder why this
configuration does not work. I tested the "nested ifs" config with trace8
logging and it seem that only the outermost <If> expression gets evaluated.

Is there a specific reason why this happens? I'd expect two possible
outcomes from this configuration, namely either a syntax error while
parsing the config (preferred imho) or a context merge, but not a no-op.

Any pointers/suggestions about where to look?

Thanks!

Luca