mirror of
https://github.com/nginx/nginx.git
synced 2025-07-25 22:56:59 +08:00
HTTP: Use common header validation function for HTTP/2 and HTTP/3
The header validation required by HTTP/2 and HTTP/3 is identical, so use a common function for both. This will make it easier to add additional validation in the future. Move the function to ngx_http_parse.c so that it can share code with the HTTP/1.x parser in the future. No functional change intended.
This commit is contained in:
parent
5b8a5c08ce
commit
80b41e1002
@ -182,6 +182,8 @@ ngx_int_t ngx_http_huff_decode(u_char *state, u_char *src, size_t len,
|
|||||||
u_char **dst, ngx_uint_t last, ngx_log_t *log);
|
u_char **dst, ngx_uint_t last, ngx_log_t *log);
|
||||||
size_t ngx_http_huff_encode(u_char *src, size_t len, u_char *dst,
|
size_t ngx_http_huff_encode(u_char *src, size_t len, u_char *dst,
|
||||||
ngx_uint_t lower);
|
ngx_uint_t lower);
|
||||||
|
ngx_int_t ngx_http_v23_validate_header(ngx_http_request_t *r,
|
||||||
|
ngx_str_t *name, ngx_str_t *value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1090,6 +1090,68 @@ header_done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HTTP_V2 || NGX_HTTP_V3)
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_v23_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);
|
||||||
|
|
||||||
|
if (name->len < 1) {
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
|
||||||
|
"BUG: internal zero-length header name");
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <= 0x20 || ch == 0x7f || 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;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_parse_uri(ngx_http_request_t *r)
|
ngx_http_parse_uri(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
|
@ -142,8 +142,6 @@ static ngx_http_v2_out_frame_t *ngx_http_v2_get_frame(
|
|||||||
static ngx_int_t ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c,
|
static ngx_int_t ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c,
|
||||||
ngx_http_v2_out_frame_t *frame);
|
ngx_http_v2_out_frame_t *frame);
|
||||||
|
|
||||||
static ngx_int_t ngx_http_v2_validate_header(ngx_http_request_t *r,
|
|
||||||
ngx_http_v2_header_t *header);
|
|
||||||
static ngx_int_t ngx_http_v2_pseudo_header(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_v2_pseudo_header(ngx_http_request_t *r,
|
||||||
ngx_http_v2_header_t *header);
|
ngx_http_v2_header_t *header);
|
||||||
static ngx_int_t ngx_http_v2_parse_path(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_v2_parse_path(ngx_http_request_t *r,
|
||||||
@ -1774,7 +1772,8 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
fc = r->connection;
|
fc = r->connection;
|
||||||
|
|
||||||
/* TODO Optimization: validate headers while parsing. */
|
/* TODO Optimization: validate headers while parsing. */
|
||||||
if (ngx_http_v2_validate_header(r, header) != NGX_OK) {
|
if (ngx_http_v23_validate_header(r, &header->name, &header->value)
|
||||||
|
!= NGX_OK) {
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -3232,58 +3231,6 @@ ngx_http_v2_get_closed_node(ngx_http_v2_connection_t *h2c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
|
||||||
ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
|
|
||||||
{
|
|
||||||
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 = (header->name.data[0] == ':'); i != header->name.len; i++) {
|
|
||||||
ch = header->name.data[i];
|
|
||||||
|
|
||||||
if ((ch >= 'a' && ch <= 'z')
|
|
||||||
|| (ch == '-')
|
|
||||||
|| (ch >= '0' && ch <= '9')
|
|
||||||
|| (ch == '_' && cscf->underscores_in_headers))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch <= 0x20 || ch == 0x7f || ch == ':'
|
|
||||||
|| (ch >= 'A' && ch <= 'Z'))
|
|
||||||
{
|
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
|
||||||
"client sent invalid header name: \"%V\"",
|
|
||||||
&header->name);
|
|
||||||
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->invalid_header = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i != header->value.len; i++) {
|
|
||||||
ch = header->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\"",
|
|
||||||
&header->name, &header->value);
|
|
||||||
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
|
ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
|
||||||
{
|
{
|
||||||
|
@ -17,8 +17,6 @@ static void ngx_http_v3_cleanup_request(void *data);
|
|||||||
static void ngx_http_v3_process_request(ngx_event_t *rev);
|
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,
|
static ngx_int_t ngx_http_v3_process_header(ngx_http_request_t *r,
|
||||||
ngx_str_t *name, ngx_str_t *value);
|
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,
|
static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r,
|
||||||
ngx_str_t *name, ngx_str_t *value);
|
ngx_str_t *name, ngx_str_t *value);
|
||||||
static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r);
|
||||||
@ -632,7 +630,7 @@ ngx_http_v3_process_header(ngx_http_request_t *r, ngx_str_t *name,
|
|||||||
|
|
||||||
r->v3_parse->header_limit -= len;
|
r->v3_parse->header_limit -= len;
|
||||||
|
|
||||||
if (ngx_http_v3_validate_header(r, name, value) != NGX_OK) {
|
if (ngx_http_v23_validate_header(r, name, value) != NGX_OK) {
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
@ -692,57 +690,6 @@ 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 <= 0x20 || ch == 0x7f || 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
|
static ngx_int_t
|
||||||
ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
|
ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
|
||||||
ngx_str_t *value)
|
ngx_str_t *value)
|
||||||
|
Loading…
Reference in New Issue
Block a user