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