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