httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Luca Toscano <toscano.l...@gmail.com>
Subject Re: [users@httpd] Problem when using nested if statements in apache 2.4
Date Fri, 17 Mar 2017 21:33:14 GMT
2017-03-09 22:47 GMT+01:00 Luca Toscano <toscano.luca@gmail.com>:

>
>
> 2017-02-24 23:27 GMT+01:00 Luca Toscano <toscano.luca@gmail.com>:
>
>> Hi everybody,
>>
>> the following users@ question is interesting in my opinion:
>>
>> 2017-02-20 18:17 GMT+01:00 Mike Schlottman <mschlott@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

Mime
View raw message