Compare commits

...

31 Commits
4.1 ... master

Author SHA1 Message Date
Neale Pickett 16e32a6d59 break-fnord.sh work with busybox expr 2024-01-02 11:09:02 -07:00
Neale Pickett 49b1797df5
Merge pull request #2 from vaerksted/master
fix punctuation and typo; fixes #1
2022-12-15 16:01:05 -07:00
musvaage ce6b071398 punctuation and typo 2022-12-15 11:00:04 -06:00
Neale Pickett 2acfd4cf2d fnord 1.11 has all the same bugs 2020-12-07 14:06:23 -07:00
Neale Pickett d524cc02d5 Make github prettier 2018-09-14 16:17:30 +00:00
Neale Pickett 2e1a3eb867 Expose port 80 in dockerfile 2017-09-11 02:26:51 +00:00
Neale Pickett 48dbc0e8e0 Dockerize 2017-09-11 01:48:41 +00:00
Neale Pickett 673aed81a2 Modify dwarf planet link in README, so it's easier for humans to parse 2017-08-13 17:13:37 +00:00
Neale Pickett 855815099a Remove unused const days, months 2017-08-06 01:38:25 +00:00
Neale Pickett f63b3f1732 Version bump 2015-02-26 16:08:45 -07:00
Neale Pickett 6dd03561d6 Add stunnel logging test (duh) 2015-02-26 16:08:05 -07:00
Neale Pickett 48bb066488 Haha, I was generating that variable 2015-02-26 16:06:13 -07:00
Neale Pickett 77c3ed33dd Better way to do stunnel addr 2015-02-26 16:04:43 -07:00
Neale Pickett 86a75813e3 Use stunnel-provided combined addr 2015-02-26 16:01:56 -07:00
Neale Pickett c3ddfae1ff 2nd pass at stunnel vars 2015-02-26 15:59:51 -07:00
Neale Pickett bdb9f0ac05 Merge branch 'master' of woozle.org:projects/net/eris 2015-02-26 15:47:44 -07:00
Neale Pickett b3c4786482 Also work with stunnel 2015-02-26 15:47:37 -07:00
Neale Pickett 9de87a3e36 Add .webm 2014-12-19 22:45:18 +00:00
Neale Pickett ecad076ec6 Fix regression test 2014-12-08 14:37:54 -07:00
Neale Pickett 86757101eb Super dumb CONNECT handling 2014-12-08 14:26:48 -07:00
Neale Pickett 68452c56fa Tabify 2014-11-19 23:50:26 +00:00
Neale Pickett aab1b7496b Update to reflect ancient sslio 2014-11-19 23:49:48 +00:00
Neale Pickett 6121939bf0 Merge branch 'master' of /home/neale/projects/net/eris 2014-10-25 04:27:38 +00:00
Neale Pickett 7a4ac95441 Output blank line in badrequest 2014-10-25 04:27:21 +00:00
Neale Pickett 76c46f481e Oops, unrenamed a variable 2014-06-23 16:17:55 -06:00
Neale Pickett c329e9ad8a A couple bugfixes 2014-06-23 16:15:32 -06:00
Neale Pickett 8cb25b363d We do not do NPH either 2014-06-23 13:33:35 -06:00
Neale Pickett 502347d9df Oops, we do not do Accept 2014-06-23 13:29:44 -06:00
Neale Pickett 0b4f892169 More README expansion 2014-03-11 18:03:43 +00:00
Neale Pickett 297d6ec919 Describe Eris 2014-03-11 17:49:35 +00:00
Neale Pickett c968d41b16 Updated README 2014-03-11 17:39:36 +00:00
13 changed files with 695 additions and 475 deletions

18
CHANGES
View File

