Claudio Jeker(cje...@diehard.n-r-g.com) on 2021.10.21 17:19:02 +0200: > > + 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.
Yes, this was actually the reason for the convoluted if (version.. ) bits, because server_abort_http() calls into server_close() to free desc->http_version and that is a crash when not pointing to the strduped string. Fixed. > > + 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 { > } Fixed. ok? diff --git usr.sbin/httpd/server_http.c usr.sbin/httpd/server_http.c index 6a74f3e45c5..e65a667c556 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; @@ -111,7 +112,7 @@ server_httpdesc_free(struct http_descriptor *desc) desc->http_query = NULL; free(desc->http_query_alias); desc->http_query_alias = NULL; - free(desc->http_version); + free(desc->http_version); //XXXXXXXXXX desc->http_version = NULL; free(desc->http_host); desc->http_host = NULL; @@ -198,6 +199,20 @@ 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) { @@ -206,7 +221,9 @@ server_read_http(struct bufferevent *bev, void *arg) struct evbuffer *src = EVBUFFER_INPUT(bev); char *line = NULL, *key, *value; const char *errstr; + char *http_version; size_t size, linelen; + int version; struct kv *hdr = NULL; getmonotime(&clt->clt_tv_last); @@ -317,24 +334,39 @@ server_read_http(struct bufferevent *bev, void *arg) if (desc->http_path == NULL) goto fail; - desc->http_version = strchr(desc->http_path, ' '); - if (desc->http_version == NULL) { + http_version = strchr(desc->http_path, ' '); + if (http_version == NULL) { server_abort_http(clt, 400, "malformed"); goto abort; } - *desc->http_version++ = '\0'; + *http_version++ = '\0'; desc->http_query = strchr(desc->http_path, '?'); if (desc->http_query != NULL) *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(http_version); + + if (version == 0) { + server_abort_http(clt, 505, "bad http version"); + goto abort; + } else if (version == 11) { + if ((desc->http_version = + strdup("HTTP/1.1")) == NULL) + goto fail; + } else { + if ((desc->http_version = + strdup(http_version)) == NULL) + goto fail; + } if (desc->http_query != NULL && (desc->http_query =