Browse Source

forbid Content-Length for GET, HEAD or OPTIONS requests

allow duplicate If-Modified-Since headers if they are equal


git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@907 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/lighttpd-1.4.11
Jan Kneschke 16 years ago
parent
commit
580823f791
  1. 5
      NEWS
  2. 8
      src/connections.c
  3. 47
      src/request.c
  4. 40
      tests/request.t

5
NEWS

@ -7,10 +7,15 @@ NEWS
* added server.core-files option (sandy <sandy@meebo.com>)
* added docs for mod_status
* added mod_evasive to limit the number of connections by IP (<w1zzard@techpowerup.com>)
* added the power-magnet to mod_cml
* added framework for internal statistics
* fixed 100% cpu loops in mod_cgi ("sandy" <sjen@cs.stanford.edu>)
* fixed handling for secure-download.timeout (jamis@37signals.com)
* fixed IE bug in content-charset in the output of mod_dirlisting (sniper@php.net)
* fixed typos and language in the docs (ryan-2005@ryandesign.com)
* fixed assertion in mod_cgi on HEAD request is Content-Length (<sandy@meebo.com>)
* fixed handling if equal but duplicate If-Modified-Since request headers
- 1.4.8 - 2005-11-23

8
src/connections.c

@ -352,7 +352,13 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
case HTTP_METHOD_PROPPATCH:
break;
case HTTP_METHOD_OPTIONS:
if (con->uri.path->ptr[0] != '*') {
/*
* 400 is coming from the request-parser BEFORE uri.path is set
* 403 is from the response handler when noone else catched it
*
* */
if (con->uri.path->used &&
con->uri.path->ptr[0] != '*') {
response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
con->http_status = 200;

47
src/request.c

@ -815,9 +815,14 @@ 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("If-Modified-Since")))) {
/* if dup, only the first one will survive */
/* Proxies sometimes send dup headers
* if they are the same we ignore the second
* if not, we raise an error */
if (!con->request.http_if_modified_since) {
con->request.http_if_modified_since = ds->value->ptr;
} else if (0 == strcasecmp(con->request.http_if_modified_since,
ds->value->ptr)) {
/* ignore it if they are the same */
} else {
con->http_status = 400;
con->keep_alive = 0;
@ -963,22 +968,25 @@ int http_request_parse(server *srv, connection *con) {
return 0;
}
/* check if we have read post data */
if (con->request.http_method == HTTP_METHOD_POST
|| (con->request.http_method != HTTP_METHOD_GET
&& con->request.http_method != HTTP_METHOD_HEAD
&& con->request.http_method != HTTP_METHOD_OPTIONS
&& con_length_set)) {
#if 0
if (con->request.http_content_type == NULL) {
switch(con->request.http_method) {
case HTTP_METHOD_GET:
case HTTP_METHOD_HEAD:
case HTTP_METHOD_OPTIONS:
/* content-length is forbidden for those */
if (con_length_set) {
/* content-length is missing */
log_error_write(srv, __FILE__, __LINE__, "s",
"Content-Length request, but content-type not set");
"GET/HEAD/OPTIONS with content-length -> 400");
con->keep_alive = 0;
con->http_status = 400;
return 0;
}
#endif
if (con_length_set == 0) {
break;
case HTTP_METHOD_POST:
/* content-length is required for them */
if (!con_length_set) {
/* content-length is missing */
log_error_write(srv, __FILE__, __LINE__, "s",
"POST-request, but content-length missing -> 411");
@ -986,8 +994,17 @@ int http_request_parse(server *srv, connection *con) {
con->http_status = 411;
return 0;
}
break;
default:
/* the may have a content-length */
break;
}
/* check if we have read post data */
if (con_length_set) {
/* don't handle more the SSIZE_MAX bytes in content-length */
if (con->request.content_length > SSIZE_MAX) {
con->http_status = 413;

40
tests/request.t

@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
use Test::More tests => 29;
use Test::More tests => 33;
use LightyTest;
my $tf = LightyTest->new();
@ -300,7 +300,45 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'GET, Range with range-requests-disabled');
$t->{REQUEST} = ( <<EOF
GET / HTTP/1.0
Content-Length: 4
1234
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'GET with Content-Length');
$t->{REQUEST} = ( <<EOF
OPTIONS / HTTP/1.0
Content-Length: 4
1234
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'OPTIONS with Content-Length');
$t->{REQUEST} = ( <<EOF
HEAD / HTTP/1.0
Content-Length: 4
1234
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'HEAD with Content-Length');
$t->{REQUEST} = ( <<EOF
GET / HTTP/1.0
If-Modified-Since: Sun, 1970 Jan 01 00:00:01 GMT
If-Modified-Since: Sun, 1970 Jan 01 00:00:01 GMT
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'Duplicate If-Mod-Since, with equal timestamps');
ok($tf->stop_proc == 0, "Stopping lighttpd");
Loading…
Cancel
Save