On Thu, Oct 21, 2021 at 04:38:43PM +0200, Sebastian Benoit wrote:
> J. K.([email protected]) on 2021.10.21 14:10:16 +0200:
> > Another question, to httpd(8). Tried the following query.
> > Used an invalid HTTP Version number (typo).
> >
> > $ telnet 10.42.42.183 80
> > [Shortened]
> > GET / HTTP/1.2
> > [content]
> >
> > httpd provide here the site. Without checking the not existent version
> > (1.2) number and the Host. Okay, that's maybe stupid from me to
> > start a request with an invalid version number. But should not also
> > the server answer with 400 (bad request)?
> >
> > According to the source only HTTP/1.1 is checked. All other request
> > will be accepted. Okay, I'm not a RFC specialist. Still a newbie.
>
> This diff makes httpd return "505 HTTP Version Not Supported"
> for < 0.9 and > 1.9 http versions. Anything from 1.1 to 1.9 is
> interpreted as 1.1. This is what nginx does too.
>
> ok?
>
> diff --git usr.sbin/httpd/server_http.c usr.sbin/httpd/server_http.c
> index 6a74f3e45c5..52aaf3711c2 100644
> --- usr.sbin/httpd/server_http.c
> +++ usr.sbin/httpd/server_http.c
> @@ -51,6 +51,7 @@ int server_http_authenticate(struct server_config
> *,
> struct client *);
> char *server_expand_http(struct client *, const char *,
> char *, size_t);
> +int http_version_num(char *);
>
> static struct http_method http_methods[] = HTTP_METHODS;
> static struct http_error http_errors[] = HTTP_ERRORS;
> @@ -198,6 +199,19 @@ done:
> return (ret);
> }
>
> +int http_version_num(char *version)
KNF please.
> +{
> + if (strcmp(version, "HTTP/0.9") == 0)
> + return (9);
> + if (strcmp(version, "HTTP/1.0") == 0)
> + return (10);
> + /* any other version 1.x gets downgraded to 1.1 */
> + if (strncmp(version, "HTTP/1", 6) == 0)
> + return (11);
> +
> + return (0);
> +}
> +
> void
> server_read_http(struct bufferevent *bev, void *arg)
> {
> @@ -207,6 +221,7 @@ server_read_http(struct bufferevent *bev, void *arg)
> char *line = NULL, *key, *value;
> const char *errstr;
> size_t size, linelen;
> + int version;
> struct kv *hdr = NULL;
>
> getmonotime(&clt->clt_tv_last);
> @@ -329,12 +344,29 @@ server_read_http(struct bufferevent *bev, void *arg)
> *desc->http_query++ = '\0';
>
> /*
> - * Have to allocate the strings because they could
> + * We have to allocate the strings because they could
> * be changed independently by the filters later.
> + * Allow HTTP version 0.9 to 1.1.
> + * Downgrade http version > 1.1 <= 1.9 to version 1.1.
> + * Return HTTP Version Not Supported for anything else.
> */
> - if ((desc->http_version =
> - strdup(desc->http_version)) == NULL)
> - goto fail;
> +
> + version = http_version_num(desc->http_version);
I woud prefer if this code would store the version not in
desc->http_version until after the strdup(). The way these strdup work is
just wonky. Especil in the failure cases this may result in calling free
on the wrong thing.
> + if (version == 11) {
> + if ((desc->http_version =
> + strdup("HTTP/1.1")) == NULL)
> + goto fail;
> + } else {
> + if ((desc->http_version =
> + strdup(desc->http_version)) == NULL)
> + goto fail;
> + }
> +
> + if (version == 0) {
> + server_abort_http(clt, 505, "bad http version");
> + goto abort;
> + }
I would prefer to have this as:
if (version == 0) {
} else if if (version == 11) {
} else {
}
--
:wq Claudio