Mercurial > hg > nginx
comparison src/http/v3/ngx_http_v3_request.c @ 8682:916a2e1d6617 quic
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.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 18 Jan 2021 13:43:36 +0300 |
parents | 58acdba9b3b2 |
children | dbe33ef9cd9a |
comparison
equal
deleted
inserted
replaced
8681:cb8185bd0507 | 8682:916a2e1d6617 |
---|---|
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | 11 |
12 | 12 |
13 static void ngx_http_v3_process_request(ngx_event_t *rev); | 13 static void ngx_http_v3_process_request(ngx_event_t *rev); |
14 static ngx_int_t ngx_http_v3_process_header(ngx_http_request_t *r, | 14 static ngx_int_t ngx_http_v3_process_header(ngx_http_request_t *r, |
15 ngx_str_t *name, ngx_str_t *value); | |
16 static ngx_int_t ngx_http_v3_validate_header(ngx_http_request_t *r, | |
15 ngx_str_t *name, ngx_str_t *value); | 17 ngx_str_t *name, ngx_str_t *value); |
16 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, | 18 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, |
17 ngx_str_t *name, ngx_str_t *value); | 19 ngx_str_t *name, ngx_str_t *value); |
18 static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r); | 20 static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r); |
19 static ngx_int_t ngx_http_v3_process_request_header(ngx_http_request_t *r); | 21 static ngx_int_t ngx_http_v3_process_request_header(ngx_http_request_t *r); |
258 ngx_http_v3_process_header(ngx_http_request_t *r, ngx_str_t *name, | 260 ngx_http_v3_process_header(ngx_http_request_t *r, ngx_str_t *name, |
259 ngx_str_t *value) | 261 ngx_str_t *value) |
260 { | 262 { |
261 ngx_table_elt_t *h; | 263 ngx_table_elt_t *h; |
262 ngx_http_header_t *hh; | 264 ngx_http_header_t *hh; |
265 ngx_http_core_srv_conf_t *cscf; | |
263 ngx_http_core_main_conf_t *cmcf; | 266 ngx_http_core_main_conf_t *cmcf; |
267 | |
268 if (ngx_http_v3_validate_header(r, name, value) != NGX_OK) { | |
269 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | |
270 return NGX_ERROR; | |
271 } | |
272 | |
273 if (r->invalid_header) { | |
274 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | |
275 | |
276 if (cscf->ignore_invalid_headers) { | |
277 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
278 "client sent invalid header: \"%V\"", name); | |
279 | |
280 return NGX_OK; | |
281 } | |
282 } | |
264 | 283 |
265 if (name->len && name->data[0] == ':') { | 284 if (name->len && name->data[0] == ':') { |
266 return ngx_http_v3_process_pseudo_header(r, name, value); | 285 return ngx_http_v3_process_pseudo_header(r, name, value); |
267 } | 286 } |
268 | 287 |
290 return NGX_ERROR; | 309 return NGX_ERROR; |
291 } | 310 } |
292 | 311 |
293 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 312 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
294 "http3 header: \"%V: %V\"", name, value); | 313 "http3 header: \"%V: %V\"", name, value); |
314 return NGX_OK; | |
315 } | |
316 | |
317 | |
318 static ngx_int_t | |
319 ngx_http_v3_validate_header(ngx_http_request_t *r, ngx_str_t *name, | |
320 ngx_str_t *value) | |
321 { | |
322 u_char ch; | |
323 ngx_uint_t i; | |
324 ngx_http_core_srv_conf_t *cscf; | |
325 | |
326 r->invalid_header = 0; | |
327 | |
328 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | |
329 | |
330 for (i = (name->data[0] == ':'); i != name->len; i++) { | |
331 ch = name->data[i]; | |
332 | |
333 if ((ch >= 'a' && ch <= 'z') | |
334 || (ch == '-') | |
335 || (ch >= '0' && ch <= '9') | |
336 || (ch == '_' && cscf->underscores_in_headers)) | |
337 { | |
338 continue; | |
339 } | |
340 | |
341 if (ch == '\0' || ch == LF || ch == CR || ch == ':' | |
342 || (ch >= 'A' && ch <= 'Z')) | |
343 { | |
344 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
345 "client sent invalid header name: \"%V\"", name); | |
346 | |
347 return NGX_ERROR; | |
348 } | |
349 | |
350 r->invalid_header = 1; | |
351 } | |
352 | |
353 for (i = 0; i != value->len; i++) { | |
354 ch = value->data[i]; | |
355 | |
356 if (ch == '\0' || ch == LF || ch == CR) { | |
357 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
358 "client sent header \"%V\" with " | |
359 "invalid value: \"%V\"", name, value); | |
360 | |
361 return NGX_ERROR; | |
362 } | |
363 } | |
364 | |
295 return NGX_OK; | 365 return NGX_OK; |
296 } | 366 } |
297 | 367 |
298 | 368 |
299 static ngx_int_t | 369 static ngx_int_t |