mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-13 15:04:42 +00:00
MEDIUM: h1: Add an option to sanitize connection headers during parsing
The flag H1_MF_CLEAN_CONN_HDR has been added to let the H1 parser sanitize connection headers. It means it will remove all "close" and "keep-alive" values during the parsing. One noticeable effect is that connection headers may be unfolded. In practice, this is not a problem because it is not frequent to have multiple values for the connection headers. If this flag is set, during the parsing The function h1_parse_next_connection_header() is called in a loop instead of h1_parse_conection_header(). No need to backport this patch
This commit is contained in:
parent
b829f4c726
commit
a51ebb7f56
@ -93,6 +93,7 @@ enum h1m_state {
|
||||
#define H1_MF_XFER_ENC 0x00000200 // transfer-encoding is present
|
||||
#define H1_MF_NO_PHDR 0x00000400 // don't add pseudo-headers in the header list
|
||||
#define H1_MF_HDRS_ONLY 0x00000800 // parse headers only
|
||||
#define H1_MF_CLEAN_CONN_HDR 0x00001000 // skip close/keep-alive values of connection headers during parsing
|
||||
|
||||
/* Note: for a connection to be persistent, we need this for the request :
|
||||
* - one of CLEN or CHNK
|
||||
@ -144,7 +145,7 @@ int h1_measure_trailers(const struct buffer *buf, unsigned int ofs, unsigned int
|
||||
|
||||
int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value);
|
||||
void h1_parse_xfer_enc_header(struct h1m *h1m, struct ist value);
|
||||
void h1_parse_connection_header(struct h1m *h1m, struct ist value);
|
||||
void h1_parse_connection_header(struct h1m *h1m, struct ist *value);
|
||||
|
||||
/* for debugging, reports the HTTP/1 message state name */
|
||||
static inline const char *h1m_state_str(enum h1m_state msg_state)
|
||||
|
46
src/h1.c
46
src/h1.c
@ -132,15 +132,20 @@ void h1_parse_xfer_enc_header(struct h1m *h1m, struct ist value)
|
||||
* "keep-alive", and "upgrade" values, and updating h1m->flags according to
|
||||
* what was found there. Note that flags are only added, not removed, so the
|
||||
* function is safe for being called multiple times if multiple occurrences
|
||||
* are found.
|
||||
* are found. If the flag H1_MF_CLEAN_CONN_HDR, the header value is cleaned
|
||||
* up from "keep-alive" and "close" values. To do so, the header value is
|
||||
* rewritten in place and its length is updated.
|
||||
*/
|
||||
void h1_parse_connection_header(struct h1m *h1m, struct ist value)
|
||||
void h1_parse_connection_header(struct h1m *h1m, struct ist *value)
|
||||
{
|
||||
char *e, *n;
|
||||
char *e, *n, *p;
|
||||
struct ist word;
|
||||
|
||||
word.ptr = value.ptr - 1; // -1 for next loop's pre-increment
|
||||
e = value.ptr + value.len;
|
||||
word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
|
||||
p = value->ptr;
|
||||
e = value->ptr + value->len;
|
||||
if (h1m->flags & H1_MF_CLEAN_CONN_HDR)
|
||||
value->len = 0;
|
||||
|
||||
while (++word.ptr < e) {
|
||||
/* skip leading delimitor and blanks */
|
||||
@ -154,14 +159,33 @@ void h1_parse_connection_header(struct h1m *h1m, struct ist value)
|
||||
while (word.len && HTTP_IS_LWS(word.ptr[word.len-1]))
|
||||
word.len--;
|
||||
|
||||
if (isteqi(word, ist("keep-alive")))
|
||||
if (isteqi(word, ist("keep-alive"))) {
|
||||
h1m->flags |= H1_MF_CONN_KAL;
|
||||
else if (isteqi(word, ist("close")))
|
||||
if (h1m->flags & H1_MF_CLEAN_CONN_HDR)
|
||||
goto skip_val;
|
||||
}
|
||||
else if (isteqi(word, ist("close"))) {
|
||||
h1m->flags |= H1_MF_CONN_CLO;
|
||||
if (h1m->flags & H1_MF_CLEAN_CONN_HDR)
|
||||
goto skip_val;
|
||||
}
|
||||
else if (isteqi(word, ist("upgrade")))
|
||||
h1m->flags |= H1_MF_CONN_UPG;
|
||||
|
||||
word.ptr = n;
|
||||
if (h1m->flags & H1_MF_CLEAN_CONN_HDR) {
|
||||
if (value->ptr + value->len == p) {
|
||||
/* no rewrite done till now */
|
||||
value->len = n - value->ptr;
|
||||
}
|
||||
else {
|
||||
if (value->len)
|
||||
value->ptr[value->len++] = ',';
|
||||
istcat(value, word, e - value->ptr);
|
||||
}
|
||||
}
|
||||
|
||||
skip_val:
|
||||
word.ptr = p = n;
|
||||
}
|
||||
}
|
||||
|
||||
@ -802,7 +826,11 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
|
||||
}
|
||||
}
|
||||
else if (isteqi(n, ist("connection"))) {
|
||||
h1_parse_connection_header(h1m, v);
|
||||
h1_parse_connection_header(h1m, &v);
|
||||
if (!v.len) {
|
||||
/* skip it */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
http_set_hdr(&hdr[hdr_count++], n, v);
|
||||
|
Loading…
Reference in New Issue
Block a user