fix DoS in Connection header value split (reported by Jesse Sipprell, CVE-2012-5533)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2860 152afb58-edef-0310-8abb-c4023f1b3aa9svn/tags/lighttpd-1.4.32
parent
6200764f05
commit
6edfc40f93
1
NEWS
1
NEWS
|
@ -14,6 +14,7 @@ NEWS
|
|||
* detect "x-gzip"/"x-bzip2" as separate encodings, more strict encoding matching (fixes #2443)
|
||||
* tests: make sure mod_proxy doesn't leave running processes (fixes #2435, thx kibi)
|
||||
* mod_extforward: log address of untrusted proxy with debug.log-request-handling
|
||||
* fix DoS in Connection header value split (reported by Jesse Sipprell, CVE-2012-5533)
|
||||
|
||||
- 1.4.31 - 2012-05-31
|
||||
* [ssl] fix segfault in counting renegotiations for openssl versions without TLSEXT/SNI (thx carpii for reporting)
|
||||
|
|
|
@ -209,9 +209,11 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) {
|
|||
#endif
|
||||
|
||||
static int http_request_split_value(array *vals, buffer *b) {
|
||||
char *s;
|
||||
size_t i;
|
||||
int state = 0;
|
||||
|
||||
const char *current;
|
||||
const char *token_start = NULL, *token_end = NULL;
|
||||
/*
|
||||
* parse
|
||||
*
|
||||
|
@ -222,53 +224,52 @@ static int http_request_split_value(array *vals, buffer *b) {
|
|||
|
||||
if (b->used == 0) return 0;
|
||||
|
||||
s = b->ptr;
|
||||
|
||||
for (i =0; i < b->used - 1; ) {
|
||||
char *start = NULL, *end = NULL;
|
||||
current = b->ptr;
|
||||
for (i = 0; i < b->used; ++i, ++current) {
|
||||
data_string *ds;
|
||||
|
||||
switch (state) {
|
||||
case 0: /* ws */
|
||||
|
||||
/* skip ws */
|
||||
for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
|
||||
|
||||
|
||||
state = 1;
|
||||
break;
|
||||
case 1: /* value */
|
||||
start = s;
|
||||
|
||||
for (; *s != ',' && i < b->used - 1; i++, s++);
|
||||
if (start == s) break; /* empty fields are skipped */
|
||||
end = s - 1;
|
||||
|
||||
for (; end > start && (*end == ' ' || *end == '\t'); end--);
|
||||
if (start == end) break; /* empty fields are skipped */
|
||||
|
||||
if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
|
||||
ds = data_string_init();
|
||||
case 0: /* find start of a token */
|
||||
switch (*current) {
|
||||
case ' ':
|
||||
case '\t': /* skip white space */
|
||||
case ',': /* skip empty token */
|
||||
break;
|
||||
case '\0': /* end of string */
|
||||
return 0;
|
||||
default:
|
||||
/* found real data, switch to state 1 to find the end of the token */
|
||||
token_start = token_end = current;
|
||||
state = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: /* find end of token and last non white space character */
|
||||
switch (*current) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
/* space - don't update token_end */
|
||||
break;
|
||||
case ',':
|
||||
case '\0': /* end of string also marks the end of a token */
|
||||
if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
|
||||
ds = data_string_init();
|
||||
}
|
||||
|
||||
buffer_copy_string_len(ds->value, start, end-start+1);
|
||||
array_insert_unique(vals, (data_unset *)ds);
|
||||
buffer_copy_string_len(ds->value, token_start, token_end-token_start+1);
|
||||
array_insert_unique(vals, (data_unset *)ds);
|
||||
|
||||
if (*s == ',') {
|
||||
state = 0;
|
||||
i++;
|
||||
s++;
|
||||
} else {
|
||||
/* end of string */
|
||||
|
||||
state = 2;
|
||||
break;
|
||||
default:
|
||||
/* no white space, update token_end to include current character */
|
||||
token_end = current;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue