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)
+{
+ 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);
+ 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;
+ }
+
if (desc->http_query != NULL &&
(desc->http_query =