HTTP/3: client header validation.

A header with the name containing null, CR, LF, colon or uppercase characters,
is now considered an error.  A header with the value containing null, CR or LF,
is also considered an error.

Also, header is considered invalid unless its name only contains lowercase
characters, digits, minus and optionally underscore.  Such header can be
optionally ignored.
This commit is contained in:
Roman Arutyunyan 2021-01-18 13:43:36 +03:00
parent 88f6b969e6
commit 7bac596afb

View File

@ -13,6 +13,8 @@
static void ngx_http_v3_process_request(ngx_event_t *rev);
static ngx_int_t ngx_http_v3_process_header(ngx_http_request_t *r,
ngx_str_t *name, ngx_str_t *value);
static ngx_int_t ngx_http_v3_validate_header(ngx_http_request_t *r,
ngx_str_t *name, ngx_str_t *value);
static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r,
ngx_str_t *name, ngx_str_t *value);
static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r);
@ -260,8 +262,25 @@ ngx_http_v3_process_header(ngx_http_request_t *r, ngx_str_t *name,
{
ngx_table_elt_t *h;
ngx_http_header_t *hh;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
if (ngx_http_v3_validate_header(r, name, value) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return NGX_ERROR;
}
if (r->invalid_header) {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (cscf->ignore_invalid_headers) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent invalid header: \"%V\"", name);
return NGX_OK;
}
}
if (name->len && name->data[0] == ':') {
return ngx_http_v3_process_pseudo_header(r, name, value);
}
@ -296,6 +315,57 @@ ngx_http_v3_process_header(ngx_http_request_t *r, ngx_str_t *name,
}
static ngx_int_t
ngx_http_v3_validate_header(ngx_http_request_t *r, ngx_str_t *name,
ngx_str_t *value)
{
u_char ch;
ngx_uint_t i;
ngx_http_core_srv_conf_t *cscf;
r->invalid_header = 0;
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
for (i = (name->data[0] == ':'); i != name->len; i++) {
ch = name->data[i];
if ((ch >= 'a' && ch <= 'z')
|| (ch == '-')
|| (ch >= '0' && ch <= '9')
|| (ch == '_' && cscf->underscores_in_headers))
{
continue;
}
if (ch == '\0' || ch == LF || ch == CR || ch == ':'
|| (ch >= 'A' && ch <= 'Z'))
{
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent invalid header name: \"%V\"", name);
return NGX_ERROR;
}
r->invalid_header = 1;
}
for (i = 0; i != value->len; i++) {
ch = value->data[i];
if (ch == '\0' || ch == LF || ch == CR) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent header \"%V\" with "
"invalid value: \"%V\"", name, value);
return NGX_ERROR;
}
}
return NGX_OK;
}
static ngx_int_t
ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
ngx_str_t *value)