On 2020-08-10 08:49, Jeremie Courreges-Anglas wrote:
On Sun, Aug 09 2020, Ross L Richardson <[email protected]> wrote:
At present, if a request contains no "Host:" header [HTTP pre-1.1] or
if the supplied header does not match any of the servers configured
in httpd.conf, the request is directed to the first server. This
isn't documented, AFAICT.
For example, if httpd.conf has just one server
server "www.example.com"
then we currently get
$ printf "HEAD / HTTP/1.0\r\nHost: www.openbsd.org\r\n\r\n" \
| nc www.example.com www | sed 1q
HTTP/1.0 200 OK
This behaviour strikes me as wrong (or at least sub-optimal) in the
case of non-matching "Host:" headers. The simplistic patch below
changes things to return a 404 status if no matching server is found.
[If status code 400 (bad request) is preferred, "goto fail;"
could be used.]
Justification:
- This seems more correct, and is consistent with the "fail closed"
approach.
- There is a net gain in functionality, as use of glob/patterns
wildcards can easily re-establish the current behaviour. In
contrast, there's no way at present to disable the implicit
match-anything behaviour.
The first server in my httpd config uses "root "/nonexistent". This
results in proper 404 replies, so there is a way to disable the current
behavior. I probably inferred this from the examples in the manpage.
I've been using the following at the top of my httpd.conf for a while
now and it seems to be working fine:
server "default" {
listen on * port 80
block return 400
}
This should also prevent httpd from wasting cycles looking for
non-existent locations on the filesystem.
My gut feeling is that the existing behavior is useful (you can
copy/paste the existing example in the manpage and serve files right
away under multiple host names) and I see no reason to break it.
Did you check whether this breaks existing mirrors?
If this is adopted, it should be document in current.html
A followup patch could merge this if statement with the one above it.
Several other issues exist in "Host:" header handling.
Ross
--
Index: server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.140
diff -u -p -r1.140 server_http.c
--- server_http.c 3 Aug 2020 10:59:53 -0000 1.140
+++ server_http.c 9 Aug 2020 04:37:08 -0000
@@ -1200,7 +1200,7 @@ server_response(struct httpd *httpd, str
struct server_config *srv_conf = &srv->srv_conf;
struct kv *kv, key, *host;
struct str_find sm;
- int portval = -1, ret;
+ int hostmatch = 0, portval = -1, ret;
char *hostval, *query;
const char *errstr = NULL;
@@ -1277,16 +1277,20 @@ server_response(struct httpd *httpd, str
/* Replace host configuration */
clt->clt_srv_conf = srv_conf;
srv_conf = NULL;
+ hostmatch = 1;
break;
}
}
}
- if (srv_conf != NULL) {
+ if (host == NULL) {
/* Use the actual server IP address */
if (server_http_host(&clt->clt_srv_ss, hostname,
sizeof(hostname)) == NULL)
goto fail;
+ } else if (!hostmatch) {
+ server_abort_http(clt, 404, "not found");
+ return (-1);
} else {
/* Host header was valid and found */
if (strlcpy(hostname, host->kv_value, sizeof(hostname)) >=