|
|
|
#! /usr/bin/perl -w
|
|
|
|
BEGIN {
|
|
|
|
# add current source dir to the include-path
|
|
|
|
# we need this for make distcheck
|
|
|
|
(my $srcdir = $0) =~ s#/[^/]+$#/#;
|
|
|
|
unshift @INC, $srcdir;
|
|
|
|
}
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use IO::Socket;
|
|
|
|
use Test::More tests => 28;
|
|
|
|
use LightyTest;
|
|
|
|
|
|
|
|
my $tf = LightyTest->new();
|
|
|
|
my $t;
|
|
|
|
|
|
|
|
ok($tf->start_proc == 0, "Starting lighttpd") or die();
|
|
|
|
|
|
|
|
## Low-Level Request-Header Parsing - URI
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET /index%2ehtml HTTP/1.0
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'URL-encoding');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET /index.html%00 HTTP/1.0
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'URL-encoding, %00');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Low-Level Request-Header Parsing - Host
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: www.example.org
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'hostname');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: 127.0.0.1
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'IPv4 address');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: [::1]
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'IPv6 address');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: www.example.org:80
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'hostname + port');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: 127.0.0.1:80
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'IPv4 address + port');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: [::1]:80
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'IPv6 address + port');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: ../123.org
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'directory traversal');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: .jsdh.sfdg.sdfg.
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'leading and trailing dot');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: jsdh.sfdg.sdfg.
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'trailing dot is ok');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: .jsdh.sfdg.sdfg
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'leading dot');
|
|
|
|
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: jsdh..sfdg.sdfg
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'two dots');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: jsdh.sfdg.sdfg:asd
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'broken port-number');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: jsdh.sfdg.sdfg:-1
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'negative port-number');
|
|
|
|
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: :80
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'port given but host missing');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: .jsdh.sfdg.:sdfg.
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'port and host are broken');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: a.b-c.d123
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'allowed characters in host-name');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: -a.c
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'leading dash');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: .
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'dot only');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: a192.168.2.10:1234
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'broken IPv4 address - non-digit');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.0
|
|
|
|
Host: 192.168.2:1234
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'broken IPv4 address - too short');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Low-Level Request-Header Parsing - Content-Length
|
|
|
|
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET /index.html HTTP/1.0
|
|
|
|
Content-Length: -2
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'negative Content-Length');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
POST /12345.txt HTTP/1.0
|
|
|
|
Host: 123.example.org
|
|
|
|
Content-Length: 2147483648
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 413 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'Content-Length > max-request-size');
|
|
|
|
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
POST /12345.txt HTTP/1.0
|
|
|
|
Host: 123.example.org
|
|
|
|
Content-Length:
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 411 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'Content-Length is empty');
|
|
|
|
|
|
|
|
print "\nLow-Level Request-Header Parsing - HTTP/1.1\n";
|
|
|
|
$t->{REQUEST} = ( <<EOF
|
|
|
|
GET / HTTP/1.1
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
$t->{RESPONSE} = ( { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400 } );
|
|
|
|
ok($tf->handle_http($t) == 0, 'Host missing');
|
|
|
|
|
|
|
|
ok($tf->stop_proc == 0, "Stopping lighttpd");
|
|
|
|
|