core-request.t 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #!/usr/bin/env perl
  2. BEGIN {
  3. # add current source dir to the include-path
  4. # we need this for make distcheck
  5. (my $srcdir = $0) =~ s,/[^/]+$,/,;
  6. unshift @INC, $srcdir;
  7. }
  8. use strict;
  9. use IO::Socket;
  10. use Test::More tests => 36;
  11. use LightyTest;
  12. my $tf = LightyTest->new();
  13. my $t;
  14. ok($tf->start_proc == 0, "Starting lighttpd") or die();
  15. ## Low-Level Request-Header Parsing - URI
  16. $t->{REQUEST} = ( <<EOF
  17. GET /index%2ehtml HTTP/1.0
  18. EOF
  19. );
  20. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  21. ok($tf->handle_http($t) == 0, 'URL-encoding');
  22. $t->{REQUEST} = ( <<EOF
  23. GET /index.html%00 HTTP/1.0
  24. EOF
  25. );
  26. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
  27. ok($tf->handle_http($t) == 0, 'URL-encoding, %00');
  28. ## Low-Level Request-Header Parsing - Host
  29. $t->{REQUEST} = ( <<EOF
  30. GET / HTTP/1.0
  31. Host: www.example.org
  32. EOF
  33. );
  34. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  35. ok($tf->handle_http($t) == 0, 'hostname');
  36. $t->{REQUEST} = ( <<EOF
  37. GET / HTTP/1.0
  38. Host: 127.0.0.1
  39. EOF
  40. );
  41. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  42. ok($tf->handle_http($t) == 0, 'IPv4 address');
  43. $t->{REQUEST} = ( <<EOF
  44. GET / HTTP/1.0
  45. Host: [::1]
  46. EOF
  47. );
  48. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  49. ok($tf->handle_http($t) == 0, 'IPv6 address');
  50. $t->{REQUEST} = ( <<EOF
  51. GET / HTTP/1.0
  52. Host: www.example.org:80
  53. EOF
  54. );
  55. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  56. ok($tf->handle_http($t) == 0, 'hostname + port');
  57. $t->{REQUEST} = ( <<EOF
  58. GET / HTTP/1.0
  59. Host: 127.0.0.1:80
  60. EOF
  61. );
  62. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  63. ok($tf->handle_http($t) == 0, 'IPv4 address + port');
  64. $t->{REQUEST} = ( <<EOF
  65. GET / HTTP/1.0
  66. Host: [::1]:80
  67. EOF
  68. );
  69. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  70. ok($tf->handle_http($t) == 0, 'IPv6 address + port');
  71. $t->{REQUEST} = ( <<EOF
  72. GET / HTTP/1.0
  73. Host: ../123.org
  74. EOF
  75. );
  76. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  77. ok($tf->handle_http($t) == 0, 'directory traversal');
  78. $t->{REQUEST} = ( <<EOF
  79. GET / HTTP/1.0
  80. Host: .jsdh.sfdg.sdfg.
  81. EOF
  82. );
  83. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  84. ok($tf->handle_http($t) == 0, 'leading and trailing dot');
  85. $t->{REQUEST} = ( <<EOF
  86. GET / HTTP/1.0
  87. Host: jsdh.sfdg.sdfg.
  88. EOF
  89. );
  90. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  91. ok($tf->handle_http($t) == 0, 'trailing dot is ok');
  92. $t->{REQUEST} = ( <<EOF
  93. GET / HTTP/1.0
  94. Host: .jsdh.sfdg.sdfg
  95. EOF
  96. );
  97. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  98. ok($tf->handle_http($t) == 0, 'leading dot');
  99. $t->{REQUEST} = ( <<EOF
  100. GET / HTTP/1.0
  101. Host: jsdh..sfdg.sdfg
  102. EOF
  103. );
  104. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  105. ok($tf->handle_http($t) == 0, 'two dots');
  106. $t->{REQUEST} = ( <<EOF
  107. GET / HTTP/1.0
  108. Host: jsdh.sfdg.sdfg:asd
  109. EOF
  110. );
  111. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  112. ok($tf->handle_http($t) == 0, 'broken port-number');
  113. $t->{REQUEST} = ( <<EOF
  114. GET / HTTP/1.0
  115. Host: jsdh.sfdg.sdfg:-1
  116. EOF
  117. );
  118. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  119. ok($tf->handle_http($t) == 0, 'negative port-number');
  120. $t->{REQUEST} = ( <<EOF
  121. GET / HTTP/1.0
  122. Host: :80
  123. EOF
  124. );
  125. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  126. ok($tf->handle_http($t) == 0, 'port given but host missing');
  127. $t->{REQUEST} = ( <<EOF
  128. GET / HTTP/1.0
  129. Host: .jsdh.sfdg.:sdfg.
  130. EOF
  131. );
  132. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  133. ok($tf->handle_http($t) == 0, 'port and host are broken');
  134. $t->{REQUEST} = ( <<EOF
  135. GET / HTTP/1.0
  136. Host: a.b-c.d123
  137. EOF
  138. );
  139. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  140. ok($tf->handle_http($t) == 0, 'allowed characters in host-name');
  141. $t->{REQUEST} = ( <<EOF
  142. GET / HTTP/1.0
  143. Host: -a.c
  144. EOF
  145. );
  146. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  147. ok($tf->handle_http($t) == 0, 'leading dash');
  148. $t->{REQUEST} = ( <<EOF
  149. GET / HTTP/1.0
  150. Host: .
  151. EOF
  152. );
  153. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  154. ok($tf->handle_http($t) == 0, 'dot only');
  155. $t->{REQUEST} = ( <<EOF
  156. GET / HTTP/1.0
  157. Host: a192.168.2.10:1234
  158. EOF
  159. );
  160. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  161. ok($tf->handle_http($t) == 0, 'broken IPv4 address - non-digit');
  162. $t->{REQUEST} = ( <<EOF
  163. GET / HTTP/1.0
  164. Host: 192.168.2:1234
  165. EOF
  166. );
  167. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  168. ok($tf->handle_http($t) == 0, 'broken IPv4 address - too short');
  169. ## Low-Level Request-Header Parsing - Content-Length
  170. $t->{REQUEST} = ( <<EOF
  171. GET /index.html HTTP/1.0
  172. Content-Length: -2
  173. EOF
  174. );
  175. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  176. ok($tf->handle_http($t) == 0, 'negative Content-Length');
  177. $t->{REQUEST} = ( <<EOF
  178. POST /12345.txt HTTP/1.0
  179. Host: 123.example.org
  180. Content-Length: 2147483648
  181. EOF
  182. );
  183. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 413 } ];
  184. ok($tf->handle_http($t) == 0, 'Content-Length > max-request-size');
  185. $t->{REQUEST} = ( <<EOF
  186. POST /12345.txt HTTP/1.0
  187. Host: 123.example.org
  188. Content-Length:
  189. EOF
  190. );
  191. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 411 } ];
  192. ok($tf->handle_http($t) == 0, 'Content-Length is empty');
  193. print "\nLow-Level Request-Header Parsing - HTTP/1.1\n";
  194. $t->{REQUEST} = ( <<EOF
  195. GET / HTTP/1.1
  196. EOF
  197. );
  198. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400 } ];
  199. ok($tf->handle_http($t) == 0, 'Host missing');
  200. print "\nContent-Type\n";
  201. $t->{REQUEST} = ( <<EOF
  202. GET /image.jpg HTTP/1.0
  203. EOF
  204. );
  205. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
  206. ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg');
  207. $t->{REQUEST} = ( <<EOF
  208. GET /image.JPG HTTP/1.0
  209. EOF
  210. );
  211. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
  212. ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg (upper case)');
  213. $t->{REQUEST} = ( <<EOF
  214. GET /a HTTP/1.0
  215. EOF
  216. );
  217. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'application/octet-stream' } ];
  218. ok($tf->handle_http($t) == 0, 'Content-Type - unknown');
  219. $t->{REQUEST} = ( <<EOF
  220. GET HTTP/1.0
  221. EOF
  222. );
  223. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
  224. ok($tf->handle_http($t) == 0, 'empty request-URI');
  225. $t->{REQUEST} = ( <<EOF
  226. GET /Foo.txt HTTP/1.0
  227. EOF
  228. );
  229. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  230. ok($tf->handle_http($t) == 0, 'uppercase filenames');
  231. $t->{REQUEST} = ( <<EOF
  232. GET / HTTP/1.0
  233. Location: foo
  234. Location: foobar
  235. baz
  236. EOF
  237. );
  238. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  239. ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping');
  240. $t->{REQUEST} = ( <<EOF
  241. GET / HTTP/1.0
  242. Location:
  243. Location: foobar
  244. baz
  245. EOF
  246. );
  247. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  248. ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping - test 2');
  249. $t->{REQUEST} = ( <<EOF
  250. GET / HTTP/1.0
  251. A:
  252. Location: foobar
  253. baz
  254. EOF
  255. );
  256. $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
  257. ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping - test 3');
  258. ok($tf->stop_proc == 0, "Stopping lighttpd");