diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/http/ngx_http_request.c | 10 | ||||
-rw-r--r-- | src/http/v3/ngx_http_v3.h | 3 | ||||
-rw-r--r-- | src/http/v3/ngx_http_v3_request.c | 49 |
3 files changed, 54 insertions, 8 deletions
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index e77c4bc35..e3d217f79 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1511,7 +1511,8 @@ ngx_http_process_request_headers(ngx_event_t *rev) switch (r->http_version) { #if (NGX_HTTP_V3) case NGX_HTTP_VERSION_30: - rc = ngx_http_v3_parse_header(r, r->header_in); + rc = ngx_http_v3_parse_header(r, r->header_in, + cscf->underscores_in_headers); break; #endif @@ -1530,9 +1531,10 @@ ngx_http_process_request_headers(ngx_event_t *rev) /* there was error while a header line parsing */ ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid header line: \"%*s\"", - r->header_end - r->header_name_start, - r->header_name_start); + "client sent invalid header line: \"%*s: %*s\"", + r->header_name_end - r->header_name_start, + r->header_name_start, + r->header_end - r->header_start, r->header_start); continue; } diff --git a/src/http/v3/ngx_http_v3.h b/src/http/v3/ngx_http_v3.h index f80b74f3a..29cc06ee9 100644 --- a/src/http/v3/ngx_http_v3.h +++ b/src/http/v3/ngx_http_v3.h @@ -68,7 +68,8 @@ typedef struct { ngx_int_t ngx_http_v3_parse_request(ngx_http_request_t *r, ngx_buf_t *b); -ngx_int_t ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b); +ngx_int_t ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, + ngx_uint_t allow_underscores); ngx_int_t ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b, ngx_http_chunked_t *ctx); ngx_chain_t *ngx_http_v3_create_header(ngx_http_request_t *r); diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c index 2bb627489..59b8ce5b8 100644 --- a/src/http/v3/ngx_http_v3_request.c +++ b/src/http/v3/ngx_http_v3_request.c @@ -116,16 +116,23 @@ failed: ngx_int_t -ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b) +ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, + ngx_uint_t allow_underscores) { + u_char ch; ngx_int_t rc; ngx_str_t *name, *value; + ngx_uint_t hash, i, n; ngx_connection_t *c; ngx_http_v3_parse_headers_t *st; c = r->connection; st = r->h3_parse; + if (st->header_rep.state == 0) { + r->invalid_header = 0; + } + if (st->state == 0) { if (r->header_name_start == NULL) { name = &st->header_rep.header.name; @@ -164,9 +171,45 @@ done: r->header_name_end = name->data + name->len; r->header_start = value->data; r->header_end = value->data + value->len; - r->header_hash = ngx_hash_key(name->data, name->len); - /* XXX r->lowcase_index = i; */ + hash = 0; + i = 0; + + for (n = 0; n < name->len; n++) { + ch = name->data[n]; + + if (ch >= 'A' && ch <= 'Z') { + /* + * A request or response containing uppercase + * header field names MUST be treated as malformed + */ + return NGX_HTTP_PARSE_INVALID_HEADER; + } + + if (ch == '\0') { + return NGX_HTTP_PARSE_INVALID_HEADER; + } + + if (ch == '_' && !allow_underscores) { + r->invalid_header = 1; + continue; + } + + if ((ch < 'a' || ch > 'z') + && (ch < '0' || ch > '9') + && ch != '-' && ch != '_') + { + r->invalid_header = 1; + continue; + } + + hash = ngx_hash(hash, ch); + r->lowcase_header[i++] = ch; + i &= (NGX_HTTP_LC_HEADER_LEN - 1); + } + + r->header_hash = hash; + r->lowcase_index = i; return NGX_OK; } |