Neale Pickett
·
2024-01-02
break-fnord.sh
1#! /bin/sh
2
3## Breaking fnord 1.11
4
5if [ "$1" = "clean" ]; then
6 rm -rf fnord-1.11
7fi
8
9# Set HTTPD= to test something else
10case ${HTTPD:=./fnord} in
11 *fnord)
12 : ${HTTPD_IDX:=$HTTPD-idx}
13 : ${HTTPD_CGI:=$HTTPD-cgi}
14 ;;
15esac
16
17tests=0
18title() {
19 printf "%-50s: " "$1"
20 tests=$(expr $tests + 1)
21}
22
23successes=0
24pass () {
25 echo 'pass'
26 successes=$(expr $successes + 1)
27}
28
29failures=0
30fail () {
31 echo 'fail'
32 failures=$(expr $failures + 1)
33}
34
35d () {
36 tr '\r\n' '#%'
37}
38
39
40if [ ! -f fnord-1.11.tar.bz2 ]; then
41 wget http://www.fefe.de/fnord/fnord-1.11.tar.bz2
42fi
43
44if [ ! -f fnord-1.11/httpd.c ]; then
45 rm -rf fnord-1.11
46 bzcat fnord-1.11.tar.bz2 | tar xf -
47fi
48
49cd fnord-1.11
50
51# Comment this out if you want to build with diet libc
52make DIET=
53
54if [ ! -d default ]; then
55 mkdir default
56 echo james > default/index.html
57 touch default/a
58 cat <<EOD > default/a.cgi
59#! /bin/sh
60echo 'Content-type: text/plain'
61ls / > /dev/null # delay a little
62set
63EOD
64 chmod +x default/a.cgi
65 mkdir empty:80
66fi
67
68cat <<EOD
69
70
71HTTPD: $HTTPD
72CGI: $HTTPD_CGI
73IDX: $HTTPD_IDX
74-----------------------------------------
75EOD
76
77# 1. Should return directory listing of /; instead segfaults
78title "Directory indexing of /"
79printf 'GET / HTTP/1.0\r\nHost: empty\r\n\r\n' | $HTTPD_IDX 2>/dev/null | grep -q 200 && pass || fail
80
81# 2. Should output \r\n\r\n; instead outputs \r\n\n
82title "CGI output bare newlines"
83printf 'GET /a.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '#%#%' && pass || fail
84
85# 3. Should process both requests; instead drops second
86title "Multiple requests in one packet"
87printf 'GET / HTTP/1.1\r\nHost: a\r\nConnection: keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost: a\r\nConnection: keep-alive\r\n\r\n' | $HTTPD 2>/dev/null | grep -c '^HTTP/1.' | grep -q 2 && pass || fail
88
89# 4. Should return 406 Not Acceptable; instead ignores Accept header
90title "Accept header"
91printf 'GET / HTTP/1.0\r\nAccept: nothing\r\n\r\n' | $HTTPD 2>/dev/null | grep 406 && pass || fail
92
93# 5. Should serve second request as default MIME-Type (text/plain); instead uses previous mime type
94title "Second MIME-Type"
95(printf 'GET / HTTP/1.1\r\nHost: a\r\nConnection: keep-alive\r\n\r\n'
96 ls / > /dev/null # Delay required to work around test #3
97 printf 'GET /a HTTP/1.1\r\nHost: a\r\nConnection: keep-alive\r\n\r\n') | $HTTPD 2>/dev/null | grep -q 'text/plain\|application/octet-stream' && pass || fail
98
99# 6. Should consume POST data; instead tries to read POST data as second request
100title "POST to static HTML"
101(printf 'POST / HTTP/1.1\r\nHost: a\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nContent-Length: 1\r\n\r\n';
102 ls / > /dev/null
103 printf 'aPOST / HTTP/1.1\r\nHost: a\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nContent-Length: 1\r\n\r\na') | $HTTPD 2>/dev/null | grep -c '200 OK' | grep -q 2 && pass || fail
104
105# 7. HTTP/1.1 should default to keepalive; instead connection is closed
106title "HTTP/1.1 default keepalive"
107(printf 'GET / HTTP/1.1\r\nHost: a\r\n\r\n'
108 ls / >/dev/null
109 printf 'GET / HTTP/1.1\r\nHost: a\r\n\r\n') | $HTTPD 2>/dev/null | grep -c '^HTTP/' | grep -q 2 && pass || fail
110
111# 8. Should parse "Thursday"; instead assumes all day names are 6 characters long
112title "RFC 850 Date"
113printf 'GET / HTTP/1.0\r\nIf-Modified-Since: Thursday, 27-Feb-30 12:12:12 GMT\r\n\r\n' | $HTTPD 2>/dev/null | grep -q '304 Not Changed' && pass || fail
114
115# 9. Should set PATH_INFO to /; instead sets it to /index.html
116title "PATH_INFO=/"
117printf 'GET /a.cgi/ HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | grep -Eq 'PATH_INFO=.?/.?$' && pass || fail
118
119cat <<EOD
120-----------------------------------------
121$successes of $tests tests passed ($failures failed).
122EOD
123
124exit $failures