@ -1,3 +1,19 @@
fix punctuation and typo
4.4:
Also log when called from stunnel
4.3.1:
Add .webm mime type
4.3:
Very stupid CONNECT handling mechanism.
4.2:
Remove some bugs in CGI's "Status:" code (reported by Alyssa Milburn).
Make extract_header_field less fragile (reported by Alyssa Milburn).
Possibly fix fake_sendfile (reported by Alyssa Milburn).
4.1:
Fix 0.9 not detected with query_string (Alyssa Milburn).
@ -141,7 +157,7 @@
Olaf: I changed my initial CGI-interface to NOT use the filesystem but
two pipes.
Add whole-host redirect (see README)
Olaf: added direcory-lists and "index.cgi" support (normal CGI only !
Olaf: added directory-lists and "index.cgi" support (normal CGI only !
"nph-index.cgi" is not supported). Fixed some problematic parts in the
CGI-interface (\n -> \r\n converter for http-header and CGI crash
handling)

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM alpine
RUN apk --no-cache add s6-networking
RUN apk --no-cache add build-base
COPY . /usr/local/src/eris
RUN make -C /usr/local/src/eris
RUN cp /usr/local/src/eris/eris /usr/bin
RUN rm -rf /usr/local/src/eris
RUN apk --no-cache del build-base
RUN addgroup -S -g 800 www
RUN adduser -S -u 800 -G www www
RUN mkdir /www
WORKDIR /www
EXPOSE 80
CMD ["s6-tcpserver", "-u", "80", "-g", "80", "0.0.0.0", "80", "/usr/bin/eris", "-."]

34
HTTPS.md Normal file
View File

@ -0,0 +1,34 @@
SSL with eris
=============
Eris does not care what transport is in use: that job is left to the invoking
program (e.g. tcpserver).
In the past you could use `sslio` with `tcpsvd`,
but `sslio` has not been updated in a long time,
and won't work with (at least) Chrome 39.
I recommend using stunnel,
which also works with IPv6.
You can invoke it like so:
#! /bin/sh
cd /srv/www
HTTPS=enabled; export HTTPS
exec stunnel -fd 3 3<<EOD
foreground = yes
setuid = http
setgid = http
debug = 4
[https]
accept = ::443
cert = /path/to/yourserver.crt
key = /path/to/yourserver.key
exec = /path/to/eris
execargs = eris -c
EOD
I set the `HTTPS` environment variable,
so CGI can tell whether or not its connection is secure.

81
README
View File

@ -1,81 +0,0 @@
Eris HTTPD is a part of Dirtbags Capture The Flag
(http://dirtbags.net/ctf/). As I was adding more and more patches
against fnord 1.10 (http://www.fefe.de/), I decided to fork fnord into
a new project. Fnord's author approved of the fork.
Significant differences between eris and fnord are:
* command-line arguments instead of compile-time defines
* eliminated use of libowfat
* no build dependency of dietlibc
* elimination of "old style symlink handling"
* elimination of user switching (you can use tcpserver -[ug])
* elimination of chroot code (you can use chroot)
* several bugfixes (sent to the fnord mail list)
* ignores Accept header (fnord does too)
----
Usage:
tcpserver -v -RHl localhost -u 1234 -g 1234 0 80 ./httpd
Will log to stderr in the form
127.0.0.1 200 23 localhost Links_(0.96;_Unix) none /index.html
where 127.0.0.1 is the client IP, 200 is the HTTP exit code, 23 is the
size of the content that was served (or 0 for unsuccessful exit codes),
localhost is the Host: header (the virtual host), the next token is the
user agent with spaces replaced by underscores, the next token (none) is
the Referer HTTP header or "none" if none was given, and the rest of
each line is the decoded requested URL.
eris does simple virtual hosting. If the Host: HTTP header is there,
eris will try to chdir to a directory of that name, i.e. if the client
asks for "/" on host "www.fefe.de", eris will look for
"www.fefe.de/index.html". Eris will also try the directory "default"
if no specific directory for the virtual host was there. If the
directory is a dangling symlink, eris will redirect the whole site.
Examples:
lrwxrwxrwx 1 leitner users 19 May 5 01:09 www.foo.de -> http://www.baz.de/
lrwxrwxrwx 1 leitner users 20 May 5 01:12 www.bar.de -> =http://www.baz.de/
http://www.foo.de/blub.html will be redirected to http://www.baz.de/blub.html.
http://www.bar.de/blub.html will be redirected to http://www.baz.de/.
eris implements el-cheapo HTTP ranges (only byte ranges and only of the
form x-y, not multiple ranges).
eris implements content type matching and Accepts: parsing, but the
content type table is compiled in, i.e. to change it, you have to change
the source code. Shouldn't be a problem because you _have_ the source
code ;)
eris implements HTTP redirection. If a file is not found, but a
dangling symlink is there under the same name, eris will issue a
redirection to the contents of that symlink. To be RFC compliant, the
symlink must point to a full URL, i.e.
ln -s ftp://foobar.math.fu-berlin.de/pub/dietlibc/dietlibc-0.11.tar.bz2 dietlibc-0.11.tar.bz2
eris will change dots at the start of file or directory names to colons
in the query before trying to answer them.
eris understands and implements keep-alive connections.
eris will use sendfile on Linux to enable zero-copy TCP.
If eris is given the -a option, it look for a file named ".http-auth"
in the root of the host directory. If it's found, eris will run it as
".http-auth $host $url" with the environment variable
"HTTP_AUTHORIZATION" set to the "Authorization" header sent by the
client. If the program returns 0, access will be granted; if it
returns 1, eris will return a 401 response.
If eris is given the -c option, it will regard files
whose names end with ".cgi" as CGI programs and try to execute them.
CGI programs starting with "nph-" will be handled as no-parse-header
CGIs. Please see http://hoohoo.ncsa.uiuc.edu/cgi/interface.html for the
CGI specification.

View File

@ -1,26 +0,0 @@
SSL with eris
=============
Eris does not care what transport is in use: that job is left to the invoking
program (eg. tcpserver).
Gerrit Pape's `ipsvd` package comes with two programs for running SSL daemons:
`sslsvd` and `sslio`. At the time of this writing, however, Gerrit's `ipsvd`
has no support for IPv6. Busybox `ipsvd`, and `ucspi-tcp-ipv6`, both do
support IPv6.
Here is how you can support SSL *and* IPv6:
cd /srv/www
HTTPS=enabled; export HTTPS
exec tcpserver -H -R 0 443 \
/usr/bin/sslio -u nobody:ssl-cert -U www-data \
-C /path/to/mydomain.crt -K /path/to/mydomain.key \
/service/httpd/eris -c
This uses `tcpserver` to listen for and accept TCP4 and TCP6 connections.
These connections are then handed to `sslio`, which drops permissions to
`nobody:ssl-cert` and starts speaking SSL to `eris` running as `www-data`.
I like to set the `HTTPS` environment variable also, so CGI can tell whether or
not its connection is secure.

105
README.md Normal file
View File

@ -0,0 +1,105 @@
About
=====
Eris is an HTTP/1.1 web server with CGI.
It is very fast,
uses very little memory,
and has a tiny codebase which has been audited at least twice by gray-hat hackers.
It relies on an external program,
such as tcpserver or netcat,
to handle networking,
and expects to be run once for every connection.
This may sound horrible,
but it's actually pretty quick,
especially since this architecture makes it trivial to use the
`sendfile` call in Linux
(added in 2003 as a reaction to Apache losing to IIS in benchmarks),
which sends an open file directly to a socket,
without having to context switch into userspace.
It conforms to the parts of HTTP/1.1 that appear to be important to clients.
I have not found any HTTP/1.1 clients which have trouble with Eris,
including curl, which breaks with fnord (the reason I began work on Eris).
Eris HTTPD is a part of [Dirtbags Capture The Flag](http://dirtbags.net/ctf/).
After many patches against [fnord 1.10](http://www.fefe.de/),
I decided to fork fnord into a new project.
Fnord's author approved of the fork.
Differences with fnord
======================
Significant differences between eris and fnord are:
* command-line arguments instead of compile-time defines
* eliminated use of libowfat
* no build dependency of dietlibc
* elimination of "old style symlink handling"
* elimination of user switching (you can use tcpserver -[ug])
* elimination of chroot code (you can use chroot)
* several bugfixes (sent to the fnord mail list)
* ignores Accept header (fnord also ignores it, but claims not to)
Usage
=====
Start with:
tcpserver -v -RHl localhost -u 1234 -g 1234 0 80 ./eris
There are many other ways to start eris.
For example, you can run an HTTPS server with stunnel.
You just need something that launches eris with stdin and stdout connected to the client.
Logging
-------
Will log to stderr in the form
127.0.0.1 200 23 localhost Links_(0.96;_Unix) none /index.html
where 127.0.0.1 is the client IP, 200 is the HTTP exit code,
23 is the size of the content that was served (or 0 for unsuccessful exit codes),
localhost is the Host: header (the virtual host),
the next token is the user agent with spaces replaced by underscores,
the next token (none) is the Referer HTTP header or "none" if none was given,
and the rest of each line is the decoded requested URL.
Features
--------
eris does simple virtual hosting. If the `Host:` HTTP header is there,
eris will try to chdir to a directory of that name, i.e. if the client
asks for "/" on host "www.fefe.de", eris will look for
"www.fefe.de/index.html". Eris will also try the directory "default"
if no specific directory for the virtual host was there.
eris implements el-cheapo HTTP ranges (only byte ranges and only of the
form x-y, not multiple ranges).
eris will change dots at the start of file or directory names to colons
in the query before trying to answer them.
eris understands and implements keep-alive connections.
eris will use sendfile on Linux to enable zero-copy TCP.
If eris is given the -c option, it will regard files
whose names end with ".cgi" as CGI programs and try to execute them.
Please see <http://hoohoo.ncsa.uiuc.edu/cgi/interface.html> for the CGI specification.
About The Name
==============
[Eris](http://en.wikipedia.org/wiki/Eris_%28dwarf_planet%29)
is the most massive (heaviest) dwarf planet in the solar system.
It's heavier than Pluto!
Its discovery is what spurred astronomers to finally define the word "planet",
which resulted in Pluto being classified a dwarf planet.
Otherwise, we would have to count Eris as a tenth planet.

View File

@ -1,9 +1,9 @@
#! /bin/sh
## Breaking fnord 1.10
## Breaking fnord 1.11
if [ "$1" = "clean" ]; then
rm -rf fnord-1.10
rm -rf fnord-1.11
fi
# Set HTTPD= to test something else
@ -14,6 +14,7 @@ case ${HTTPD:=./fnord} in
;;
esac
tests=0
title() {
printf "%-50s: " "$1"
tests=$(expr $tests + 1)
@ -36,16 +37,16 @@ d () {
}
if [ ! -f fnord-1.10.tar.bz2 ]; then
wget http://www.fefe.de/fnord/fnord-1.10.tar.bz2
if [ ! -f fnord-1.11.tar.bz2 ]; then
wget http://www.fefe.de/fnord/fnord-1.11.tar.bz2
fi
if [ ! -f fnord-1.10/httpd.c ]; then
rm -rf fnord-1.10
bzcat fnord-1.10.tar.bz2 | tar xf -
if [ ! -f fnord-1.11/httpd.c ]; then
rm -rf fnord-1.11
bzcat fnord-1.11.tar.bz2 | tar xf -
fi
cd fnord-1.10
cd fnord-1.11
# Comment this out if you want to build with diet libc
make DIET=

View File

@ -5,5 +5,5 @@ a little easier.
Quite a lot of web software these days is written to work with
Apache and nothing else. PHP is a notable example: even PHP-CGI,
as shipped on Debian, requires special environment variables that
only Apache sets, and doesn't work with eg. mathopd, boa, busybox
only Apache sets, and doesn't work with, e.g. mathopd, boa, busybox
httpd, or eris.

826
eris.c

File diff suppressed because it is too large Load Diff

1
mime.c
View File

@ -19,6 +19,7 @@ static struct mimeentry {
"jpeg", "image/jpeg"}, {
"jpg", "image/jpeg"}, {
"svg", "image/svg+xml"}, {
"webm", "video/webm"}, {
"mpeg", "video/mpeg"}, {
"mpg", "video/mpeg"}, {
"avi", "video/x-msvideo"}, {

View File

@ -75,7 +75,7 @@ extract_header_field(char *buf, char **val, int cgi)
}
}
for (; (buf[len-1] == '\n') || (buf[len-1] == '\r'); len -= 1);
for (; (len > 0) && ((buf[len-1] == '\n') || (buf[len-1] == '\r')); len -= 1);
buf[len] = 0;
return len;

34
test.sh
View File

@ -4,6 +4,10 @@
: ${HTTPD_CGI:=./eris -c}
: ${HTTPD_IDX:=./eris -d}
tests=0
successes=0
failures=0
H () {
section="$*"
printf "\n%-20s " "$*"
@ -64,7 +68,18 @@ chmod +x default/redir.cgi
cat <<'EOD' > default/status.cgi
#! /bin/sh
echo "Status: 300 wat"
case "$PATH_INFO" in
/empty)
echo "Status"
exit 0
;;
/nostat)
echo "Status: "
;;
*)
echo "Status: 300 wat"
;;
esac
echo "Merf: merf"
echo
echo "james"
@ -127,6 +142,10 @@ title "Logging busybox"
(printf 'GET /index.html HTTP/1.1\r\nHost: host\r\n\r\n' |
PROTO=TCP TCPREMOTEADDR=[::1]:8765 $HTTPD >/dev/null) 2>&1 | grep -Fxq '[::1]:8765 200 6 host (null) (null) /index.html' && pass || fail
title "Logging stunnel"
(printf 'GET /index.html HTTP/1.1\r\nHost: host\r\n\r\n' |
REMOTE_HOST=::1 REMOTE_PORT=8765 $HTTPD >/dev/null) 2>&1 | grep -Fxq '::1:8765 200 6 host (null) (null) /index.html' && pass || fail
H "Options"
@ -240,7 +259,13 @@ title "Redirect"
printf 'GET /redir.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | grep -Fq 'Location: http://example.com/froot' && pass || fail
title "Status"
printf 'GET /status.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '^HTTP/1.0 300 wat#%' && pass || fail
printf 'GET /status.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>&1 | d | grep -q '^HTTP/1.0 300 wat#%.*.null. 300 6' && pass || fail
title "Status bug"
printf 'GET /status.cgi/empty HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '^HTTP/1.0 500 ' && pass || fail
title "No status"
printf 'GET /status.cgi/nostat HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '^HTTP/1.0 500 ' && pass || fail
H "Timeouts"
@ -249,6 +274,11 @@ title "Read timeout"
(sleep 2.1; printf 'GET / HTTP/1.0\r\n\r\n') | $HTTPD 2>/dev/null | grep -q '.' && fail || pass
H "CONNECT handler"
title "Basic test"
printf 'CONNECT /etc HTTP/1.1\r\n\r\n' | $HTTPD -o /bin/ls | grep -q passwd && pass || fail
H "fnord bugs"

View File

@ -40,9 +40,6 @@
#include <string.h>
#include "timerfc.h"
static const char days[] = "SunMonTueWedThuFriSat";
static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
time_t
timerfc(const char *s)
{