Browse Source

fixed #25 by setting all duplicates to 400

git-svn-id: svn://svn.lighttpd.net/lighttpd/trunk@60 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/release-1.3.12
Jan Kneschke 17 years ago
parent
commit
0f779ce2f9
  1. 1
      configure.in
  2. 104
      src/request.c
  3. 82
      tests/run-tests.pl

1
configure.in

@ -380,6 +380,7 @@ AC_CONFIG_FILES([Makefile debian/Makefile src/Makefile doc/Makefile tests/Makefi
tests/docroot/www/Makefile \
tests/docroot/www/go/Makefile \
tests/docroot/www/indexfile/Makefile \
tests/docroot/www/expire/Makefile \
lighttpd.spec distribute.sh cygwin/Makefile cygwin/lighttpd.README
openwrt/Makefile openwrt/control openwrt/lighttpd.mk])
AC_OUTPUT

104
src/request.c

@ -732,6 +732,20 @@ int http_request_parse(server *srv, connection *con) {
unsigned long int r;
size_t j;
if (con_length_set) {
con->http_status = 400;
con->keep_alive = 0;
log_error_write(srv, __FILE__, __LINE__, "s",
"duplicate Content-Length-header -> 400");
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "Sb",
"request-header:\n",
con->request.request);
}
return 0;
}
if (ds->value->used == 0) SEGFAULT();
for (j = 0; j < ds->value->used - 1; j++) {
@ -764,7 +778,22 @@ int http_request_parse(server *srv, connection *con) {
return 0;
}
} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Type")))) {
con->request.http_content_type = ds->value->ptr;
/* if dup, only the first one will survive */
if (!con->request.http_content_type) {
con->request.http_content_type = ds->value->ptr;
} else {
con->http_status = 400;
con->keep_alive = 0;
log_error_write(srv, __FILE__, __LINE__, "s",
"duplicate Content-Type-header -> 400");
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "Sb",
"request-header:\n",
con->request.request);
}
return 0;
}
} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
/* HTTP 2616 8.2.3
* Expect: 100-continue
@ -781,18 +810,77 @@ int http_request_parse(server *srv, connection *con) {
array_insert_unique(con->request.headers, (data_unset *)ds);
return 0;
} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
con->request.http_host = ds->value;
if (!con->request.http_host) {
con->request.http_host = ds->value;
} else {
con->http_status = 400;
con->keep_alive = 0;
log_error_write(srv, __FILE__, __LINE__, "s",
"duplicate Host-header -> 400");
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "Sb",
"request-header:\n",
con->request.request);
}
return 0;
}
} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
con->request.http_if_modified_since = ds->value->ptr;
/* if dup, only the first one will survive */
if (!con->request.http_if_modified_since) {
con->request.http_if_modified_since = ds->value->ptr;
} else {
con->http_status = 400;
con->keep_alive = 0;
log_error_write(srv, __FILE__, __LINE__, "s",
"duplicate If-Modified-Since header -> 400");
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "Sb",
"request-header:\n",
con->request.request);
}
return 0;
}
} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
con->request.http_if_none_match = ds->value->ptr;
/* if dup, only the first one will survive */
if (!con->request.http_if_none_match) {
con->request.http_if_none_match = ds->value->ptr;
} else {
con->http_status = 400;
con->keep_alive = 0;
log_error_write(srv, __FILE__, __LINE__, "s",
"duplicate If-None-Match-header -> 400");
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "Sb",
"request-header:\n",
con->request.request);
}
return 0;
}
} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
/* bytes=.*-.* */
if (!con->request.http_range) {
/* bytes=.*-.* */
if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
NULL != strchr(ds->value->ptr+6, '-')) {
if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
NULL != strchr(ds->value->ptr+6, '-')) {
/* if dup, only the first one will survive */
con->request.http_range = ds->value->ptr + 6;
}
} else {
con->http_status = 400;
con->keep_alive = 0;
con->request.http_range = ds->value->ptr + 6;
log_error_write(srv, __FILE__, __LINE__, "s",
"duplicate Host-header -> 400");
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "Sb",
"request-header:\n",
con->request.request);
}
return 0;
}
}

82
tests/run-tests.pl

@ -2,7 +2,7 @@
use strict;
use IO::Socket;
use Test::More tests => 114;
use Test::More tests => 120;
my $testname;
@ -510,6 +510,12 @@ EOF
ok(handle_http == 0, 'Host missing');
print "\nLow-Level Response-Header Parsing - Content-Length:\n";
@request = ( <<EOF
GET /12345.html HTTP/1.0
@ -528,6 +534,14 @@ EOF
ok(handle_http == 0, 'Content-Length for text/plain');
print "\nLow-Level Response-Header Parsing - Location:\n";
@request = ( <<EOF
GET /dummydir HTTP/1.0
@ -544,6 +558,16 @@ EOF
ok(handle_http == 0, 'internal redirect in directory + querystring');
print "\nBasic Request-Handling\n";
@request = ( <<EOF
GET /foobar HTTP/1.0
@ -764,6 +788,62 @@ EOF
ok(handle_http == 0, 'larger headers');
@request = ( <<EOF
GET / HTTP/1.0
Host: www.example.org
Host: 123.example.org
EOF
);
@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
ok(handle_http == 0, 'Duplicate Host headers, Bug #25');
@request = ( <<EOF
GET / HTTP/1.0
Content-Length: 5
Content-Length: 4
EOF
);
@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
ok(handle_http == 0, 'Duplicate Content-Length headers');
@request = ( <<EOF
GET / HTTP/1.0
Content-Type: 5
Content-Type: 4
EOF
);
@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
ok(handle_http == 0, 'Duplicate Content-Type headers');
@request = ( <<EOF
GET / HTTP/1.0
Range: bytes=5-6
Range: bytes=5-9
EOF
);
@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
ok(handle_http == 0, 'Duplicate Range headers');
@request = ( <<EOF
GET / HTTP/1.0
If-None-Match: 5
If-None-Match: 4
EOF
);
@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
ok(handle_http == 0, 'Duplicate If-None-Match headers');
@request = ( <<EOF
GET / HTTP/1.0
If-Modified-Since: 5
If-Modified-Since: 4
EOF
);
@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
ok(handle_http == 0, 'Duplicate If-Modified-Since headers');

Loading…
Cancel
Save