diff options
author | Roman Arutyunyan <arut@nginx.com> | 2021-01-22 15:57:41 +0300 |
---|---|---|
committer | Roman Arutyunyan <arut@nginx.com> | 2021-01-22 15:57:41 +0300 |
commit | 4e312daa7ec04e52cdefcbc8749ef2f6d366064b (patch) | |
tree | 2c75e21853a064f02d23ec64128b54a23ccd285f /src/http/v3/ngx_http_v3_request.c | |
parent | 9e489d208fff35c490b43980a064c38cc8dc4f2c (diff) | |
download | nginx-4e312daa7ec04e52cdefcbc8749ef2f6d366064b.tar.gz nginx-4e312daa7ec04e52cdefcbc8749ef2f6d366064b.zip |
HTTP/3: client pseudo-headers restrictions.
- :method, :path and :scheme are expected exactly once and not empty
- :method and :scheme character validation is added
- :authority cannot appear more than once
Diffstat (limited to 'src/http/v3/ngx_http_v3_request.c')
-rw-r--r-- | src/http/v3/ngx_http_v3_request.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c index 09c1ec335..59a8889bf 100644 --- a/src/http/v3/ngx_http_v3_request.c +++ b/src/http/v3/ngx_http_v3_request.c @@ -300,6 +300,7 @@ static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, ngx_str_t *value) { + u_char ch, c; ngx_uint_t i; if (r->request_line.len) { @@ -310,6 +311,18 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, if (name->len == 7 && ngx_strncmp(name->data, ":method", 7) == 0) { + if (r->method_name.len) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate \":method\" header"); + goto failed; + } + + if (value->len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent empty \":method\" header"); + goto failed; + } + r->method_name = *value; for (i = 0; i < sizeof(ngx_http_v3_methods) @@ -325,6 +338,16 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, } } + for (i = 0; i < value->len; i++) { + ch = value->data[i]; + + if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid method: \"%V\"", value); + goto failed; + } + } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http3 method \"%V\" %ui", value, r->method); return NGX_OK; @@ -332,6 +355,18 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, if (name->len == 5 && ngx_strncmp(name->data, ":path", 5) == 0) { + if (r->uri_start) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate \":path\" header"); + goto failed; + } + + if (value->len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent empty \":path\" header"); + goto failed; + } + r->uri_start = value->data; r->uri_end = value->data + value->len; @@ -349,6 +384,39 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, if (name->len == 7 && ngx_strncmp(name->data, ":scheme", 7) == 0) { + if (r->schema.len) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate \":scheme\" header"); + goto failed; + } + + if (value->len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent empty \":scheme\" header"); + goto failed; + } + + for (i = 0; i < value->len; i++) { + ch = value->data[i]; + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'z') { + continue; + } + + if (((ch >= '0' && ch <= '9') + || ch == '+' || ch == '-' || ch == '.') + && i > 0) + { + continue; + } + + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid \":scheme\" header: \"%V\"", + value); + goto failed; + } + r->schema = *value; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -358,6 +426,12 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, if (name->len == 10 && ngx_strncmp(name->data, ":authority", 10) == 0) { + if (r->host_start) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate \":authority\" header"); + goto failed; + } + r->host_start = value->data; r->host_end = value->data + value->len; @@ -388,6 +462,24 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r) return NGX_OK; } + if (r->method_name.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no \":method\" header"); + goto failed; + } + + if (r->schema.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no \":scheme\" header"); + goto failed; + } + + if (r->uri_start == NULL) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no \":path\" header"); + goto failed; + } + len = r->method_name.len + 1 + (r->uri_end - r->uri_start) + 1 + sizeof("HTTP/3.0") - 1; |