httpd.conf(5) examples for httpd(8). I'm trying to achieve `/foo/bar/`
auth success -> block 410 & auth fail -> (block) 401; this is not
possible either by design with undocumented behavior, or due to an error
in httpd(8) logic.
```
server "foo.example" {
listen on * port 80
location "/foo/" {
authenticate with "conf/foo.htpasswd"
directory auto index
}
location "/foo/bar/*" {
authenticate with "conf/foo.htpasswd"
block return 410
}
}
```
* `/foo/` requires auth, returns directory contents or 401 Unauthorized.
* `/foo/bar/` does not require auth, returns 410.
* `/foo/baz/` does not require auth, returns contents (403/404).
I expected `/foo/bar/` to require authentication, and then to return 401
Unauthorized or 410 Gone depending on authentication.
`/foo/` and `/foo/baz/` are behaving as written into the config.
----
```
server "foo.example" {
listen on * port 80
location "/foo/*" {
authenticate with "conf/foo.htpasswd"
directory auto index
}
location "/foo/bar/*" {
authenticate with "conf/foo.htpasswd" # no-op
block return 410
}
}
```
* `/foo/` requires auth, returns directory autoindex or 401 Unauthorized.
* `/foo/bar/` requires auth, returns directory index or 401 Unauthorized.
* `/foo/baz/` requires auth, returns directory index (403/404) or 401
Unauthorized.
Notice `/foo/bar/` didn't return 410. This is supposedly correct,
because:
> In case of multiple location statements in the same context, the first
> matching location statement will be put into effect, while all later
> ones will be ignored. Therefore it is advisable to match for more
> specific paths first and for generic ones later on.
----
```
server "foo.example" {
listen on * port 80
location "/foo/bar/*" {
authenticate with "conf/foo.htpasswd"
block return 410
}
location "/foo/*" {
authenticate with "conf/foo.htpasswd"
directory auto index
}
}
```
* `/foo/` requires auth, returns directory autoindex or 401 Unauthorized.
* `/foo/bar/` does not require auth, returns 410.
* `/foo/baz/` requires auth, returns directory index (403/404) or 401
Unauthorized.
So what just happened? I requested `/foo/bar/` to be authenticated, and
only then after authentication to return 410 Gone but no authentication
was required.
This is troubling me particularly when disclosing the existence of
`/foo/` is not sensitive, but when `/foo/bar/` may be. In my case, `bar`
name in path represented private information of a recipient's name. I
don't have plausible deniability while returning 410 Gone, but only by
removing the directory and letting the server return directory contents
(404 Not Found) without `block`.
A quick look at `server_http.c` (revision 1.135) reveals conditional
branching:
```
if (srv_conf->flags & SRVFLAG_BLOCK) {
server_abort_http(clt, srv_conf->return_code,
srv_conf->return_uri);
return (-1);
} else if (srv_conf->flags & SRVFLAG_AUTH &&
server_http_authenticate(srv_conf, clt) == -1) {
server_abort_http(clt, 401, srv_conf->auth_realm);
return (-1);
} else
return (server_file(httpd, clt));
```
That behavior isn't documented, but code says it does the `block`. So I
guess it deserves either a code patch, a doc patch, or both: `block` and
`authenticate` could be documented to be exclusive of each other,
documented to be evaluated in some order, and/or `authenticate` should
be evaluated before `block` statements.
lucas@ contributed comments and acknowledged my issue (while questioning
the usefulness of auth success -> block use case).