blob: d3a20c2ed263f2285f44b5e24862a18db6633b2f [file] [log] [blame]
Willy Tarreau0da5b3b2017-09-21 09:30:46 +02001/*
2 * HTTP/1 protocol analyzer
3 *
4 * Copyright 2000-2017 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreau794f9af2017-07-26 09:07:47 +020013#include <ctype.h>
Willy Tarreau0da5b3b2017-09-21 09:30:46 +020014#include <common/config.h>
Willy Tarreau794f9af2017-07-26 09:07:47 +020015#include <common/http-hdr.h>
Willy Tarreau0da5b3b2017-09-21 09:30:46 +020016
17#include <proto/h1.h>
Willy Tarreau8740c8b2017-09-21 10:22:25 +020018#include <proto/hdr_idx.h>
Willy Tarreau0da5b3b2017-09-21 09:30:46 +020019
20/* It is about twice as fast on recent architectures to lookup a byte in a
21 * table than to perform a boolean AND or OR between two tests. Refer to
22 * RFC2616/RFC5234/RFC7230 for those chars. A token is any ASCII char that is
23 * neither a separator nor a CTL char. An http ver_token is any ASCII which can
24 * be found in an HTTP version, which includes 'H', 'T', 'P', '/', '.' and any
25 * digit. Note: please do not overwrite values in assignment since gcc-2.95
26 * will not handle them correctly. It's worth noting that chars 128..255 are
27 * nothing, not even control chars.
28 */
29const unsigned char h1_char_classes[256] = {
30 [ 0] = H1_FLG_CTL,
31 [ 1] = H1_FLG_CTL,
32 [ 2] = H1_FLG_CTL,
33 [ 3] = H1_FLG_CTL,
34 [ 4] = H1_FLG_CTL,
35 [ 5] = H1_FLG_CTL,
36 [ 6] = H1_FLG_CTL,
37 [ 7] = H1_FLG_CTL,
38 [ 8] = H1_FLG_CTL,
39 [ 9] = H1_FLG_SPHT | H1_FLG_LWS | H1_FLG_SEP | H1_FLG_CTL,
40 [ 10] = H1_FLG_CRLF | H1_FLG_LWS | H1_FLG_CTL,
41 [ 11] = H1_FLG_CTL,
42 [ 12] = H1_FLG_CTL,
43 [ 13] = H1_FLG_CRLF | H1_FLG_LWS | H1_FLG_CTL,
44 [ 14] = H1_FLG_CTL,
45 [ 15] = H1_FLG_CTL,
46 [ 16] = H1_FLG_CTL,
47 [ 17] = H1_FLG_CTL,
48 [ 18] = H1_FLG_CTL,
49 [ 19] = H1_FLG_CTL,
50 [ 20] = H1_FLG_CTL,
51 [ 21] = H1_FLG_CTL,
52 [ 22] = H1_FLG_CTL,
53 [ 23] = H1_FLG_CTL,
54 [ 24] = H1_FLG_CTL,
55 [ 25] = H1_FLG_CTL,
56 [ 26] = H1_FLG_CTL,
57 [ 27] = H1_FLG_CTL,
58 [ 28] = H1_FLG_CTL,
59 [ 29] = H1_FLG_CTL,
60 [ 30] = H1_FLG_CTL,
61 [ 31] = H1_FLG_CTL,
62 [' '] = H1_FLG_SPHT | H1_FLG_LWS | H1_FLG_SEP,
63 ['!'] = H1_FLG_TOK,
64 ['"'] = H1_FLG_SEP,
65 ['#'] = H1_FLG_TOK,
66 ['$'] = H1_FLG_TOK,
67 ['%'] = H1_FLG_TOK,
68 ['&'] = H1_FLG_TOK,
69 [ 39] = H1_FLG_TOK,
70 ['('] = H1_FLG_SEP,
71 [')'] = H1_FLG_SEP,
72 ['*'] = H1_FLG_TOK,
73 ['+'] = H1_FLG_TOK,
74 [','] = H1_FLG_SEP,
75 ['-'] = H1_FLG_TOK,
76 ['.'] = H1_FLG_TOK | H1_FLG_VER,
77 ['/'] = H1_FLG_SEP | H1_FLG_VER,
Willy Tarreau1b4cf9b2017-11-09 11:15:45 +010078 ['0'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
79 ['1'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
80 ['2'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
81 ['3'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
82 ['4'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
83 ['5'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
84 ['6'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
85 ['7'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
86 ['8'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
87 ['9'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
Willy Tarreau0da5b3b2017-09-21 09:30:46 +020088 [':'] = H1_FLG_SEP,
89 [';'] = H1_FLG_SEP,
90 ['<'] = H1_FLG_SEP,
91 ['='] = H1_FLG_SEP,
92 ['>'] = H1_FLG_SEP,
93 ['?'] = H1_FLG_SEP,
94 ['@'] = H1_FLG_SEP,
95 ['A'] = H1_FLG_TOK,
96 ['B'] = H1_FLG_TOK,
97 ['C'] = H1_FLG_TOK,
98 ['D'] = H1_FLG_TOK,
99 ['E'] = H1_FLG_TOK,
100 ['F'] = H1_FLG_TOK,
101 ['G'] = H1_FLG_TOK,
102 ['H'] = H1_FLG_TOK | H1_FLG_VER,
103 ['I'] = H1_FLG_TOK,
104 ['J'] = H1_FLG_TOK,
105 ['K'] = H1_FLG_TOK,
106 ['L'] = H1_FLG_TOK,
107 ['M'] = H1_FLG_TOK,
108 ['N'] = H1_FLG_TOK,
109 ['O'] = H1_FLG_TOK,
110 ['P'] = H1_FLG_TOK | H1_FLG_VER,
111 ['Q'] = H1_FLG_TOK,
112 ['R'] = H1_FLG_TOK | H1_FLG_VER,
113 ['S'] = H1_FLG_TOK | H1_FLG_VER,
114 ['T'] = H1_FLG_TOK | H1_FLG_VER,
115 ['U'] = H1_FLG_TOK,
116 ['V'] = H1_FLG_TOK,
117 ['W'] = H1_FLG_TOK,
118 ['X'] = H1_FLG_TOK,
119 ['Y'] = H1_FLG_TOK,
120 ['Z'] = H1_FLG_TOK,
121 ['['] = H1_FLG_SEP,
122 [ 92] = H1_FLG_SEP,
123 [']'] = H1_FLG_SEP,
124 ['^'] = H1_FLG_TOK,
125 ['_'] = H1_FLG_TOK,
126 ['`'] = H1_FLG_TOK,
127 ['a'] = H1_FLG_TOK,
128 ['b'] = H1_FLG_TOK,
129 ['c'] = H1_FLG_TOK,
130 ['d'] = H1_FLG_TOK,
131 ['e'] = H1_FLG_TOK,
132 ['f'] = H1_FLG_TOK,
133 ['g'] = H1_FLG_TOK,
134 ['h'] = H1_FLG_TOK,
135 ['i'] = H1_FLG_TOK,
136 ['j'] = H1_FLG_TOK,
137 ['k'] = H1_FLG_TOK,
138 ['l'] = H1_FLG_TOK,
139 ['m'] = H1_FLG_TOK,
140 ['n'] = H1_FLG_TOK,
141 ['o'] = H1_FLG_TOK,
142 ['p'] = H1_FLG_TOK,
143 ['q'] = H1_FLG_TOK,
144 ['r'] = H1_FLG_TOK,
145 ['s'] = H1_FLG_TOK,
146 ['t'] = H1_FLG_TOK,
147 ['u'] = H1_FLG_TOK,
148 ['v'] = H1_FLG_TOK,
149 ['w'] = H1_FLG_TOK,
150 ['x'] = H1_FLG_TOK,
151 ['y'] = H1_FLG_TOK,
152 ['z'] = H1_FLG_TOK,
153 ['{'] = H1_FLG_SEP,
154 ['|'] = H1_FLG_TOK,
155 ['}'] = H1_FLG_SEP,
156 ['~'] = H1_FLG_TOK,
157 [127] = H1_FLG_CTL,
158};
Willy Tarreaudb4893d2017-09-21 08:40:02 +0200159
160
Willy Tarreau8740c8b2017-09-21 10:22:25 +0200161/*
162 * This function parses a status line between <ptr> and <end>, starting with
163 * parser state <state>. Only states HTTP_MSG_RPVER, HTTP_MSG_RPVER_SP,
164 * HTTP_MSG_RPCODE, HTTP_MSG_RPCODE_SP and HTTP_MSG_RPREASON are handled. Others
165 * will give undefined results.
166 * Note that it is upon the caller's responsibility to ensure that ptr < end,
167 * and that msg->sol points to the beginning of the response.
168 * If a complete line is found (which implies that at least one CR or LF is
169 * found before <end>, the updated <ptr> is returned, otherwise NULL is
170 * returned indicating an incomplete line (which does not mean that parts have
171 * not been updated). In the incomplete case, if <ret_ptr> or <ret_state> are
172 * non-NULL, they are fed with the new <ptr> and <state> values to be passed
173 * upon next call.
174 *
175 * This function was intentionally designed to be called from
176 * http_msg_analyzer() with the lowest overhead. It should integrate perfectly
177 * within its state machine and use the same macros, hence the need for same
178 * labels and variable names. Note that msg->sol is left unchanged.
179 */
180const char *http_parse_stsline(struct http_msg *msg,
181 enum h1_state state, const char *ptr, const char *end,
182 unsigned int *ret_ptr, enum h1_state *ret_state)
183{
184 const char *msg_start = msg->chn->buf->p;
185
186 switch (state) {
187 case HTTP_MSG_RPVER:
188 http_msg_rpver:
189 if (likely(HTTP_IS_VER_TOKEN(*ptr)))
190 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpver, http_msg_ood, state, HTTP_MSG_RPVER);
191
192 if (likely(HTTP_IS_SPHT(*ptr))) {
193 msg->sl.st.v_l = ptr - msg_start;
194 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpver_sp, http_msg_ood, state, HTTP_MSG_RPVER_SP);
195 }
196 msg->err_state = HTTP_MSG_RPVER;
197 state = HTTP_MSG_ERROR;
198 break;
199
200 case HTTP_MSG_RPVER_SP:
201 http_msg_rpver_sp:
202 if (likely(!HTTP_IS_LWS(*ptr))) {
203 msg->sl.st.c = ptr - msg_start;
204 goto http_msg_rpcode;
205 }
206 if (likely(HTTP_IS_SPHT(*ptr)))
207 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpver_sp, http_msg_ood, state, HTTP_MSG_RPVER_SP);
208 /* so it's a CR/LF, this is invalid */
209 msg->err_state = HTTP_MSG_RPVER_SP;
210 state = HTTP_MSG_ERROR;
211 break;
212
213 case HTTP_MSG_RPCODE:
214 http_msg_rpcode:
215 if (likely(!HTTP_IS_LWS(*ptr)))
216 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode, http_msg_ood, state, HTTP_MSG_RPCODE);
217
218 if (likely(HTTP_IS_SPHT(*ptr))) {
219 msg->sl.st.c_l = ptr - msg_start - msg->sl.st.c;
220 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode_sp, http_msg_ood, state, HTTP_MSG_RPCODE_SP);
221 }
222
223 /* so it's a CR/LF, so there is no reason phrase */
224 msg->sl.st.c_l = ptr - msg_start - msg->sl.st.c;
225 http_msg_rsp_reason:
226 /* FIXME: should we support HTTP responses without any reason phrase ? */
227 msg->sl.st.r = ptr - msg_start;
228 msg->sl.st.r_l = 0;
229 goto http_msg_rpline_eol;
230
231 case HTTP_MSG_RPCODE_SP:
232 http_msg_rpcode_sp:
233 if (likely(!HTTP_IS_LWS(*ptr))) {
234 msg->sl.st.r = ptr - msg_start;
235 goto http_msg_rpreason;
236 }
237 if (likely(HTTP_IS_SPHT(*ptr)))
238 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode_sp, http_msg_ood, state, HTTP_MSG_RPCODE_SP);
239 /* so it's a CR/LF, so there is no reason phrase */
240 goto http_msg_rsp_reason;
241
242 case HTTP_MSG_RPREASON:
243 http_msg_rpreason:
244 if (likely(!HTTP_IS_CRLF(*ptr)))
245 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpreason, http_msg_ood, state, HTTP_MSG_RPREASON);
246 msg->sl.st.r_l = ptr - msg_start - msg->sl.st.r;
247 http_msg_rpline_eol:
248 /* We have seen the end of line. Note that we do not
249 * necessarily have the \n yet, but at least we know that we
250 * have EITHER \r OR \n, otherwise the response would not be
251 * complete. We can then record the response length and return
252 * to the caller which will be able to register it.
253 */
254 msg->sl.st.l = ptr - msg_start - msg->sol;
255 return ptr;
256
257 default:
258#ifdef DEBUG_FULL
259 fprintf(stderr, "FIXME !!!! impossible state at %s:%d = %d\n", __FILE__, __LINE__, state);
260 exit(1);
261#endif
262 ;
263 }
264
265 http_msg_ood:
266 /* out of valid data */
267 if (ret_state)
268 *ret_state = state;
269 if (ret_ptr)
270 *ret_ptr = ptr - msg_start;
271 return NULL;
272}
273
274/*
275 * This function parses a request line between <ptr> and <end>, starting with
276 * parser state <state>. Only states HTTP_MSG_RQMETH, HTTP_MSG_RQMETH_SP,
277 * HTTP_MSG_RQURI, HTTP_MSG_RQURI_SP and HTTP_MSG_RQVER are handled. Others
278 * will give undefined results.
279 * Note that it is upon the caller's responsibility to ensure that ptr < end,
280 * and that msg->sol points to the beginning of the request.
281 * If a complete line is found (which implies that at least one CR or LF is
282 * found before <end>, the updated <ptr> is returned, otherwise NULL is
283 * returned indicating an incomplete line (which does not mean that parts have
284 * not been updated). In the incomplete case, if <ret_ptr> or <ret_state> are
285 * non-NULL, they are fed with the new <ptr> and <state> values to be passed
286 * upon next call.
287 *
288 * This function was intentionally designed to be called from
289 * http_msg_analyzer() with the lowest overhead. It should integrate perfectly
290 * within its state machine and use the same macros, hence the need for same
291 * labels and variable names. Note that msg->sol is left unchanged.
292 */
293const char *http_parse_reqline(struct http_msg *msg,
294 enum h1_state state, const char *ptr, const char *end,
295 unsigned int *ret_ptr, enum h1_state *ret_state)
296{
297 const char *msg_start = msg->chn->buf->p;
298
299 switch (state) {
300 case HTTP_MSG_RQMETH:
301 http_msg_rqmeth:
302 if (likely(HTTP_IS_TOKEN(*ptr)))
303 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqmeth, http_msg_ood, state, HTTP_MSG_RQMETH);
304
305 if (likely(HTTP_IS_SPHT(*ptr))) {
306 msg->sl.rq.m_l = ptr - msg_start;
307 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqmeth_sp, http_msg_ood, state, HTTP_MSG_RQMETH_SP);
308 }
309
310 if (likely(HTTP_IS_CRLF(*ptr))) {
311 /* HTTP 0.9 request */
312 msg->sl.rq.m_l = ptr - msg_start;
313 http_msg_req09_uri:
314 msg->sl.rq.u = ptr - msg_start;
315 http_msg_req09_uri_e:
316 msg->sl.rq.u_l = ptr - msg_start - msg->sl.rq.u;
317 http_msg_req09_ver:
318 msg->sl.rq.v = ptr - msg_start;
319 msg->sl.rq.v_l = 0;
320 goto http_msg_rqline_eol;
321 }
322 msg->err_state = HTTP_MSG_RQMETH;
323 state = HTTP_MSG_ERROR;
324 break;
325
326 case HTTP_MSG_RQMETH_SP:
327 http_msg_rqmeth_sp:
328 if (likely(!HTTP_IS_LWS(*ptr))) {
329 msg->sl.rq.u = ptr - msg_start;
330 goto http_msg_rquri;
331 }
332 if (likely(HTTP_IS_SPHT(*ptr)))
333 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqmeth_sp, http_msg_ood, state, HTTP_MSG_RQMETH_SP);
334 /* so it's a CR/LF, meaning an HTTP 0.9 request */
335 goto http_msg_req09_uri;
336
337 case HTTP_MSG_RQURI:
338 http_msg_rquri:
339#if defined(__x86_64__) || \
340 defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || \
341 defined(__ARM_ARCH_7A__)
342 /* speedup: skip bytes not between 0x21 and 0x7e inclusive */
343 while (ptr <= end - sizeof(int)) {
344 int x = *(int *)ptr - 0x21212121;
345 if (x & 0x80808080)
346 break;
347
348 x -= 0x5e5e5e5e;
349 if (!(x & 0x80808080))
350 break;
351
352 ptr += sizeof(int);
353 }
354#endif
355 if (ptr >= end) {
356 state = HTTP_MSG_RQURI;
357 goto http_msg_ood;
358 }
359 http_msg_rquri2:
360 if (likely((unsigned char)(*ptr - 33) <= 93)) /* 33 to 126 included */
361 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri2, http_msg_ood, state, HTTP_MSG_RQURI);
362
363 if (likely(HTTP_IS_SPHT(*ptr))) {
364 msg->sl.rq.u_l = ptr - msg_start - msg->sl.rq.u;
365 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri_sp, http_msg_ood, state, HTTP_MSG_RQURI_SP);
366 }
367
368 if (likely((unsigned char)*ptr >= 128)) {
369 /* non-ASCII chars are forbidden unless option
370 * accept-invalid-http-request is enabled in the frontend.
371 * In any case, we capture the faulty char.
372 */
373 if (msg->err_pos < -1)
374 goto invalid_char;
375 if (msg->err_pos == -1)
376 msg->err_pos = ptr - msg_start;
377 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri, http_msg_ood, state, HTTP_MSG_RQURI);
378 }
379
380 if (likely(HTTP_IS_CRLF(*ptr))) {
381 /* so it's a CR/LF, meaning an HTTP 0.9 request */
382 goto http_msg_req09_uri_e;
383 }
384
385 /* OK forbidden chars, 0..31 or 127 */
386 invalid_char:
387 msg->err_pos = ptr - msg_start;
388 msg->err_state = HTTP_MSG_RQURI;
389 state = HTTP_MSG_ERROR;
390 break;
391
392 case HTTP_MSG_RQURI_SP:
393 http_msg_rquri_sp:
394 if (likely(!HTTP_IS_LWS(*ptr))) {
395 msg->sl.rq.v = ptr - msg_start;
396 goto http_msg_rqver;
397 }
398 if (likely(HTTP_IS_SPHT(*ptr)))
399 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri_sp, http_msg_ood, state, HTTP_MSG_RQURI_SP);
400 /* so it's a CR/LF, meaning an HTTP 0.9 request */
401 goto http_msg_req09_ver;
402
403 case HTTP_MSG_RQVER:
404 http_msg_rqver:
405 if (likely(HTTP_IS_VER_TOKEN(*ptr)))
406 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqver, http_msg_ood, state, HTTP_MSG_RQVER);
407
408 if (likely(HTTP_IS_CRLF(*ptr))) {
409 msg->sl.rq.v_l = ptr - msg_start - msg->sl.rq.v;
410 http_msg_rqline_eol:
411 /* We have seen the end of line. Note that we do not
412 * necessarily have the \n yet, but at least we know that we
413 * have EITHER \r OR \n, otherwise the request would not be
414 * complete. We can then record the request length and return
415 * to the caller which will be able to register it.
416 */
417 msg->sl.rq.l = ptr - msg_start - msg->sol;
418 return ptr;
419 }
420
421 /* neither an HTTP_VER token nor a CRLF */
422 msg->err_state = HTTP_MSG_RQVER;
423 state = HTTP_MSG_ERROR;
424 break;
425
426 default:
427#ifdef DEBUG_FULL
428 fprintf(stderr, "FIXME !!!! impossible state at %s:%d = %d\n", __FILE__, __LINE__, state);
429 exit(1);
430#endif
431 ;
432 }
433
434 http_msg_ood:
435 /* out of valid data */
436 if (ret_state)
437 *ret_state = state;
438 if (ret_ptr)
439 *ret_ptr = ptr - msg_start;
440 return NULL;
441}
442
443/*
444 * This function parses an HTTP message, either a request or a response,
445 * depending on the initial msg->msg_state. The caller is responsible for
446 * ensuring that the message does not wrap. The function can be preempted
447 * everywhere when data are missing and recalled at the exact same location
448 * with no information loss. The message may even be realigned between two
449 * calls. The header index is re-initialized when switching from
450 * MSG_R[PQ]BEFORE to MSG_RPVER|MSG_RQMETH. It modifies msg->sol among other
451 * fields. Note that msg->sol will be initialized after completing the first
452 * state, so that none of the msg pointers has to be initialized prior to the
453 * first call.
454 */
455void http_msg_analyzer(struct http_msg *msg, struct hdr_idx *idx)
456{
457 enum h1_state state; /* updated only when leaving the FSM */
458 register char *ptr, *end; /* request pointers, to avoid dereferences */
459 struct buffer *buf;
460
461 state = msg->msg_state;
462 buf = msg->chn->buf;
463 ptr = buf->p + msg->next;
464 end = buf->p + buf->i;
465
466 if (unlikely(ptr >= end))
467 goto http_msg_ood;
468
469 switch (state) {
470 /*
471 * First, states that are specific to the response only.
472 * We check them first so that request and headers are
473 * closer to each other (accessed more often).
474 */
475 case HTTP_MSG_RPBEFORE:
476 http_msg_rpbefore:
477 if (likely(HTTP_IS_TOKEN(*ptr))) {
478 /* we have a start of message, but we have to check
479 * first if we need to remove some CRLF. We can only
480 * do this when o=0.
481 */
482 if (unlikely(ptr != buf->p)) {
483 if (buf->o)
484 goto http_msg_ood;
485 /* Remove empty leading lines, as recommended by RFC2616. */
486 bi_fast_delete(buf, ptr - buf->p);
487 }
488 msg->sol = 0;
489 msg->sl.st.l = 0; /* used in debug mode */
490 hdr_idx_init(idx);
491 state = HTTP_MSG_RPVER;
492 goto http_msg_rpver;
493 }
494
495 if (unlikely(!HTTP_IS_CRLF(*ptr))) {
496 state = HTTP_MSG_RPBEFORE;
497 goto http_msg_invalid;
498 }
499
500 if (unlikely(*ptr == '\n'))
501 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpbefore, http_msg_ood, state, HTTP_MSG_RPBEFORE);
502 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpbefore_cr, http_msg_ood, state, HTTP_MSG_RPBEFORE_CR);
503 /* stop here */
504
505 case HTTP_MSG_RPBEFORE_CR:
506 http_msg_rpbefore_cr:
507 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_RPBEFORE_CR);
508 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpbefore, http_msg_ood, state, HTTP_MSG_RPBEFORE);
509 /* stop here */
510
511 case HTTP_MSG_RPVER:
512 http_msg_rpver:
513 case HTTP_MSG_RPVER_SP:
514 case HTTP_MSG_RPCODE:
515 case HTTP_MSG_RPCODE_SP:
516 case HTTP_MSG_RPREASON:
517 ptr = (char *)http_parse_stsline(msg,
518 state, ptr, end,
519 &msg->next, &msg->msg_state);
520 if (unlikely(!ptr))
521 return;
522
523 /* we have a full response and we know that we have either a CR
524 * or an LF at <ptr>.
525 */
526 hdr_idx_set_start(idx, msg->sl.st.l, *ptr == '\r');
527
528 msg->sol = ptr - buf->p;
529 if (likely(*ptr == '\r'))
530 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpline_end, http_msg_ood, state, HTTP_MSG_RPLINE_END);
531 goto http_msg_rpline_end;
532
533 case HTTP_MSG_RPLINE_END:
534 http_msg_rpline_end:
535 /* msg->sol must point to the first of CR or LF. */
536 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_RPLINE_END);
537 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_first, http_msg_ood, state, HTTP_MSG_HDR_FIRST);
538 /* stop here */
539
540 /*
541 * Second, states that are specific to the request only
542 */
543 case HTTP_MSG_RQBEFORE:
544 http_msg_rqbefore:
545 if (likely(HTTP_IS_TOKEN(*ptr))) {
546 /* we have a start of message, but we have to check
547 * first if we need to remove some CRLF. We can only
548 * do this when o=0.
549 */
550 if (likely(ptr != buf->p)) {
551 if (buf->o)
552 goto http_msg_ood;
553 /* Remove empty leading lines, as recommended by RFC2616. */
554 bi_fast_delete(buf, ptr - buf->p);
555 }
556 msg->sol = 0;
557 msg->sl.rq.l = 0; /* used in debug mode */
558 state = HTTP_MSG_RQMETH;
559 goto http_msg_rqmeth;
560 }
561
562 if (unlikely(!HTTP_IS_CRLF(*ptr))) {
563 state = HTTP_MSG_RQBEFORE;
564 goto http_msg_invalid;
565 }
566
567 if (unlikely(*ptr == '\n'))
568 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqbefore, http_msg_ood, state, HTTP_MSG_RQBEFORE);
569 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqbefore_cr, http_msg_ood, state, HTTP_MSG_RQBEFORE_CR);
570 /* stop here */
571
572 case HTTP_MSG_RQBEFORE_CR:
573 http_msg_rqbefore_cr:
574 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_RQBEFORE_CR);
575 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqbefore, http_msg_ood, state, HTTP_MSG_RQBEFORE);
576 /* stop here */
577
578 case HTTP_MSG_RQMETH:
579 http_msg_rqmeth:
580 case HTTP_MSG_RQMETH_SP:
581 case HTTP_MSG_RQURI:
582 case HTTP_MSG_RQURI_SP:
583 case HTTP_MSG_RQVER:
584 ptr = (char *)http_parse_reqline(msg,
585 state, ptr, end,
586 &msg->next, &msg->msg_state);
587 if (unlikely(!ptr))
588 return;
589
590 /* we have a full request and we know that we have either a CR
591 * or an LF at <ptr>.
592 */
593 hdr_idx_set_start(idx, msg->sl.rq.l, *ptr == '\r');
594
595 msg->sol = ptr - buf->p;
596 if (likely(*ptr == '\r'))
597 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rqline_end, http_msg_ood, state, HTTP_MSG_RQLINE_END);
598 goto http_msg_rqline_end;
599
600 case HTTP_MSG_RQLINE_END:
601 http_msg_rqline_end:
602 /* check for HTTP/0.9 request : no version information available.
603 * msg->sol must point to the first of CR or LF.
604 */
605 if (unlikely(msg->sl.rq.v_l == 0))
606 goto http_msg_last_lf;
607
608 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_RQLINE_END);
609 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_first, http_msg_ood, state, HTTP_MSG_HDR_FIRST);
610 /* stop here */
611
612 /*
613 * Common states below
614 */
615 case HTTP_MSG_HDR_FIRST:
616 http_msg_hdr_first:
617 msg->sol = ptr - buf->p;
618 if (likely(!HTTP_IS_CRLF(*ptr))) {
619 goto http_msg_hdr_name;
620 }
621
622 if (likely(*ptr == '\r'))
623 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_last_lf, http_msg_ood, state, HTTP_MSG_LAST_LF);
624 goto http_msg_last_lf;
625
626 case HTTP_MSG_HDR_NAME:
627 http_msg_hdr_name:
628 /* assumes msg->sol points to the first char */
629 if (likely(HTTP_IS_TOKEN(*ptr)))
630 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_name, http_msg_ood, state, HTTP_MSG_HDR_NAME);
631
632 if (likely(*ptr == ':'))
633 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, HTTP_MSG_HDR_L1_SP);
634
635 if (likely(msg->err_pos < -1) || *ptr == '\n') {
636 state = HTTP_MSG_HDR_NAME;
637 goto http_msg_invalid;
638 }
639
640 if (msg->err_pos == -1) /* capture error pointer */
641 msg->err_pos = ptr - buf->p; /* >= 0 now */
642
643 /* and we still accept this non-token character */
644 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_name, http_msg_ood, state, HTTP_MSG_HDR_NAME);
645
646 case HTTP_MSG_HDR_L1_SP:
647 http_msg_hdr_l1_sp:
648 /* assumes msg->sol points to the first char */
649 if (likely(HTTP_IS_SPHT(*ptr)))
650 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, HTTP_MSG_HDR_L1_SP);
651
652 /* header value can be basically anything except CR/LF */
653 msg->sov = ptr - buf->p;
654
655 if (likely(!HTTP_IS_CRLF(*ptr))) {
656 goto http_msg_hdr_val;
657 }
658
659 if (likely(*ptr == '\r'))
660 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_lf, http_msg_ood, state, HTTP_MSG_HDR_L1_LF);
661 goto http_msg_hdr_l1_lf;
662
663 case HTTP_MSG_HDR_L1_LF:
664 http_msg_hdr_l1_lf:
665 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_HDR_L1_LF);
666 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_lws, http_msg_ood, state, HTTP_MSG_HDR_L1_LWS);
667
668 case HTTP_MSG_HDR_L1_LWS:
669 http_msg_hdr_l1_lws:
670 if (likely(HTTP_IS_SPHT(*ptr))) {
671 /* replace HT,CR,LF with spaces */
672 for (; buf->p + msg->sov < ptr; msg->sov++)
673 buf->p[msg->sov] = ' ';
674 goto http_msg_hdr_l1_sp;
675 }
676 /* we had a header consisting only in spaces ! */
677 msg->eol = msg->sov;
678 goto http_msg_complete_header;
679
680 case HTTP_MSG_HDR_VAL:
681 http_msg_hdr_val:
682 /* assumes msg->sol points to the first char, and msg->sov
683 * points to the first character of the value.
684 */
685
686 /* speedup: we'll skip packs of 4 or 8 bytes not containing bytes 0x0D
687 * and lower. In fact since most of the time is spent in the loop, we
688 * also remove the sign bit test so that bytes 0x8e..0x0d break the
689 * loop, but we don't care since they're very rare in header values.
690 */
691#if defined(__x86_64__)
692 while (ptr <= end - sizeof(long)) {
693 if ((*(long *)ptr - 0x0e0e0e0e0e0e0e0eULL) & 0x8080808080808080ULL)
694 goto http_msg_hdr_val2;
695 ptr += sizeof(long);
696 }
697#endif
698#if defined(__x86_64__) || \
699 defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || \
700 defined(__ARM_ARCH_7A__)
701 while (ptr <= end - sizeof(int)) {
702 if ((*(int*)ptr - 0x0e0e0e0e) & 0x80808080)
703 goto http_msg_hdr_val2;
704 ptr += sizeof(int);
705 }
706#endif
707 if (ptr >= end) {
708 state = HTTP_MSG_HDR_VAL;
709 goto http_msg_ood;
710 }
711 http_msg_hdr_val2:
712 if (likely(!HTTP_IS_CRLF(*ptr)))
713 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_val2, http_msg_ood, state, HTTP_MSG_HDR_VAL);
714
715 msg->eol = ptr - buf->p;
716 /* Note: we could also copy eol into ->eoh so that we have the
717 * real header end in case it ends with lots of LWS, but is this
718 * really needed ?
719 */
720 if (likely(*ptr == '\r'))
721 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l2_lf, http_msg_ood, state, HTTP_MSG_HDR_L2_LF);
722 goto http_msg_hdr_l2_lf;
723
724 case HTTP_MSG_HDR_L2_LF:
725 http_msg_hdr_l2_lf:
726 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_HDR_L2_LF);
727 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l2_lws, http_msg_ood, state, HTTP_MSG_HDR_L2_LWS);
728
729 case HTTP_MSG_HDR_L2_LWS:
730 http_msg_hdr_l2_lws:
731 if (unlikely(HTTP_IS_SPHT(*ptr))) {
732 /* LWS: replace HT,CR,LF with spaces */
733 for (; buf->p + msg->eol < ptr; msg->eol++)
734 buf->p[msg->eol] = ' ';
735 goto http_msg_hdr_val;
736 }
737 http_msg_complete_header:
738 /*
739 * It was a new header, so the last one is finished.
740 * Assumes msg->sol points to the first char, msg->sov points
741 * to the first character of the value and msg->eol to the
742 * first CR or LF so we know how the line ends. We insert last
743 * header into the index.
744 */
745 if (unlikely(hdr_idx_add(msg->eol - msg->sol, buf->p[msg->eol] == '\r',
746 idx, idx->tail) < 0)) {
747 state = HTTP_MSG_HDR_L2_LWS;
748 goto http_msg_invalid;
749 }
750
751 msg->sol = ptr - buf->p;
752 if (likely(!HTTP_IS_CRLF(*ptr))) {
753 goto http_msg_hdr_name;
754 }
755
756 if (likely(*ptr == '\r'))
757 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_last_lf, http_msg_ood, state, HTTP_MSG_LAST_LF);
758 goto http_msg_last_lf;
759
760 case HTTP_MSG_LAST_LF:
761 http_msg_last_lf:
762 /* Assumes msg->sol points to the first of either CR or LF.
763 * Sets ->sov and ->next to the total header length, ->eoh to
764 * the last CRLF, and ->eol to the last CRLF length (1 or 2).
765 */
766 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_LAST_LF);
767 ptr++;
768 msg->sov = msg->next = ptr - buf->p;
769 msg->eoh = msg->sol;
770 msg->sol = 0;
771 msg->eol = msg->sov - msg->eoh;
772 msg->msg_state = HTTP_MSG_BODY;
773 return;
774
775 case HTTP_MSG_ERROR:
776 /* this may only happen if we call http_msg_analyser() twice with an error */
777 break;
778
779 default:
780#ifdef DEBUG_FULL
781 fprintf(stderr, "FIXME !!!! impossible state at %s:%d = %d\n", __FILE__, __LINE__, state);
782 exit(1);
783#endif
784 ;
785 }
786 http_msg_ood:
787 /* out of data */
788 msg->msg_state = state;
789 msg->next = ptr - buf->p;
790 return;
791
792 http_msg_invalid:
793 /* invalid message */
794 msg->err_state = state;
795 msg->msg_state = HTTP_MSG_ERROR;
796 msg->next = ptr - buf->p;
797 return;
798}
799
Willy Tarreau794f9af2017-07-26 09:07:47 +0200800/* This function parses a contiguous HTTP/1 headers block starting at <start>
801 * and ending before <stop>, at once, and converts it a list of (name,value)
802 * pairs representing header fields into the array <hdr> of size <hdr_num>,
803 * whose last entry will have an empty name and an empty value. If <hdr_num> is
804 * too small to represent the whole message, an error is returned. If <h1m> is
805 * not NULL, some protocol elements such as content-length and transfer-encoding
806 * will be parsed and stored there as well.
807 *
808 * For now it's limited to the response. If the header block is incomplete,
809 * 0 is returned, waiting to be called again with more data to try it again.
810 *
811 * The code derived from the main HTTP/1 parser above but was simplified and
812 * optimized to process responses produced or forwarded by haproxy. The caller
813 * is responsible for ensuring that the message doesn't wrap, and should ensure
814 * it is complete to avoid having to retry the operation after a failed
815 * attempt. The message is not supposed to be invalid, which is why a few
816 * properties such as the character set used in the header field names are not
817 * checked. In case of an unparsable response message, a negative value will be
818 * returned with h1m->err_pos and h1m->err_state matching the location and
819 * state where the error was met. Leading blank likes are tolerated but not
820 * recommended.
821 *
822 * This function returns :
823 * -1 in case of error. In this case, h1m->err_state is filled (if h1m is
824 * set) with the state the error occurred in and h2-m>err_pos with the
825 * the position relative to <start>
826 * -2 if the output is full (hdr_num reached). err_state and err_pos also
827 * indicate where it failed.
828 * 0 in case of missing data.
829 * > 0 on success, it then corresponds to the number of bytes read since
830 * <start> so that the caller can go on with the payload.
831 */
832int h1_headers_to_hdr_list(char *start, const char *stop,
833 struct http_hdr *hdr, unsigned int hdr_num,
834 struct h1m *h1m)
835{
836 enum h1_state state = HTTP_MSG_RPBEFORE;
837 register char *ptr = start;
838 register const char *end = stop;
839 unsigned int hdr_count = 0;
840 unsigned int code = 0; /* status code, ASCII form */
841 unsigned int st_c; /* beginning of status code, relative to msg_start */
842 unsigned int st_c_l; /* length of status code */
843 unsigned int sol = 0; /* start of line */
844 unsigned int col = 0; /* position of the colon */
845 unsigned int eol = 0; /* end of line */
846 unsigned int sov = 0; /* start of value */
847 unsigned int skip = 0; /* number of bytes skipped at the beginning */
848 struct ist n, v; /* header name and value during parsing */
849
850 if (unlikely(ptr >= end))
851 goto http_msg_ood;
852
853 switch (state) {
854 case HTTP_MSG_RPBEFORE:
855 http_msg_rpbefore:
856 if (likely(HTTP_IS_TOKEN(*ptr))) {
857 /* we have a start of message, we may have skipped some
858 * heading CRLF. Skip them now.
859 */
860 skip += ptr - start;
861 start = ptr;
862
863 sol = 0;
864 hdr_count = 0;
865 state = HTTP_MSG_RPVER;
866 goto http_msg_rpver;
867 }
868
869 if (unlikely(!HTTP_IS_CRLF(*ptr))) {
870 state = HTTP_MSG_RPBEFORE;
871 goto http_msg_invalid;
872 }
873
874 if (unlikely(*ptr == '\n'))
875 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpbefore, http_msg_ood, state, HTTP_MSG_RPBEFORE);
876 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpbefore_cr, http_msg_ood, state, HTTP_MSG_RPBEFORE_CR);
877 /* stop here */
878
879 case HTTP_MSG_RPBEFORE_CR:
880 http_msg_rpbefore_cr:
881 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_RPBEFORE_CR);
882 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpbefore, http_msg_ood, state, HTTP_MSG_RPBEFORE);
883 /* stop here */
884
885 case HTTP_MSG_RPVER:
886 http_msg_rpver:
887 if (likely(HTTP_IS_VER_TOKEN(*ptr)))
888 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpver, http_msg_ood, state, HTTP_MSG_RPVER);
889
890 if (likely(HTTP_IS_SPHT(*ptr))) {
891 /* version length = ptr - start */
892 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpver_sp, http_msg_ood, state, HTTP_MSG_RPVER_SP);
893 }
894 state = HTTP_MSG_RPVER;
895 goto http_msg_invalid;
896
897 case HTTP_MSG_RPVER_SP:
898 http_msg_rpver_sp:
899 if (likely(!HTTP_IS_LWS(*ptr))) {
900 code = 0;
901 st_c = ptr - start;
902 goto http_msg_rpcode;
903 }
904 if (likely(HTTP_IS_SPHT(*ptr)))
905 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpver_sp, http_msg_ood, state, HTTP_MSG_RPVER_SP);
906 /* so it's a CR/LF, this is invalid */
907 state = HTTP_MSG_RPVER_SP;
908 goto http_msg_invalid;
909
910 case HTTP_MSG_RPCODE:
911 http_msg_rpcode:
Willy Tarreau1b4cf9b2017-11-09 11:15:45 +0100912 if (likely(HTTP_IS_DIGIT(*ptr))) {
Willy Tarreaud22e83a2017-10-31 08:02:24 +0100913 code = code * 10 + *ptr - '0';
Willy Tarreau794f9af2017-07-26 09:07:47 +0200914 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode, http_msg_ood, state, HTTP_MSG_RPCODE);
915 }
916
Willy Tarreau1b4cf9b2017-11-09 11:15:45 +0100917 if (unlikely(!HTTP_IS_LWS(*ptr))) {
918 state = HTTP_MSG_RPCODE;
919 goto http_msg_invalid;
920 }
921
Willy Tarreau794f9af2017-07-26 09:07:47 +0200922 if (likely(HTTP_IS_SPHT(*ptr))) {
923 st_c_l = ptr - start - st_c;
924 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode_sp, http_msg_ood, state, HTTP_MSG_RPCODE_SP);
925 }
926
927 /* so it's a CR/LF, so there is no reason phrase */
928 st_c_l = ptr - start - st_c;
929
930 http_msg_rsp_reason:
931 /* reason = ptr - start; */
932 /* reason length = 0 */
933 goto http_msg_rpline_eol;
934
935 case HTTP_MSG_RPCODE_SP:
936 http_msg_rpcode_sp:
937 if (likely(!HTTP_IS_LWS(*ptr))) {
938 /* reason = ptr - start */
939 goto http_msg_rpreason;
940 }
941 if (likely(HTTP_IS_SPHT(*ptr)))
942 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpcode_sp, http_msg_ood, state, HTTP_MSG_RPCODE_SP);
943 /* so it's a CR/LF, so there is no reason phrase */
944 goto http_msg_rsp_reason;
945
946 case HTTP_MSG_RPREASON:
947 http_msg_rpreason:
948 if (likely(!HTTP_IS_CRLF(*ptr)))
949 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpreason, http_msg_ood, state, HTTP_MSG_RPREASON);
950 /* reason length = ptr - start - reason */
951 http_msg_rpline_eol:
952 /* We have seen the end of line. Note that we do not
953 * necessarily have the \n yet, but at least we know that we
954 * have EITHER \r OR \n, otherwise the response would not be
955 * complete. We can then record the response length and return
956 * to the caller which will be able to register it.
957 */
958
959 if (unlikely(hdr_count >= hdr_num)) {
960 state = HTTP_MSG_RPREASON;
961 goto http_output_full;
962 }
963 http_set_hdr(&hdr[hdr_count++], ist(":status"), ist2(start + st_c, st_c_l));
Willy Tarreaud22e83a2017-10-31 08:02:24 +0100964 if (h1m)
965 h1m->status = code;
Willy Tarreau794f9af2017-07-26 09:07:47 +0200966
967 sol = ptr - start;
968 if (likely(*ptr == '\r'))
969 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rpline_end, http_msg_ood, state, HTTP_MSG_RPLINE_END);
970 goto http_msg_rpline_end;
971
972 case HTTP_MSG_RPLINE_END:
973 http_msg_rpline_end:
974 /* sol must point to the first of CR or LF. */
975 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_RPLINE_END);
976 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_first, http_msg_ood, state, HTTP_MSG_HDR_FIRST);
977 /* stop here */
978
979 case HTTP_MSG_HDR_FIRST:
980 http_msg_hdr_first:
981 sol = ptr - start;
982 if (likely(!HTTP_IS_CRLF(*ptr))) {
983 goto http_msg_hdr_name;
984 }
985
986 if (likely(*ptr == '\r'))
987 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_last_lf, http_msg_ood, state, HTTP_MSG_LAST_LF);
988 goto http_msg_last_lf;
989
990 case HTTP_MSG_HDR_NAME:
991 http_msg_hdr_name:
992 /* assumes sol points to the first char */
993 if (likely(HTTP_IS_TOKEN(*ptr))) {
994 /* turn it to lower case if needed */
995 if (isupper((unsigned char)*ptr))
996 *ptr = tolower(*ptr);
997 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_name, http_msg_ood, state, HTTP_MSG_HDR_NAME);
998 }
999
1000 if (likely(*ptr == ':')) {
1001 col = ptr - start;
1002 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, HTTP_MSG_HDR_L1_SP);
1003 }
1004
1005 if (HTTP_IS_LWS(*ptr)) {
1006 state = HTTP_MSG_HDR_NAME;
1007 goto http_msg_invalid;
1008 }
1009
1010 /* now we have a non-token character in the header field name,
1011 * it's up to the H1 layer to have decided whether or not it
1012 * was acceptable. If we find it here, it was considered
1013 * acceptable due to configuration rules so we obey.
1014 */
1015 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_name, http_msg_ood, state, HTTP_MSG_HDR_NAME);
1016
1017 case HTTP_MSG_HDR_L1_SP:
1018 http_msg_hdr_l1_sp:
1019 /* assumes sol points to the first char */
1020 if (likely(HTTP_IS_SPHT(*ptr)))
1021 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, HTTP_MSG_HDR_L1_SP);
1022
1023 /* header value can be basically anything except CR/LF */
1024 sov = ptr - start;
1025
1026 if (likely(!HTTP_IS_CRLF(*ptr))) {
1027 goto http_msg_hdr_val;
1028 }
1029
1030 if (likely(*ptr == '\r'))
1031 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_lf, http_msg_ood, state, HTTP_MSG_HDR_L1_LF);
1032 goto http_msg_hdr_l1_lf;
1033
1034 case HTTP_MSG_HDR_L1_LF:
1035 http_msg_hdr_l1_lf:
1036 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_HDR_L1_LF);
1037 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_lws, http_msg_ood, state, HTTP_MSG_HDR_L1_LWS);
1038
1039 case HTTP_MSG_HDR_L1_LWS:
1040 http_msg_hdr_l1_lws:
1041 if (likely(HTTP_IS_SPHT(*ptr))) {
1042 /* replace HT,CR,LF with spaces */
1043 for (; start + sov < ptr; sov++)
1044 start[sov] = ' ';
1045 goto http_msg_hdr_l1_sp;
1046 }
1047 /* we had a header consisting only in spaces ! */
1048 eol = sov;
1049 goto http_msg_complete_header;
1050
1051 case HTTP_MSG_HDR_VAL:
1052 http_msg_hdr_val:
1053 /* assumes sol points to the first char, and sov
1054 * points to the first character of the value.
1055 */
1056
1057 /* speedup: we'll skip packs of 4 or 8 bytes not containing bytes 0x0D
1058 * and lower. In fact since most of the time is spent in the loop, we
1059 * also remove the sign bit test so that bytes 0x8e..0x0d break the
1060 * loop, but we don't care since they're very rare in header values.
1061 */
1062#if defined(__x86_64__)
1063 while (ptr <= end - sizeof(long)) {
1064 if ((*(long *)ptr - 0x0e0e0e0e0e0e0e0eULL) & 0x8080808080808080ULL)
1065 goto http_msg_hdr_val2;
1066 ptr += sizeof(long);
1067 }
1068#endif
1069#if defined(__x86_64__) || \
1070 defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || \
1071 defined(__ARM_ARCH_7A__)
1072 while (ptr <= end - sizeof(int)) {
1073 if ((*(int*)ptr - 0x0e0e0e0e) & 0x80808080)
1074 goto http_msg_hdr_val2;
1075 ptr += sizeof(int);
1076 }
1077#endif
1078 if (ptr >= end) {
1079 state = HTTP_MSG_HDR_VAL;
1080 goto http_msg_ood;
1081 }
1082 http_msg_hdr_val2:
1083 if (likely(!HTTP_IS_CRLF(*ptr)))
1084 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_val2, http_msg_ood, state, HTTP_MSG_HDR_VAL);
1085
1086 eol = ptr - start;
1087 /* Note: we could also copy eol into ->eoh so that we have the
1088 * real header end in case it ends with lots of LWS, but is this
1089 * really needed ?
1090 */
1091 if (likely(*ptr == '\r'))
1092 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l2_lf, http_msg_ood, state, HTTP_MSG_HDR_L2_LF);
1093 goto http_msg_hdr_l2_lf;
1094
1095 case HTTP_MSG_HDR_L2_LF:
1096 http_msg_hdr_l2_lf:
1097 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_HDR_L2_LF);
1098 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l2_lws, http_msg_ood, state, HTTP_MSG_HDR_L2_LWS);
1099
1100 case HTTP_MSG_HDR_L2_LWS:
1101 http_msg_hdr_l2_lws:
1102 if (unlikely(HTTP_IS_SPHT(*ptr))) {
1103 /* LWS: replace HT,CR,LF with spaces */
1104 for (; start + eol < ptr; eol++)
1105 start[eol] = ' ';
1106 goto http_msg_hdr_val;
1107 }
1108 http_msg_complete_header:
1109 /*
1110 * It was a new header, so the last one is finished. Assumes
1111 * <sol> points to the first char of the name, <col> to the
1112 * colon, <sov> points to the first character of the value and
1113 * <eol> to the first CR or LF so we know how the line ends. We
1114 * will trim spaces around the value. It's possible to do it by
1115 * adjusting <eol> and <sov> which are no more used after this.
1116 * We can add the header field to the list.
1117 */
1118 while (sov < eol && HTTP_IS_LWS(start[sov]))
1119 sov++;
1120
1121 while (eol - 1 > sov && HTTP_IS_LWS(start[eol - 1]))
1122 eol--;
1123
1124
1125 n = ist2(start + sol, col - sol);
1126 v = ist2(start + sov, eol - sov);
1127
1128 if (unlikely(hdr_count >= hdr_num)) {
1129 state = HTTP_MSG_HDR_L2_LWS;
1130 goto http_output_full;
1131 }
1132 http_set_hdr(&hdr[hdr_count++], n, v);
1133
1134 if (h1m) {
1135 long long cl;
1136
Willy Tarreaud22e83a2017-10-31 08:02:24 +01001137 if (h1m->status >= 100 && h1m->status < 200)
1138 h1m->curr_len = h1m->body_len = 0;
1139 else if (h1m->status == 304 || h1m->status == 204) {
Willy Tarreau8ea0f382017-10-30 19:31:59 +01001140 /* no contents, claim c-len is present and set to zero */
1141 h1m->flags |= H1_MF_CLEN;
1142 h1m->curr_len = h1m->body_len = 0;
1143 }
1144 else if (isteq(n, ist("transfer-encoding"))) {
Willy Tarreau794f9af2017-07-26 09:07:47 +02001145 h1m->flags &= ~H1_MF_CLEN;
1146 h1m->flags |= H1_MF_CHNK;
1147 }
1148 else if (isteq(n, ist("content-length")) && !(h1m->flags & H1_MF_CHNK)) {
1149 h1m->flags |= H1_MF_CLEN;
1150 strl2llrc(v.ptr, v.len, &cl);
1151 h1m->curr_len = h1m->body_len = cl;
1152 }
1153 }
1154
1155 sol = ptr - start;
1156 if (likely(!HTTP_IS_CRLF(*ptr)))
1157 goto http_msg_hdr_name;
1158
1159 if (likely(*ptr == '\r'))
1160 EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_last_lf, http_msg_ood, state, HTTP_MSG_LAST_LF);
1161 goto http_msg_last_lf;
1162
1163 case HTTP_MSG_LAST_LF:
1164 http_msg_last_lf:
1165 EXPECT_LF_HERE(ptr, http_msg_invalid, state, HTTP_MSG_LAST_LF);
1166 ptr++;
1167 /* <ptr> now points to the first byte of payload. If needed sol
1168 * still points to the first of either CR or LF of the empty
1169 * line ending the headers block.
1170 */
1171 if (unlikely(hdr_count >= hdr_num)) {
1172 state = HTTP_MSG_LAST_LF;
1173 goto http_output_full;
1174 }
1175 http_set_hdr(&hdr[hdr_count++], ist(""), ist(""));
1176 state = HTTP_MSG_BODY;
1177 break;
1178
1179 default:
1180 /* impossible states */
1181 goto http_msg_invalid;
1182 }
1183
1184 /* reaching here, we've parsed the whole message and the state is
1185 * HTTP_MSG_BODY.
1186 */
1187 return ptr - start + skip;
1188
1189 http_msg_ood:
1190 /* out of data at <ptr> during state <state> */
1191 return 0;
1192
1193 http_msg_invalid:
1194 /* invalid message, error at <ptr> */
1195 if (h1m) {
1196 h1m->err_state = state;
1197 h1m->err_pos = ptr - start + skip;
1198 }
1199 return -1;
1200
1201 http_output_full:
1202 /* no more room to store the current header, error at <ptr> */
1203 if (h1m) {
1204 h1m->err_state = state;
1205 h1m->err_pos = ptr - start + skip;
1206 }
1207 return -2;
1208}
1209
Willy Tarreau2510f702017-10-31 17:14:16 +01001210/* This function performs a very minimal parsing of the trailers block present
1211 * in the output part of <buf>, and returns the number of bytes to delete to
1212 * skip the trailers. It may return 0 if it's missing some input data, or < 0
1213 * in case of parse error (in which case the caller may have to decide how to
1214 * proceed, possibly eating everything).
1215 */
1216int h1_measure_trailers(const struct buffer *buf)
1217{
1218 int count = 0;
1219
1220 while (1) {
1221 const char *p1 = NULL, *p2 = NULL;
1222 const char *start = b_ptr(buf, (int)(count - buf->o));
1223 const char *stop = bo_end(buf);
1224 const char *ptr = start;
1225 int bytes = 0;
1226
1227 /* scan current line and stop at LF or CRLF */
1228 while (1) {
1229 if (ptr == stop)
1230 return 0;
1231
1232 if (*ptr == '\n') {
1233 if (!p1)
1234 p1 = ptr;
1235 p2 = ptr;
1236 break;
1237 }
1238
1239 if (*ptr == '\r') {
1240 if (p1)
1241 return -1;
1242 p1 = ptr;
1243 }
1244
1245 ptr++;
1246 if (ptr >= buf->data + buf->size)
1247 ptr = buf->data;
1248 }
1249
1250 /* after LF; point to beginning of next line */
1251 p2++;
1252 if (p2 >= buf->data + buf->size)
1253 p2 = buf->data;
1254
1255 bytes = p2 - start;
1256 if (bytes < 0)
1257 bytes += buf->size;
1258
1259 count += bytes;
1260
1261 /* LF/CRLF at beginning of line => end of trailers at p2.
1262 * Everything was scheduled for forwarding, there's nothing left
1263 * from this message. */
1264 if (p1 == start)
1265 break;
1266 /* OK, next line then */
1267 }
1268 return count;
1269}
1270
Willy Tarreaudb4893d2017-09-21 08:40:02 +02001271/* This function skips trailers in the buffer associated with HTTP message
1272 * <msg>. The first visited position is msg->next. If the end of the trailers is
1273 * found, the function returns >0. So, the caller can automatically schedul it
1274 * to be forwarded, and switch msg->msg_state to HTTP_MSG_DONE. If not enough
1275 * data are available, the function does not change anything except maybe
1276 * msg->sol if it could parse some lines, and returns zero. If a parse error
1277 * is encountered, the function returns < 0 and does not change anything except
1278 * maybe msg->sol. Note that the message must already be in HTTP_MSG_TRAILERS
1279 * state before calling this function, which implies that all non-trailers data
1280 * have already been scheduled for forwarding, and that msg->next exactly
1281 * matches the length of trailers already parsed and not forwarded. It is also
1282 * important to note that this function is designed to be able to parse wrapped
1283 * headers at end of buffer.
1284 */
1285int http_forward_trailers(struct http_msg *msg)
1286{
1287 const struct buffer *buf = msg->chn->buf;
1288
1289 /* we have msg->next which points to next line. Look for CRLF. But
1290 * first, we reset msg->sol */
1291 msg->sol = 0;
1292 while (1) {
1293 const char *p1 = NULL, *p2 = NULL;
1294 const char *start = b_ptr(buf, msg->next + msg->sol);
1295 const char *stop = bi_end(buf);
1296 const char *ptr = start;
1297 int bytes = 0;
1298
1299 /* scan current line and stop at LF or CRLF */
1300 while (1) {
1301 if (ptr == stop)
1302 return 0;
1303
1304 if (*ptr == '\n') {
1305 if (!p1)
1306 p1 = ptr;
1307 p2 = ptr;
1308 break;
1309 }
1310
1311 if (*ptr == '\r') {
1312 if (p1) {
1313 msg->err_pos = buffer_count(buf, buf->p, ptr);
1314 return -1;
1315 }
1316 p1 = ptr;
1317 }
1318
1319 ptr++;
1320 if (ptr >= buf->data + buf->size)
1321 ptr = buf->data;
1322 }
1323
1324 /* after LF; point to beginning of next line */
1325 p2++;
1326 if (p2 >= buf->data + buf->size)
1327 p2 = buf->data;
1328
1329 bytes = p2 - start;
1330 if (bytes < 0)
1331 bytes += buf->size;
1332 msg->sol += bytes;
1333
1334 /* LF/CRLF at beginning of line => end of trailers at p2.
1335 * Everything was scheduled for forwarding, there's nothing left
1336 * from this message. */
1337 if (p1 == start)
1338 return 1;
1339
1340 /* OK, next line then */
1341 }
1342}