You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Chris Darroch <ch...@pearsoncmg.com> on 2005/12/22 23:18:05 UTC
[PATCH 38019, 36908] make SetEnv run during post_read_req
Hi --
Well, this may be a sore point, but I'll tackle it anyway,
so apologies in advance. The fact that environment variables
created with SetEnv are applied during the fixups phase,
while SetEnvIf creates its variables during the post_read_request
and header_parser phases, does make my life a little more
painful.
This has been raised in various bug reports, including #36908
and #35611. These are marked "won't fix", with the explanation
that SetEnv is intended for use by content generators like CGI
scripts.
However, as I've described in a new bug (sorry!), #38019,
I have a particular setup where what I'd like to do is reject all
requests that contain a particular HTTP header (in this case, a header
injected by hardware that means the request is coming from outside our
private network). Here's what I thought I could do:
SetEnv FOO 1
SetEnvIf Http-X-Foo .+ !FOO
<Directory /foo>
Allow from env=FOO
</Directory>
The logic being, set FOO=1, then unset FOO if the HTTP header is
present, and only allow access to a resource if FOO is still present.
I attach a patch to the bug report in #38019 that simply moves
mod_env's handler up to the post_read_request phase, ahead of
mod_setenvif.
Now, there may be historical reasons why this isn't desired,
and it might, I suppose, also cause existing users' configurations
to malfunction. Still, I'd propose it as a 2.3/2.4 change, because
it does enable functionality like that I outlined above, and more
generally, it makes sense that all of the SetEnv* and PassEnv*, etc.,
directives would take effect at the same time.
If this change isn't accepted, then I would strongly suggest
changing the documentation regarding environment variables to indicate
the order in which directives take effect; at the moment, that's not
clear. In fact, the current documentation says the following, which
may be true for the special purpose environment variables listed on
the page, but isn't true in general for variables used in other ways
(e.g., in "Allow from env"):
"To make these mechanisms as flexible as possible, they are invoked
by defining environment variables, typically with BrowserMatch,
though SetEnv and PassEnv could also be used, for example."
This section in particular, to my mind, clearly implies to the reader
that SetEnv and SetEnvIf take effect at the same time. So does
the section on the Allow direction from mod_authz_host, which says:
"The third format of the arguments to the Allow directive allows
access to the server to be controlled based on the existence of an
_environment_variable_. When Allow from env=env-variable is
specified, then the request is allowed access if the environment
variable env-variable exists. The server provides the ability to
set environment variables in a flexible way based on characteristics
of the client request using the directives provided by mod_setenvif."
The link to the "Environment Variables" page, and the wording,
imply that while mod_setenvif directives may be used to control
access based on request characteristics, that's not the only
way it could work, and other mechanisms for setting environment
variables should work too.
If it's going to stay the way it is now for historical and
user support reasons, let me know and I'll try to write
something more obvious for docs/manual/env.xml, mod/mod_env.xml,
mod/mod_authz_host.xml, etc.
Thanks!
Chris.
--
GPG Key ID: 366A375B
GPG Key Fingerprint: 485E 5041 17E1 E2BB C263 E4DE C8E3 FA36 366A 375B
Re: [PATCH 38019, 36908] make SetEnv run during post_read_req
Posted by Nick Kew <ni...@webthing.com>.
On Thursday 22 December 2005 22:18, Chris Darroch wrote:
> Well, this may be a sore point, but I'll tackle it anyway,
> so apologies in advance. The fact that environment variables
> created with SetEnv are applied during the fixups phase,
> while SetEnvIf creates its variables during the post_read_request
> and header_parser phases, does make my life a little more
> painful.
>
> This has been raised in various bug reports, including #36908
> and #35611. These are marked "won't fix", with the explanation
> that SetEnv is intended for use by content generators like CGI
> scripts.
This looks a lot like the situation with mod_headers, that we solved
some time ago by introducing the "early" keyword. AFAICS the same
solution would work for mod_env. The number of bug reports you
cite evidences a demand for it. That would be a very quick and
easy solution.
The solution you propose in your followup seems rather close to
folding mod_env into mod_setenvif in a manner designed to be
internally consistent. That too makes sense to me, but would want
a little more thought.
Anyone else?
--
Nick Kew
Re: [PATCH 38019, 36908] make SetEnv run during post_read_req
Posted by Chris Darroch <ch...@pearsoncmg.com>.
Hi --
> I have a particular setup where what I'd like to do is reject all
> requests that contain a particular HTTP header (in this case, a header
> injected by hardware that means the request is coming from outside our
> private network). Here's what I thought I could do:
>
> SetEnv FOO 1
> SetEnvIf Http-X-Foo .+ !FOO
> <Directory /foo>
> Allow from env=FOO
> </Directory>
>
> The logic being, set FOO=1, then unset FOO if the HTTP header is
> present, and only allow access to a resource if FOO is still present.
I thought a bit more about this last night, did some experimentation,
and have a different proposal now. :-/ I found that for my
particular situation, I can use:
SetEnvIf Http-X-Foo ^$ FOO
which works because SetEnvIf matches an empty regex if either the
Http-X-Foo header is present and empty, or if it isn't present at all.
I find this somewhat counter-intuitive (albeit useful in this
particular case): how can a missing header match against anything?
So, here's the proposal. Alas, I am deeply short of "round tuits"
these days, but perhaps in a couple of months I can supply a patch.
Comments welcome beforehand, though.
1) Leave mod_env as-is for the moment, but document that it only
functions for content generators, and not for any prior part
of the request handling process. In a future release (2.4? 3.0?)
change the name of the directives to SetEnvCGI, etc.
2) Alter mod_setenvif so that SetEnvIf only matches if a header
is present. To my mind, this is simply the single-header
equivalent of what you'd want to happen when using a regex
to match header names, e.g.:
SetEnvIf ^Http-X-.*$ ...
I'd presumably want nothing to happen if no headers match the
name regex. In the case where I'm using a simple header name,
like Http-X-Foo, that should be equivalent to using ^Http-X-Foo$,
and thus follow the same logic; if no header is present that
matches that name, nothing should happen (i.e., all value
string regexs should fail to match, even for ^.*$ and other
always-matching regexs).
3) Add to mod_setenvif a new directive, SetEnvPre, which works
like this:
SetEnvPre env-variable[=value]
and simply sets env-variable to the given value (or an empty
string if no value is supplied) before any SetEnvIf directives
are applied.
4) Add to mod_setenvif another new directive, SetEnvExists, which
works like this:
SetEnvExists header|header-regex [!]env-variable[=value]
[[!]env-variable[=value]] ...
That is, just like SetEnvIf, but it only deals with headers
(not other request attributes like Request_URI, etc.), and
sets or unsets the env-variables based on whether any matching
headers exist in the request.
With these directives, one could set up something like:
SetEnvPre FOO=false
SetEnvExists ^Http-X-Foo-.*$ FOO=true
SetEnvPre FOO_IGNORE
SetEnvExists Http-X-Foo-Ignore FOO_IGNORE=all
SetEnvIfNoCase Http-X-Foo-Ignore ^header=(.*)$ FOO_IGNORE=$1
so that FOO is "false" unless at least one Http-X-Foo-* header
exists, in which case it's "true", and FOO_IGNORE is empty
unless the Http-X-Foo-Ignore header exists, in which case
FOO_IGNORE is "all", or if Http-X-Foo-Ignore has the form
header=foo then FOO_IGNORE is "foo".
Does that all make sense? As I said, comments welcome,
and flames also. ("What's this?! Santa flambé??")
Chris.
--
GPG Key ID: 366A375B
GPG Key Fingerprint: 485E 5041 17E1 E2BB C263 E4DE C8E3 FA36 366A 375B