comparison src/http/v3/ngx_http_v3_request.c @ 8406:66feab03d9b7 quic

HTTP/3: restricted symbols in header names. As per HTTP/3 draft 27, a request or response containing uppercase header field names MUST be treated as malformed. Also, existing rules applied when parsing HTTP/1 header names are also applied to HTTP/3 header names: - null character is not allowed - underscore character may or may not be treated as invalid depending on the value of "underscores_in_headers" - all non-alphanumeric characters with the exception of '-' are treated as invalid Also, the r->locase_header field is now filled while parsing an HTTP/3 header. Error logging for invalid headers is fixed as well.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 19 May 2020 15:34:00 +0300
parents d2759e4cc437
children d6feece1288a
comparison
equal deleted inserted replaced
8405:d2759e4cc437 8406:66feab03d9b7
114 return NGX_HTTP_PARSE_INVALID_REQUEST; 114 return NGX_HTTP_PARSE_INVALID_REQUEST;
115 } 115 }
116 116
117 117
118 ngx_int_t 118 ngx_int_t
119 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b) 119 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b,
120 ngx_uint_t allow_underscores)
120 { 121 {
122 u_char ch;
121 ngx_int_t rc; 123 ngx_int_t rc;
122 ngx_str_t *name, *value; 124 ngx_str_t *name, *value;
125 ngx_uint_t hash, i, n;
123 ngx_connection_t *c; 126 ngx_connection_t *c;
124 ngx_http_v3_parse_headers_t *st; 127 ngx_http_v3_parse_headers_t *st;
125 128
126 c = r->connection; 129 c = r->connection;
127 st = r->h3_parse; 130 st = r->h3_parse;
131
132 if (st->header_rep.state == 0) {
133 r->invalid_header = 0;
134 }
128 135
129 if (st->state == 0) { 136 if (st->state == 0) {
130 if (r->header_name_start == NULL) { 137 if (r->header_name_start == NULL) {
131 name = &st->header_rep.header.name; 138 name = &st->header_rep.header.name;
132 139
162 169
163 r->header_name_start = name->data; 170 r->header_name_start = name->data;
164 r->header_name_end = name->data + name->len; 171 r->header_name_end = name->data + name->len;
165 r->header_start = value->data; 172 r->header_start = value->data;
166 r->header_end = value->data + value->len; 173 r->header_end = value->data + value->len;
167 r->header_hash = ngx_hash_key(name->data, name->len); 174
168 175 hash = 0;
169 /* XXX r->lowcase_index = i; */ 176 i = 0;
177
178 for (n = 0; n < name->len; n++) {
179 ch = name->data[n];
180
181 if (ch >= 'A' && ch <= 'Z') {
182 /*
183 * A request or response containing uppercase
184 * header field names MUST be treated as malformed
185 */
186 return NGX_HTTP_PARSE_INVALID_HEADER;
187 }
188
189 if (ch == '\0') {
190 return NGX_HTTP_PARSE_INVALID_HEADER;
191 }
192
193 if (ch == '_' && !allow_underscores) {
194 r->invalid_header = 1;
195 continue;
196 }
197
198 if ((ch < 'a' || ch > 'z')
199 && (ch < '0' || ch > '9')
200 && ch != '-' && ch != '_')
201 {
202 r->invalid_header = 1;
203 continue;
204 }
205
206 hash = ngx_hash(hash, ch);
207 r->lowcase_header[i++] = ch;
208 i &= (NGX_HTTP_LC_HEADER_LEN - 1);
209 }
210
211 r->header_hash = hash;
212 r->lowcase_index = i;
170 213
171 return NGX_OK; 214 return NGX_OK;
172 } 215 }
173 216
174 217