Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Add version 20170201 of Bozohttpd |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b786821675919a4f5b0de762b51d71ad |
User & Date: | atomicules 2017-11-24 21:16:52 |
2021-05-19
| ||
09:43 | Create new branch named "upstream" check-in: ec9d46659f user: atomicules tags: upstream | |
2017-11-25
| ||
19:08 |
Initial work on setting Cache-Control headers
The bit that foxed me was understanding getopts and that the "h" needed a ":" This definitely and utterly sets a header. It doesn't seem that it's recognised - https://developers.google.com/speed/pagespeed/insights/ and here: - http://highloadtools.com/cachecontrol But what can you do? At the moment this just sets a header everywhere for everything being served. | |
2017-11-24
| ||
21:16 | Add version 20170201 of Bozohttpd check-in: b786821675 user: atomicules tags: trunk | |
21:05 | initial empty check-in check-in: 0fe8cd1d44 user: atomicules tags: trunk | |
Added CHANGES.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | $NetBSD: CHANGES,v 1.25 2017/01/31 14:33:54 mrg Exp $ changes in bozohttpd 20170201: o fix an infinite loop in cgi processing o fixes and clean up for the testsuite o no longer sends encoding header for compressed formats changes in bozohttpd 20160517: o add a bozo_get_version() function which returns the version number changes in bozohttpd 20160415: o add search-word support for CGI o fix a security issue in CGI suffix handler support which would allow remote code execution, from shm@netbsd.org o -C option supports now CGI scripts only changes in bozohttpd 20151028: o add CGI support for ~user translation (-E switch) o add redirects to ~user translation o fix bugs around ~user translation o add schema detection for absolute redirects o fixed few memory leaks o bunch of minor tweaks o removed -r support o smarter redirects changes in bozohttpd 20150320: o fix redirection handling o support transport stream (.ts) and video object (.vob) files o directory listings show correct file sizes for large files changes in bozohttpd 20140717: o properly handle SSL errors changes in bozohttpd 20140708: o fixes for virtual host support, from rajeev_v_pillai@yahoo.com o avoid printing double errors, from shm@netbsd.org o fix a security issue in basic HTTP authentication which would allow authentication to be bypassed, from shm@netbsd.org changes in bozohttpd 20140201: o support .svg files o fix a core dump when requests timeout changes in bozohttpd 20140102: o update a few content types o add support for directly calling lua scripts to handle processes, from mbalmer@netbsd.org o properly escape generated HTML o add authentication for redirections, from martin@netbsd.org o handle chained ssl certifications, from elric@netbsd.org o add basic support for gzipped files, from elric@netbsd.org o properly escape generated URIs changes in bozohttpd 20111118: o add -P <pidfile> option, from jmmv@netbsd.org o avoid crashes with http basic auth, from pooka@netbsd.org o add support for REDIRECT_STATUS variable, from tls@netbsd.org o support .mp4 files in the default map o directory indexes with files with : are now displayed properly, from reed@netbsd.org o allow -I option to be useful in non-inetd mode as well changes in bozohttpd 20100920: o properly fully disable multi-file mode for now o fix the -t and -U options when used without the -e option, broken since the library-ifcation o be explicit that logs go to the FTP facility in syslog o use scandir() with alphasort() for sorted directory lists, from moof o fix a serious error in vhost handling; "Host:.." would allow access to the next level directory from the virtual root directory, from seanb o fix some various non standard compile time errors, from rudolf o fix dynamic CGI content maps, from rudolf changes in bozohttpd 20100617: o fix some compile issues o fix SSL mode. from rtr o fix some cgi-bin issues, as seen with cvsweb o disable multi-file daemon mode for now, it breaks o return 404's instead of 403's when chdir of ~user dirs fail o remove "noreturn" attribute from bozo_http_error() that was causing incorrect runtime behaviour changes in bozohttpd 20100509: o major rework and clean up of internal interfaces. move the main program into main.c, the remaining parts are useable as library. add bindings for lua. by Alistair G. Crooks <agc@netbsd.org> o fix http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=566325 changes in bozohttpd 20090522: o avoid dying in daemon mode for some uncommon, but recoverable, errors o close leaking file descriptors for CGI and daemon mode o handle poll errors properly o don't try to handle more than one request per process yet o add subdirs for build "debug" and "small" versions o clean up a bad merge / duplicate code o make mmap() usage portable, fixes linux & ranges: support o document the -f option o daemon mode now serves 6 files per child changes in bozohttpd 20090417: o make bozohttpd internally more modular, preparing the way to handle more than one request per process o fix http-auth, set $REMOTE_USER not $REMOTEUSER. also fix cgi-bin with cvsweb, from Holger Weiss <holger@CIS.FU-Berlin.DE> o fix an uninitialised variable use in daemon mode o fix ssl mode with newer OpenSSL o mmap large files in manageable sizes so we can serve any size file o refactor url processing to handle query strings correctly for CGI from Sergey Katsev at Coyote Point o add If-Modified-Since support, from Joerg Sonnenberger <joerg@netbsd.org> o many more manual fixes, from NetBSD changes in bozohttpd 20080303: o fix some cgi header processing, from <thelsdj@gmail.com> o add simple Range: header processing, from <bad@bsd.de> o man page fixes, from NetBSD o clean up various parts, from NetBSD changes in bozohttpd 20060710: o prefix some function names with "bozo" o align directory indexing <hr> markers o clean up some code GCC4 grumbled about changes in bozohttpd 20060517: o don't allow "/.." or "../" files o don't write ":80" into urls for the http port o fix a fd leak when fork() fails o make directory indexing mode not look so ugly o build a text version of the manual page o make "make clean" work properly changes in bozohttpd 20050410: o fix some off-by-one errors from <roland.illig@gmx.de> o properly support nph- CGI o make content maps case insensitive o fix proto header merging to include the missing comma o major source reorganisation; most features are in separate files now o new -V flag that makes unknown virtualhosts use slashdir from <rumble@ephemeral.org> o HTTP/1.x protocol headers are now properly merged for CGI changes in bozohttpd 20040808: o CGI status is now properly handled (-a flag has been removed) o CGI file upload support works o %xy translations are no longer ever applied after the first '?', ala RFC2396. from lukem o daemon mode (-b) should no longer hang spinning forever if it sees no children. from lukem o new .bzabsredirect file support. from <martin@netbsd.org> o return a 404 error if we see %00 or %2f (/) o don't print 2 "200" headers for CGI o support .torrent files changes in bozohttpd 20040218: o new .bzredirect file support for sane directory redirection o new -Z option that enables SSL mode, from <rtr@eterna.com.au> o the -C option has been changed to take two explicit options, rather than a single option with a space separating the suffix and the interpreter. ``-C ".foo /path/to/bar"'' should now be written as ``-C .foo /path/to/bar'' o the -M option has been changed like -C and no longer requires or supports a single argument with space-separated options o with -a, still print the 200 OK. from <rtr@eterna.com.au> o with -r, if a .bzdirect file appears in a directory, allow direct access to this directory changes in bozohttpd 20031005: o fixes for basic authorisation. from <ecu@ipv42.net> o always display file size in directory index mode o add .xbel, .xml & .xsl -> text/xml mappings. from <wiz@danbala.ifoer.tuwien.ac.at> changes in bozohttpd 20030626: o fix a recent core dump when given no input o add new -r flag that ensures referrer is set to this host o fix several compile time errors with -DNO_CGIBIN_SUPPORT o fix some man page details. from lukem@wasabisystems.com o re-add a missing memset(), fixing a core dump. from lukem o support HTTP basic authorisation, disabled by default. from lukem o print the port number in redirects and errors. from lukem o only syslog the basename of the program. from lukem o add __attribute__() format checking. from lukem o fix cgibin SCRIPT_NAME to have a leading /. from zakj@nox.cx o simplify some code in -C to avoid a core dump. from lukem o add a .css -> css/text entry to the content_map[]. from zakj@nox.cx changes in bozohttpd 20030409: o -d without DEBUG enabled only prints one warning and continues o one can now define the C macro SERVER_SOFTWARE when building to change the Server: header and CGI variable of the same name o add new -s flag the force logging output to stderr. from zakj@nox.cx o add new -a flag for CGI bin that stops bozohttpd from outputting any HTTP reply, the CGI program must output these. from zakj@nox.cx o new REQUEST_URI and DATE_GMT environment variables for CGI. from zakj@nox.cx o add a "Makefile.boot" that should work with any make program o build on linux again o fix core dumps when using -C changes in bozohttpd 20030313: o deprecate -r flag; make this the default and silently ignore -r now o add support for file extentions to call CGI programs (from lukem) o add dynamic support to add new content map entries, allowing both new file types and non /cgi-bin CGI programs to be run with the new -C "suffix cgihandler" and -M "suffix type encoding encoding11" options o in -b mode, set the http date after accept() returns, not before we call accept() o in -b mode, bind all addresses found not just the first one o unsupport old hostname API o in -b mode, set the SO_REUSEADDR socket option (lukem) o allow -x (index.html) mode to work with CGI handlers changes in bozohttpd 20021106: o add .bz2 support o properly escape <, > and & in error messages, partly from Nicolas Jombart <ecu@mariejeanne.net> o new -H flag to hide .* files in directory index mode o fix buffer reallocation when parsing a request, to avoid overflowing the buffer with carriage returns (\r) o do not decode "%XY"-style cgi-bin data beyond the "?" changes in bozohttpd 5.15 (20020913): o add .ogg support -> `application/x-ogg' o fix CGI requests with "/" in the query part changes in bozohttpd 5.14 (20020823): o allow -X mode to work for "/" o work on systems without MADV_SEQUENTIAL o make a local cut-down copy of "queue.h" (fixes linux & solaris support at the very least) o portability fixes for pre-ipv6 socket api systems (eg, solaris 7) o portability fixes for missing _PATH_DEFPATH, LOG_FTP and __progname o better documentation on virtual host support changes in bozohttpd 5.13 (20020804): o support .mp3 files (type audio/mpeg) o use stat() to find out if something is a directory, for -X mode changes in bozohttpd 5.12 (20020803): o constification o fixes & enhancements for directory index mode (-X) changes in bozohttpd 5.11 (20020730): o more man page fixes from Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at> o de-K&R C-ification o fix Date: header for daemon mode o fix core dump when asking for /cgi-bin/ when CGI isn't configured o use a valid Server: header changes in bozohttpd 5.10 (20020710): - add freebsd support - fix a couple of header typos - many cgi-bin fixes from lukem@netbsd.org - add -T chrootdir and -U user, plus several minor other cleanups with signals and return values. from xs@kittenz.org - add -e that does not clear the environment for -T/-U - fix a formatting error noticed by ISIHARA Takanori <ishit@oak.dti.ne.jp> changes in bozohttpd 5.09 (20010922): - add a daemon mode - document how to use bozohttpd in netbsd inetd with more than 40 connections per minute and also with cgibin - man page fixes from wiz@netbsd.org changes in bozohttpd 5.08 (20010812): - add directory index generation support (-X) from ad@netbsd.org - add .pa as an alias for .pac - make server software version configurable (RFC) changes in bozohttpd 5.07 (20010610): - add .png support - new "-x index.html" flag to change default file - new "-p public_html" flag to change default ~user directory - fixes cgi-bin support and more from chuck@research.att.com - add many new content-types, now support most common ones changes in bozohttpd 5.06 (20000825): - add IPv6 suppor from itojun@iijlab.net - man page fixes from jlam@netbsd.org changes in bozohttpd 5.05 (20000815): - fix a virtual host bug, from kleink@netbsd.org changes in bozohttpd 5.04 (20000427): - fix virtual host support; URI takes precedence over Host: changes in bozohttpd 5.03 (20000427): - fix a bug with chdir() changes in bozohttpd 5.02 (20000426): - .pac spport from simonb changes in bozohttpd 5.01 (20000421): - .swf support - virtual hosting support |
Added Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | # $NetBSD: Makefile,v 1.26 2015/10/30 23:21:05 christos Exp $ # # $eterna: Makefile,v 1.30 2010/07/11 00:34:27 mrg Exp $ # # berkeley (netbsd) makefile. see Makefile.boot for other systems. # compile-time options are: # NO_DEBUG /* don't include debugging support */ # NO_USER_SUPPORT /* don't support /~user requests */ # NO_CGIBIN_SUPPORT /* don't support cgi-bin requests */ # NO_DIRINDEX_SUPPORT /* don't support directory indexing */ # NO_DAEMON_MODE /* don't support daemon mode */ # NO_DYNAMIC_CONTENT /* don't support dynamic content updates */ # NO_SSL_SUPPORT /* don't support ssl (https) */ # DO_HTPASSWD /* support .htpasswd files */ # NO_LUA_SUPPORT /* don't support Lua for dynamic content */ # # other system specific defines: # HAVE_NBUTIL_H /* netbsd compat is in <nbutil.h> # (don't forget to also enable -lnbutil) # # these are usually set via the "COPTS" variable, or some other method # for setting CFLAGS relevant to your make, eg # % make COPTS="-DDO_HTPASSWD" COPTS+= -DDO_HTPASSWD PROG= bozohttpd LINKS= ${BINDIR}/bozohttpd ${BINDIR}/httpd MAN= bozohttpd.8 MLINKS+=bozohttpd.8 httpd.8 SRCS= bozohttpd.c ssl-bozo.c auth-bozo.c cgi-bozo.c daemon-bozo.c \ tilde-luzah-bozo.c dir-index-bozo.c content-bozo.c lua-bozo.c SRCS+= main.c LDADD= -lcrypt -llua -lm DPADD= ${LIBCRYPT} ${LIBLUA} ${LIBM} WARNS?= 4 .if defined(.OS.MAKE) OPSYS= ${.OS.MAKE} .else OPSYS:= ${:!uname -s!:S/-//g:S/\///g} .endif .if ${OPSYS} == "QNX" CPPFLAGS+= -DHAVE_NBUTIL_H LDADD+= -lnbutil .endif .include <bsd.own.mk> .if ${MKCRYPTO} != "no" LDADD+= -lssl -lcrypto DPADD+= ${LIBSSL} ${LIBCRYPTO} .else COPTS+= -DNO_SSL_SUPPORT .endif # # Build release things. # NROFF?= nroff PREHTMLFROB= sed \ -e 's/&/\&/' \ -e 's/</\</' \ -e 's/>/\>/' HTMLFROB= sed \ -e 's/\([MC] "[^"]*\)<dd>$$/\1<b>"<\/b><dd>/' \ -e 's/'"''"'/\”/' \ -e 's/""/\“/' \ -e 's/<a href="\.\.\/html[^>]*>\(.*\)<\/a>/\1/' TXTFROB= col -b bozohttpd.8.html: bozohttpd.8 $(PREHTMLFROB) $> | $(NROFF) -mdoc2html | $(HTMLFROB) > $@ bozohttpd.8.txt: bozohttpd.8 $(NROFF) -mdoc -Tascii $> | $(TXTFROB) > $@ CLEANFILES+= bozohttpd.8.html bozohttpd.8.txt # Create a distfile: uses /tmp BASE=bozohttpd-${BOZOVER} TAR=${BASE}.tar export-distfile: dir=`mktemp -d /tmp/bozo-export-XXXXXX`; \ cd "$${dir}" || exit; \ mkdir ${BASE}; \ ( cd ${BASE} || exit; \ cp -r "${.CURDIR}/." "."; \ find . -name .CVS | xargs rm -r; \ ); \ pax -wf ${TAR} ${BASE}; \ gzip -nc9 ${TAR} > ${TAR}.gz; \ bzip2 -9 ${TAR}; \ echo "Exported two files in $${dir}:"; \ echo ${TAR}.gz; \ echo ${TAR}.bz2 .include <bsd.prog.mk> |
Added Makefile.boot.
> > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # $eterna: Makefile.boot,v 1.9 2010/05/10 04:57:50 mrg Exp $ # # very simple makefile to compile bozohttpd, should work with every make. # see Makefile for a list of compile options that may be placed in CFLAGS. CC= cc OPT= -O LARGE_CFLAGS= -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 LOCAL_CFLAGS= -DNO_LUA_SUPPORT CFLAGS= $(OPT) $(LARGE_CFLAGS) $(LOCAL_CFLAGS) GROFF= groff -Tascii CRYPTOLIBDIR= # -L/usr/local/lib CRYPTOLIBS= $(CRYPTOLIBDIR) -lcrypto -lssl FILES= bozohttpd.c auth-bozo.c cgi-bozo.c content-bozo.c daemon-bozo.c \ dir-index-bozo.c lua-bozo.c ssl-bozo.c tilde-luzah-bozo.c main.c all: $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o bozohttpd $(FILES) $(CRYPTOLIBS) man: $(GROFF) -mandoc bozohttpd.8 > bozohttpd.cat8 clean: rm -f bozohttpd bozohttpd.cat8 *.o |
Added auth-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | /* $NetBSD: auth-bozo.c,v 1.18 2015/12/27 10:21:35 mrg Exp $ */ /* $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2014 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements "http basic authorisation" for bozohttpd */ #ifdef DO_HTPASSWD #include <sys/param.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include "bozohttpd.h" #ifndef AUTH_FILE #define AUTH_FILE ".htpasswd" #endif static ssize_t base64_decode(const unsigned char *, size_t, unsigned char *, size_t); /* * Check if HTTP authentication is required */ int bozo_auth_check(bozo_httpreq_t *request, const char *file) { bozohttpd_t *httpd = request->hr_httpd; struct stat sb; char dir[MAXPATHLEN], authfile[MAXPATHLEN], *basename; char user[BUFSIZ], *pass; FILE *fp; int len; /* get dir=dirname(file) */ snprintf(dir, sizeof(dir), "%s", file); if ((basename = strrchr(dir, '/')) == NULL) strcpy(dir, "."); else { *basename++ = '\0'; /* ensure basename(file) != AUTH_FILE */ if (bozo_check_special_files(request, basename)) return 1; } request->hr_authrealm = bozostrdup(httpd, request, dir); if ((size_t)snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE) >= sizeof(authfile)) { return bozo_http_error(httpd, 404, request, "authfile path too long"); } if (stat(authfile, &sb) < 0) { debug((httpd, DEBUG_NORMAL, "bozo_auth_check realm `%s' dir `%s' authfile `%s' missing", dir, file, authfile)); return 0; } if ((fp = fopen(authfile, "r")) == NULL) return bozo_http_error(httpd, 403, request, "no permission to open authfile"); debug((httpd, DEBUG_NORMAL, "bozo_auth_check realm `%s' dir `%s' authfile `%s' open", dir, file, authfile)); if (request->hr_authuser && request->hr_authpass) { while (fgets(user, sizeof(user), fp) != NULL) { len = strlen(user); if (len > 0 && user[len-1] == '\n') user[--len] = '\0'; if ((pass = strchr(user, ':')) == NULL) continue; *pass++ = '\0'; debug((httpd, DEBUG_NORMAL, "bozo_auth_check authfile `%s':`%s' " "client `%s':`%s'", user, pass, request->hr_authuser, request->hr_authpass)); if (strcmp(request->hr_authuser, user) != 0) continue; if (strcmp(crypt(request->hr_authpass, pass), pass) != 0) break; fclose(fp); return 0; } } fclose(fp); return bozo_http_error(httpd, 401, request, "bad auth"); } void bozo_auth_init(bozo_httpreq_t *request) { request->hr_authuser = NULL; request->hr_authpass = NULL; } void bozo_auth_cleanup(bozo_httpreq_t *request) { if (request == NULL) return; free(request->hr_authuser); free(request->hr_authpass); free(request->hr_authrealm); } int bozo_auth_check_headers(bozo_httpreq_t *request, char *val, char *str, ssize_t len) { bozohttpd_t *httpd = request->hr_httpd; if (strcasecmp(val, "authorization") == 0 && strncasecmp(str, "Basic ", 6) == 0) { char authbuf[BUFSIZ]; char *pass = NULL; ssize_t alen; alen = base64_decode((unsigned char *)str + 6, (size_t)(len - 6), (unsigned char *)authbuf, sizeof(authbuf) - 1); if (alen != -1) authbuf[alen] = '\0'; if (alen == -1 || (pass = strchr(authbuf, ':')) == NULL) return bozo_http_error(httpd, 400, request, "bad authorization field"); *pass++ = '\0'; free(request->hr_authuser); free(request->hr_authpass); request->hr_authuser = bozostrdup(httpd, request, authbuf); request->hr_authpass = bozostrdup(httpd, request, pass); debug((httpd, DEBUG_FAT, "decoded authorization `%s' as `%s':`%s'", str, request->hr_authuser, request->hr_authpass)); /* don't store in request->headers */ return 1; } return 0; } int bozo_auth_check_special_files(bozo_httpreq_t *request, const char *name) { bozohttpd_t *httpd = request->hr_httpd; if (strcmp(name, AUTH_FILE) == 0) return bozo_http_error(httpd, 403, request, "no permission to open authfile"); return 0; } void bozo_auth_check_401(bozo_httpreq_t *request, int code) { bozohttpd_t *httpd = request->hr_httpd; if (code == 401) bozo_printf(httpd, "WWW-Authenticate: Basic realm=\"%s\"\r\n", request->hr_authrealm ? request->hr_authrealm : "default realm"); } #ifndef NO_CGIBIN_SUPPORT void bozo_auth_cgi_setenv(bozo_httpreq_t *request, char ***curenvpp) { bozohttpd_t *httpd = request->hr_httpd; if (request->hr_authuser && *request->hr_authuser) { bozo_setenv(httpd, "AUTH_TYPE", "Basic", (*curenvpp)++); bozo_setenv(httpd, "REMOTE_USER", request->hr_authuser, (*curenvpp)++); } } int bozo_auth_cgi_count(bozo_httpreq_t *request) { return (request->hr_authuser && *request->hr_authuser) ? 2 : 0; } #endif /* NO_CGIBIN_SUPPORT */ /* * Decode len bytes starting at in using base64 encoding into out. * Result is *not* NUL terminated. * Written by Luke Mewburn <lukem@NetBSD.org> */ const unsigned char decodetable[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, }; static ssize_t base64_decode(const unsigned char *in, size_t ilen, unsigned char *out, size_t olen) { unsigned char *cp; size_t i; if (ilen == 0) { if (olen) *out = '\0'; return 0; } cp = out; for (i = 0; i < ilen; i += 4) { if (cp + 3 > out + olen) return (-1); #define IN_CHECK(x) \ if ((x) > sizeof(decodetable) || decodetable[(x)] == 255) \ return(-1) IN_CHECK(in[i + 0]); /*LINTED*/ *(cp++) = decodetable[in[i + 0]] << 2 | decodetable[in[i + 1]] >> 4; IN_CHECK(in[i + 1]); /*LINTED*/ *(cp++) = decodetable[in[i + 1]] << 4 | decodetable[in[i + 2]] >> 2; IN_CHECK(in[i + 2]); *(cp++) = decodetable[in[i + 2]] << 6 | decodetable[in[i + 3]]; #undef IN_CHECK } while (i > 0 && in[i - 1] == '=') cp--,i--; return (cp - out); } #endif /* DO_HTPASSWD */ |
Added bozohttpd.8.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | .\" $NetBSD: bozohttpd.8,v 1.65 2017/01/31 14:36:09 mrg Exp $ .\" .\" $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $ .\" .\" Copyright (c) 1997-2017 Matthew R. Green .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED .\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .Dd February 1, 2017 .Dt BOZOHTTPD 8 .Os .Sh NAME .Nm bozohttpd .Nd hyper text transfer protocol version 1.1 daemon .Sh SYNOPSIS .Nm .Op Fl EGHVXefhnsu .Op Fl C Ar suffix cgihandler .Op Fl I Ar port .Op Fl L Ar prefix script .Op Fl M Ar suffix type encoding encoding11 .Op Fl P Ar pidfile .Op Fl S Ar server_software .Op Fl U Ar username .Op Fl Z Ar cert privkey .Op Fl c Ar cgibin .Op Fl i Ar address .Op Fl p Ar pubdir .Op Fl t Ar chrootdir .Op Fl v Ar virtualroot .Op Fl x Ar index .Op Fl z Ar ciphers .Ar slashdir .Op Ar myname .Sh DESCRIPTION The .Nm program reads a .Em HTTP request from the standard input, and sends a reply to the standard output. Besides ~user translation and virtual hosting support (see below), all file requests are from .Ar slashdir directory. The server uses .Ar myname as its name, which defaults to the local hostname, obtained from .Xr gethostname 3 (but see the .Fl v option for virtual hosting.) .Nm writes logs to .Xr syslog 3 using the ftp facility (but see the .Fl s option for testing.) .Nm is designed to be small, simple and relatively featureless, hopefully increasing its security. .Ss OPTIONS The following options are available: .Bl -tag -width xxxcgibin .It Fl b Enables daemon mode, where .Nm detaches from the current terminal, running in the background and servicing HTTP requests. .It Fl C Ar suffix cgihandler Adds a new CGI handler program for a particular file type. The .Ar suffix should be any normal file suffix, and the .Ar cgihandler should be a full path to an interpreter. This option is the only way to enable CGI programs that exist outside of the cgibin directory to be executed. Multiple .Fl C options may be passed. .It Fl c Ar cgibin Enables the CGI/1.1 interface. The .Ar cgibin directory is expected to contain the CGI programs to be used. .Nm looks for URL's in the form of .Em /cgi-bin/\*[Lt]scriptname\*[Gt] where .Aq scriptname is a valid CGI program in the .Ar cgibin directory. In other words, all CGI URL's must begin with .Em \%/cgi-bin/ . Note that the CGI/1.1 interface is available with .Em ~user translation using .Fl E switch. .It Fl e Causes .Nm to not clear the environment when used with either the .Fl t or .Fl U options. .It Fl f Stops the .Fl b flag from .Nm detaching from the tty and going into the background. .It Fl G Get the .Nm version string, print it on standard output, and exit. .It Fl H Causes directory index mode to hide files and directories that start with a period, except for .Pa .. . Also see .Fl X . .It Fl I Ar port Causes .Nm to use .Ar port instead of the default .Dq http port. When used with the .Fl b option, it changes the bound port. Otherwise it forces redirections to use this port instead of the value obtained via .Xr getsockname 2 . .It Fl i Ar address Causes .Ar address to be used as the address to bind daemon mode. If otherwise unspecified, the address used to bind is derived from the .Ar myname , which defaults to the name returned by .Xr gethostname 3 . Only the last .Fl i option is used. This option is only valid with the .Fl b option. .It Fl L Ar prefix script Adds a new Lua script for a particular prefix. The .Ar prefix should be an arbitrary text, and the .Ar script should be a full path to a Lua script. Multiple .Fl L options may be passed. A separate Lua state is created for each prefix. The Lua script can register callbacks using the httpd.register_handler('<name>', function) Lua function, which will trigger the execution of the Lua function .Em function when a URL in the form .Em http://<hostname>/<prefix>/<name> is being accessed. The function is passed three tables as arguments, the server environment, the request headers, and the decoded query string plus any data that was sent as application/x-www-form-urlencoded. .It Fl M Ar suffix type encoding encoding11 Adds a new entry to the table that converts file suffixes to content type and encoding. This option takes four additional arguments containing the file prefix, its .Dq Content-Type , .Dq Content-Encoding , and .Dq Content-Encoding for HTTP/1.1 connections, respectively. If any of these are a single dash .Pq Dq - , the empty string is used instead. Multiple .Fl M options may be passed. .It Fl n Stops .Nm from doing IP address to name resolution of hosts for setting the .Ev REMOTE_HOST variable before running a CGI program. This option has no effect without the .Fl c option. .It Fl P Ar pidfile Causes .Nm to create a pid file in .Ar pidfile when run in daemon mode with the .Fl b option. .It Fl p Ar pubdir Changes the default user directory for .Em /~user/ translations from .Dq public_html to .Ar pubdir . .It Fl S Ar server_software Sets the internal server version to .Ar server_software . .It Fl s Forces logging to be set to stderr always. .It Fl t Ar chrootdir Makes .Nm chroot to the specified directory before answering requests. Every other path should be specified relative to the new root, if this option is used. Note that the current environment is normally replaced with an empty environment with this option, unless the .Fl e option is also used. .It Fl U Ar username Causes .Nm to switch to the user and the groups of .Ar username after initialization. This option, like .Fl t above, causes .Nm to clear the environment unless the .Fl e option is given. .It Fl u Enables the transformation of Uniform Resource Locators of the form .Em /~user/ into the directory .Pa ~user/public_html (but see the .Fl p option above). .It Fl E Enables CGI/1.1 interface for .Em ~user translation. Note that enabling this support implies that users can run commands as web server user, this may have security implications. .It Fl V Sets the backup virtual host directory to the .Ar slashdir argument. If no directory exists in .Ar virtualroot for the request, then .Ar slashdir will be used. The default behaviour is to return 404 (Not Found.) .It Fl v Ar virtualroot Enables virtual hosting support. Directories in .Ar virtualroot will be searched for a matching virtual host name, when parsing the HTML request. If a matching name is found, it will be used as both the server's real name, .Op Ar myname , and as the .Ar slashdir . See the .Sx EXAMPLES section for an example of using this option. .It Fl X Enables directory indexing. A directory index will be generated only when the default file (i.e. .Pa index.html normally) is not present. .It Fl x Ar index Changes the default file read for directories from .Dq index.html to .Ar index . .It Fl z Ar ciphers Sets the list of SSL ciphers (see .Xr SSL_CTX_set_cipher_list 3 ) . .It Fl Z Ar certificate_path privatekey_path Sets the path to the server certificate file and the private key file in pem format. It also causes .Nm to start SSL mode. .El .Pp Note that in .Nm versions 20031005 and prior that supported the .Fl C and .Fl M options, they took a single space-separated argument that was parsed. since version 20040828, they take multiple options (2 in the case of .Fl C and 4 in the case of .Fl M . ) .Ss INETD CONFIGURATION As .Nm uses .Xr inetd 8 by default to process incoming TCP connections for HTTP requests (but see the .Fl b option), .Nm has little internal networking knowledge. (Indeed, you can run it on the command line with little change of functionality.) A typical .Xr inetd.conf 5 entry would be: .Bd -literal http stream tcp nowait:600 _httpd /usr/libexec/httpd httpd /var/www http stream tcp6 nowait:600 _httpd /usr/libexec/httpd httpd /var/www .Ed .Pp This would serve web pages from .Pa /var/www on both IPv4 and IPv6 ports. The .Em :600 changes the requests per minute to 600, up from the .Xr inetd 8 default of 40. .Pp Using the .Nx .Xr inetd 8 , you can provide multiple IP-address based HTTP servers by having multiple listening ports with different configurations. .Ss NOTES This server supports the .Em HTTP/0.9 , .Em HTTP/1.0 , and .Em HTTP/1.1 standards. Support for these protocols is very minimal and many optional features are not supported. .Pp .Nm can be compiled without CGI support (NO_CGIBIN_SUPPORT), user transformations (NO_USER_SUPPORT), directory index support (NO_DIRINDEX_SUPPORT), daemon mode support (NO_DAEMON_MODE), dynamic MIME content (NO_DYNAMIC_CONTENT), Lua support (NO_LUA_SUPPORT), and SSL support (NO_SSL_SUPPORT) by defining the listed macros when building .Nm . .Ss HTTP BASIC AUTHORISATION .Nm has support for HTTP Basic Authorisation. If a file named .Pa .htpasswd exists in the directory of the current request, .Nm will restrict access to documents in that directory using the RFC 2617 HTTP .Dq Basic authentication scheme. .Pp Note: This does not recursively protect any sub-directories. .Pp The .Pa .htpasswd file contains lines delimited with a colon containing usernames and passwords hashed with .Xr crypt 3 , for example: .Bd -literal heather:$1$pZWI4tH/$DzDPl63i6VvVRv2lJNV7k1 jeremy:A.xewbx2DpQ8I .Ed .Pp On .Nx , the .Xr pwhash 1 utility may be used to generate hashed passwords. .Pp While .Nm distributed with .Nx has support for HTTP Basic Authorisation enabled by default, in the portable distribution it is excluded. Compile .Nm with .Dq -DDO_HTPASSWD on the compiler command line to enable this support. It may require linking with the crypt library, using .Dq -lcrypt . .Ss SSL SUPPORT .Nm has support for TLSv1.1 and TLSv1.2 protocols that are included by default. It requires linking with the crypto and ssl library, using .Dq -lcrypto -lssl . To disable SSL SUPPORT compile .Nm with .Dq -DNO_SSL_SUPPORT on the compiler command line. .Ss COMPRESSION .Nm supports a very basic form of compression. .Nm will serve the requested file postpended with .Dq Pa .gz if it exists, it is readable, the client requested gzip compression, and the client did not make a ranged request. .Sh FILES .Nm looks for a couple of special files in directories that allow certain features to be provided on a per-directory basis. In addition to the .Pa .htpasswd used by HTTP basic authorisation, if a .Pa .bzdirect file is found (contents are irrelevant) .Nm will allow direct access even with the .Fl r option. If a .Pa .bzredirect symbolic link is found, .Nm will perform a smart redirect to the target of this symlink. The target is assumed to live on the same server. If target starts with slash then absolute redirection is performed, otherwise it's handled as relative. If a .Pa .bzabsredirect symbolic link is found, .Nm will redirect to the absolute url pointed to by this symlink. This is useful to redirect to different servers. Two forms of redirection are supported - symbolic link without schema will use .Em http:// as default i.e. link to .Em NetBSD.org will redirect to .Em http://NetBSD.org/ Otherwise provided schema will be used i.e. symbolic link to .Em ftp://NetBSD.org/ will redirect to provided the URL. .Sh EXAMPLES To configure set of virtual hosts, one would use an .Xr inetd.conf 5 entry like: .Bd -literal http stream tcp nowait:600 _httpd /usr/libexec/httpd httpd -v /var/vroot /var/www .Ed .Pp and inside .Pa /var/vroot create a directory (or a symlink to a directory) with the same name as the virtual host, for each virtual host. Lookups for these names are done in a case-insensitive manner, and may include the port number part of the request, allowing for distinct virtual hosts on the same name. .Pp To use .Nm with PHP, one must use the .Fl C option to specify a CGI handler for a particular file type. Typically this will be like: .Bd -literal httpd -C .php /usr/pkg/bin/php-cgi /var/www .Ed .Sh SEE ALSO .Xr inetd.conf 5 , .Xr inetd 8 .Sh HISTORY .Nm was first written in perl, based on another perl http server called .Dq tinyhttpd . It was then rewritten from scratch in perl, and then once again in C. From .Dq bozohttpd version 20060517, it has been integrated into .Nx . The focus has always been simplicity and security, with minimal features and regular code audits. This manual documents .Nm version 20170201. .Sh AUTHORS .An -nosplit .Nm was written by .An Matthew R. Green .Aq Mt mrg@eterna.com.au . .Pp The large list of contributors includes: .Bl -dash .It .An Marc Balmer .Aq Mt mbalmer@NetBSD.org added Lua support for dynamic content creation .It .An Christoph Badura .Aq Mt bad@bsd.de provided Range: header support .It .An Sean Boudreau .Aq Mt seanb@NetBSD.org provided a security fix for virtual hosting .It .An Julian Coleman .Aq Mt jdc@coris.org.uk provided an IPv6 bugfix .It .An Chuck Cranor .Aq Mt chuck@research.att.com provided cgi-bin support fixes, and more .It .An Alistair G. Crooks .Aq Mt agc@NetBSD.org cleaned up many internal interfaces, made .Nm linkable as a library and provided the Lua binding. .It .An DEGROOTE Arnaud .Aq Mt degroote@NetBSD.org provided a fix for daemon mode .It .An Andrew Doran .Aq Mt ad@NetBSD.org provided directory indexing support .It .An Per Ekman .Aq Mt pek@pdc.kth.se provided a fix for a minor (non-security) buffer overflow condition .It .An Roland Dowdeswell .Aq Mt elric@NetBSD.org added support for serving gzipped files and better SSL handling .It .An Jun-ichiro itojun Hagino, KAME .Aq Mt itojun@iijlab.net provided initial IPv6 support .It .An Martin Husemann .Aq Mt martin@NetBSD.org provided .bzabsredirect support, and fixed various redirection issues .It .An Arto Huusko .Aq Mt arto.huusko@pp2.inet.fi provided fixes cgi-bin .It .An Roland Illig .Aq Mt roland.illig@gmx.de provided some off-by-one fixes .It .An Zak Johnson .Aq Mt zakj@nox.cx provided cgi-bin enhancements .It .An Nicolas Jombart .Aq Mt ecu@ipv42.net provided fixes for HTTP basic authorisation support .It .An Antti Kantee .Aq Mt pooka@NetBSD.org provided fixes for HTTP basic authorisation support .It .An Thomas Klausner .Aq Mt wiz@NetBSD.org provided many fixes and enhancements for the man page .It .An Mateusz Kocielski .Aq Mt shm@NetBSD.org fixed memory leaks, various issues with userdir support, information disclosure issues, added support for using CGI handlers with directory indexing, found several security issues and provided various other fixes. .It .An Arnaud Lacombe .Aq Mt alc@NetBSD.org provided some clean up for memory leaks .It .An Johnny Lam .Aq Mt jlam@NetBSD.org provided man page fixes .It .An Dennis Lindroos .Aq Mt denafcm@gmail.com provided a cgi-bin fix .It .An Julio Merino .Aq Mt jmmv@NetBSD.org Added the .Fl P option (pidfile support) and provided some man page fixes. .It .An Luke Mewburn .Aq Mt lukem@NetBSD.org provided many various fixes, including cgi-bin fixes and enhancements, HTTP basic authorisation support and much code clean up .It .An Rajeev V. Pillai .Aq Mt rajeev_v_pillai@yahoo.com provided several fixes for virtual hosting .It .An Jeremy C. Reed .Aq Mt reed@NetBSD.org provided several clean up fixes, and man page updates .It .An Scott Reynolds .Aq Mt scottr@NetBSD.org provided various fixes .It .An Tyler Retzlaff .Aq Mt rtr@eterna.com.au provided SSL support, cgi-bin fixes and much other random other stuff .It .An rudolf .Aq Mt netbsd@eq.cz provided minor compile fixes and a CGI content map fix .It .An Steve Rumble .Aq Mt rumble@ephemeral.org provided the .Fl V option. .It .An Thor Lancelot Simon .Aq Mt tls@NetBSD.org enhanced cgi-bin support. .It .An Joerg Sonnenberger .Aq Mt joerg@NetBSD.org implemented If-Modified-Since support .It .An ISIHARA Takanori .Aq Mt ishit@oak.dti.ne.jp provided a man page fix .It .An Holger Weiss .Aq Mt holger@CIS.FU-Berlin.DE provided http authorisation fixes .It .Aq Mt xs@kittenz.org provided chroot and change-to-user support, and other various fixes .It Coyote Point provided various CGI fixes. .El .Pp There are probably others I have forgotten (let me know if you care) .Pp Please send all updates to .Nm to .Aq Mt mrg@eterna.com.au for inclusion in future releases. .Sh BUGS .Nm does not handle HTTP/1.1 chunked input from the client yet. |
Added bozohttpd.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 | /* $NetBSD: bozohttpd.c,v 1.85 2017/01/31 14:36:09 mrg Exp $ */ /* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2017 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this program is dedicated to the Great God of Processed Cheese */ /* * bozohttpd.c: minimal httpd; provides only these features: * - HTTP/0.9 (by virtue of ..) * - HTTP/1.0 * - HTTP/1.1 * - CGI/1.1 this will only be provided for "system" scripts * - automatic "missing trailing slash" redirections * - configurable translation of /~user/ to ~user/public_html, * however, this does not include cgi-bin support * - access lists via libwrap via inetd/tcpd * - virtual hosting * - not that we do not even pretend to understand MIME, but * rely only on the HTTP specification * - ipv6 support * - automatic `index.html' generation * - configurable server name * - directory index generation * - daemon mode (lacks libwrap support) * - .htpasswd support */ /* * requirements for minimal http/1.1 (at least, as documented in * RFC 2616 (HTTP/1.1): * * - 14.11: content-encoding handling. [1] * * - 14.13: content-length handling. this is only a SHOULD header * thus we could just not send it ever. [1] * * - 14.17: content-type handling. [1] * * - 14.28: if-unmodified-since handling. if-modified-since is * done since, shouldn't be too hard for this one. * * [1] need to revisit to ensure proper behaviour * * and the following is a list of features that we do not need * to have due to other limits, or are too lazy. there are more * of these than are listed, but these are of particular note, * and could perhaps be implemented. * * - 3.5/3.6: content/transfer codings. probably can ignore * this? we "SHOULD"n't. but 4.4 says we should ignore a * `content-length' header upon reciept of a `transfer-encoding' * header. * * - 5.1.1: request methods. only MUST support GET and HEAD, * but there are new ones besides POST that are currently * supported: OPTIONS PUT DELETE TRACE and CONNECT, plus * extensions not yet known? * * - 10.1: we can ignore informational status codes * * - 10.3.3/10.3.4/10.3.8: just use '302' codes always. * * - 14.1/14.2/14.3/14.27: we do not support Accept: headers. * just ignore them and send the request anyway. they are * only SHOULD. * * - 14.5/14.16/14.35: only support simple ranges: %d- and %d-%d * would be nice to support more. * * - 14.9: we aren't a cache. * * - 14.15: content-md5 would be nice. * * - 14.24/14.26/14.27: if-match, if-none-match, if-range. be * nice to support this. * * - 14.44: Vary: seems unneeded. ignore it for now. */ #ifndef INDEX_HTML #define INDEX_HTML "index.html" #endif #ifndef SERVER_SOFTWARE #define SERVER_SOFTWARE "bozohttpd/20170102" #endif #ifndef DIRECT_ACCESS_FILE #define DIRECT_ACCESS_FILE ".bzdirect" #endif #ifndef REDIRECT_FILE #define REDIRECT_FILE ".bzredirect" #endif #ifndef ABSREDIRECT_FILE #define ABSREDIRECT_FILE ".bzabsredirect" #endif #ifndef PUBLIC_HTML #define PUBLIC_HTML "public_html" #endif #ifndef USE_ARG #define USE_ARG(x) /*LINTED*/(void)&(x) #endif /* * And so it begins .. */ #include <sys/param.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/mman.h> #include <arpa/inet.h> #include <ctype.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> #include <netdb.h> #include <pwd.h> #include <grp.h> #include <signal.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <time.h> #include <unistd.h> #include "bozohttpd.h" #ifndef MAX_WAIT_TIME #define MAX_WAIT_TIME 60 /* hang around for 60 seconds max */ #endif /* variables and functions */ #ifndef LOG_FTP #define LOG_FTP LOG_DAEMON #endif volatile sig_atomic_t alarmhit; /* * check there's enough space in the prefs and names arrays. */ static int size_arrays(bozoprefs_t *bozoprefs, size_t needed) { char **temp; if (bozoprefs->size == 0) { /* only get here first time around */ bozoprefs->name = calloc(sizeof(char *), needed); if (bozoprefs->name == NULL) return 0; bozoprefs->value = calloc(sizeof(char *), needed); if (bozoprefs->value == NULL) { free(bozoprefs->name); return 0; } bozoprefs->size = needed; } else if (bozoprefs->count == bozoprefs->size) { /* only uses 'needed' when filled array */ temp = realloc(bozoprefs->name, sizeof(char *) * needed); if (temp == NULL) return 0; bozoprefs->name = temp; temp = realloc(bozoprefs->value, sizeof(char *) * needed); if (temp == NULL) return 0; bozoprefs->value = temp; bozoprefs->size += needed; } return 1; } static ssize_t findvar(bozoprefs_t *bozoprefs, const char *name) { size_t i; for (i = 0; i < bozoprefs->count; i++) if (strcmp(bozoprefs->name[i], name) == 0) return (ssize_t)i; return -1; } int bozo_set_pref(bozohttpd_t *httpd, bozoprefs_t *bozoprefs, const char *name, const char *value) { ssize_t i; if ((i = findvar(bozoprefs, name)) < 0) { /* add the element to the array */ if (!size_arrays(bozoprefs, bozoprefs->size + 15)) return 0; i = bozoprefs->count++; bozoprefs->name[i] = bozostrdup(httpd, NULL, name); } else { /* replace the element in the array */ if (bozoprefs->value[i]) { free(bozoprefs->value[i]); bozoprefs->value[i] = NULL; } } bozoprefs->value[i] = bozostrdup(httpd, NULL, value); return 1; } /* * get a variable's value, or NULL */ char * bozo_get_pref(bozoprefs_t *bozoprefs, const char *name) { ssize_t i; i = findvar(bozoprefs, name); return i < 0 ? NULL : bozoprefs->value[i]; } char * bozo_http_date(char *date, size_t datelen) { struct tm *tm; time_t now; /* Sun, 06 Nov 1994 08:49:37 GMT */ now = time(NULL); tm = gmtime(&now); /* HTTP/1.1 spec rev 06 sez GMT only */ strftime(date, datelen, "%a, %d %b %Y %H:%M:%S GMT", tm); return date; } /* * convert "in" into the three parts of a request (first line). * we allocate into file and query, but return pointers into * "in" for proto and method. */ static void parse_request(bozohttpd_t *httpd, char *in, char **method, char **file, char **query, char **proto) { ssize_t len; char *val; USE_ARG(httpd); debug((httpd, DEBUG_EXPLODING, "parse in: %s", in)); *method = *file = *query = *proto = NULL; len = (ssize_t)strlen(in); val = bozostrnsep(&in, " \t\n\r", &len); if (len < 1 || val == NULL) return; *method = val; while (*in == ' ' || *in == '\t') in++; val = bozostrnsep(&in, " \t\n\r", &len); if (len < 1) { if (len == 0) *file = val; else *file = in; } else { *file = val; *query = strchr(*file, '?'); if (*query) *(*query)++ = '\0'; if (in) { while (*in && (*in == ' ' || *in == '\t')) in++; if (*in) *proto = in; } } /* allocate private copies */ *file = bozostrdup(httpd, NULL, *file); if (*query) *query = bozostrdup(httpd, NULL, *query); debug((httpd, DEBUG_FAT, "url: method: \"%s\" file: \"%s\" query: \"%s\" proto: \"%s\"", *method, *file, *query, *proto)); } /* * cleanup a bozo_httpreq_t after use */ void bozo_clean_request(bozo_httpreq_t *request) { struct bozoheaders *hdr, *ohdr = NULL; if (request == NULL) return; /* If SSL enabled cleanup SSL structure. */ bozo_ssl_destroy(request->hr_httpd); /* clean up request */ free(request->hr_remotehost); free(request->hr_remoteaddr); free(request->hr_serverport); free(request->hr_virthostname); free(request->hr_file); free(request->hr_oldfile); free(request->hr_query); free(request->hr_host); bozo_user_free(request->hr_user); bozo_auth_cleanup(request); for (hdr = SIMPLEQ_FIRST(&request->hr_headers); hdr; hdr = SIMPLEQ_NEXT(hdr, h_next)) { free(hdr->h_value); free(hdr->h_header); free(ohdr); ohdr = hdr; } free(ohdr); ohdr = NULL; for (hdr = SIMPLEQ_FIRST(&request->hr_replheaders); hdr; hdr = SIMPLEQ_NEXT(hdr, h_next)) { free(hdr->h_value); free(hdr->h_header); free(ohdr); ohdr = hdr; } free(ohdr); free(request); } /* * send a HTTP/1.1 408 response if we timeout. */ /* ARGSUSED */ static void alarmer(int sig) { alarmhit = 1; } /* * a list of header quirks: currently, a list of headers that * can't be folded into a single line. */ const char *header_quirks[] = { "WWW-Authenticate", NULL }; /* * add or merge this header (val: str) into the requests list */ static bozoheaders_t * addmerge_header(bozo_httpreq_t *request, struct qheaders *headers, const char *val, const char *str, ssize_t len) { struct bozohttpd_t *httpd = request->hr_httpd; struct bozoheaders *hdr = NULL; const char **quirk; USE_ARG(len); for (quirk = header_quirks; *quirk; quirk++) if (strcasecmp(*quirk, val) == 0) break; if (*quirk == NULL) { /* do we exist already? */ SIMPLEQ_FOREACH(hdr, headers, h_next) { if (strcasecmp(val, hdr->h_header) == 0) break; } } if (hdr) { /* yup, merge it in */ char *nval; bozoasprintf(httpd, &nval, "%s, %s", hdr->h_value, str); free(hdr->h_value); hdr->h_value = nval; } else { /* nope, create a new one */ hdr = bozomalloc(httpd, sizeof *hdr); hdr->h_header = bozostrdup(httpd, request, val); if (str && *str) hdr->h_value = bozostrdup(httpd, request, str); else hdr->h_value = bozostrdup(httpd, request, " "); SIMPLEQ_INSERT_TAIL(headers, hdr, h_next); request->hr_nheaders++; } return hdr; } bozoheaders_t * addmerge_reqheader(bozo_httpreq_t *request, const char *val, const char *str, ssize_t len) { return addmerge_header(request, &request->hr_headers, val, str, len); } bozoheaders_t * addmerge_replheader(bozo_httpreq_t *request, const char *val, const char *str, ssize_t len) { return addmerge_header(request, &request->hr_replheaders, val, str, len); } /* * as the prototype string is not constant (eg, "HTTP/1.1" is equivalent * to "HTTP/001.01"), we MUST parse this. */ static int process_proto(bozo_httpreq_t *request, const char *proto) { struct bozohttpd_t *httpd = request->hr_httpd; char majorstr[16], *minorstr; int majorint, minorint; if (proto == NULL) { got_proto_09: request->hr_proto = httpd->consts.http_09; debug((httpd, DEBUG_FAT, "request %s is http/0.9", request->hr_file)); return 0; } if (strncasecmp(proto, "HTTP/", 5) != 0) goto bad; strncpy(majorstr, proto + 5, sizeof majorstr); majorstr[sizeof(majorstr)-1] = 0; minorstr = strchr(majorstr, '.'); if (minorstr == NULL) goto bad; *minorstr++ = 0; majorint = atoi(majorstr); minorint = atoi(minorstr); switch (majorint) { case 0: if (minorint != 9) break; goto got_proto_09; case 1: if (minorint == 0) request->hr_proto = httpd->consts.http_10; else if (minorint == 1) request->hr_proto = httpd->consts.http_11; else break; debug((httpd, DEBUG_FAT, "request %s is %s", request->hr_file, request->hr_proto)); SIMPLEQ_INIT(&request->hr_headers); request->hr_nheaders = 0; return 0; } bad: return bozo_http_error(httpd, 404, NULL, "unknown prototype"); } /* * process each type of HTTP method, setting this HTTP requests * method type. */ static struct method_map { const char *name; int type; } method_map[] = { { "GET", HTTP_GET, }, { "POST", HTTP_POST, }, { "HEAD", HTTP_HEAD, }, #if 0 /* other non-required http/1.1 methods */ { "OPTIONS", HTTP_OPTIONS, }, { "PUT", HTTP_PUT, }, { "DELETE", HTTP_DELETE, }, { "TRACE", HTTP_TRACE, }, { "CONNECT", HTTP_CONNECT, }, #endif { NULL, 0, }, }; static int process_method(bozo_httpreq_t *request, const char *method) { struct bozohttpd_t *httpd = request->hr_httpd; struct method_map *mmp; if (request->hr_proto == httpd->consts.http_11) request->hr_allow = "GET, HEAD, POST"; for (mmp = method_map; mmp->name; mmp++) if (strcasecmp(method, mmp->name) == 0) { request->hr_method = mmp->type; request->hr_methodstr = mmp->name; return 0; } return bozo_http_error(httpd, 404, request, "unknown method"); } /* * This function reads a http request from stdin, returning a pointer to a * bozo_httpreq_t structure, describing the request. */ bozo_httpreq_t * bozo_read_request(bozohttpd_t *httpd) { struct sigaction sa; char *str, *val, *method, *file, *proto, *query; char *host, *addr, *port; char bufport[10]; char hbuf[NI_MAXHOST], abuf[NI_MAXHOST]; struct sockaddr_storage ss; ssize_t len; int line = 0; socklen_t slen; bozo_httpreq_t *request; /* * if we're in daemon mode, bozo_daemon_fork() will return here twice * for each call. once in the child, returning 0, and once in the * parent, returning 1. for each child, then we can setup SSL, and * the parent can signal the caller there was no request to process * and it will wait for another. */ if (bozo_daemon_fork(httpd)) return NULL; if (bozo_ssl_accept(httpd)) return NULL; request = bozomalloc(httpd, sizeof(*request)); memset(request, 0, sizeof(*request)); request->hr_httpd = httpd; request->hr_allow = request->hr_host = NULL; request->hr_content_type = request->hr_content_length = NULL; request->hr_range = NULL; request->hr_last_byte_pos = -1; request->hr_if_modified_since = NULL; request->hr_virthostname = NULL; request->hr_file = NULL; request->hr_oldfile = NULL; SIMPLEQ_INIT(&request->hr_replheaders); bozo_auth_init(request); slen = sizeof(ss); if (getpeername(0, (struct sockaddr *)(void *)&ss, &slen) < 0) host = addr = NULL; else { if (getnameinfo((struct sockaddr *)(void *)&ss, slen, abuf, sizeof abuf, NULL, 0, NI_NUMERICHOST) == 0) addr = abuf; else addr = NULL; if (httpd->numeric == 0 && getnameinfo((struct sockaddr *)(void *)&ss, slen, hbuf, sizeof hbuf, NULL, 0, 0) == 0) host = hbuf; else host = NULL; } if (host != NULL) request->hr_remotehost = bozostrdup(httpd, request, host); if (addr != NULL) request->hr_remoteaddr = bozostrdup(httpd, request, addr); slen = sizeof(ss); /* * Override the bound port from the request value, so it works even * if passed through a proxy that doesn't rewrite the port. */ if (httpd->bindport) { if (strcmp(httpd->bindport, "80") != 0) port = httpd->bindport; else port = NULL; } else { if (getsockname(0, (struct sockaddr *)(void *)&ss, &slen) < 0) port = NULL; else { if (getnameinfo((struct sockaddr *)(void *)&ss, slen, NULL, 0, bufport, sizeof bufport, NI_NUMERICSERV) == 0) port = bufport; else port = NULL; } } if (port != NULL) request->hr_serverport = bozostrdup(httpd, request, port); /* * setup a timer to make sure the request is not hung */ sa.sa_handler = alarmer; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGALRM); sa.sa_flags = 0; sigaction(SIGALRM, &sa, NULL); alarm(MAX_WAIT_TIME); while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) { alarm(0); if (alarmhit) { (void)bozo_http_error(httpd, 408, NULL, "request timed out"); goto cleanup; } line++; if (line == 1) { if (len < 1) { (void)bozo_http_error(httpd, 404, NULL, "null method"); goto cleanup; } bozowarn(httpd, "got request ``%s'' from host %s to port %s", str, host ? host : addr ? addr : "<local>", port ? port : "<stdin>"); /* we allocate return space in file and query only */ parse_request(httpd, str, &method, &file, &query, &proto); request->hr_file = file; request->hr_query = query; if (method == NULL) { (void)bozo_http_error(httpd, 404, NULL, "null method"); goto cleanup; } if (file == NULL) { (void)bozo_http_error(httpd, 404, NULL, "null file"); goto cleanup; } /* * note that we parse the proto first, so that we * can more properly parse the method and the url. */ if (process_proto(request, proto) || process_method(request, method)) { goto cleanup; } debug((httpd, DEBUG_FAT, "got file \"%s\" query \"%s\"", request->hr_file, request->hr_query ? request->hr_query : "<none>")); /* http/0.9 has no header processing */ if (request->hr_proto == httpd->consts.http_09) break; } else { /* incoming headers */ bozoheaders_t *hdr; if (*str == '\0') break; val = bozostrnsep(&str, ":", &len); debug((httpd, DEBUG_EXPLODING, "read_req2: after bozostrnsep: str ``%s'' val ``%s''", str, val)); if (val == NULL || len == -1) { (void)bozo_http_error(httpd, 404, request, "no header"); goto cleanup; } while (*str == ' ' || *str == '\t') len--, str++; while (*val == ' ' || *val == '\t') val++; if (bozo_auth_check_headers(request, val, str, len)) goto next_header; hdr = addmerge_reqheader(request, val, str, len); if (strcasecmp(hdr->h_header, "content-type") == 0) request->hr_content_type = hdr->h_value; else if (strcasecmp(hdr->h_header, "content-length") == 0) request->hr_content_length = hdr->h_value; else if (strcasecmp(hdr->h_header, "host") == 0) request->hr_host = bozostrdup(httpd, request, hdr->h_value); /* RFC 2616 (HTTP/1.1): 14.20 */ else if (strcasecmp(hdr->h_header, "expect") == 0) { (void)bozo_http_error(httpd, 417, request, "we don't support Expect:"); goto cleanup; } else if (strcasecmp(hdr->h_header, "referrer") == 0 || strcasecmp(hdr->h_header, "referer") == 0) request->hr_referrer = hdr->h_value; else if (strcasecmp(hdr->h_header, "range") == 0) request->hr_range = hdr->h_value; else if (strcasecmp(hdr->h_header, "if-modified-since") == 0) request->hr_if_modified_since = hdr->h_value; else if (strcasecmp(hdr->h_header, "accept-encoding") == 0) request->hr_accept_encoding = hdr->h_value; debug((httpd, DEBUG_FAT, "adding header %s: %s", hdr->h_header, hdr->h_value)); } next_header: alarm(MAX_WAIT_TIME); } /* now, clear it all out */ alarm(0); signal(SIGALRM, SIG_DFL); /* RFC1945, 8.3 */ if (request->hr_method == HTTP_POST && request->hr_content_length == NULL) { (void)bozo_http_error(httpd, 400, request, "missing content length"); goto cleanup; } /* RFC 2616 (HTTP/1.1), 14.23 & 19.6.1.1 */ if (request->hr_proto == httpd->consts.http_11 && /*(strncasecmp(request->hr_file, "http://", 7) != 0) &&*/ request->hr_host == NULL) { (void)bozo_http_error(httpd, 400, request, "missing Host header"); goto cleanup; } if (request->hr_range != NULL) { debug((httpd, DEBUG_FAT, "hr_range: %s", request->hr_range)); /* support only simple ranges %d- and %d-%d */ if (strchr(request->hr_range, ',') == NULL) { const char *rstart, *dash; rstart = strchr(request->hr_range, '='); if (rstart != NULL) { rstart++; dash = strchr(rstart, '-'); if (dash != NULL && dash != rstart) { dash++; request->hr_have_range = 1; request->hr_first_byte_pos = strtoll(rstart, NULL, 10); if (request->hr_first_byte_pos < 0) request->hr_first_byte_pos = 0; if (*dash != '\0') { request->hr_last_byte_pos = strtoll(dash, NULL, 10); if (request->hr_last_byte_pos < 0) request->hr_last_byte_pos = -1; } } } } } debug((httpd, DEBUG_FAT, "bozo_read_request returns url %s in request", request->hr_file)); return request; cleanup: bozo_clean_request(request); return NULL; } static int mmap_and_write_part(bozohttpd_t *httpd, int fd, off_t first_byte_pos, size_t sz) { size_t mappedsz, wroffset; off_t mappedoffset; char *addr; void *mappedaddr; /* * we need to ensure that both the size *and* offset arguments to * mmap() are page-aligned. our formala for this is: * * input offset: first_byte_pos * input size: sz * * mapped offset = page align truncate (input offset) * mapped size = * page align extend (input offset - mapped offset + input size) * write offset = input offset - mapped offset * * we use the write offset in all writes */ mappedoffset = first_byte_pos & ~(httpd->page_size - 1); mappedsz = (size_t) (first_byte_pos - mappedoffset + sz + httpd->page_size - 1) & ~(httpd->page_size - 1); wroffset = (size_t)(first_byte_pos - mappedoffset); addr = mmap(0, mappedsz, PROT_READ, MAP_SHARED, fd, mappedoffset); if (addr == (char *)-1) { bozowarn(httpd, "mmap failed: %s", strerror(errno)); return -1; } mappedaddr = addr; #ifdef MADV_SEQUENTIAL (void)madvise(addr, sz, MADV_SEQUENTIAL); #endif while (sz > BOZO_WRSZ) { if (bozo_write(httpd, STDOUT_FILENO, addr + wroffset, BOZO_WRSZ) != BOZO_WRSZ) { bozowarn(httpd, "write failed: %s", strerror(errno)); goto out; } debug((httpd, DEBUG_OBESE, "wrote %d bytes", BOZO_WRSZ)); sz -= BOZO_WRSZ; addr += BOZO_WRSZ; } if (sz && (size_t)bozo_write(httpd, STDOUT_FILENO, addr + wroffset, sz) != sz) { bozowarn(httpd, "final write failed: %s", strerror(errno)); goto out; } debug((httpd, DEBUG_OBESE, "wrote %d bytes", (int)sz)); out: if (munmap(mappedaddr, mappedsz) < 0) { bozowarn(httpd, "munmap failed"); return -1; } return 0; } static int parse_http_date(const char *val, time_t *timestamp) { char *remainder; struct tm tm; if ((remainder = strptime(val, "%a, %d %b %Y %T GMT", &tm)) == NULL && (remainder = strptime(val, "%a, %d-%b-%y %T GMT", &tm)) == NULL && (remainder = strptime(val, "%a %b %d %T %Y", &tm)) == NULL) return 0; /* Invalid HTTP date format */ if (*remainder) return 0; /* No trailing garbage */ *timestamp = timegm(&tm); return 1; } /* * given an url, encode it ala rfc 3986. ie, escape ? and friends. * note that this function returns a static buffer, and thus needs * to be updated for any sort of parallel processing. escape only * chosen characters for absolute redirects */ char * bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute) { static char *buf; static size_t buflen = 0; size_t len; const char *s; char *d; len = strlen(url); if (buflen < len * 3 + 1) { buflen = len * 3 + 1; buf = bozorealloc(httpd, buf, buflen); } for (len = 0, s = url, d = buf; *s;) { if (*s & 0x80) goto encode_it; switch (*s) { case ':': case '?': case '#': case '[': case ']': case '@': case '!': case '$': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case ';': case '=': case '%': case '"': if (absolute) goto leave_it; case '\n': case '\r': case ' ': encode_it: snprintf(d, 4, "%%%02X", *s++); d += 3; len += 3; break; leave_it: default: *d++ = *s++; len++; break; } } buf[len] = 0; return buf; } /* * do automatic redirection -- if there are query parameters or userdir for * the URL we will tack these on to the new (redirected) URL. */ static void handle_redirect(bozo_httpreq_t *request, const char *url, int absolute) { bozohttpd_t *httpd = request->hr_httpd; char *finalurl, *urlbuf; #ifndef NO_USER_SUPPORT char *userbuf; #endif /* !NO_USER_SUPPORT */ char portbuf[20]; const char *scheme, *query, *quest; const char *hostname = BOZOHOST(httpd, request); int absproto = 0; /* absolute redirect provides own schema */ if (url == NULL) { bozoasprintf(httpd, &urlbuf, "/%s/", request->hr_file); url = urlbuf; } else urlbuf = NULL; #ifndef NO_USER_SUPPORT if (request->hr_user && !absolute) { bozoasprintf(httpd, &userbuf, "/~%s%s", request->hr_user, url); url = userbuf; } else userbuf = NULL; #endif /* !NO_USER_SUPPORT */ if (absolute) { char *sep = NULL; const char *s; /* * absolute redirect may specify own protocol i.e. to redirect * to another schema like https:// or ftp://. * Details: RFC 3986, section 3. */ /* 1. check if url contains :// */ sep = strstr(url, "://"); /* * RFC 3986, section 3.1: * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */ if (sep) { for (s = url; s != sep;) { if (!isalnum((int)*s) && *s != '+' && *s != '-' && *s != '.') break; if (++s == sep) { absproto = 1; } } } } /* construct final redirection url */ scheme = absproto ? "" : httpd->sslinfo ? "https://" : "http://"; if (absolute) { hostname = ""; portbuf[0] = '\0'; } else { const char *defport = httpd->sslinfo ? "443" : "80"; if (request->hr_serverport && strcmp(request->hr_serverport, defport) != 0) snprintf(portbuf, sizeof(portbuf), ":%s", request->hr_serverport); else portbuf[0] = '\0'; } url = bozo_escape_rfc3986(httpd, url, absolute); if (request->hr_query && strlen(request->hr_query)) { query = request->hr_query; quest = "?"; } else { query = quest = ""; } bozoasprintf(httpd, &finalurl, "%s%s%s%s%s%s", scheme, hostname, portbuf, url, quest, query); bozowarn(httpd, "redirecting %s", finalurl); debug((httpd, DEBUG_FAT, "redirecting %s", finalurl)); bozo_printf(httpd, "%s 301 Document Moved\r\n", request->hr_proto); if (request->hr_proto != httpd->consts.http_09) bozo_print_header(request, NULL, "text/html", NULL); if (request->hr_proto != httpd->consts.http_09) bozo_printf(httpd, "Location: %s\r\n", finalurl); bozo_printf(httpd, "\r\n"); if (request->hr_method == HTTP_HEAD) goto head; bozo_printf(httpd, "<html><head><title>Document Moved</title></head>\n"); bozo_printf(httpd, "<body><h1>Document Moved</h1>\n"); bozo_printf(httpd, "This document had moved <a href=\"%s\">here</a>\n", finalurl); bozo_printf(httpd, "</body></html>\n"); head: bozo_flush(httpd, stdout); free(urlbuf); free(finalurl); #ifndef NO_USER_SUPPORT free(userbuf); #endif /* !NO_USER_SUPPORT */ } /* * deal with virtual host names; we do this: * if we have a virtual path root (httpd->virtbase), and we are given a * virtual host spec (Host: ho.st or http://ho.st/), see if this * directory exists under httpd->virtbase. if it does, use this as the # new slashdir. */ static int check_virtual(bozo_httpreq_t *request) { bozohttpd_t *httpd = request->hr_httpd; char *file = request->hr_file, *s; size_t len; /* * convert http://virtual.host/ to request->hr_host */ debug((httpd, DEBUG_OBESE, "checking for http:// virtual host in ``%s''", file)); if (strncasecmp(file, "http://", 7) == 0) { /* we would do virtual hosting here? */ file += 7; /* RFC 2616 (HTTP/1.1), 5.2: URI takes precedence over Host: */ free(request->hr_host); request->hr_host = bozostrdup(httpd, request, file); if ((s = strchr(request->hr_host, '/')) != NULL) *s = '\0'; s = strchr(file, '/'); free(request->hr_file); request->hr_file = bozostrdup(httpd, request, s ? s : "/"); debug((httpd, DEBUG_OBESE, "got host ``%s'' file is now ``%s''", request->hr_host, request->hr_file)); } else if (!request->hr_host) goto use_slashdir; /* * canonicalise hr_host - that is, remove any :80. */ len = strlen(request->hr_host); if (len > 3 && strcmp(request->hr_host + len - 3, ":80") == 0) { request->hr_host[len - 3] = '\0'; len = strlen(request->hr_host); } if (!httpd->virtbase) { /* * if we don't use vhost support, then set virthostname if * user supplied Host header. It will be used for possible * redirections */ if (request->hr_host) { s = strrchr(request->hr_host, ':'); if (s != NULL) /* truncate Host: as we want to copy it without port part */ *s = '\0'; request->hr_virthostname = bozostrdup(httpd, request, request->hr_host); if (s != NULL) /* fix Host: again, if we truncated it */ *s = ':'; } goto use_slashdir; } /* * ok, we have a virtual host, use opendir(3) to find a case * insensitive match for the virtual host we are asked for. * note that if the virtual host is the same as the master, * we don't need to do anything special. */ debug((httpd, DEBUG_OBESE, "check_virtual: checking host `%s' under httpd->virtbase `%s' " "for file `%s'", request->hr_host, httpd->virtbase, request->hr_file)); if (strncasecmp(httpd->virthostname, request->hr_host, len) != 0) { s = 0; DIR *dirp; struct dirent *d; if ((dirp = opendir(httpd->virtbase)) != NULL) { while ((d = readdir(dirp)) != NULL) { if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) { continue; } debug((httpd, DEBUG_OBESE, "looking at dir``%s''", d->d_name)); if (strcmp(d->d_name, request->hr_host) == 0) { /* found it, punch it */ debug((httpd, DEBUG_OBESE, "found it punch it")); request->hr_virthostname = bozostrdup(httpd, request, d->d_name); bozoasprintf(httpd, &s, "%s/%s", httpd->virtbase, request->hr_virthostname); break; } } closedir(dirp); } else { debug((httpd, DEBUG_FAT, "opendir %s failed: %s", httpd->virtbase, strerror(errno))); } if (s == 0) { if (httpd->unknown_slash) goto use_slashdir; return bozo_http_error(httpd, 404, request, "unknown URL"); } } else use_slashdir: s = httpd->slashdir; /* * ok, nailed the correct slashdir, chdir to it */ if (chdir(s) < 0) return bozo_http_error(httpd, 404, request, "can't chdir to slashdir"); return 0; } /* * checks to see if this request has a valid .bzredirect file. returns * 0 when no redirection happend, or 1 when handle_redirect() has been * called, -1 on error. */ static int check_bzredirect(bozo_httpreq_t *request) { bozohttpd_t *httpd = request->hr_httpd; struct stat sb; char dir[MAXPATHLEN], redir[MAXPATHLEN], redirpath[MAXPATHLEN + 1], path[MAXPATHLEN]; char *basename, *finalredir; int rv, absolute; /* * if this pathname is really a directory, but doesn't end in /, * use it as the directory to look for the redir file. */ if((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >= sizeof(dir)) { bozo_http_error(httpd, 404, request, "file path too long"); return -1; } debug((httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir)); basename = strrchr(dir, '/'); if ((!basename || basename[1] != '\0') && lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) { strcpy(path, dir); } else if (basename == NULL) { strcpy(path, "."); strcpy(dir, ""); } else { *basename++ = '\0'; bozo_check_special_files(request, basename); strcpy(path, dir); } debug((httpd, DEBUG_FAT, "check_bzredirect: path %s", path)); if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", path, REDIRECT_FILE) >= sizeof(redir)) { bozo_http_error(httpd, 404, request, "redirectfile path too long"); return -1; } if (lstat(redir, &sb) == 0) { if (!S_ISLNK(sb.st_mode)) return 0; absolute = 0; } else { if((size_t)snprintf(redir, sizeof(redir), "%s/%s", path, ABSREDIRECT_FILE) >= sizeof(redir)) { bozo_http_error(httpd, 404, request, "redirectfile path too long"); return -1; } if (lstat(redir, &sb) < 0 || !S_ISLNK(sb.st_mode)) return 0; absolute = 1; } debug((httpd, DEBUG_FAT, "check_bzredirect: calling readlink")); rv = readlink(redir, redirpath, sizeof redirpath - 1); if (rv == -1 || rv == 0) { debug((httpd, DEBUG_FAT, "readlink failed")); return 0; } redirpath[rv] = '\0'; debug((httpd, DEBUG_FAT, "readlink returned \"%s\"", redirpath)); /* check if we need authentication */ snprintf(path, sizeof(path), "%s/", dir); if (bozo_auth_check(request, path)) return 1; /* now we have the link pointer, redirect to the real place */ if (!absolute && redirpath[0] != '/') { if ((size_t)snprintf(finalredir = redir, sizeof(redir), "%s%s/%s", (strlen(dir) > 0 ? "/" : ""), dir, redirpath) >= sizeof(redir)) { bozo_http_error(httpd, 404, request, "redirect path too long"); return -1; } } else finalredir = redirpath; debug((httpd, DEBUG_FAT, "check_bzredirect: new redir %s", finalredir)); handle_redirect(request, finalredir, absolute); return 1; } /* this fixes the %HH hack that RFC2396 requires. */ int bozo_decode_url_percent(bozo_httpreq_t *request, char *str) { bozohttpd_t *httpd = request->hr_httpd; char *s, *t, buf[3]; char *end; /* if end is not-zero, we don't translate beyond that */ end = str + strlen(str); /* fast forward to the first % */ if ((s = strchr(str, '%')) == NULL) return 0; t = s; do { if (end && s >= end) { debug((httpd, DEBUG_EXPLODING, "fu_%%: past end, filling out..")); while (*s) *t++ = *s++; break; } debug((httpd, DEBUG_EXPLODING, "fu_%%: got s == %%, s[1]s[2] == %c%c", s[1], s[2])); if (s[1] == '\0' || s[2] == '\0') { (void)bozo_http_error(httpd, 400, request, "percent hack missing two chars afterwards"); return 1; } if (s[1] == '0' && s[2] == '0') { (void)bozo_http_error(httpd, 404, request, "percent hack was %00"); return 1; } if (s[1] == '2' && s[2] == 'f') { (void)bozo_http_error(httpd, 404, request, "percent hack was %2f (/)"); return 1; } buf[0] = *++s; buf[1] = *++s; buf[2] = '\0'; s++; *t = (char)strtol(buf, NULL, 16); debug((httpd, DEBUG_EXPLODING, "fu_%%: strtol put '%02x' into *t", *t)); if (*t++ == '\0') { (void)bozo_http_error(httpd, 400, request, "percent hack got a 0 back"); return 1; } while (*s && *s != '%') { if (end && s >= end) break; *t++ = *s++; } } while (*s); *t = '\0'; debug((httpd, DEBUG_FAT, "bozo_decode_url_percent returns `%s'", request->hr_file)); return 0; } /* * transform_request does this: * - ``expand'' %20 crapola * - punt if it doesn't start with / * - look for "http://myname/" and deal with it. * - maybe call bozo_process_cgi() * - check for ~user and call bozo_user_transform() if so * - if the length > 1, check for trailing slash. if so, * add the index.html file * - if the length is 1, return the index.html file * - disallow anything ending up with a file starting * at "/" or having ".." in it. * - anything else is a really weird internal error * - returns malloced file to serve, if unhandled */ static int transform_request(bozo_httpreq_t *request, int *isindex) { bozohttpd_t *httpd = request->hr_httpd; char *file, *newfile = NULL; size_t len; file = NULL; *isindex = 0; debug((httpd, DEBUG_FAT, "tf_req: file %s", request->hr_file)); if (bozo_decode_url_percent(request, request->hr_file)) { goto bad_done; } if (check_virtual(request)) { goto bad_done; } file = request->hr_file; if (file[0] != '/') { (void)bozo_http_error(httpd, 404, request, "unknown URL"); goto bad_done; } /* omit additional slashes at the beginning */ while (file[1] == '/') file++; /* fix file provided by user as it's used in other handlers */ request->hr_file = file; len = strlen(file); #ifndef NO_USER_SUPPORT /* first of all expand user path */ if (len > 1 && httpd->enable_users && file[1] == '~') { if (file[2] == '\0') { (void)bozo_http_error(httpd, 404, request, "missing username"); goto bad_done; } if (strchr(file + 2, '/') == NULL) { char *userredirecturl; bozoasprintf(httpd, &userredirecturl, "%s/", file); handle_redirect(request, userredirecturl, 0); free(userredirecturl); return 0; } debug((httpd, DEBUG_FAT, "calling bozo_user_transform")); if (!bozo_user_transform(request)) return 0; file = request->hr_file; len = strlen(file); } #endif /* NO_USER_SUPPORT */ switch (check_bzredirect(request)) { case -1: goto bad_done; case 1: return 0; } if (len > 1) { debug((httpd, DEBUG_FAT, "file[len-1] == %c", file[len-1])); if (file[len-1] == '/') { /* append index.html */ *isindex = 1; debug((httpd, DEBUG_FAT, "appending index.html")); newfile = bozomalloc(httpd, len + strlen(httpd->index_html) + 1); strcpy(newfile, file + 1); strcat(newfile, httpd->index_html); } else newfile = bozostrdup(httpd, request, file + 1); } else if (len == 1) { debug((httpd, DEBUG_EXPLODING, "tf_req: len == 1")); newfile = bozostrdup(httpd, request, httpd->index_html); *isindex = 1; } else { /* len == 0 ? */ (void)bozo_http_error(httpd, 500, request, "request->hr_file is nul?"); goto bad_done; } if (newfile == NULL) { (void)bozo_http_error(httpd, 500, request, "internal failure"); goto bad_done; } /* * stop traversing outside our domain * * XXX true security only comes from our parent using chroot(2) * before execve(2)'ing us. or our own built in chroot(2) support. */ debug((httpd, DEBUG_FAT, "newfile: %s", newfile)); if (*newfile == '/' || strcmp(newfile, "..") == 0 || strstr(newfile, "/..") || strstr(newfile, "../")) { (void)bozo_http_error(httpd, 403, request, "illegal request"); goto bad_done; } if (bozo_auth_check(request, newfile)) goto bad_done; if (strlen(newfile)) { request->hr_oldfile = request->hr_file; request->hr_file = newfile; } if (bozo_process_cgi(request)) return 0; if (bozo_process_lua(request)) return 0; debug((httpd, DEBUG_FAT, "transform_request set: %s", newfile)); return 1; bad_done: debug((httpd, DEBUG_FAT, "transform_request returning: 0")); free(newfile); return 0; } /* * can_gzip checks if the request supports and prefers gzip encoding. * * XXX: we do not consider the associated q with gzip in making our * decision which is broken. */ static int can_gzip(bozo_httpreq_t *request) { const char *pos; const char *tmp; size_t len; /* First we decide if the request can be gzipped at all. */ /* not if we already are encoded... */ tmp = bozo_content_encoding(request, request->hr_file); if (tmp && *tmp) return 0; /* not if we are not asking for the whole file... */ if (request->hr_last_byte_pos != -1 || request->hr_have_range) return 0; /* Then we determine if gzip is on the cards. */ for (pos = request->hr_accept_encoding; pos && *pos; pos += len) { while (*pos == ' ') pos++; len = strcspn(pos, ";,"); if ((len == 4 && strncasecmp("gzip", pos, 4) == 0) || (len == 6 && strncasecmp("x-gzip", pos, 6) == 0)) return 1; if (pos[len] == ';') len += strcspn(&pos[len], ","); if (pos[len]) len++; } return 0; } /* * bozo_process_request does the following: * - check the request is valid * - process cgi-bin if necessary * - transform a filename if necesarry * - return the HTTP request */ void bozo_process_request(bozo_httpreq_t *request) { bozohttpd_t *httpd = request->hr_httpd; struct stat sb; time_t timestamp; char *file; const char *type, *encoding; int fd, isindex; /* * note that transform_request chdir()'s if required. also note * that cgi is handed here. if transform_request() returns 0 * then the request has been handled already. */ if (transform_request(request, &isindex) == 0) return; fd = -1; encoding = NULL; if (can_gzip(request)) { bozoasprintf(httpd, &file, "%s.gz", request->hr_file); fd = open(file, O_RDONLY); if (fd >= 0) encoding = "gzip"; free(file); } file = request->hr_file; if (fd < 0) fd = open(file, O_RDONLY); if (fd < 0) { debug((httpd, DEBUG_FAT, "open failed: %s", strerror(errno))); switch (errno) { case EPERM: case EACCES: (void)bozo_http_error(httpd, 403, request, "no permission to open file"); break; case ENAMETOOLONG: /*FALLTHROUGH*/ case ENOENT: if (!bozo_dir_index(request, file, isindex)) (void)bozo_http_error(httpd, 404, request, "no file"); break; default: (void)bozo_http_error(httpd, 500, request, "open file"); } goto cleanup_nofd; } if (fstat(fd, &sb) < 0) { (void)bozo_http_error(httpd, 500, request, "can't fstat"); goto cleanup; } if (S_ISDIR(sb.st_mode)) { handle_redirect(request, NULL, 0); goto cleanup; } if (request->hr_if_modified_since && parse_http_date(request->hr_if_modified_since, ×tamp) && timestamp >= sb.st_mtime) { /* XXX ignore subsecond of timestamp */ bozo_printf(httpd, "%s 304 Not Modified\r\n", request->hr_proto); bozo_printf(httpd, "\r\n"); bozo_flush(httpd, stdout); goto cleanup; } /* validate requested range */ if (request->hr_last_byte_pos == -1 || request->hr_last_byte_pos >= sb.st_size) request->hr_last_byte_pos = sb.st_size - 1; if (request->hr_have_range && request->hr_first_byte_pos > request->hr_last_byte_pos) { request->hr_have_range = 0; /* punt */ request->hr_first_byte_pos = 0; request->hr_last_byte_pos = sb.st_size - 1; } debug((httpd, DEBUG_FAT, "have_range %d first_pos %lld last_pos %lld", request->hr_have_range, (long long)request->hr_first_byte_pos, (long long)request->hr_last_byte_pos)); if (request->hr_have_range) bozo_printf(httpd, "%s 206 Partial Content\r\n", request->hr_proto); else bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto); if (request->hr_proto != httpd->consts.http_09) { type = bozo_content_type(request, file); if (!encoding) encoding = bozo_content_encoding(request, file); bozo_print_header(request, &sb, type, encoding); bozo_printf(httpd, "\r\n"); } bozo_flush(httpd, stdout); if (request->hr_method != HTTP_HEAD) { off_t szleft, cur_byte_pos; szleft = request->hr_last_byte_pos - request->hr_first_byte_pos + 1; cur_byte_pos = request->hr_first_byte_pos; retry: while (szleft) { size_t sz; if ((off_t)httpd->mmapsz < szleft) sz = httpd->mmapsz; else sz = (size_t)szleft; if (mmap_and_write_part(httpd, fd, cur_byte_pos, sz)) { if (errno == ENOMEM) { httpd->mmapsz /= 2; if (httpd->mmapsz >= httpd->page_size) goto retry; } goto cleanup; } cur_byte_pos += sz; szleft -= sz; } } cleanup: close(fd); cleanup_nofd: close(STDIN_FILENO); close(STDOUT_FILENO); /*close(STDERR_FILENO);*/ } /* make sure we're not trying to access special files */ int bozo_check_special_files(bozo_httpreq_t *request, const char *name) { bozohttpd_t *httpd = request->hr_httpd; /* ensure basename(name) != special files */ if (strcmp(name, DIRECT_ACCESS_FILE) == 0) return bozo_http_error(httpd, 403, request, "no permission to open direct access file"); if (strcmp(name, REDIRECT_FILE) == 0) return bozo_http_error(httpd, 403, request, "no permission to open redirect file"); if (strcmp(name, ABSREDIRECT_FILE) == 0) return bozo_http_error(httpd, 403, request, "no permission to open redirect file"); return bozo_auth_check_special_files(request, name); } /* generic header printing routine */ void bozo_print_header(bozo_httpreq_t *request, struct stat *sbp, const char *type, const char *encoding) { bozohttpd_t *httpd = request->hr_httpd; off_t len; char date[40]; bozoheaders_t *hdr; SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) { bozo_printf(httpd, "%s: %s\r\n", hdr->h_header, hdr->h_value); } bozo_printf(httpd, "Date: %s\r\n", bozo_http_date(date, sizeof(date))); bozo_printf(httpd, "Server: %s\r\n", httpd->server_software); bozo_printf(httpd, "Accept-Ranges: bytes\r\n"); if (sbp) { char filedate[40]; struct tm *tm; tm = gmtime(&sbp->st_mtime); strftime(filedate, sizeof filedate, "%a, %d %b %Y %H:%M:%S GMT", tm); bozo_printf(httpd, "Last-Modified: %s\r\n", filedate); } if (type && *type) bozo_printf(httpd, "Content-Type: %s\r\n", type); if (encoding && *encoding) bozo_printf(httpd, "Content-Encoding: %s\r\n", encoding); if (sbp) { if (request->hr_have_range) { len = request->hr_last_byte_pos - request->hr_first_byte_pos +1; bozo_printf(httpd, "Content-Range: bytes %qd-%qd/%qd\r\n", (long long) request->hr_first_byte_pos, (long long) request->hr_last_byte_pos, (long long) sbp->st_size); } else len = sbp->st_size; bozo_printf(httpd, "Content-Length: %qd\r\n", (long long)len); } if (request->hr_proto == httpd->consts.http_11) bozo_printf(httpd, "Connection: close\r\n"); bozo_flush(httpd, stdout); } #ifndef NO_DEBUG void debug__(bozohttpd_t *httpd, int level, const char *fmt, ...) { va_list ap; int savederrno; /* only log if the level is low enough */ if (httpd->debug < level) return; savederrno = errno; va_start(ap, fmt); if (httpd->logstderr) { vfprintf(stderr, fmt, ap); fputs("\n", stderr); } else vsyslog(LOG_DEBUG, fmt, ap); va_end(ap); errno = savederrno; } #endif /* NO_DEBUG */ /* these are like warn() and err(), except for syslog not stderr */ void bozowarn(bozohttpd_t *httpd, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (httpd->logstderr || isatty(STDERR_FILENO)) { //fputs("warning: ", stderr); vfprintf(stderr, fmt, ap); fputs("\n", stderr); } else vsyslog(LOG_INFO, fmt, ap); va_end(ap); } void bozoerr(bozohttpd_t *httpd, int code, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (httpd->logstderr || isatty(STDERR_FILENO)) { //fputs("error: ", stderr); vfprintf(stderr, fmt, ap); fputs("\n", stderr); } else vsyslog(LOG_ERR, fmt, ap); va_end(ap); exit(code); } void bozoasprintf(bozohttpd_t *httpd, char **str, const char *fmt, ...) { va_list ap; int e; va_start(ap, fmt); e = vasprintf(str, fmt, ap); va_end(ap); if (e < 0) bozoerr(httpd, EXIT_FAILURE, "asprintf"); } /* * this escapes HTML tags. returns allocated escaped * string if needed, or NULL on allocation failure or * lack of escape need. * call with NULL httpd in error paths, to avoid recursive * malloc failure. call with valid httpd in normal paths * to get automatic allocation failure handling. */ char * bozo_escape_html(bozohttpd_t *httpd, const char *url) { int i, j; char *tmp; size_t len; for (i = 0, j = 0; url[i]; i++) { switch (url[i]) { case '<': case '>': j += 4; break; case '&': j += 5; break; } } if (j == 0) return NULL; /* * we need to handle being called from different * pathnames. */ len = strlen(url) + j; if (httpd) tmp = bozomalloc(httpd, len); else if ((tmp = malloc(len)) == 0) return NULL; for (i = 0, j = 0; url[i]; i++) { switch (url[i]) { case '<': memcpy(tmp + j, "<", 4); j += 4; break; case '>': memcpy(tmp + j, ">", 4); j += 4; break; case '&': memcpy(tmp + j, "&", 5); j += 5; break; default: tmp[j++] = url[i]; } } tmp[j] = 0; return tmp; } /* short map between error code, and short/long messages */ static struct errors_map { int code; /* HTTP return code */ const char *shortmsg; /* short version of message */ const char *longmsg; /* long version of message */ } errors_map[] = { { 400, "400 Bad Request", "The request was not valid", }, { 401, "401 Unauthorized", "No authorization", }, { 403, "403 Forbidden", "Access to this item has been denied",}, { 404, "404 Not Found", "This item has not been found", }, { 408, "408 Request Timeout", "This request took too long", }, { 417, "417 Expectation Failed","Expectations not available", }, { 420, "420 Enhance Your Calm","Chill, Winston", }, { 500, "500 Internal Error", "An error occured on the server", }, { 501, "501 Not Implemented", "This request is not available", }, { 0, NULL, NULL, }, }; static const char *help = "DANGER! WILL ROBINSON! DANGER!"; static const char * http_errors_short(int code) { struct errors_map *ep; for (ep = errors_map; ep->code; ep++) if (ep->code == code) return (ep->shortmsg); return (help); } static const char * http_errors_long(int code) { struct errors_map *ep; for (ep = errors_map; ep->code; ep++) if (ep->code == code) return (ep->longmsg); return (help); } /* the follow functions and variables are used in handling HTTP errors */ /* ARGSUSED */ int bozo_http_error(bozohttpd_t *httpd, int code, bozo_httpreq_t *request, const char *msg) { char portbuf[20]; const char *header = http_errors_short(code); const char *reason = http_errors_long(code); const char *proto = (request && request->hr_proto) ? request->hr_proto : httpd->consts.http_11; int size; bozoheaders_t *hdr; debug((httpd, DEBUG_FAT, "bozo_http_error %d: %s", code, msg)); if (header == NULL || reason == NULL) { bozoerr(httpd, 1, "bozo_http_error() failed (short = %p, long = %p)", header, reason); return code; } if (request && request->hr_serverport && strcmp(request->hr_serverport, "80") != 0) snprintf(portbuf, sizeof(portbuf), ":%s", request->hr_serverport); else portbuf[0] = '\0'; if (request && request->hr_file) { char *file = NULL, *user = NULL, *user_escaped = NULL; int file_alloc = 0; const char *hostname = BOZOHOST(httpd, request); /* bozo_escape_html() failure here is just too bad. */ file = bozo_escape_html(NULL, request->hr_file); if (file == NULL) file = request->hr_file; else file_alloc = 1; #ifndef NO_USER_SUPPORT if (request->hr_user != NULL) { user_escaped = bozo_escape_html(NULL, request->hr_user); if (user_escaped == NULL) user_escaped = request->hr_user; /* expand username to ~user/ */ bozoasprintf(httpd, &user, "~%s/", user_escaped); if (user_escaped != request->hr_user) free(user_escaped); } #endif /* !NO_USER_SUPPORT */ size = snprintf(httpd->errorbuf, BUFSIZ, "<html><head><title>%s</title></head>\n" "<body><h1>%s</h1>\n" "%s%s: <pre>%s</pre>\n" "<hr><address><a href=\"http://%s%s/\">%s%s</a></address>\n" "</body></html>\n", header, header, user ? user : "", file, reason, hostname, portbuf, hostname, portbuf); free(user); if (size >= (int)BUFSIZ) { bozowarn(httpd, "bozo_http_error buffer too small, truncated"); size = (int)BUFSIZ; } if (file_alloc) free(file); } else size = 0; bozo_printf(httpd, "%s %s\r\n", proto, header); if (request) { bozo_auth_check_401(request, code); SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) { bozo_printf(httpd, "%s: %s\r\n", hdr->h_header, hdr->h_value); } } bozo_printf(httpd, "Content-Type: text/html\r\n"); bozo_printf(httpd, "Content-Length: %d\r\n", size); bozo_printf(httpd, "Server: %s\r\n", httpd->server_software); if (request && request->hr_allow) bozo_printf(httpd, "Allow: %s\r\n", request->hr_allow); bozo_printf(httpd, "\r\n"); /* According to the RFC 2616 sec. 9.4 HEAD method MUST NOT return a * message-body in the response */ if (size && request && request->hr_method != HTTP_HEAD) bozo_printf(httpd, "%s", httpd->errorbuf); bozo_flush(httpd, stdout); return code; } /* Below are various modified libc functions */ /* * returns -1 in lenp if the string ran out before finding a delimiter, * but is otherwise the same as strsep. Note that the length must be * correctly passed in. */ char * bozostrnsep(char **strp, const char *delim, ssize_t *lenp) { char *s; const char *spanp; int c, sc; char *tok; if ((s = *strp) == NULL) return (NULL); for (tok = s;;) { if (lenp && --(*lenp) == -1) return (NULL); c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = '\0'; *strp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } /* * inspired by fgetln(3), but works for fd's. should work identically * except it, however, does *not* return the newline, and it does nul * terminate the string. */ char * bozodgetln(bozohttpd_t *httpd, int fd, ssize_t *lenp, ssize_t (*readfn)(bozohttpd_t *, int, void *, size_t)) { ssize_t len; int got_cr = 0; char c, *nbuffer; /* initialise */ if (httpd->getln_buflen == 0) { /* should be plenty for most requests */ httpd->getln_buflen = 128; httpd->getln_buffer = malloc((size_t)httpd->getln_buflen); if (httpd->getln_buffer == NULL) { httpd->getln_buflen = 0; return NULL; } } len = 0; /* * we *have* to read one byte at a time, to not break cgi * programs (for we pass stdin off to them). could fix this * by becoming a fd-passing program instead of just exec'ing * the program * * the above is no longer true, we are the fd-passing * program already. */ for (; readfn(httpd, fd, &c, 1) == 1; ) { debug((httpd, DEBUG_EXPLODING, "bozodgetln read %c", c)); if (len >= httpd->getln_buflen - 1) { httpd->getln_buflen *= 2; debug((httpd, DEBUG_EXPLODING, "bozodgetln: " "reallocating buffer to buflen %zu", httpd->getln_buflen)); nbuffer = bozorealloc(httpd, httpd->getln_buffer, (size_t)httpd->getln_buflen); httpd->getln_buffer = nbuffer; } httpd->getln_buffer[len++] = c; if (c == '\r') { got_cr = 1; continue; } else if (c == '\n') { /* * HTTP/1.1 spec says to ignore CR and treat * LF as the real line terminator. even though * the same spec defines CRLF as the line * terminator, it is recommended in section 19.3 * to do the LF trick for tolerance. */ if (got_cr) len -= 2; else len -= 1; break; } } httpd->getln_buffer[len] = '\0'; debug((httpd, DEBUG_OBESE, "bozodgetln returns: ``%s'' with len %zd", httpd->getln_buffer, len)); *lenp = len; return httpd->getln_buffer; } void * bozorealloc(bozohttpd_t *httpd, void *ptr, size_t size) { void *p; p = realloc(ptr, size); if (p) return p; (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure"); exit(EXIT_FAILURE); } void * bozomalloc(bozohttpd_t *httpd, size_t size) { void *p; p = malloc(size); if (p) return p; (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure"); exit(EXIT_FAILURE); } char * bozostrdup(bozohttpd_t *httpd, bozo_httpreq_t *request, const char *str) { char *p; p = strdup(str); if (p) return p; if (!request) bozoerr(httpd, EXIT_FAILURE, "strdup"); (void)bozo_http_error(httpd, 500, request, "memory allocation failure"); exit(EXIT_FAILURE); } /* set default values in bozohttpd_t struct */ int bozo_init_httpd(bozohttpd_t *httpd) { /* make sure everything is clean */ (void) memset(httpd, 0x0, sizeof(*httpd)); /* constants */ httpd->consts.http_09 = "HTTP/0.9"; httpd->consts.http_10 = "HTTP/1.0"; httpd->consts.http_11 = "HTTP/1.1"; httpd->consts.text_plain = "text/plain"; /* mmap region size */ httpd->mmapsz = BOZO_MMAPSZ; /* error buffer for bozo_http_error() */ if ((httpd->errorbuf = malloc(BUFSIZ)) == NULL) { (void) fprintf(stderr, "bozohttpd: memory_allocation failure\n"); return 0; } #ifndef NO_LUA_SUPPORT SIMPLEQ_INIT(&httpd->lua_states); #endif return 1; } /* set default values in bozoprefs_t struct */ int bozo_init_prefs(bozohttpd_t *httpd, bozoprefs_t *prefs) { /* make sure everything is clean */ (void) memset(prefs, 0x0, sizeof(*prefs)); /* set up default values */ if (!bozo_set_pref(httpd, prefs, "server software", SERVER_SOFTWARE) || !bozo_set_pref(httpd, prefs, "index.html", INDEX_HTML) || !bozo_set_pref(httpd, prefs, "public_html", PUBLIC_HTML)) return 0; return 1; } /* set default values */ int bozo_set_defaults(bozohttpd_t *httpd, bozoprefs_t *prefs) { return bozo_init_httpd(httpd) && bozo_init_prefs(httpd, prefs); } /* set the virtual host name, port and root */ int bozo_setup(bozohttpd_t *httpd, bozoprefs_t *prefs, const char *vhost, const char *root) { struct passwd *pw; extern char **environ; static char *cleanenv[1] = { NULL }; uid_t uid; int uidset = 0; char *chrootdir; char *username; char *portnum; char *cp; int dirtyenv; dirtyenv = 0; if (vhost == NULL) { httpd->virthostname = bozomalloc(httpd, MAXHOSTNAMELEN+1); if (gethostname(httpd->virthostname, MAXHOSTNAMELEN+1) < 0) bozoerr(httpd, 1, "gethostname"); httpd->virthostname[MAXHOSTNAMELEN] = '\0'; } else { httpd->virthostname = bozostrdup(httpd, NULL, vhost); } httpd->slashdir = bozostrdup(httpd, NULL, root); if ((portnum = bozo_get_pref(prefs, "port number")) != NULL) { httpd->bindport = bozostrdup(httpd, NULL, portnum); } /* go over preferences now */ if ((cp = bozo_get_pref(prefs, "numeric")) != NULL && strcmp(cp, "true") == 0) { httpd->numeric = 1; } if ((cp = bozo_get_pref(prefs, "log to stderr")) != NULL && strcmp(cp, "true") == 0) { httpd->logstderr = 1; } if ((cp = bozo_get_pref(prefs, "bind address")) != NULL) { httpd->bindaddress = bozostrdup(httpd, NULL, cp); } if ((cp = bozo_get_pref(prefs, "background")) != NULL) { httpd->background = atoi(cp); } if ((cp = bozo_get_pref(prefs, "foreground")) != NULL && strcmp(cp, "true") == 0) { httpd->foreground = 1; } if ((cp = bozo_get_pref(prefs, "pid file")) != NULL) { httpd->pidfile = bozostrdup(httpd, NULL, cp); } if ((cp = bozo_get_pref(prefs, "unknown slash")) != NULL && strcmp(cp, "true") == 0) { httpd->unknown_slash = 1; } if ((cp = bozo_get_pref(prefs, "virtual base")) != NULL) { httpd->virtbase = bozostrdup(httpd, NULL, cp); } if ((cp = bozo_get_pref(prefs, "enable users")) != NULL && strcmp(cp, "true") == 0) { httpd->enable_users = 1; } if ((cp = bozo_get_pref(prefs, "enable user cgibin")) != NULL && strcmp(cp, "true") == 0) { httpd->enable_cgi_users = 1; } if ((cp = bozo_get_pref(prefs, "dirty environment")) != NULL && strcmp(cp, "true") == 0) { dirtyenv = 1; } if ((cp = bozo_get_pref(prefs, "hide dots")) != NULL && strcmp(cp, "true") == 0) { httpd->hide_dots = 1; } if ((cp = bozo_get_pref(prefs, "directory indexing")) != NULL && strcmp(cp, "true") == 0) { httpd->dir_indexing = 1; } if ((cp = bozo_get_pref(prefs, "public_html")) != NULL) { httpd->public_html = bozostrdup(httpd, NULL, cp); } httpd->server_software = bozostrdup(httpd, NULL, bozo_get_pref(prefs, "server software")); httpd->index_html = bozostrdup(httpd, NULL, bozo_get_pref(prefs, "index.html")); /* * initialise ssl and daemon mode if necessary. */ bozo_ssl_init(httpd); bozo_daemon_init(httpd); username = bozo_get_pref(prefs, "username"); if (username != NULL) { if ((pw = getpwnam(username)) == NULL) bozoerr(httpd, 1, "getpwnam(%s): %s", username, strerror(errno)); if (initgroups(pw->pw_name, pw->pw_gid) == -1) bozoerr(httpd, 1, "initgroups: %s", strerror(errno)); if (setgid(pw->pw_gid) == -1) bozoerr(httpd, 1, "setgid(%u): %s", pw->pw_gid, strerror(errno)); uid = pw->pw_uid; uidset = 1; } /* * handle chroot. */ if ((chrootdir = bozo_get_pref(prefs, "chroot dir")) != NULL) { httpd->rootdir = bozostrdup(httpd, NULL, chrootdir); if (chdir(httpd->rootdir) == -1) bozoerr(httpd, 1, "chdir(%s): %s", httpd->rootdir, strerror(errno)); if (chroot(httpd->rootdir) == -1) bozoerr(httpd, 1, "chroot(%s): %s", httpd->rootdir, strerror(errno)); } if (uidset && setuid(uid) == -1) bozoerr(httpd, 1, "setuid(%d): %s", uid, strerror(errno)); /* * prevent info leakage between different compartments. * some PATH values in the environment would be invalided * by chroot. cross-user settings might result in undesirable * effects. */ if ((chrootdir != NULL || username != NULL) && !dirtyenv) environ = cleanenv; #ifdef _SC_PAGESIZE httpd->page_size = (long)sysconf(_SC_PAGESIZE); #else httpd->page_size = 4096; #endif debug((httpd, DEBUG_OBESE, "myname is %s, slashdir is %s", httpd->virthostname, httpd->slashdir)); return 1; } int bozo_get_version(char *buf, size_t size) { return snprintf(buf, size, "%s", SERVER_SOFTWARE); } |
Added bozohttpd.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | /* $NetBSD: bozohttpd.h,v 1.47 2017/01/31 14:36:09 mrg Exp $ */ /* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2017 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef BOZOHTTOPD_H_ #define BOZOHTTOPD_H_ 1 #include "netbsd_queue.h" #include <sys/stat.h> #ifndef NO_LUA_SUPPORT #include <lua.h> #endif #include <stdio.h> /* QNX provides a lot of NetBSD things in nbutil.h */ #ifdef HAVE_NBUTIL_H #include <nbutil.h> #endif /* lots of "const" but gets free()'ed etc at times, sigh */ /* headers */ typedef struct bozoheaders { /*const*/ char *h_header; /*const*/ char *h_value; /* this gets free()'ed etc at times */ SIMPLEQ_ENTRY(bozoheaders) h_next; } bozoheaders_t; SIMPLEQ_HEAD(qheaders, bozoheaders); #ifndef NO_LUA_SUPPORT typedef struct lua_handler { const char *name; int ref; SIMPLEQ_ENTRY(lua_handler) h_next; } lua_handler_t; typedef struct lua_state_map { const char *script; const char *prefix; lua_State *L; SIMPLEQ_HEAD(, lua_handler) handlers; SIMPLEQ_ENTRY(lua_state_map) s_next; } lua_state_map_t; #endif typedef struct bozo_content_map_t { const char *name; /* postfix of file */ const char *type; /* matching content-type */ const char *encoding; /* matching content-encoding */ const char *encoding11; /* matching content-encoding (HTTP/1.1) */ const char *cgihandler; /* optional CGI handler */ } bozo_content_map_t; /* this struct holds the bozo constants */ typedef struct bozo_consts_t { const char *http_09; /* "HTTP/0.9" */ const char *http_10; /* "HTTP/1.0" */ const char *http_11; /* "HTTP/1.1" */ const char *text_plain; /* "text/plain" */ } bozo_consts_t; /* this structure encapsulates all the bozo flags and control vars */ typedef struct bozohttpd_t { char *rootdir; /* root directory */ int numeric; /* avoid gethostby*() */ char *virtbase; /* virtual directory base */ int unknown_slash; /* unknown vhosts go to normal slashdir */ int logstderr; /* log to stderr (even if not tty) */ int background; /* drop into daemon mode */ int foreground; /* keep daemon mode in foreground */ char *pidfile; /* path to the pid file, if any */ size_t page_size; /* page size */ char *slashdir; /* www slash directory */ char *bindport; /* bind port; default "http" */ char *bindaddress; /* address for binding - INADDR_ANY */ int debug; /* debugging level */ char *virthostname; /* my name */ const char *server_software;/* our brand :-) */ const char *index_html; /* our home page */ const char *public_html; /* ~user/public_html page */ int enable_users; /* enable public_html */ int enable_cgi_users; /* use the cgi handler */ int *sock; /* bound sockets */ int nsock; /* number of above */ struct pollfd *fds; /* current poll fd set */ int request_times; /* # times a request was processed */ int dir_indexing; /* handle directories */ int hide_dots; /* hide .* */ int process_cgi; /* use the cgi handler */ char *cgibin; /* cgi-bin directory */ #ifndef NO_LUA_SUPPORT int process_lua; /* use the Lua handler */ SIMPLEQ_HEAD(, lua_state_map) lua_states; #endif void *sslinfo; /* pointer to ssl struct */ int dynamic_content_map_size;/* size of dyn cont map */ bozo_content_map_t *dynamic_content_map;/* dynamic content map */ size_t mmapsz; /* size of region to mmap */ char *getln_buffer; /* space for getln buffer */ ssize_t getln_buflen; /* length of allocated space */ char *errorbuf; /* no dynamic allocation allowed */ bozo_consts_t consts; /* various constants */ } bozohttpd_t; /* bozo_httpreq_t */ typedef struct bozo_httpreq_t { bozohttpd_t *hr_httpd; int hr_method; #define HTTP_GET 0x01 #define HTTP_POST 0x02 #define HTTP_HEAD 0x03 #define HTTP_OPTIONS 0x04 /* not supported */ #define HTTP_PUT 0x05 /* not supported */ #define HTTP_DELETE 0x06 /* not supported */ #define HTTP_TRACE 0x07 /* not supported */ #define HTTP_CONNECT 0x08 /* not supported */ const char *hr_methodstr; char *hr_virthostname; /* server name (if not identical to hr_httpd->virthostname) */ char *hr_file; char *hr_oldfile; /* if we added an index_html */ char *hr_query; char *hr_host; /* HTTP/1.1 Host: or virtual hostname, possibly including a port number */ #ifndef NO_USER_SUPPORT char *hr_user; /* username if we hit userdir request */ #endif /* !NO_USER_SUPPORT */ const char *hr_proto; const char *hr_content_type; const char *hr_content_length; const char *hr_allow; const char *hr_referrer; const char *hr_range; const char *hr_if_modified_since; const char *hr_accept_encoding; int hr_have_range; off_t hr_first_byte_pos; off_t hr_last_byte_pos; /*const*/ char *hr_remotehost; /*const*/ char *hr_remoteaddr; /*const*/ char *hr_serverport; #ifdef DO_HTPASSWD /*const*/ char *hr_authrealm; /*const*/ char *hr_authuser; /*const*/ char *hr_authpass; #endif struct qheaders hr_headers; struct qheaders hr_replheaders; int hr_nheaders; } bozo_httpreq_t; /* helper to access the "active" host name from a httpd/request pair */ #define BOZOHOST(HTTPD,REQUEST) ((REQUEST)->hr_virthostname ? \ (REQUEST)->hr_virthostname : \ (HTTPD)->virthostname) /* structure to hold string based (name, value) pairs with preferences */ typedef struct bozoprefs_t { size_t size; /* size of the two arrays */ size_t count; /* # of entries in arrays */ char **name; /* names of each entry */ char **value; /* values for the name entries */ } bozoprefs_t; /* by default write in upto 64KiB chunks, and mmap in upto 64MiB chunks */ #ifndef BOZO_WRSZ #define BOZO_WRSZ (64 * 1024) #endif #ifndef BOZO_MMAPSZ #define BOZO_MMAPSZ (BOZO_WRSZ * 1024) #endif /* debug flags */ #define DEBUG_NORMAL 1 #define DEBUG_FAT 2 #define DEBUG_OBESE 3 #define DEBUG_EXPLODING 4 #define strornull(x) ((x) ? (x) : "<null>") #if defined(__GNUC__) && __GNUC__ >= 3 #define BOZO_PRINTFLIKE(x,y) __attribute__((__format__(__printf__, x,y))) #define BOZO_DEAD __attribute__((__noreturn__)) #endif #ifndef NO_DEBUG void debug__(bozohttpd_t *, int, const char *, ...) BOZO_PRINTFLIKE(3, 4); #define debug(x) debug__ x #else #define debug(x) #endif /* NO_DEBUG */ int bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *); int bozo_check_special_files(bozo_httpreq_t *, const char *); char *bozo_http_date(char *, size_t); void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, const char *); char *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute); char *bozo_escape_html(bozohttpd_t *httpd, const char *url); int bozo_decode_url_percent(bozo_httpreq_t *, char *); /* these are similar to libc functions, no underscore here */ void bozowarn(bozohttpd_t *, const char *, ...) BOZO_PRINTFLIKE(2, 3); void bozoerr(bozohttpd_t *, int, const char *, ...) BOZO_PRINTFLIKE(3, 4) BOZO_DEAD; void bozoasprintf(bozohttpd_t *, char **, const char *, ...) BOZO_PRINTFLIKE(3, 4); char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *, int, void *, size_t)); char *bozostrnsep(char **, const char *, ssize_t *); void *bozomalloc(bozohttpd_t *, size_t); void *bozorealloc(bozohttpd_t *, void *, size_t); char *bozostrdup(bozohttpd_t *, bozo_httpreq_t *, const char *); #define bozo_noop do { /* nothing */ } while (/*CONSTCOND*/0) /* ssl-bozo.c */ #ifdef NO_SSL_SUPPORT #define bozo_ssl_set_opts(w, x, y) bozo_noop #define bozo_ssl_set_ciphers(w, x, y) bozo_noop #define bozo_ssl_init(x) bozo_noop #define bozo_ssl_accept(x) (0) #define bozo_ssl_destroy(x) bozo_noop #else void bozo_ssl_set_opts(bozohttpd_t *, const char *, const char *); void bozo_ssl_set_ciphers(bozohttpd_t *, const char *); void bozo_ssl_init(bozohttpd_t *); int bozo_ssl_accept(bozohttpd_t *); void bozo_ssl_destroy(bozohttpd_t *); #endif /* auth-bozo.c */ #ifdef DO_HTPASSWD void bozo_auth_init(bozo_httpreq_t *); int bozo_auth_check(bozo_httpreq_t *, const char *); void bozo_auth_cleanup(bozo_httpreq_t *); int bozo_auth_check_headers(bozo_httpreq_t *, char *, char *, ssize_t); int bozo_auth_check_special_files(bozo_httpreq_t *, const char *); void bozo_auth_check_401(bozo_httpreq_t *, int); void bozo_auth_cgi_setenv(bozo_httpreq_t *, char ***); int bozo_auth_cgi_count(bozo_httpreq_t *); #else #define bozo_auth_init(x) bozo_noop #define bozo_auth_check(x, y) 0 #define bozo_auth_cleanup(x) bozo_noop #define bozo_auth_check_headers(y, z, a, b) 0 #define bozo_auth_check_special_files(x, y) 0 #define bozo_auth_check_401(x, y) bozo_noop #define bozo_auth_cgi_setenv(x, y) bozo_noop #define bozo_auth_cgi_count(x) 0 #endif /* DO_HTPASSWD */ /* cgi-bozo.c */ #ifdef NO_CGIBIN_SUPPORT #define bozo_process_cgi(h) 0 #else void bozo_cgi_setbin(bozohttpd_t *, const char *); void bozo_setenv(bozohttpd_t *, const char *, const char *, char **); int bozo_process_cgi(bozo_httpreq_t *); void bozo_add_content_map_cgi(bozohttpd_t *, const char *, const char *); #endif /* NO_CGIBIN_SUPPORT */ /* lua-bozo.c */ #ifdef NO_LUA_SUPPORT #define bozo_process_lua(h) 0 #else void bozo_add_lua_map(bozohttpd_t *, const char *, const char *); int bozo_process_lua(bozo_httpreq_t *); #endif /* NO_LUA_SUPPORT */ /* daemon-bozo.c */ #ifdef NO_DAEMON_MODE #define bozo_daemon_init(x) bozo_noop #define bozo_daemon_fork(x) 0 #define bozo_daemon_closefds(x) bozo_noop #else void bozo_daemon_init(bozohttpd_t *); int bozo_daemon_fork(bozohttpd_t *); void bozo_daemon_closefds(bozohttpd_t *); #endif /* NO_DAEMON_MODE */ /* tilde-luzah-bozo.c */ #ifdef NO_USER_SUPPORT #define bozo_user_transform(x) 0 #define bozo_user_free(x) 0 #else int bozo_user_transform(bozo_httpreq_t *); #define bozo_user_free(x) free(x) #endif /* NO_USER_SUPPORT */ /* dir-index-bozo.c */ #ifdef NO_DIRINDEX_SUPPORT #define bozo_dir_index(a, b, c) 0 #else int bozo_dir_index(bozo_httpreq_t *, const char *, int); #endif /* NO_DIRINDEX_SUPPORT */ /* content-bozo.c */ const char *bozo_content_type(bozo_httpreq_t *, const char *); const char *bozo_content_encoding(bozo_httpreq_t *, const char *); bozo_content_map_t *bozo_match_content_map(bozohttpd_t *, const char *, int); bozo_content_map_t *bozo_get_content_map(bozohttpd_t *, const char *); #ifndef NO_DYNAMIC_CONTENT void bozo_add_content_map_mime(bozohttpd_t *, const char *, const char *, const char *, const char *); #endif /* I/O */ int bozo_printf(bozohttpd_t *, const char *, ...) BOZO_PRINTFLIKE(2, 3);; ssize_t bozo_read(bozohttpd_t *, int, void *, size_t); ssize_t bozo_write(bozohttpd_t *, int, const void *, size_t); int bozo_flush(bozohttpd_t *, FILE *); /* misc */ int bozo_init_httpd(bozohttpd_t *); int bozo_init_prefs(bozohttpd_t *, bozoprefs_t *); int bozo_set_defaults(bozohttpd_t *, bozoprefs_t *); int bozo_setup(bozohttpd_t *, bozoprefs_t *, const char *, const char *); bozo_httpreq_t *bozo_read_request(bozohttpd_t *); void bozo_process_request(bozo_httpreq_t *); void bozo_clean_request(bozo_httpreq_t *); bozoheaders_t *addmerge_reqheader(bozo_httpreq_t *, const char *, const char *, ssize_t); bozoheaders_t *addmerge_replheader(bozo_httpreq_t *, const char *, const char *, ssize_t); /* variables */ int bozo_set_pref(bozohttpd_t *, bozoprefs_t *, const char *, const char *); char *bozo_get_pref(bozoprefs_t *, const char *); int bozo_get_version(char */*buf*/, size_t /*size*/); #endif /* BOZOHTTOPD_H_ */ |
Added cgi-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | /* $NetBSD: cgi-bozo.c,v 1.37 2017/01/31 14:36:09 mrg Exp $ */ /* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2017 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements CGI/1.2 for bozohttpd */ #ifndef NO_CGIBIN_SUPPORT #include <sys/param.h> #include <sys/socket.h> #include <ctype.h> #include <errno.h> #include <paths.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h> #include <netinet/in.h> #include "bozohttpd.h" #define CGIBIN_PREFIX "cgi-bin/" #define CGIBIN_PREFIX_LEN (sizeof(CGIBIN_PREFIX)-1) #ifndef USE_ARG #define USE_ARG(x) /*LINTED*/(void)&(x) #endif /* * given the file name, return a CGI interpreter */ static const char * content_cgihandler(bozohttpd_t *httpd, bozo_httpreq_t *request, const char *file) { bozo_content_map_t *map; USE_ARG(request); debug((httpd, DEBUG_FAT, "content_cgihandler: trying file %s", file)); map = bozo_match_content_map(httpd, file, 0); if (map) return map->cgihandler; return NULL; } static int parse_header(bozo_httpreq_t *request, const char *str, ssize_t len, char **hdr_str, char **hdr_val) { struct bozohttpd_t *httpd = request->hr_httpd; char *name, *value; /* if the string passed is zero-length bail out */ if (*str == '\0') return -1; value = bozostrdup(httpd, request, str); /* locate the ':' separator in the header/value */ name = bozostrnsep(&value, ":", &len); if (NULL == name || -1 == len) { free(value); return -1; } /* skip leading space/tab */ while (*value == ' ' || *value == '\t') len--, value++; *hdr_str = name; *hdr_val = value; return 0; } /* * handle parsing a CGI header output, transposing a Status: header * into the HTTP reply (ie, instead of "200 OK"). */ static void finish_cgi_output(bozohttpd_t *httpd, bozo_httpreq_t *request, int in, int nph) { char buf[BOZO_WRSZ]; char *str; ssize_t len; ssize_t rbytes; SIMPLEQ_HEAD(, bozoheaders) headers; bozoheaders_t *hdr, *nhdr; int write_header, nheaders = 0; /* much of this code is like bozo_read_request()'s header loop. */ SIMPLEQ_INIT(&headers); write_header = nph == 0; /* was read(2) here - XXX - agc */ while (nph == 0 && (str = bozodgetln(httpd, in, &len, bozo_read)) != NULL) { char *hdr_name, *hdr_value; if (parse_header(request, str, len, &hdr_name, &hdr_value)) break; /* * The CGI 1.{1,2} spec both say that if the cgi program * returns a `Status:' header field then the server MUST * return it in the response. If the cgi program does * not return any `Status:' header then the server should * respond with 200 OK. * XXX The CGI 1.1 and 1.2 specification differ slightly on * this in that v1.2 says that the script MUST NOT return a * `Status:' header if it is returning a `Location:' header. * For compatibility we are going with the CGI 1.1 behavior. */ if (strcasecmp(hdr_name, "status") == 0) { debug((httpd, DEBUG_OBESE, "bozo_process_cgi: writing HTTP header " "from status %s ..", hdr_value)); bozo_printf(httpd, "%s %s\r\n", request->hr_proto, hdr_value); bozo_flush(httpd, stdout); write_header = 0; free(hdr_name); break; } hdr = bozomalloc(httpd, sizeof *hdr); hdr->h_header = hdr_name; hdr->h_value = hdr_value; SIMPLEQ_INSERT_TAIL(&headers, hdr, h_next); nheaders++; } if (write_header) { debug((httpd, DEBUG_OBESE, "bozo_process_cgi: writing HTTP header ..")); bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto); bozo_flush(httpd, stdout); } if (nheaders) { debug((httpd, DEBUG_OBESE, "bozo_process_cgi: writing delayed HTTP headers ..")); SIMPLEQ_FOREACH_SAFE(hdr, &headers, h_next, nhdr) { bozo_printf(httpd, "%s: %s\r\n", hdr->h_header, hdr->h_value); free(hdr->h_header); free(hdr); } bozo_printf(httpd, "\r\n"); bozo_flush(httpd, stdout); } /* XXX we should have some goo that times us out */ while ((rbytes = read(in, buf, sizeof buf)) > 0) { ssize_t wbytes; char *bp = buf; while (rbytes) { wbytes = bozo_write(httpd, STDOUT_FILENO, buf, (size_t)rbytes); if (wbytes > 0) { rbytes -= wbytes; bp += wbytes; } else bozoerr(httpd, 1, "cgi output write failed: %s", strerror(errno)); } } } static void append_index_html(bozohttpd_t *httpd, char **url) { *url = bozorealloc(httpd, *url, strlen(*url) + strlen(httpd->index_html) + 1); strcat(*url, httpd->index_html); debug((httpd, DEBUG_NORMAL, "append_index_html: url adjusted to `%s'", *url)); } /* This function parse search-string according to section 4.4 of RFC3875 */ static char ** parse_search_string(bozo_httpreq_t *request, const char *query, size_t *args_len) { struct bozohttpd_t *httpd = request->hr_httpd; size_t i; char *s, *str, **args; *args_len = 0; /* URI MUST not contain any unencoded '=' - RFC3875, section 4.4 */ if (strchr(query, '=')) { return NULL; } str = bozostrdup(httpd, request, query); /* * there's no more arguments than '+' chars in the query string as it's * the separator */ *args_len = 1; /* count '+' in str */ for (s = str; (s = strchr(s, '+')); (*args_len)++) s++; args = bozomalloc(httpd, sizeof(*args) * (*args_len + 1)); args[0] = str; args[*args_len] = NULL; for (s = str, i = 0; (s = strchr(s, '+'));) { *s = '\0'; s++; args[i++] = s; } /* * check if search-strings are valid: * * RFC3875, section 4.4: * * search-string = search-word *( "+" search-word ) * search-word = 1*schar * schar = unreserved | escaped | xreserved * xreserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," | * "$" * * section 2.3: * * hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | * "b" | "c" | "d" | "e" | "f" * escaped = "%" hex hex * unreserved = alpha | digit | mark * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" * * section 2.2: * * alpha = lowalpha | hialpha * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | * "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | * "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | * "y" | "z" * hialpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | * "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | * "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | * "Y" | "Z" * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | * "8" | "9" */ #define UNRESERVED_CHAR "-_.!~*'()" #define XRESERVED_CHAR ";/?:@&=,$" for (i = 0; i < *args_len; i++) { s = args[i]; /* search-word MUST have at least one schar */ if (*s == '\0') goto parse_err; while(*s) { /* check if it's unreserved */ if (isalpha((int)*s) || isdigit((int)*s) || strchr(UNRESERVED_CHAR, *s)) { s++; continue; } /* check if it's escaped */ if (*s == '%') { if (s[1] == '\0' || s[2] == '\0') goto parse_err; if (!isxdigit((int)s[1]) || !isxdigit((int)s[2])) goto parse_err; s += 3; continue; } /* check if it's xreserved */ if (strchr(XRESERVED_CHAR, *s)) { s++; continue; } goto parse_err; } } /* decode percent encoding */ for (i = 0; i < *args_len; i++) { if (bozo_decode_url_percent(request, args[i])) goto parse_err; } /* allocate each arg separately */ for (i = 0; i < *args_len; i++) args[i] = bozostrdup(httpd, request, args[i]); free(str); return args; parse_err: free (str); free (*args); free(args); *args_len = 0; return NULL; } void bozo_cgi_setbin(bozohttpd_t *httpd, const char *path) { httpd->cgibin = bozostrdup(httpd, NULL, path); debug((httpd, DEBUG_OBESE, "cgibin (cgi-bin directory) is %s", httpd->cgibin)); } /* help build up the environ pointer */ void bozo_setenv(bozohttpd_t *httpd, const char *env, const char *val, char **envp) { char *s1 = bozomalloc(httpd, strlen(env) + strlen(val) + 2); strcpy(s1, env); strcat(s1, "="); strcat(s1, val); debug((httpd, DEBUG_OBESE, "bozo_setenv: %s", s1)); *envp = s1; } /* * Checks if the request has asked for a cgi-bin. Should only be called if * cgibin is set. If it starts CGIBIN_PREFIX or has a ncontent handler, * process the cgi, otherwise just return. Returns 0 if it did not handle * the request. */ int bozo_process_cgi(bozo_httpreq_t *request) { bozohttpd_t *httpd = request->hr_httpd; char buf[BOZO_WRSZ]; char date[40]; bozoheaders_t *headp; const char *type, *clen, *info, *cgihandler; char *query, *s, *t, *path, *env, *command, *file, *url; char **envp, **curenvp, **argv, **search_string_argv = NULL; char *uri; size_t i, len, search_string_argc = 0; ssize_t rbytes; pid_t pid; int envpsize, ix, nph; int sv[2]; if (!httpd->cgibin && !httpd->process_cgi) return 0; #ifndef NO_USER_SUPPORT if (request->hr_user && !httpd->enable_cgi_users) return 0; #endif /* !NO_USER_SUPPORT */ if (request->hr_oldfile && strcmp(request->hr_oldfile, "/") != 0) uri = request->hr_oldfile; else uri = request->hr_file; if (uri[0] == '/') file = bozostrdup(httpd, request, uri); else bozoasprintf(httpd, &file, "/%s", uri); if (request->hr_query && strlen(request->hr_query)) query = bozostrdup(httpd, request, request->hr_query); else query = NULL; bozoasprintf(httpd, &url, "%s%s%s", file, query ? "?" : "", query ? query : ""); debug((httpd, DEBUG_NORMAL, "bozo_process_cgi: url `%s'", url)); path = NULL; envp = NULL; cgihandler = NULL; command = NULL; info = NULL; len = strlen(url); if (bozo_auth_check(request, url + 1)) goto out; if (!httpd->cgibin || strncmp(url + 1, CGIBIN_PREFIX, CGIBIN_PREFIX_LEN) != 0) { cgihandler = content_cgihandler(httpd, request, file + 1); if (cgihandler == NULL) { debug((httpd, DEBUG_FAT, "bozo_process_cgi: no handler, returning")); goto out; } if (len == 0 || file[len - 1] == '/') append_index_html(httpd, &file); debug((httpd, DEBUG_NORMAL, "bozo_process_cgi: cgihandler `%s'", cgihandler)); } else if (len - 1 == CGIBIN_PREFIX_LEN) /* url is "/cgi-bin/" */ append_index_html(httpd, &file); /* RFC3875 sect. 4.4. - search-string support */ if (query != NULL) { search_string_argv = parse_search_string(request, query, &search_string_argc); } debug((httpd, DEBUG_NORMAL, "parse_search_string args no: %zu", search_string_argc)); for (i = 0; i < search_string_argc; i++) { debug((httpd, DEBUG_FAT, "search_string[%zu]: `%s'", i, search_string_argv[i])); } argv = bozomalloc(httpd, sizeof(*argv) * (3 + search_string_argc)); ix = 0; if (cgihandler) { command = file + 1; path = bozostrdup(httpd, request, cgihandler); } else { command = file + CGIBIN_PREFIX_LEN + 1; if ((s = strchr(command, '/')) != NULL) { info = bozostrdup(httpd, request, s); *s = '\0'; } path = bozomalloc(httpd, strlen(httpd->cgibin) + 1 + strlen(command) + 1); strcpy(path, httpd->cgibin); strcat(path, "/"); strcat(path, command); } argv[ix++] = path; /* copy search-string args */ for (i = 0; i < search_string_argc; i++) argv[ix++] = search_string_argv[i]; argv[ix++] = NULL; nph = strncmp(command, "nph-", 4) == 0; type = request->hr_content_type; clen = request->hr_content_length; envpsize = 13 + request->hr_nheaders + (info && *info ? 1 : 0) + (query && *query ? 1 : 0) + (type && *type ? 1 : 0) + (clen && *clen ? 1 : 0) + (request->hr_remotehost && *request->hr_remotehost ? 1 : 0) + (request->hr_remoteaddr && *request->hr_remoteaddr ? 1 : 0) + bozo_auth_cgi_count(request) + (request->hr_serverport && *request->hr_serverport ? 1 : 0); debug((httpd, DEBUG_FAT, "bozo_process_cgi: path `%s', cmd `%s', info `%s', " "query `%s', nph `%d', envpsize `%d'", path, command, strornull(info), strornull(query), nph, envpsize)); envp = bozomalloc(httpd, sizeof(*envp) * envpsize); for (ix = 0; ix < envpsize; ix++) envp[ix] = NULL; curenvp = envp; SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) { const char *s2; env = bozomalloc(httpd, 6 + strlen(headp->h_header) + 1 + strlen(headp->h_value)); t = env; strcpy(t, "HTTP_"); t += strlen(t); for (s2 = headp->h_header; *s2; t++, s2++) if (islower((u_int)*s2)) *t = toupper((u_int)*s2); else if (*s2 == '-') *t = '_'; else *t = *s2; *t = '\0'; debug((httpd, DEBUG_OBESE, "setting header %s as %s = %s", headp->h_header, env, headp->h_value)); bozo_setenv(httpd, env, headp->h_value, curenvp++); free(env); } #ifndef _PATH_DEFPATH #define _PATH_DEFPATH "/usr/bin:/bin" #endif bozo_setenv(httpd, "PATH", _PATH_DEFPATH, curenvp++); bozo_setenv(httpd, "IFS", " \t\n", curenvp++); bozo_setenv(httpd, "SERVER_NAME", BOZOHOST(httpd,request), curenvp++); bozo_setenv(httpd, "GATEWAY_INTERFACE", "CGI/1.1", curenvp++); bozo_setenv(httpd, "SERVER_PROTOCOL", request->hr_proto, curenvp++); bozo_setenv(httpd, "REQUEST_METHOD", request->hr_methodstr, curenvp++); bozo_setenv(httpd, "SCRIPT_NAME", file, curenvp++); bozo_setenv(httpd, "SCRIPT_FILENAME", file + 1, curenvp++); bozo_setenv(httpd, "SERVER_SOFTWARE", httpd->server_software, curenvp++); bozo_setenv(httpd, "REQUEST_URI", uri, curenvp++); bozo_setenv(httpd, "DATE_GMT", bozo_http_date(date, sizeof(date)), curenvp++); /* RFC3875 section 4.1.7 says that QUERY_STRING MUST be defined. */ if (query && *query) bozo_setenv(httpd, "QUERY_STRING", query, curenvp++); else bozo_setenv(httpd, "QUERY_STRING", "", curenvp++); if (info && *info) bozo_setenv(httpd, "PATH_INFO", info, curenvp++); if (type && *type) bozo_setenv(httpd, "CONTENT_TYPE", type, curenvp++); if (clen && *clen) bozo_setenv(httpd, "CONTENT_LENGTH", clen, curenvp++); if (request->hr_serverport && *request->hr_serverport) bozo_setenv(httpd, "SERVER_PORT", request->hr_serverport, curenvp++); if (request->hr_remotehost && *request->hr_remotehost) bozo_setenv(httpd, "REMOTE_HOST", request->hr_remotehost, curenvp++); if (request->hr_remoteaddr && *request->hr_remoteaddr) bozo_setenv(httpd, "REMOTE_ADDR", request->hr_remoteaddr, curenvp++); /* * Apache does this when invoking content handlers, and PHP * 5.3 requires it as a "security" measure. */ if (cgihandler) bozo_setenv(httpd, "REDIRECT_STATUS", "200", curenvp++); bozo_auth_cgi_setenv(request, &curenvp); debug((httpd, DEBUG_FAT, "bozo_process_cgi: going exec %s with args:", path)); for (i = 0; argv[i] != NULL; i++) { debug((httpd, DEBUG_FAT, "bozo_process_cgi: argv[%zu] = `%s'", i, argv[i])); } if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1) bozoerr(httpd, 1, "child socketpair failed: %s", strerror(errno)); /* * We create 2 procs: one to become the CGI, one read from * the CGI and output to the network, and this parent will * continue reading from the network and writing to the * CGI procsss. */ switch (fork()) { case -1: /* eep, failure */ bozoerr(httpd, 1, "child fork failed: %s", strerror(errno)); /*NOTREACHED*/ case 0: close(sv[0]); dup2(sv[1], STDIN_FILENO); dup2(sv[1], STDOUT_FILENO); close(2); close(sv[1]); closelog(); bozo_daemon_closefds(httpd); if (-1 == execve(path, argv, envp)) bozoerr(httpd, 1, "child exec failed: %s: %s", path, strerror(errno)); /* NOT REACHED */ bozoerr(httpd, 1, "child execve returned?!"); } free(query); free(file); free(url); for (i = 0; i < search_string_argc; i++) free(search_string_argv[i]); free(search_string_argv); close(sv[1]); /* parent: read from stdin (bozo_read()) write to sv[0] */ /* child: read from sv[0] (bozo_write()) write to stdout */ pid = fork(); if (pid == -1) bozoerr(httpd, 1, "io child fork failed: %s", strerror(errno)); else if (pid == 0) { /* child reader/writer */ close(STDIN_FILENO); finish_cgi_output(httpd, request, sv[0], nph); /* if we're done output, our parent is useless... */ kill(getppid(), SIGKILL); debug((httpd, DEBUG_FAT, "done processing cgi output")); _exit(0); } close(STDOUT_FILENO); /* XXX we should have some goo that times us out */ while ((rbytes = bozo_read(httpd, STDIN_FILENO, buf, sizeof buf)) > 0) { ssize_t wbytes; char *bp = buf; while (rbytes) { wbytes = write(sv[0], buf, (size_t)rbytes); if (wbytes > 0) { rbytes -= wbytes; bp += wbytes; } else bozoerr(httpd, 1, "write failed: %s", strerror(errno)); } } debug((httpd, DEBUG_FAT, "done processing cgi input")); exit(0); out: for (i = 0; i < search_string_argc; i++) free(search_string_argv[i]); free(search_string_argv); free(query); free(file); free(url); return 0; } #ifndef NO_DYNAMIC_CONTENT /* cgi maps are simple ".postfix /path/to/prog" */ void bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg, const char *cgihandler) { bozo_content_map_t *map; debug((httpd, DEBUG_NORMAL, "bozo_add_content_map_cgi: name %s cgi %s", arg, cgihandler)); httpd->process_cgi = 1; map = bozo_get_content_map(httpd, arg); map->name = arg; map->type = map->encoding = map->encoding11 = NULL; map->cgihandler = cgihandler; } #endif /* NO_DYNAMIC_CONTENT */ #endif /* NO_CGIBIN_SUPPORT */ |
Added content-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | /* $NetBSD: content-bozo.c,v 1.14 2016/07/19 09:27:40 shm Exp $ */ /* $eterna: content-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2015 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements content-type handling for bozohttpd */ #include <sys/param.h> #include <errno.h> #include <string.h> #include "bozohttpd.h" /* * this map and the functions below map between filenames and the * content type and content encoding definitions. this should become * a configuration file, perhaps like apache's mime.types (but that * has less info per-entry). */ static bozo_content_map_t static_content_map[] = { { ".html", "text/html", "", "", NULL }, { ".htm", "text/html", "", "", NULL }, { ".gif", "image/gif", "", "", NULL }, { ".jpeg", "image/jpeg", "", "", NULL }, { ".jpg", "image/jpeg", "", "", NULL }, { ".jpe", "image/jpeg", "", "", NULL }, { ".png", "image/png", "", "", NULL }, { ".mp3", "audio/mpeg", "", "", NULL }, { ".css", "text/css", "", "", NULL }, { ".txt", "text/plain", "", "", NULL }, { ".swf", "application/x-shockwave-flash","", "", NULL }, { ".dcr", "application/x-director", "", "", NULL }, { ".pac", "application/x-ns-proxy-autoconfig", "", "", NULL }, { ".pa", "application/x-ns-proxy-autoconfig", "", "", NULL }, { ".tar", "multipart/x-tar", "", "", NULL }, { ".gtar", "application/x-gtar-compressed", "", "", NULL }, { ".tar.Z", "application/x-gtar-compressed", "", "", NULL }, { ".tar.gz", "application/x-gtar-compressed", "", "", NULL }, { ".taz", "application/x-gtar-compressed", "", "", NULL }, { ".tgz", "application/x-gtar-compressed", "", "", NULL }, { ".tar.z", "application/x-gtar-compressed", "", "", NULL }, { ".Z", "application/x-compress", "", "", NULL }, { ".gz", "application/x-gzip", "", "", NULL }, { ".z", "unknown", "", "", NULL }, { ".bz2", "application/x-bzip2", "", "", NULL }, { ".ogg", "application/x-ogg", "", "", NULL }, { ".mkv", "video/x-matroska", "", "", NULL }, { ".xbel", "text/xml", "", "", NULL }, { ".xml", "text/xml", "", "", NULL }, { ".xsl", "text/xml", "", "", NULL }, { ".hqx", "application/mac-binhex40", "", "", NULL }, { ".cpt", "application/mac-compactpro", "", "", NULL }, { ".doc", "application/msword", "", "", NULL }, { ".bin", "application/octet-stream", "", "", NULL }, { ".dms", "application/octet-stream", "", "", NULL }, { ".lha", "application/octet-stream", "", "", NULL }, { ".lzh", "application/octet-stream", "", "", NULL }, { ".exe", "application/octet-stream", "", "", NULL }, { ".class", "application/octet-stream", "", "", NULL }, { ".oda", "application/oda", "", "", NULL }, { ".pdf", "application/pdf", "", "", NULL }, { ".ai", "application/postscript", "", "", NULL }, { ".eps", "application/postscript", "", "", NULL }, { ".ps", "application/postscript", "", "", NULL }, { ".ppt", "application/powerpoint", "", "", NULL }, { ".rtf", "application/rtf", "", "", NULL }, { ".bcpio", "application/x-bcpio", "", "", NULL }, { ".torrent", "application/x-bittorrent", "", "", NULL }, { ".vcd", "application/x-cdlink", "", "", NULL }, { ".cpio", "application/x-cpio", "", "", NULL }, { ".csh", "application/x-csh", "", "", NULL }, { ".dir", "application/x-director", "", "", NULL }, { ".dxr", "application/x-director", "", "", NULL }, { ".dvi", "application/x-dvi", "", "", NULL }, { ".hdf", "application/x-hdf", "", "", NULL }, { ".cgi", "application/x-httpd-cgi", "", "", NULL }, { ".skp", "application/x-koan", "", "", NULL }, { ".skd", "application/x-koan", "", "", NULL }, { ".skt", "application/x-koan", "", "", NULL }, { ".skm", "application/x-koan", "", "", NULL }, { ".latex", "application/x-latex", "", "", NULL }, { ".mif", "application/x-mif", "", "", NULL }, { ".nc", "application/x-netcdf", "", "", NULL }, { ".cdf", "application/x-netcdf", "", "", NULL }, { ".patch", "application/x-patch", "", "", NULL }, { ".sh", "application/x-sh", "", "", NULL }, { ".shar", "application/x-shar", "", "", NULL }, { ".sit", "application/x-stuffit", "", "", NULL }, { ".sv4cpio", "application/x-sv4cpio", "", "", NULL }, { ".sv4crc", "application/x-sv4crc", "", "", NULL }, { ".tar", "application/x-tar", "", "", NULL }, { ".tcl", "application/x-tcl", "", "", NULL }, { ".tex", "application/x-tex", "", "", NULL }, { ".texinfo", "application/x-texinfo", "", "", NULL }, { ".texi", "application/x-texinfo", "", "", NULL }, { ".t", "application/x-troff", "", "", NULL }, { ".tr", "application/x-troff", "", "", NULL }, { ".roff", "application/x-troff", "", "", NULL }, { ".man", "application/x-troff-man", "", "", NULL }, { ".me", "application/x-troff-me", "", "", NULL }, { ".ms", "application/x-troff-ms", "", "", NULL }, { ".ustar", "application/x-ustar", "", "", NULL }, { ".src", "application/x-wais-source", "", "", NULL }, { ".zip", "application/zip", "", "", NULL }, { ".au", "audio/basic", "", "", NULL }, { ".snd", "audio/basic", "", "", NULL }, { ".mpga", "audio/mpeg", "", "", NULL }, { ".mp2", "audio/mpeg", "", "", NULL }, { ".aif", "audio/x-aiff", "", "", NULL }, { ".aiff", "audio/x-aiff", "", "", NULL }, { ".aifc", "audio/x-aiff", "", "", NULL }, { ".ram", "audio/x-pn-realaudio", "", "", NULL }, { ".rpm", "audio/x-pn-realaudio-plugin", "", "", NULL }, { ".ra", "audio/x-realaudio", "", "", NULL }, { ".wav", "audio/x-wav", "", "", NULL }, { ".pdb", "chemical/x-pdb", "", "", NULL }, { ".xyz", "chemical/x-pdb", "", "", NULL }, { ".ief", "image/ief", "", "", NULL }, { ".tiff", "image/tiff", "", "", NULL }, { ".tif", "image/tiff", "", "", NULL }, { ".ras", "image/x-cmu-raster", "", "", NULL }, { ".pnm", "image/x-portable-anymap", "", "", NULL }, { ".pbm", "image/x-portable-bitmap", "", "", NULL }, { ".pgm", "image/x-portable-graymap", "", "", NULL }, { ".ppm", "image/x-portable-pixmap", "", "", NULL }, { ".rgb", "image/x-rgb", "", "", NULL }, { ".xbm", "image/x-xbitmap", "", "", NULL }, { ".xpm", "image/x-xpixmap", "", "", NULL }, { ".xwd", "image/x-xwindowdump", "", "", NULL }, { ".rtx", "text/richtext", "", "", NULL }, { ".tsv", "text/tab-separated-values", "", "", NULL }, { ".etx", "text/x-setext", "", "", NULL }, { ".sgml", "text/x-sgml", "", "", NULL }, { ".sgm", "text/x-sgml", "", "", NULL }, { ".mpeg", "video/mpeg", "", "", NULL }, { ".mpg", "video/mpeg", "", "", NULL }, { ".mpe", "video/mpeg", "", "", NULL }, { ".ts", "video/mpeg", "", "", NULL }, { ".vob", "video/mpeg", "", "", NULL }, { ".mp4", "video/mp4", "", "", NULL }, { ".qt", "video/quicktime", "", "", NULL }, { ".mov", "video/quicktime", "", "", NULL }, { ".avi", "video/x-msvideo", "", "", NULL }, { ".movie", "video/x-sgi-movie", "", "", NULL }, { ".ice", "x-conference/x-cooltalk", "", "", NULL }, { ".wrl", "x-world/x-vrml", "", "", NULL }, { ".vrml", "x-world/x-vrml", "", "", NULL }, { ".svg", "image/svg+xml", "", "", NULL }, { NULL, NULL, NULL, NULL, NULL } }; static bozo_content_map_t * search_map(bozo_content_map_t *map, const char *name, size_t len) { for ( ; map && map->name; map++) { const size_t namelen = strlen(map->name); if (namelen < len && strcasecmp(map->name, name + (len - namelen)) == 0) return map; } return NULL; } /* match a suffix on a file - dynamiconly means no static content search */ bozo_content_map_t * bozo_match_content_map(bozohttpd_t *httpd, const char *name, const int dynamiconly) { bozo_content_map_t *map; size_t len; len = strlen(name); if ((map = search_map(httpd->dynamic_content_map, name, len)) != NULL) { return map; } if (!dynamiconly) { if ((map = search_map(static_content_map, name, len)) != NULL) { return map; } } return NULL; } /* * given the file name, return a valid Content-Type: value. */ /* ARGSUSED */ const char * bozo_content_type(bozo_httpreq_t *request, const char *file) { bozohttpd_t *httpd = request->hr_httpd; bozo_content_map_t *map; map = bozo_match_content_map(httpd, file, 0); if (map) return map->type; return httpd->consts.text_plain; } /* * given the file name, return a valid Content-Encoding: value. */ const char * bozo_content_encoding(bozo_httpreq_t *request, const char *file) { bozohttpd_t *httpd = request->hr_httpd; bozo_content_map_t *map; map = bozo_match_content_map(httpd, file, 0); if (map) return (request->hr_proto == httpd->consts.http_11) ? map->encoding11 : map->encoding; return NULL; } #ifndef NO_DYNAMIC_CONTENT bozo_content_map_t * bozo_get_content_map(bozohttpd_t *httpd, const char *name) { bozo_content_map_t *map; if ((map = bozo_match_content_map(httpd, name, 1)) != NULL) return map; httpd->dynamic_content_map_size++; httpd->dynamic_content_map = bozorealloc(httpd, httpd->dynamic_content_map, (httpd->dynamic_content_map_size + 1) * sizeof *map); if (httpd->dynamic_content_map == NULL) bozoerr(httpd, 1, "out of memory allocating content map"); map = &httpd->dynamic_content_map[httpd->dynamic_content_map_size]; map->name = map->type = map->encoding = map->encoding11 = map->cgihandler = NULL; map--; return map; } /* * mime content maps look like: * ".name type encoding encoding11" * where any of type, encoding or encoding11 a dash "-" means "". * eg the .gtar, .tar.Z from above could be written like: * ".gtar multipart/x-gtar - -" * ".tar.Z multipart/x-tar x-compress compress" * or * ".gtar multipart/x-gtar" * ".tar.Z multipart/x-tar x-compress compress" * NOTE: we destroy 'arg' */ void bozo_add_content_map_mime(bozohttpd_t *httpd, const char *cmap0, const char *cmap1, const char *cmap2, const char *cmap3) { bozo_content_map_t *map; debug((httpd, DEBUG_FAT, "add_content_map: name %s type %s enc %s enc11 %s ", cmap0, cmap1, cmap2, cmap3)); map = bozo_get_content_map(httpd, cmap0); #define CHECKMAP(s) (!s || ((s)[0] == '-' && (s)[1] == '\0') ? "" : (s)) map->name = CHECKMAP(cmap0); map->type = CHECKMAP(cmap1); map->encoding = CHECKMAP(cmap2); map->encoding11 = CHECKMAP(cmap3); #undef CHECKMAP map->cgihandler = NULL; } #endif /* NO_DYNAMIC_CONTENT */ |
Added daemon-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | /* $NetBSD: daemon-bozo.c,v 1.17 2015/12/28 07:37:59 mrg Exp $ */ /* $eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2014 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements daemon mode for bozohttpd */ #ifndef NO_DAEMON_MODE #include <sys/param.h> #include <sys/socket.h> #include <sys/wait.h> #include <netinet/in.h> #include <assert.h> #include <errno.h> #include <netdb.h> #include <poll.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "bozohttpd.h" static void sigchild(int); /* SIGCHLD handler */ #ifndef POLLRDNORM #define POLLRDNORM 0 #endif #ifndef POLLRDBAND #define POLLRDBAND 0 #endif #ifndef INFTIM #define INFTIM -1 #endif static const char* pidfile_path = NULL; static pid_t pidfile_pid = 0; /* ARGSUSED */ static void sigchild(int signo) { while (waitpid(-1, NULL, WNOHANG) > 0) { } } /* Signal handler to exit in a controlled manner. This ensures that * any atexit(3) handlers are properly executed. */ /* ARGSUSED */ BOZO_DEAD static void controlled_exit(int signo) { exit(EXIT_SUCCESS); } static void remove_pidfile(void) { if (pidfile_path != NULL && pidfile_pid == getpid()) { (void)unlink(pidfile_path); pidfile_path = NULL; } } static void create_pidfile(bozohttpd_t *httpd) { FILE *file; assert(pidfile_path == NULL); if (httpd->pidfile == NULL) return; if (atexit(remove_pidfile) == -1) bozoerr(httpd, 1, "Failed to install pidfile handler"); if ((file = fopen(httpd->pidfile, "w")) == NULL) bozoerr(httpd, 1, "Failed to create pidfile '%s'", httpd->pidfile); (void)fprintf(file, "%d\n", getpid()); (void)fclose(file); pidfile_path = httpd->pidfile; pidfile_pid = getpid(); debug((httpd, DEBUG_FAT, "Created pid file '%s' for pid %d", pidfile_path, pidfile_pid)); } void bozo_daemon_init(bozohttpd_t *httpd) { struct addrinfo h, *r, *r0; const char *portnum; int e, i, on = 1; if (!httpd->background) return; portnum = (httpd->bindport) ? httpd->bindport : "http"; memset(&h, 0, sizeof(h)); h.ai_family = PF_UNSPEC; h.ai_socktype = SOCK_STREAM; h.ai_flags = AI_PASSIVE; e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0); if (e) bozoerr(httpd, 1, "getaddrinfo([%s]:%s): %s", httpd->bindaddress ? httpd->bindaddress : "*", portnum, gai_strerror(e)); for (r = r0; r != NULL; r = r->ai_next) httpd->nsock++; httpd->sock = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->sock)); httpd->fds = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->fds)); for (i = 0, r = r0; r != NULL; r = r->ai_next) { httpd->sock[i] = socket(r->ai_family, SOCK_STREAM, 0); if (httpd->sock[i] == -1) continue; if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) bozowarn(httpd, "setsockopt SO_REUSEADDR: %s", strerror(errno)); if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1) continue; if (listen(httpd->sock[i], SOMAXCONN) == -1) continue; httpd->fds[i].events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND | POLLERR; httpd->fds[i].fd = httpd->sock[i]; i++; } if (i == 0) bozoerr(httpd, 1, "could not find any addresses to bind"); httpd->nsock = i; freeaddrinfo(r0); if (httpd->foreground == 0) daemon(1, 0); create_pidfile(httpd); bozowarn(httpd, "started in daemon mode as `%s' port `%s' root `%s'", httpd->virthostname, portnum, httpd->slashdir); signal(SIGHUP, controlled_exit); signal(SIGINT, controlled_exit); signal(SIGTERM, controlled_exit); signal(SIGCHLD, sigchild); } void bozo_daemon_closefds(bozohttpd_t *httpd) { int i; for (i = 0; i < httpd->nsock; i++) close(httpd->sock[i]); } static void daemon_runchild(bozohttpd_t *httpd, int fd) { httpd->request_times++; /* setup stdin/stdout/stderr */ dup2(fd, 0); dup2(fd, 1); /*dup2(fd, 2);*/ close(fd); } static int daemon_poll_err(bozohttpd_t *httpd, int fd, int idx) { if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0) return 0; bozowarn(httpd, "poll on fd %d pid %d revents %d: %s", httpd->fds[idx].fd, getpid(), httpd->fds[idx].revents, strerror(errno)); bozowarn(httpd, "nsock = %d", httpd->nsock); close(httpd->sock[idx]); httpd->nsock--; bozowarn(httpd, "nsock now = %d", httpd->nsock); /* no sockets left */ if (httpd->nsock == 0) exit(0); /* last socket closed is the easy case */ if (httpd->nsock != idx) { memmove(&httpd->fds[idx], &httpd->fds[idx+1], (httpd->nsock - idx) * sizeof(*httpd->fds)); memmove(&httpd->sock[idx], &httpd->sock[idx+1], (httpd->nsock - idx) * sizeof(*httpd->sock)); } return 1; } /* * the parent never returns from this function, only children that * are ready to run... XXXMRG - still true in fork-lesser bozo? */ int bozo_daemon_fork(bozohttpd_t *httpd) { int i; debug((httpd, DEBUG_FAT, "%s: pid %u request_times %d", __func__, getpid(), httpd->request_times)); /* if we've handled 5 files, exit and let someone else work */ if (httpd->request_times > 5 || (httpd->background == 2 && httpd->request_times > 0)) _exit(0); #if 1 if (httpd->request_times > 0) _exit(0); #endif while (httpd->background) { struct sockaddr_storage ss; socklen_t slen; int fd; if (httpd->nsock == 0) exit(0); /* * wait for a connection, then fork() and return NULL in * the parent, who will come back here waiting for another * connection. read the request in in the child, and return * it, for processing. */ again: if (poll(httpd->fds, (unsigned)httpd->nsock, INFTIM) == -1) { /* fail on programmer errors */ if (errno == EFAULT || errno == EINVAL) bozoerr(httpd, 1, "poll: %s", strerror(errno)); /* sleep on some temporary kernel failures */ if (errno == ENOMEM || errno == EAGAIN) sleep(1); goto again; } for (i = 0; i < httpd->nsock; i++) { if (daemon_poll_err(httpd, fd, i)) break; if (httpd->fds[i].revents == 0) continue; slen = sizeof(ss); fd = accept(httpd->fds[i].fd, (struct sockaddr *)(void *)&ss, &slen); if (fd == -1) { if (errno == EFAULT || errno == EINVAL) bozoerr(httpd, 1, "accept: %s", strerror(errno)); if (errno == ENOMEM || errno == EAGAIN) sleep(1); continue; } #if 0 /* * This code doesn't work. It interacts very poorly * with ~user translation and needs to be fixed. */ if (httpd->request_times > 0) { daemon_runchild(httpd, fd); return 0; } #endif switch (fork()) { case -1: /* eep, failure */ bozowarn(httpd, "fork() failed, sleeping for " "10 seconds: %s", strerror(errno)); close(fd); sleep(10); break; case 0: /* child */ daemon_runchild(httpd, fd); return 0; default: /* parent */ close(fd); break; } } } return 0; } #endif /* NO_DAEMON_MODE */ |
Added debug/Makefile.
> > > > > > > > > | 1 2 3 4 5 6 7 8 9 | # $eterna: Makefile,v 1.1 2009/05/22 21:51:39 mrg Exp $ # build a debug bozohttpd PROG= bozohttpd-debug COPTS+= -DDEBUG -I$(.CURDIR)/.. .include "../Makefile" .PATH: $(.CURDIR)/.. |
Added dir-index-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | /* $NetBSD: dir-index-bozo.c,v 1.25 2015/12/29 04:21:46 mrg Exp $ */ /* $eterna: dir-index-bozo.c,v 1.20 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2014 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements directory index generation for bozohttpd */ #ifndef NO_DIRINDEX_SUPPORT #include <sys/param.h> #include <dirent.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <assert.h> #include "bozohttpd.h" static void directory_hr(bozohttpd_t *httpd) { bozo_printf(httpd, "<hr noshade align=\"left\" width=\"80%%\">\r\n\r\n"); } /* * output a directory index. return 1 if it actually did something.. */ int bozo_dir_index(bozo_httpreq_t *request, const char *dirpath, int isindex) { bozohttpd_t *httpd = request->hr_httpd; struct stat sb; struct dirent **de, **deo; struct tm *tm; DIR *dp; char buf[MAXPATHLEN]; char spacebuf[48]; char *file = NULL, *printname = NULL; int l, k, j, i; if (!isindex || !httpd->dir_indexing) return 0; if (strlen(dirpath) <= strlen(httpd->index_html)) dirpath = "."; else { file = bozostrdup(httpd, request, dirpath); file[strlen(file) - strlen(httpd->index_html)] = '\0'; dirpath = file; } debug((httpd, DEBUG_FAT, "bozo_dir_index: dirpath ``%s''", dirpath)); if (stat(dirpath, &sb) < 0 || (dp = opendir(dirpath)) == NULL) { if (errno == EPERM) (void)bozo_http_error(httpd, 403, request, "no permission to open directory"); else if (errno == ENOENT) (void)bozo_http_error(httpd, 404, request, "no file"); else (void)bozo_http_error(httpd, 500, request, "open directory"); goto done; /* NOTREACHED */ } bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto); if (request->hr_proto != httpd->consts.http_09) { bozo_print_header(request, NULL, "text/html", ""); bozo_printf(httpd, "\r\n"); } bozo_flush(httpd, stdout); if (request->hr_method == HTTP_HEAD) { closedir(dp); goto done; } #ifndef NO_USER_SUPPORT if (request->hr_user) { bozoasprintf(httpd, &printname, "~%s/%s", request->hr_user, request->hr_file); } else printname = bozostrdup(httpd, request, request->hr_file); #else printname = bozostrdup(httpd, request, request->hr_file); #endif /* !NO_USER_SUPPORT */ bozo_printf(httpd, "<html><head><title>Index of %s</title></head>\r\n", printname); bozo_printf(httpd, "<body><h1>Index of %s</h1>\r\n", printname); bozo_printf(httpd, "<pre>\r\n"); #define NAMELEN 40 #define LMODLEN 19 bozo_printf(httpd, "Name " "Last modified " "Size\n"); bozo_printf(httpd, "</pre>"); directory_hr(httpd); bozo_printf(httpd, "<pre>"); for (j = k = scandir(dirpath, &de, NULL, alphasort), deo = de; j--; de++) { int nostat = 0; char *name = (*de)->d_name; char *urlname, *htmlname; if (strcmp(name, ".") == 0 || (strcmp(name, "..") != 0 && httpd->hide_dots && name[0] == '.')) continue; snprintf(buf, sizeof buf, "%s/%s", dirpath, name); if (stat(buf, &sb)) nostat = 1; l = 0; urlname = bozo_escape_rfc3986(httpd, name, 0); htmlname = bozo_escape_html(httpd, name); if (htmlname == NULL) htmlname = name; if (strcmp(name, "..") == 0) { bozo_printf(httpd, "<a href=\"../\">"); l += bozo_printf(httpd, "Parent Directory"); } else if (S_ISDIR(sb.st_mode)) { bozo_printf(httpd, "<a href=\"%s/\">", urlname); l += bozo_printf(httpd, "%s/", htmlname); } else if (strchr(name, ':') != NULL) { /* RFC 3986 4.2 */ bozo_printf(httpd, "<a href=\"./%s\">", urlname); l += bozo_printf(httpd, "%s", htmlname); } else { bozo_printf(httpd, "<a href=\"%s\">", urlname); l += bozo_printf(httpd, "%s", htmlname); } if (htmlname != name) free(htmlname); bozo_printf(httpd, "</a>"); /* NAMELEN spaces */ /*LINTED*/ assert(/*CONSTCOND*/sizeof(spacebuf) > NAMELEN); i = (l < NAMELEN) ? (NAMELEN - l) : 0; i++; memset(spacebuf, ' ', (size_t)i); spacebuf[i] = '\0'; bozo_printf(httpd, "%s", spacebuf); l += i; if (nostat) bozo_printf(httpd, "? ?"); else { tm = gmtime(&sb.st_mtime); strftime(buf, sizeof buf, "%d-%b-%Y %R", tm); l += bozo_printf(httpd, "%s", buf); /* LMODLEN spaces */ /*LINTED*/ assert(/*CONSTCOND*/sizeof(spacebuf) > LMODLEN); i = (l < (LMODLEN+NAMELEN+1)) ? ((LMODLEN+NAMELEN+1) - l) : 0; i++; memset(spacebuf, ' ', (size_t)i); spacebuf[i] = '\0'; bozo_printf(httpd, "%s", spacebuf); bozo_printf(httpd, "%12llukB", (unsigned long long)sb.st_size >> 10); } bozo_printf(httpd, "\r\n"); } closedir(dp); while (k--) free(deo[k]); free(deo); bozo_printf(httpd, "</pre>"); directory_hr(httpd); bozo_printf(httpd, "</body></html>\r\n\r\n"); bozo_flush(httpd, stdout); done: free(file); free(printname); return 1; } #endif /* NO_DIRINDEX_SUPPORT */ |
Added libbozohttpd/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # $eterna: Makefile,v 1.1 2010/05/10 02:24:31 mrg Exp $ .PATH: $(.CURDIR)/.. # build bozohttpd library LIB= bozohttpd COPTS+= -I$(.CURDIR)/.. COPTS+= -DDO_HTPASSWD CPPFLAGS+= -DDO_HTPASSWD SRCS= bozohttpd.c ssl-bozo.c auth-bozo.c cgi-bozo.c daemon-bozo.c SRCS+= tilde-luzah-bozo.c dir-index-bozo.c content-bozo.c SRCS+= lua-bozo.c LDADD= -lcrypt DPADD= ${LIBCRYPT} MAN= libbozohttpd.3 WARNS= 4 INCS= bozohttpd.h INCSDIR= /usr/include .include <bsd.own.mk> .if ${MKCRYPTO} != "no" LDADD+= -lssl -lcrypto DPADD+= ${LIBSSL} ${LIBCRYPTO} .else COPTS+= -DNO_SSL_SUPPORT .endif .include <bsd.lib.mk> |
Added libbozohttpd/libbozohttpd.3.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | .\" $NetBSD: libbozohttpd.3,v 1.3 2014/03/18 18:20:38 riastradh Exp $ .\" .\" $eterna: libbozohttpd.3,v 1.2 2010/05/10 02:48:23 mrg Exp $ .\" .\" Copyright (c) 2009 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This manual page is derived from software contributed to The .\" NetBSD Foundation by Alistair Crooks (agc@NetBSD.org) .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" .Dd November 5, 2009 .Dt LIBBOZOHTTPD 3 .Os .Sh NAME .Nm libbozohttpd .Nd embedded web server library .Sh LIBRARY .Lb libbozohttpd .Sh SYNOPSIS .In bozohttpd.h .Ft int .Fo bozo_set_pref .Fa "bozoprefs_t *prefs" "char *name" "char *value" .Fc .Ft char * .Fo bozo_get_pref .Fa "bozoprefs_t *prefs" "char *name" .Fc .Ft int .Fo bozo_set_defaults .Fa "bozohttpd_t *httpd" "bozoprefs_t *prefs" .Fc .Ft void .Fo bozo_setup .Fa "bozohttpd_t *httpd" "bozoprefs_t *prefs" "const char *vhost" "char *slash" .Fc .Ft bozo_httpreq_t * .Fo bozo_read_request .Fa "bozohttpd_t *httpd" .Fc .Ft void .Fo bozo_process_request .Fa "bozo_httpreq_t *" .Fc .Ft void .Fo bozo_clean_request .Fa "bozo_httpreq_t *" .Fc .Sh DESCRIPTION .Nm is a library interface to the .Xr bozohttpd 8 web server. The .Nm library can be used to embed a webserver in your applications. .Pp Normal operation sees the .Nm process be initialised using the .Fn bozo_set_defaults function, which will set up the default port and other internal settings, allocating any necessary space as needed. The .Fn bozo_set_defaults function returns 1 on sucess, 0 on failure. .Pp The .Fn bozo_setup function is used to specify the virtual host name for the web server. A NULL host name will mean that .Nm will use the local value for the host name, as returned by .Xr gethostname 3 . This virtual hostname should be a fully qualified domain name. The final argument to .Fn bozo_setup is the name of the directory to serve as the root directory of the web server tree. .Pp Once the server has been set up, it serves requests by using the .Fn bozo_read_request function, which returns a pointer to a request structure, and .Fn bozo_process_request , which deals with the request, and answers the client. The request space is de-allocated using the .Fn bozo_clean_request function. .Pp Preferences are set using the function .Fn bozo_set_pref function and queried using the two .Fn bozo_get_pref function. This is the main interface for selecting options, and for setting preferences. .Sh SEE ALSO .Xr gethostname 3 , .Xr ssl 3 , .Xr services 5 , .Xr httpd 8 .Sh HISTORY The .Nm library first appeared in .Nx 6.0 . .Sh AUTHORS .An Matthew R. Green Aq Mt mrg@eterna.com.au .An Alistair Crooks Aq Mt agc@NetBSD.org wrote this high-level interface. .Pp This manual page was written by .An Alistair Crooks . |
Added libbozohttpd/shlib_version.
> > | 1 2 | major=0 minor=0 |
Added lua-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | /* $NetBSD: lua-bozo.c,v 1.14 2015/12/28 07:37:59 mrg Exp $ */ /* * Copyright (c) 2013 Marc Balmer <marc@msys.ch> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements dynamic content generation using Lua for bozohttpd */ #ifndef NO_LUA_SUPPORT #include <sys/param.h> #include <lua.h> #include <lauxlib.h> #include <lualib.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "bozohttpd.h" /* Lua binding for bozohttp */ #if LUA_VERSION_NUM < 502 #define LUA_HTTPDLIBNAME "httpd" #endif #define FORM "application/x-www-form-urlencoded" static int lua_flush(lua_State *L) { bozohttpd_t *httpd; lua_pushstring(L, "bozohttpd"); lua_gettable(L, LUA_REGISTRYINDEX); httpd = lua_touserdata(L, -1); lua_pop(L, 1); bozo_flush(httpd, stdout); return 0; } static int lua_print(lua_State *L) { bozohttpd_t *httpd; lua_pushstring(L, "bozohttpd"); lua_gettable(L, LUA_REGISTRYINDEX); httpd = lua_touserdata(L, -1); lua_pop(L, 1); bozo_printf(httpd, "%s\r\n", lua_tostring(L, -1)); return 0; } static int lua_read(lua_State *L) { bozohttpd_t *httpd; int n, len; char *data; lua_pushstring(L, "bozohttpd"); lua_gettable(L, LUA_REGISTRYINDEX); httpd = lua_touserdata(L, -1); lua_pop(L, 1); len = luaL_checkinteger(L, -1); data = bozomalloc(httpd, len + 1); n = bozo_read(httpd, STDIN_FILENO, data, len); if (n >= 0) { data[n] = '\0'; lua_pushstring(L, data); } else lua_pushnil(L); free(data); return 1; } static int lua_register_handler(lua_State *L) { lua_state_map_t *map; lua_handler_t *handler; bozohttpd_t *httpd; lua_pushstring(L, "lua_state_map"); lua_gettable(L, LUA_REGISTRYINDEX); map = lua_touserdata(L, -1); lua_pushstring(L, "bozohttpd"); lua_gettable(L, LUA_REGISTRYINDEX); httpd = lua_touserdata(L, -1); lua_pop(L, 2); luaL_checkstring(L, 1); luaL_checktype(L, 2, LUA_TFUNCTION); handler = bozomalloc(httpd, sizeof(lua_handler_t)); handler->name = bozostrdup(httpd, NULL, lua_tostring(L, 1)); handler->ref = luaL_ref(L, LUA_REGISTRYINDEX); SIMPLEQ_INSERT_TAIL(&map->handlers, handler, h_next); httpd->process_lua = 1; return 0; } static int lua_write(lua_State *L) { bozohttpd_t *httpd; const char *data; lua_pushstring(L, "bozohttpd"); lua_gettable(L, LUA_REGISTRYINDEX); httpd = lua_touserdata(L, -1); lua_pop(L, 1); data = luaL_checkstring(L, -1); lua_pushinteger(L, bozo_write(httpd, STDIN_FILENO, data, strlen(data))); return 1; } static int luaopen_httpd(lua_State *L) { struct luaL_Reg functions[] = { { "flush", lua_flush }, { "print", lua_print }, { "read", lua_read }, { "register_handler", lua_register_handler }, { "write", lua_write }, { NULL, NULL } }; #if LUA_VERSION_NUM >= 502 luaL_newlib(L, functions); #else luaL_register(L, LUA_HTTPDLIBNAME, functions); #endif lua_pushstring(L, "httpd 1.0.0"); lua_setfield(L, -2, "_VERSION"); return 1; } #if LUA_VERSION_NUM < 502 static void lua_openlib(lua_State *L, const char *name, lua_CFunction fn) { lua_pushcfunction(L, fn); lua_pushstring(L, name); lua_call(L, 1, 0); } #endif /* bozohttpd integration */ void bozo_add_lua_map(bozohttpd_t *httpd, const char *prefix, const char *script) { lua_state_map_t *map; map = bozomalloc(httpd, sizeof(lua_state_map_t)); map->prefix = bozostrdup(httpd, NULL, prefix); if (*script == '/') map->script = bozostrdup(httpd, NULL, script); else { char cwd[MAXPATHLEN], *path; getcwd(cwd, sizeof(cwd) - 1); bozoasprintf(httpd, &path, "%s/%s", cwd, script); map->script = path; } map->L = luaL_newstate(); if (map->L == NULL) bozoerr(httpd, 1, "can't create Lua state"); SIMPLEQ_INIT(&map->handlers); #if LUA_VERSION_NUM >= 502 luaL_openlibs(map->L); lua_getglobal(map->L, "package"); lua_getfield(map->L, -1, "preload"); lua_pushcfunction(map->L, luaopen_httpd); lua_setfield(map->L, -2, "httpd"); lua_pop(map->L, 2); #else lua_openlib(map->L, "", luaopen_base); lua_openlib(map->L, LUA_LOADLIBNAME, luaopen_package); lua_openlib(map->L, LUA_TABLIBNAME, luaopen_table); lua_openlib(map->L, LUA_STRLIBNAME, luaopen_string); lua_openlib(map->L, LUA_MATHLIBNAME, luaopen_math); lua_openlib(map->L, LUA_OSLIBNAME, luaopen_os); lua_openlib(map->L, LUA_IOLIBNAME, luaopen_io); lua_openlib(map->L, LUA_HTTPDLIBNAME, luaopen_httpd); #endif lua_pushstring(map->L, "lua_state_map"); lua_pushlightuserdata(map->L, map); lua_settable(map->L, LUA_REGISTRYINDEX); lua_pushstring(map->L, "bozohttpd"); lua_pushlightuserdata(map->L, httpd); lua_settable(map->L, LUA_REGISTRYINDEX); if (luaL_loadfile(map->L, script)) bozoerr(httpd, 1, "failed to load script %s: %s", script, lua_tostring(map->L, -1)); if (lua_pcall(map->L, 0, 0, 0)) bozoerr(httpd, 1, "failed to execute script %s: %s", script, lua_tostring(map->L, -1)); SIMPLEQ_INSERT_TAIL(&httpd->lua_states, map, s_next); } static void lua_env(lua_State *L, const char *name, const char *value) { lua_pushstring(L, value); lua_setfield(L, -2, name); } /* decode query string */ static void lua_url_decode(lua_State *L, char *s) { char *v, *p, *val, *q; char buf[3]; int c; v = strchr(s, '='); if (v == NULL) return; *v++ = '\0'; val = malloc(strlen(v) + 1); if (val == NULL) return; for (p = v, q = val; *p; p++) { switch (*p) { case '%': if (*(p + 1) == '\0' || *(p + 2) == '\0') { free(val); return; } buf[0] = *++p; buf[1] = *++p; buf[2] = '\0'; sscanf(buf, "%2x", &c); *q++ = (char)c; break; case '+': *q++ = ' '; break; default: *q++ = *p; } } *q = '\0'; lua_pushstring(L, val); lua_setfield(L, -2, s); free(val); } static void lua_decode_query(lua_State *L, char *query) { char *s; s = strtok(query, "&"); while (s) { lua_url_decode(L, s); s = strtok(NULL, "&"); } } int bozo_process_lua(bozo_httpreq_t *request) { bozohttpd_t *httpd = request->hr_httpd; lua_state_map_t *map; lua_handler_t *hndlr; int n, ret, length; char date[40]; bozoheaders_t *headp; char *s, *query, *uri, *file, *command, *info, *content; const char *type, *clen; char *prefix, *handler, *p; int rv = 0; if (!httpd->process_lua) return 0; info = NULL; query = NULL; prefix = NULL; uri = request->hr_oldfile ? request->hr_oldfile : request->hr_file; if (*uri == '/') { file = bozostrdup(httpd, request, uri); if (file == NULL) goto out; prefix = bozostrdup(httpd, request, &uri[1]); } else { if (asprintf(&file, "/%s", uri) < 0) goto out; prefix = bozostrdup(httpd, request, uri); } if (prefix == NULL) goto out; if (request->hr_query && request->hr_query[0]) query = bozostrdup(httpd, request, request->hr_query); p = strchr(prefix, '/'); if (p == NULL) goto out; *p++ = '\0'; handler = p; if (!*handler) goto out; p = strchr(handler, '/'); if (p != NULL) *p++ = '\0'; command = file + 1; if ((s = strchr(command, '/')) != NULL) { info = bozostrdup(httpd, request, s); *s = '\0'; } type = request->hr_content_type; clen = request->hr_content_length; SIMPLEQ_FOREACH(map, &httpd->lua_states, s_next) { if (strcmp(map->prefix, prefix)) continue; SIMPLEQ_FOREACH(hndlr, &map->handlers, h_next) { if (strcmp(hndlr->name, handler)) continue; lua_rawgeti(map->L, LUA_REGISTRYINDEX, hndlr->ref); /* Create the "environment" */ lua_newtable(map->L); lua_env(map->L, "SERVER_NAME", BOZOHOST(httpd, request)); lua_env(map->L, "GATEWAY_INTERFACE", "Luigi/1.0"); lua_env(map->L, "SERVER_PROTOCOL", request->hr_proto); lua_env(map->L, "REQUEST_METHOD", request->hr_methodstr); lua_env(map->L, "SCRIPT_PREFIX", map->prefix); lua_env(map->L, "SCRIPT_NAME", file); lua_env(map->L, "HANDLER_NAME", hndlr->name); lua_env(map->L, "SCRIPT_FILENAME", map->script); lua_env(map->L, "SERVER_SOFTWARE", httpd->server_software); lua_env(map->L, "REQUEST_URI", uri); lua_env(map->L, "DATE_GMT", bozo_http_date(date, sizeof(date))); if (query && *query) lua_env(map->L, "QUERY_STRING", query); if (info && *info) lua_env(map->L, "PATH_INFO", info); if (type && *type) lua_env(map->L, "CONTENT_TYPE", type); if (clen && *clen) lua_env(map->L, "CONTENT_LENGTH", clen); if (request->hr_serverport && *request->hr_serverport) lua_env(map->L, "SERVER_PORT", request->hr_serverport); if (request->hr_remotehost && *request->hr_remotehost) lua_env(map->L, "REMOTE_HOST", request->hr_remotehost); if (request->hr_remoteaddr && *request->hr_remoteaddr) lua_env(map->L, "REMOTE_ADDR", request->hr_remoteaddr); /* Pass the headers in a separate table */ lua_newtable(map->L); SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) lua_env(map->L, headp->h_header, headp->h_value); /* Pass the query variables */ if ((query && *query) || (type && *type && !strcmp(type, FORM))) { lua_newtable(map->L); if (query && *query) lua_decode_query(map->L, query); if (type && *type && !strcmp(type, FORM)) { if (clen && *clen && atol(clen) > 0) { length = atol(clen); content = bozomalloc(httpd, length + 1); n = bozo_read(httpd, STDIN_FILENO, content, length); if (n >= 0) { content[n] = '\0'; lua_decode_query(map->L, content); } else { lua_pop(map->L, 1); lua_pushnil(map->L); } free(content); } } } else lua_pushnil(map->L); ret = lua_pcall(map->L, 3, 0, 0); if (ret) printf("<br>Lua error: %s\n", lua_tostring(map->L, -1)); bozo_flush(httpd, stdout); rv = 1; goto out; } } out: free(prefix); free(uri); free(info); free(query); free(file); return rv; } #endif /* NO_LUA_SUPPORT */ |
Added lua/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #PREFIX=/Users/agcrooks PREFIX=/usr #LIBDIR=/usr/lib LIB=luabozohttpd SRCS=glue.c MKMAN=no CPPFLAGS+=-g -I${PREFIX}/pkg/include LDADD+= -lbozohttpd WARNS=4 CLEANFILES+= a a.sig .include <bsd.lib.mk> .include <bsd.own.mk> LUABOZOOBJDIR != cd ${.CURDIR} && ${PRINTOBJDIR} OPSYS!= uname -s .if ${OPSYS} == "Darwin" .sinclude <bsd.warns.mk> lib${LIB}.dylib: libtool -dynamic -o ${.TARGET} ${OBJS} ${PREFIX}/pkg/lib/liblua.dylib /usr/lib/libc.dylib ${PREFIX}/pkg/lib/libbozohttpd.dylib t: lib${LIB}.dylib cp Makefile a ./bozo.lua --sign --detached a ./bozo.lua --verify a.sig .else t: cp Makefile a env LD_LIBRARY_PATH=${LUABOZOOBJDIR}:/lib:/usr/lib:${PREFIX}/lib \ ./bozo.lua --sign --detached a env LD_LIBRARY_PATH=${LUABOZOOBJDIR}:/lib:/usr/lib:${PREFIX}/lib \ ./bozo.lua --verify a.sig .endif |
Added lua/bozo.lua.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | #! /usr/bin/env lua -- -- Copyright (c) 2009 The NetBSD Foundation, Inc. -- All rights reserved. -- -- This code is derived from software contributed to The NetBSD Foundation -- by Alistair Crooks (agc@netbsd.org) -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions -- are met: -- 1. Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- 2. Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution. -- -- THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- POSSIBILITY OF SUCH DAMAGE. -- -- command line args dofile "optparse.lua" opt = OptionParser{usage="%prog [options] root [vhost]", version="20091105"} opt.add_option{"-C", "--cgimap", action="store", dest="cgimap", help="--cgimap 's t'"} opt.add_option{"-E", "--enable-user-cgibin", action="store_true", dest="enableusercgibin", help="--enable-user-cgibin"} opt.add_option{"-H", "--hide-dots", action="store_true", dest="hidedots", help="--hide-dots"} opt.add_option{"-I", "--portnum", action="store", dest="portnum", help="--portnum number"} opt.add_option{"-M", "--dynamicmime", action="store", dest="dynmime", help="--dynamicmime 'suffix type a b'"} opt.add_option{"-S", "--server-software", action="store", dest="serversw", help="--server-software name"} opt.add_option{"-U", "--username", action="store", dest="username", help="--username name"} opt.add_option{"-V", "--unknown-slash", action="store_true", dest="unknown", help="--unknown-slash"} opt.add_option{"-X", "--dir-index", action="store_true", dest="dirindex", help="--dir-index"} opt.add_option{"-Z", "--ssl", action="store", dest="ssl", help="--ssl 'cert priv'"} opt.add_option{"-b", "--background", action="store", dest="background", help="--background count"} opt.add_option{"-c", "--cgibin", action="store", dest="cgibin", help="--cgibin bin"} opt.add_option{"-e", "--dirtyenv", action="store_true", dest="dirtyenv", help="--dirtyenv"} opt.add_option{"-f", "--foreground", action="store_true", dest="foreground", help="--foreground"} opt.add_option{"-i", "--bindaddr", action="store", dest="bindaddress", help="--bindaddr address"} opt.add_option{"-n", "--numeric", action="store_true", dest="numeric", help="--numeric"} opt.add_option{"-p", "--public-html", action="store", dest="public_html", help="--public-html dir"} opt.add_option{"-s", "--logtostderr", action="store_true", dest="logstderr", help="log to stderr"} opt.add_option{"-t", "--chroot", action="store", dest="chroot", help="--chroot dir"} opt.add_option{"-u", "--enable-users", action="store_true", dest="enableusers", help="--enable-users"} opt.add_option{"-v", "--virtbase", action="store", dest="virtbase", help="virtual base location"} opt.add_option{"-x", "--index-html", action="store", dest="indexhtml", help="index.html name"} -- caller lua script local extension = ".so" f = io.open("libluabozohttpd.dylib", "r") if f then extension = ".dylib" io.close(f) end glupkg = package.loadlib("./" .. "libluabozohttpd" .. extension, "luaopen_bozohttpd") bozohttpd = glupkg() -- initialise httpd = bozohttpd.new() bozohttpd.init_httpd(httpd) prefs = bozohttpd.init_prefs() -- parse command line args options,args = opt.parse_args() if options.portnum then bozohttpd.set_pref(prefs, "port number", options.portnum) end if options.background then bozohttpd.set_pref(prefs, "background", options.background) end if options.numeric then bozohttpd.set_pref(prefs, "numeric", "true") end if options.logstderr then bozohttpd.set_pref(prefs, "log to stderr", "true") end if options.foreground then bozohttpd.set_pref(prefs, "foreground", "true") end if options.trustedref then bozohttpd.set_pref(prefs, "trusted referal", "true") end if options.dynmime then suffix, type, s1, s2 = string.find(options.dynmime, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+)") bozohttpd.dynamic_mime(httpd, suffix, type, s1, s2) end if options.serversw then bozohttpd.set_pref(prefs, "server software", options.serversw) end if options.ssl then cert, priv = string.find(options.ssl, "(%S+)%s+(%S+)") bozohttpd.dynamic_mime(httpd, cert, priv) end if options.username then bozohttpd.set_pref(prefs, "username", options.username) end if options.unknownslash then bozohttpd.set_pref(prefs, "unknown slash", "true") end if options.virtbase then bozohttpd.set_pref(prefs, "virtual base", options.virtbase) end if options.indexhtml then bozohttpd.set_pref(prefs, "index.html", options.indexhtml) end if options.dirtyenv then bozohttpd.set_pref(prefs, "dirty environment", "true") end if options.bindaddr then bozohttpd.set_pref(prefs, "bind address", options.bindaddr) end if options.cgibin then bozohttpd.cgi_setbin(httpd, options.cgibin) end if options.cgimap then name, handler = string.find(options.cgimap, "(%S+)%s+(%S+)") bozohttpd.cgi_map(httpd, name, handler) end if options.public_html then bozohttpd.set_pref(prefs, "public_html", options.public_html) end if options.chroot then bozohttpd.set_pref(prefs, "chroot dir", options.chroot) end if options.enableusers then bozohttpd.set_pref(prefs, "enable users", "true") end if options.hidedots then bozohttpd.set_pref(prefs, "hide dots", "true") end if options.enableusercgibin then bozohttpd.set_pref(prefs, "enable user cgibin", "true") end if options.dirindex then bozohttpd.set_pref(prefs, "directory indexing", "true") end if #args < 1 then print("At least one arg needed for root directory") else -- set up connections local vhost = args[2] or "" bozohttpd.setup(httpd, prefs, vhost, args[1]) -- loop, serving requests local numreps = options.background or 0 repeat req = bozohttpd.read_request(httpd) bozohttpd.process_request(httpd, req) bozohttpd.clean_request(req) until numreps == 0 end |
Added lua/glue.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Alistair Crooks (agc@netbsd.org) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/types.h> #include <sys/param.h> #include <sys/stat.h> #include <bozohttpd.h> #include <inttypes.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define LUA_LIB #include <lua.h> #include <lauxlib.h> #include <lualib.h> #ifndef __UNCONST #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #endif /* !__UNCONST */ int luaopen_bozohttpd(lua_State *); #if 0 typedef struct strarg_t { const char *s; /* string */ const int n; /* corresponding int value */ } strarg_t; /* map a string onto an int */ static int findtype(strarg_t *strs, const char *s) { strarg_t *sp; for (sp = strs ; sp->s && strcasecmp(sp->s, s) != 0 ; sp++) { } return sp->n; } #endif /* init() */ static int l_new(lua_State *L) { bozohttpd_t *httpd; httpd = lua_newuserdata(L, sizeof(*httpd)); (void) memset(httpd, 0x0, sizeof(*httpd)); return 1; } /* initialise(httpd) */ static int l_init_httpd(lua_State *L) { bozohttpd_t *httpd; httpd = lua_touserdata(L, 1); lua_pushnumber(L, bozo_init_httpd(httpd)); return 1; } /* initialise(prefs) */ static int l_init_prefs(lua_State *L) { bozohttpd_t *httpd; bozoprefs_t *prefs; prefs = lua_newuserdata(L, sizeof(*prefs)); (void) memset(prefs, 0x0, sizeof(*prefs)); httpd = lua_touserdata(L, 1); (void) bozo_init_prefs(httpd, prefs); return 1; } /* bozo_set_pref(prefs, name, value) */ static int l_bozo_set_pref(lua_State *L) { bozoprefs_t *prefs; const char *name; const char *value; prefs = lua_touserdata(L, 1); name = luaL_checkstring(L, 2); value = luaL_checkstring(L, 3); lua_pushnumber(L, bozo_set_pref(prefs, name, value)); return 1; } /* bozo_get_pref(prefs, name) */ static int l_bozo_get_pref(lua_State *L) { bozoprefs_t *prefs; const char *name; prefs = lua_touserdata(L, 1); name = luaL_checkstring(L, 2); lua_pushstring(L, bozo_get_pref(prefs, name)); return 1; } /* bozo_setup(httpd, prefs, host, root) */ static int l_bozo_setup(lua_State *L) { bozohttpd_t *httpd; bozoprefs_t *prefs; const char *vhost; const char *root; httpd = lua_touserdata(L, 1); prefs = lua_touserdata(L, 2); vhost = luaL_checkstring(L, 3); if (vhost && *vhost == 0x0) { vhost = NULL; } root = luaL_checkstring(L, 4); lua_pushnumber(L, bozo_setup(httpd, prefs, vhost, root)); return 1; } /* bozo_read_request(httpd) */ static int l_bozo_read_request(lua_State *L) { bozo_httpreq_t *req; bozohttpd_t *httpd; httpd = lua_touserdata(L, 1); req = bozo_read_request(httpd); lua_pushlightuserdata(L, req); return 1; } /* bozo_process_request(httpd, req) */ static int l_bozo_process_request(lua_State *L) { bozo_httpreq_t *req; bozohttpd_t *httpd; httpd = lua_touserdata(L, 1); req = lua_touserdata(L, 2); bozo_process_request(httpd, req); lua_pushnumber(L, 1); return 1; } /* bozo_clean_request(req) */ static int l_bozo_clean_request(lua_State *L) { bozo_httpreq_t *req; req = lua_touserdata(L, 1); bozo_clean_request(req); lua_pushnumber(L, 1); return 1; } /* dynamic_mime(httpd, one, two, three, four) */ static int l_bozo_dynamic_mime(lua_State *L) { bozohttpd_t *httpd; const char *s[4]; httpd = lua_touserdata(L, 1); s[0] = luaL_checkstring(L, 2); s[1] = luaL_checkstring(L, 3); s[2] = luaL_checkstring(L, 4); s[3] = luaL_checkstring(L, 5); bozo_add_content_map_mime(httpd, s[0], s[1], s[2], s[3]); lua_pushnumber(L, 1); return 1; } /* ssl_set_opts(httpd, one, two) */ static int l_bozo_ssl_set_opts(lua_State *L) { bozohttpd_t *httpd; const char *s[2]; httpd = lua_touserdata(L, 1); s[0] = luaL_checkstring(L, 2); s[1] = luaL_checkstring(L, 3); bozo_ssl_set_opts(httpd, s[0], s[1]); lua_pushnumber(L, 1); return 1; } /* cgi_setbin(httpd, bin) */ static int l_bozo_cgi_setbin(lua_State *L) { bozohttpd_t *httpd; const char *bin; httpd = lua_touserdata(L, 1); bin = luaL_checkstring(L, 2); bozo_cgi_setbin(httpd, bin); lua_pushnumber(L, 1); return 1; } /* cgi_map(httpd, 1, 2) */ static int l_bozo_cgi_map(lua_State *L) { bozohttpd_t *httpd; const char *s[2]; httpd = lua_touserdata(L, 1); s[0] = luaL_checkstring(L, 2); s[1] = luaL_checkstring(L, 3); bozo_add_content_map_cgi(httpd, s[0], s[1]); lua_pushnumber(L, 1); return 1; } const struct luaL_reg libluabozohttpd[] = { { "new", l_new }, { "init_httpd", l_init_httpd }, { "init_prefs", l_init_prefs }, { "set_pref", l_bozo_set_pref }, { "get_pref", l_bozo_get_pref }, { "setup", l_bozo_setup }, { "dynamic_mime", l_bozo_dynamic_mime }, { "ssl_set_opts", l_bozo_ssl_set_opts }, { "cgi_setbin", l_bozo_cgi_setbin }, { "cgi_map", l_bozo_cgi_map }, { "read_request", l_bozo_read_request }, { "process_request", l_bozo_process_request }, { "clean_request", l_bozo_clean_request }, { NULL, NULL } }; int luaopen_bozohttpd(lua_State *L) { luaL_openlib(L, "bozohttpd", libluabozohttpd, 0); return 1; } |
Added lua/optparse.lua.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | -- Lua command line option parser. -- Interface based on Pythons optparse. -- http://docs.python.org/lib/module-optparse.html -- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license) -- -- To be used like this: -- t={usage="<some usage message>", version="<version string>"} -- op=OptionParser(t) -- op=add_option{"<opt>", action=<action>, dest=<dest>, help="<help message for this option>"} -- -- with : -- <opt> the option string to be used (can be anything, if one letter opt, then should be -x val, more letters: -xy=val ) -- <action> one of -- - store: store in options as key, val -- - store_true: stores key, true -- - store_false: stores key, false -- <dest> is the key under which the option is saved -- -- options,args = op.parse_args() -- -- now options is the table of options (key, val) and args is the table with non-option arguments. -- You can use op.fail(message) for failing and op.print_help() for printing the usage as you like. function OptionParser(t) local usage = t.usage local version = t.version local o = {} local option_descriptions = {} local option_of = {} function o.fail(s) -- extension io.stderr:write(s .. '\n') os.exit(1) end function o.add_option(optdesc) option_descriptions[#option_descriptions+1] = optdesc for _,v in ipairs(optdesc) do option_of[v] = optdesc end end function o.parse_args() -- expand options (e.g. "--input=file" -> "--input", "file") local arg = {unpack(arg)} for i=#arg,1,-1 do local v = arg[i] local flag, val = v:match('^(%-%-%w+)=(.*)') if flag then arg[i] = flag table.insert(arg, i+1, val) end end local options = {} local args = {} local i = 1 while i <= #arg do local v = arg[i] local optdesc = option_of[v] if optdesc then local action = optdesc.action local val if action == 'store' or action == nil then i = i + 1 val = arg[i] if not val then o.fail('option requires an argument ' .. v) end elseif action == 'store_true' then val = true elseif action == 'store_false' then val = false end options[optdesc.dest] = val else if v:match('^%-') then o.fail('invalid option ' .. v) end args[#args+1] = v end i = i + 1 end if options.help then o.print_help() os.exit() end if options.version then io.stdout:write(t.version .. "\n") os.exit() end return options, args end local function flags_str(optdesc) local sflags = {} local action = optdesc.action for _,flag in ipairs(optdesc) do local sflagend if action == nil or action == 'store' then local metavar = optdesc.metavar or optdesc.dest:upper() sflagend = #flag == 2 and ' ' .. metavar or '=' .. metavar else sflagend = '' end sflags[#sflags+1] = flag .. sflagend end return table.concat(sflags, ', ') end function o.print_help() io.stdout:write("Usage: " .. usage:gsub('%%prog', arg[0]) .. "\n") io.stdout:write("\n") io.stdout:write("Options:\n") for _,optdesc in ipairs(option_descriptions) do io.stdout:write(" " .. flags_str(optdesc) .. " " .. optdesc.help .. "\n") end end o.add_option{"--help", action="store_true", dest="help", help="show this help message and exit"} if t.version then o.add_option{"--version", action="store_true", dest="version", help="output version info."} end return o end |
Added lua/shlib_version.
> > | 1 2 | major=0 minor=0 |
Added main.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | /* $NetBSD: main.c,v 1.16 2016/10/04 18:33:00 mrg Exp $ */ /* $eterna: main.c,v 1.6 2011/11/18 09:21:15 mrg Exp $ */ /* from: eterna: bozohttpd.c,v 1.159 2009/05/23 02:14:30 mrg Exp */ /* * Copyright (c) 1997-2016 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this program is dedicated to the Great God of Processed Cheese */ /* * main.c: C front end to bozohttpd */ #include <sys/types.h> #include <sys/param.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <time.h> #include <unistd.h> #include "bozohttpd.h" /* variables and functions */ #ifndef LOG_FTP #define LOG_FTP LOG_DAEMON #endif /* print a usage message, and then exit */ BOZO_DEAD static void usage(bozohttpd_t *httpd, char *progname) { bozowarn(httpd, "usage: %s [options] slashdir [virtualhostname]", progname); bozowarn(httpd, "options:"); #ifndef NO_DEBUG bozowarn(httpd, " -d\t\t\tenable debug support"); #endif bozowarn(httpd, " -s\t\t\talways log to stderr"); #ifndef NO_DYNAMIC_CONTENT bozowarn(httpd, " -M arg t c c11\tadd this mime extenstion"); #endif #ifndef NO_USER_SUPPORT bozowarn(httpd, " -u\t\t\tenable ~user/public_html support"); bozowarn(httpd, " -p dir\t\tchange `public_html' directory name"); #ifndef NO_CGIBIN_SUPPORT bozowarn(httpd, " -E\t\t\tenable CGI support for user dirs"); #endif #endif #ifndef NO_CGIBIN_SUPPORT #ifndef NO_DYNAMIC_CONTENT bozowarn(httpd, " -C arg prog\t\tadd this CGI handler"); #endif bozowarn(httpd, " -c cgibin\t\tenable cgi-bin support in this directory"); #endif #ifndef NO_LUA_SUPPORT bozowarn(httpd, " -L arg script\tadd this Lua script"); #endif bozowarn(httpd, " -I port\t\tbind or use on this port"); #ifndef NO_DAEMON_MODE bozowarn(httpd, " -b\t\t\tbackground and go into daemon mode"); bozowarn(httpd, " -f\t\t\tkeep daemon mode in the foreground"); bozowarn(httpd, " -i address\t\tbind on this address (daemon mode only)"); bozowarn(httpd, " -P pidfile\t\tpath to the pid file to create"); #endif bozowarn(httpd, " -S version\t\tset server version string"); bozowarn(httpd, " -t dir\t\tchroot to `dir'"); bozowarn(httpd, " -U username\t\tchange user to `user'"); bozowarn(httpd, " -e\t\t\tdon't clean the environment (-t and -U only)"); bozowarn(httpd, " -v virtualroot\tenable virtual host support " "in this directory"); bozowarn(httpd, " -V\t\tUnknown virtual hosts go to `slashdir'"); #ifndef NO_DIRINDEX_SUPPORT bozowarn(httpd, " -X\t\t\tenable automatic directory index support"); bozowarn(httpd, " -H\t\t\thide files starting with a period (.)" " in index mode"); #endif bozowarn(httpd, " -x index\t\tchange default `index.html' file name"); #ifndef NO_SSL_SUPPORT bozowarn(httpd, " -z ciphers\t\tspecify SSL ciphers"); bozowarn(httpd, " -Z cert privkey\tspecify path to server certificate" " and private key file\n" "\t\t\tin pem format and enable bozohttpd in SSL mode"); #endif /* NO_SSL_SUPPORT */ bozowarn(httpd, " -G print version number and exit"); bozoerr(httpd, 1, "%s failed to start", progname); } int main(int argc, char **argv) { bozo_httpreq_t *request; bozohttpd_t httpd; bozoprefs_t prefs; char *progname; const char *val; int c; (void) memset(&httpd, 0x0, sizeof(httpd)); (void) memset(&prefs, 0x0, sizeof(prefs)); if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; else progname++; openlog(progname, LOG_PID|LOG_NDELAY, LOG_FTP); bozo_set_defaults(&httpd, &prefs); /* * -r option was removed, do not reuse it for a while */ while ((c = getopt(argc, argv, "C:EGHI:L:M:P:S:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) { switch (c) { case 'L': #ifdef NO_LUA_SUPPORT bozoerr(&httpd, 1, "Lua support is not enabled"); /* NOTREACHED */ #else /* make sure there's two argument */ if (argc - optind < 1) usage(&httpd, progname); bozo_add_lua_map(&httpd, optarg, argv[optind]); optind++; break; #endif /* NO_LUA_SUPPORT */ case 'M': #ifdef NO_DYNAMIC_CONTENT bozoerr(&httpd, 1, "dynamic mime content support is not enabled"); /* NOTREACHED */ #else /* make sure there's four arguments */ if (argc - optind < 3) usage(&httpd, progname); bozo_add_content_map_mime(&httpd, optarg, argv[optind], argv[optind+1], argv[optind+2]); optind += 3; break; #endif /* NO_DYNAMIC_CONTENT */ case 'n': bozo_set_pref(&httpd, &prefs, "numeric", "true"); break; case 's': bozo_set_pref(&httpd, &prefs, "log to stderr", "true"); break; case 'S': bozo_set_pref(&httpd, &prefs, "server software", optarg); break; case 'Z': #ifdef NO_SSL_SUPPORT bozoerr(&httpd, 1, "ssl support is not enabled"); /* NOT REACHED */ #else /* make sure there's two arguments */ if (argc - optind < 1) usage(&httpd, progname); bozo_ssl_set_opts(&httpd, optarg, argv[optind++]); break; #endif /* NO_SSL_SUPPORT */ case 'z': #ifdef NO_SSL_SUPPORT bozoerr(&httpd, 1, "ssl support is not enabled"); /* NOT REACHED */ #else bozo_ssl_set_ciphers(&httpd, optarg); break; #endif /* NO_SSL_SUPPORT */ case 'U': bozo_set_pref(&httpd, &prefs, "username", optarg); break; case 'V': bozo_set_pref(&httpd, &prefs, "unknown slash", "true"); break; case 'v': bozo_set_pref(&httpd, &prefs, "virtual base", optarg); break; case 'x': bozo_set_pref(&httpd, &prefs, "index.html", optarg); break; case 'I': bozo_set_pref(&httpd, &prefs, "port number", optarg); break; #ifdef NO_DAEMON_MODE case 'b': case 'e': case 'f': case 'i': case 'P': bozoerr(&httpd, 1, "Daemon mode is not enabled"); /* NOTREACHED */ #else case 'b': /* * test suite support - undocumented * background == 2 (aka, -b -b) means to * only process 1 per kid */ val = bozo_get_pref(&prefs, "background") == NULL ? "1" : "2"; bozo_set_pref(&httpd, &prefs, "background", val); break; case 'e': bozo_set_pref(&httpd, &prefs, "dirty environment", "true"); break; case 'f': bozo_set_pref(&httpd, &prefs, "foreground", "true"); break; case 'i': bozo_set_pref(&httpd, &prefs, "bind address", optarg); break; case 'P': bozo_set_pref(&httpd, &prefs, "pid file", optarg); break; #endif /* NO_DAEMON_MODE */ #ifdef NO_CGIBIN_SUPPORT case 'c': case 'C': bozoerr(&httpd, 1, "CGI is not enabled"); /* NOTREACHED */ #else case 'c': bozo_cgi_setbin(&httpd, optarg); break; case 'C': # ifdef NO_DYNAMIC_CONTENT bozoerr(&httpd, 1, "dynamic CGI handler support is not enabled"); /* NOTREACHED */ # else /* make sure there's two arguments */ if (argc - optind < 1) usage(&httpd, progname); bozo_add_content_map_cgi(&httpd, optarg, argv[optind++]); break; # endif /* NO_DYNAMIC_CONTENT */ #endif /* NO_CGIBIN_SUPPORT */ case 'd': httpd.debug++; #ifdef NO_DEBUG if (httpd.debug == 1) bozowarn(&httpd, "Debugging is not enabled"); #endif /* NO_DEBUG */ break; case 't': bozo_set_pref(&httpd, &prefs, "chroot dir", optarg); break; #ifdef NO_USER_SUPPORT case 'p': case 'u': case 'E': bozoerr(&httpd, 1, "User support is not enabled"); /* NOTREACHED */ #else case 'p': bozo_set_pref(&httpd, &prefs, "public_html", optarg); break; case 'u': bozo_set_pref(&httpd, &prefs, "enable users", "true"); break; #ifndef NO_CGIBIN_SUPPORT case 'E': bozo_set_pref(&httpd, &prefs, "enable user cgibin", "true"); break; #else case 'E': bozoerr(&httpd, 1, "CGI is not enabled"); /* NOTREACHED */ #endif /* NO_CGIBIN_SPPORT */ #endif /* NO_USER_SUPPORT */ #ifdef NO_DIRINDEX_SUPPORT case 'H': case 'X': bozoerr(&httpd, 1, "directory indexing is not enabled"); /* NOTREACHED */ #else case 'H': bozo_set_pref(&httpd, &prefs, "hide dots", "true"); break; case 'X': bozo_set_pref(&httpd, &prefs, "directory indexing", "true"); break; #endif /* NO_DIRINDEX_SUPPORT */ case 'G': { char version[128]; bozo_get_version(version, sizeof(version)); printf("bozohttpd version %s\n", version); } return 0; default: usage(&httpd, progname); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc == 0 || argc > 2) { usage(&httpd, progname); } /* virtual host, and root of tree to serve */ bozo_setup(&httpd, &prefs, argv[1], argv[0]); /* * read and process the HTTP request. */ do { if ((request = bozo_read_request(&httpd)) != NULL) { bozo_process_request(request); bozo_clean_request(request); } } while (httpd.background); return (0); } |
Added netbsd_queue.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | /* $eterna: queue.h,v 1.6 2009/04/18 08:36:03 mrg Exp $ */ /* from: NetBSD: queue.h,v 1.51 2009/03/11 06:51:53 mrg Exp */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ #ifndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ /* * Simple queue definitions. */ #define SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } #define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } /* * Simple queue functions. */ #define SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_FOREACH(var, head, field) \ for ((var) = ((head)->sqh_first); \ (var); \ (var) = ((var)->field.sqe_next)) #define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \ for ((var) = ((head)->sqh_first); \ (var) && ((next = ((var)->field.sqe_next)), 1); \ (var) = (next)) /* * Simple queue access methods. */ #define SIMPLEQ_FIRST(head) ((head)->sqh_first) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) #endif /* !_SYS_QUEUE_H_ */ |
Added printenv.lua.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | -- $NetBSD: printenv.lua,v 1.3 2015/12/07 03:11:48 kamil Exp $ -- this small Lua script demonstrates the use of Lua in (bozo)httpd -- it will simply output the "environment" -- Keep in mind that bozohttpd forks for each request when started in -- daemon mode, you can set global veriables here, but they will have -- the same value on each invocation. You can not keep state between -- two calls. -- You can test this example by running the following command: -- /usr/libexec/httpd -b -f -I 8080 -L test printenv.lua . -- and then navigate to: http://127.0.0.1:8080/test/printenv local httpd = require 'httpd' function printenv(env, headers, query) -- we get the "environment" in the env table, the values are more -- or less the same as the variable for a CGI program -- output headers using httpd.write() -- httpd.write() will not append newlines httpd.write("HTTP/1.1 200 Ok\r\n") httpd.write("Content-Type: text/html\r\n\r\n") -- output html using httpd.print() -- you can also use print() and io.write() but they will not work with SSL httpd.print([[ <html> <head> <title>Bozotic Lua Environment</title> </head> <body> <h1>Bozotic Lua Environment</h1> ]]) httpd.print('module version: ' .. httpd._VERSION .. '<br>') httpd.print('<h2>Server Environment</h2>') -- print the list of "environment" variables for k, v in pairs(env) do httpd.print(k .. '=' .. v .. '<br/>') end httpd.print('<h2>Request Headers</h2>') for k, v in pairs(headers) do httpd.print(k .. '=' .. v .. '<br/>') end if query ~= nil then httpd.print('<h2>Query Variables</h2>') for k, v in pairs(query) do httpd.print(k .. '=' .. v .. '<br/>') end end httpd.print('<h2>Form Test</h2>') httpd.print([[ <form method="POST" action="form?sender=me"> <input type="text" name="a_value"> <input type="submit"> </form> ]]) -- output a footer httpd.print([[ </body> </html> ]]) end function form(env, header, query) httpd.write("HTTP/1.1 200 Ok\r\n") httpd.write("Content-Type: text/html\r\n\r\n") if query ~= nil then httpd.print('<h2>Form Variables</h2>') if env.CONTENT_TYPE ~= nil then httpd.print('Content-type: ' .. env.CONTENT_TYPE .. '<br>') end for k, v in pairs(query) do httpd.print(k .. '=' .. v .. '<br/>') end else httpd.print('No values') end end -- register this handler for http://<hostname>/<prefix>/printenv httpd.register_handler('printenv', printenv) httpd.register_handler('form', form) |
Added small/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # $eterna: Makefile,v 1.1 2009/05/22 21:51:39 mrg Exp $ # build a 100% lean bozohttpd-small.c PROG= bozohttpd-small NOMAN= # defined SRCS= bozohttpd-small.c content-bozo-small.c ssl-bozo.c main.c: LEAN_IFDEF_FLAGS= -UDEBUG -DNO_USER_SUPPORT \ -DNO_CGIBIN_SUPPORT -DNO_DIRINDEX_SUPPORT \ -DNO_DAEMON_MODE -DNO_DYNAMIC_CONTENT \ -DNO_SSL_SUPPORT -UDO_HTPASSWD \ -DNO_LUA_SUPPORT CFLAGS= -I$(.CURDIR)/.. ${LEAN_IFDEF_FLAGS} bozohttpd-small.c: bozohttpd.c unifdef $(LEAN_IFDEF_FLAGS) < $> > $@.tmp ;\ if [ $$? -ne 1 ]; then echo "unifdef returned $?, expecting 1" 2>&1; false; fi mv -f $@.tmp $@ content-bozo-small.c: content-bozo.c unifdef $(LEAN_IFDEF_FLAGS) < $> > $@.tmp ;\ if [ $$? -ne 1 ]; then echo "unifdef returned $?, expecting 1" 2>&1; false; fi mv -f $@.tmp $@ CLEANFILES+= content-bozo-small.c bozohttpd-small.c .PATH: $(.CURDIR)/.. .include <bsd.prog.mk> |
Added ssl-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | /* $NetBSD: ssl-bozo.c,v 1.22 2015/12/28 07:37:59 mrg Exp $ */ /* $eterna: ssl-bozo.c,v 1.15 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2014 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements SSL and backend IO for bozohttpd */ #include <stdarg.h> #include <stdio.h> #include <syslog.h> #include <unistd.h> #include "bozohttpd.h" #ifndef NO_SSL_SUPPORT #include <openssl/ssl.h> #include <openssl/err.h> #ifndef USE_ARG #define USE_ARG(x) /*LINTED*/(void)&(x) #endif #ifndef BOZO_SSL_CIPHERS #define BOZO_SSL_CIPHERS \ "AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:" \ "AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:" \ "AES:" \ "-SHA:" \ "!aNULL:!eNULL:" \ "!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:" \ "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:" \ "!KRB5-DES-CBC3-SHA" #endif #ifndef BOZO_SSL_OPTIONS #define BOZO_SSL_OPTIONS \ (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1) #endif /* this structure encapsulates the ssl info */ /* this structure encapsulates the ssl info */ typedef struct sslinfo_t { SSL_CTX *ssl_context; const SSL_METHOD *ssl_method; SSL *bozossl; char *certificate_file; char *privatekey_file; char *ciphers; } sslinfo_t; /* * bozo_clear_ssl_queue: print the contents of the SSL error queue */ static void bozo_clear_ssl_queue(bozohttpd_t *httpd) { unsigned long sslcode = ERR_get_error(); do { static const char sslfmt[] = "SSL Error: %s:%s:%s"; if (httpd->logstderr || isatty(STDERR_FILENO)) { fprintf(stderr, sslfmt, ERR_lib_error_string(sslcode), ERR_func_error_string(sslcode), ERR_reason_error_string(sslcode)); } else { syslog(LOG_ERR, sslfmt, ERR_lib_error_string(sslcode), ERR_func_error_string(sslcode), ERR_reason_error_string(sslcode)); } } while (0 != (sslcode = ERR_get_error())); } /* * bozo_ssl_warn works just like bozowarn, plus the SSL error queue */ BOZO_PRINTFLIKE(2, 3) static void bozo_ssl_warn(bozohttpd_t *httpd, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (httpd->logstderr || isatty(STDERR_FILENO)) { vfprintf(stderr, fmt, ap); fputs("\n", stderr); } else vsyslog(LOG_ERR, fmt, ap); va_end(ap); bozo_clear_ssl_queue(httpd); } /* * bozo_ssl_err works just like bozoerr, plus the SSL error queue */ BOZO_PRINTFLIKE(3, 4) BOZO_DEAD static void bozo_ssl_err(bozohttpd_t *httpd, int code, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (httpd->logstderr || isatty(STDERR_FILENO)) { vfprintf(stderr, fmt, ap); fputs("\n", stderr); } else vsyslog(LOG_ERR, fmt, ap); va_end(ap); bozo_clear_ssl_queue(httpd); exit(code); } /* * bozo_check_error_queue: print warnings if the error isn't expected */ static void bozo_check_error_queue(bozohttpd_t *httpd, const char *tag, int ret) { if (ret > 0) return; const sslinfo_t *sslinfo = httpd->sslinfo; const int sslerr = SSL_get_error(sslinfo->bozossl, ret); if (sslerr != SSL_ERROR_ZERO_RETURN && sslerr != SSL_ERROR_SYSCALL && sslerr != SSL_ERROR_NONE) bozo_ssl_warn(httpd, "%s: SSL_ERROR %d", tag, sslerr); } static BOZO_PRINTFLIKE(2, 0) int bozo_ssl_printf(bozohttpd_t *httpd, const char * fmt, va_list ap) { char *buf; int nbytes; if ((nbytes = vasprintf(&buf, fmt, ap)) != -1) { const sslinfo_t *sslinfo = httpd->sslinfo; int ret = SSL_write(sslinfo->bozossl, buf, nbytes); bozo_check_error_queue(httpd, "write", ret); } free(buf); return nbytes; } static ssize_t bozo_ssl_read(bozohttpd_t *httpd, int fd, void *buf, size_t nbytes) { const sslinfo_t *sslinfo = httpd->sslinfo; int ret; USE_ARG(fd); ret = SSL_read(sslinfo->bozossl, buf, (int)nbytes); bozo_check_error_queue(httpd, "read", ret); return (ssize_t)ret; } static ssize_t bozo_ssl_write(bozohttpd_t *httpd, int fd, const void *buf, size_t nbytes) { const sslinfo_t *sslinfo = httpd->sslinfo; int ret; USE_ARG(fd); ret = SSL_write(sslinfo->bozossl, buf, (int)nbytes); bozo_check_error_queue(httpd, "write", ret); return (ssize_t)ret; } void bozo_ssl_init(bozohttpd_t *httpd) { sslinfo_t *sslinfo = httpd->sslinfo; long options; if (sslinfo == NULL || !sslinfo->certificate_file) return; SSL_library_init(); SSL_load_error_strings(); sslinfo->ssl_method = SSLv23_server_method(); sslinfo->ssl_context = SSL_CTX_new(sslinfo->ssl_method); if (NULL == sslinfo->ssl_context) bozo_ssl_err(httpd, EXIT_FAILURE, "SSL context creation failed"); options = SSL_CTX_set_options(sslinfo->ssl_context, BOZO_SSL_OPTIONS); if ((options & BOZO_SSL_OPTIONS) != BOZO_SSL_OPTIONS) bozo_ssl_err(httpd, EXIT_FAILURE, "Error setting ssl options requested %#lx, got %#lx", BOZO_SSL_OPTIONS, options); if (!SSL_CTX_set_cipher_list(sslinfo->ssl_context, sslinfo->ciphers ? sslinfo->ciphers : BOZO_SSL_CIPHERS)) bozo_ssl_err(httpd, EXIT_FAILURE, "Error setting cipher list '%s'", sslinfo->ciphers); if (1 != SSL_CTX_use_certificate_chain_file(sslinfo->ssl_context, sslinfo->certificate_file)) bozo_ssl_err(httpd, EXIT_FAILURE, "Unable to use certificate file '%s'", sslinfo->certificate_file); if (1 != SSL_CTX_use_PrivateKey_file(sslinfo->ssl_context, sslinfo->privatekey_file, SSL_FILETYPE_PEM)) bozo_ssl_err(httpd, EXIT_FAILURE, "Unable to use private key file '%s'", sslinfo->privatekey_file); /* check consistency of key vs certificate */ if (!SSL_CTX_check_private_key(sslinfo->ssl_context)) bozo_ssl_err(httpd, EXIT_FAILURE, "Check private key failed"); } /* * returns non-zero for failure */ int bozo_ssl_accept(bozohttpd_t *httpd) { sslinfo_t *sslinfo = httpd->sslinfo; if (sslinfo == NULL || !sslinfo->ssl_context) return 0; sslinfo->bozossl = SSL_new(sslinfo->ssl_context); if (sslinfo->bozossl == NULL) bozoerr(httpd, 1, "SSL_new failed"); SSL_set_rfd(sslinfo->bozossl, 0); SSL_set_wfd(sslinfo->bozossl, 1); const int ret = SSL_accept(sslinfo->bozossl); bozo_check_error_queue(httpd, "accept", ret); return ret != 1; } void bozo_ssl_destroy(bozohttpd_t *httpd) { const sslinfo_t *sslinfo = httpd->sslinfo; if (sslinfo && sslinfo->bozossl) SSL_free(sslinfo->bozossl); } static sslinfo_t * bozo_get_sslinfo(bozohttpd_t *httpd) { sslinfo_t *sslinfo; if (httpd->sslinfo) return httpd->sslinfo; sslinfo = bozomalloc(httpd, sizeof(*sslinfo)); if (sslinfo == NULL) bozoerr(httpd, 1, "sslinfo allocation failed"); memset(sslinfo, 0, sizeof(*sslinfo)); return httpd->sslinfo = sslinfo; } void bozo_ssl_set_opts(bozohttpd_t *httpd, const char *cert, const char *priv) { sslinfo_t *sslinfo = bozo_get_sslinfo(httpd); sslinfo->certificate_file = bozostrdup(httpd, NULL, cert); sslinfo->privatekey_file = bozostrdup(httpd, NULL, priv); debug((httpd, DEBUG_NORMAL, "using cert/priv files: %s & %s", sslinfo->certificate_file, sslinfo->privatekey_file)); if (!httpd->bindport) httpd->bindport = bozostrdup(httpd, NULL, "https"); } void bozo_ssl_set_ciphers(bozohttpd_t *httpd, const char *ciphers) { sslinfo_t *sslinfo = bozo_get_sslinfo(httpd); sslinfo->ciphers = bozostrdup(httpd, NULL, ciphers); debug((httpd, DEBUG_NORMAL, "using ciphers: %s", sslinfo->ciphers)); } #endif /* NO_SSL_SUPPORT */ int bozo_printf(bozohttpd_t *httpd, const char *fmt, ...) { va_list args; int cc; va_start(args, fmt); #ifndef NO_SSL_SUPPORT if (httpd->sslinfo) cc = bozo_ssl_printf(httpd, fmt, args); else #endif cc = vprintf(fmt, args); va_end(args); return cc; } ssize_t bozo_read(bozohttpd_t *httpd, int fd, void *buf, size_t len) { #ifndef NO_SSL_SUPPORT if (httpd->sslinfo) return bozo_ssl_read(httpd, fd, buf, len); #endif return read(fd, buf, len); } ssize_t bozo_write(bozohttpd_t *httpd, int fd, const void *buf, size_t len) { #ifndef NO_SSL_SUPPORT if (httpd->sslinfo) return bozo_ssl_write(httpd, fd, buf, len); #endif return write(fd, buf, len); } int bozo_flush(bozohttpd_t *httpd, FILE *fp) { #ifndef NO_SSL_SUPPORT if (httpd->sslinfo) return 0; #endif return fflush(fp); } |
Added testsuite/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # $eterna: Makefile,v 1.14 2009/05/22 21:51:39 mrg Exp $ SIMPLETESTS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 CGITESTS= t11 BIGFILETESTS= partial4000 partial8000 BOZOHTTPD?= ../bozohttpd BOZOHTTPD?= ../debug/bozohttpd-debug WGET?= wget DATA?= $(.CURDIR)/data VERBOSE?= yes .if ${VERBOSE} != "yes" SILENT= @ .else SILENT= .endif all: clean: for a in $(SIMPLETESTS) $(BIGFILETESTS); do \ rm -f tmp.$$a.out tmp.$$a.err; \ done check: check-simple check-cgi check-bigfile check-simple: .for a in $(SIMPLETESTS) ${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}" .endfor check-cgi: .for a in $(CGITESTS) ${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}" -c "${.CURDIR}/cgi-bin" .endfor check-bigfile: .for a in $(BIGFILETESTS) ${SILENT}$(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "${DATA}" "${VERBOSE}" .endfor .include <bsd.obj.mk> |
Added testsuite/cgi-bin/empty.
Added testsuite/data/bigfile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | this is the big data file. it has to be over 1 page size in length. 0123456789 these lines are all 80 long. this is the second line. 012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 012345678901 this is the seventh line. 12345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 456789 this is the 13th line, and there 127 lines in total. 67890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 901234567890123456789012345 this is the 18th line. 456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 78901234567890123456 this is the 31st line. 345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 90123456789012345678901234567890123456789 this is the 38th line. 78901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 012345678901234567890123456 this is the 47th line. 4567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 789012345678901234567890123456789012345678901234567 50th 7890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 56789012 this is the 52nd line. 1234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012 54th 1234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345 this is the 60th line. 2345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 678901234 this is the 71st line. 12345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567 this is the 80th line. 567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456 this is the 93th line. 3456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456 this is the 101st line. 456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345 this is the 106th line. 3456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 789012345678901234 110th 4567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 34567890123456789012345678 114th 9012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 67890123 this is the 121st line. 12345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 this is the last line. this is the end of the file. there is no more. good bye. |
Added testsuite/data/bigfile.partial4000.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | this is the big data file. it has to be over 1 page size in length. 0123456789 these lines are all 80 long. this is the second line. 012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 012345678901 this is the seventh line. 12345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 456789 this is the 13th line, and there 127 lines in total. 67890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 901234567890123456789012345 this is the 18th line. 456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 78901234567890123456 this is the 31st line. 345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 90123456789012345678901234567890123456789 this is the 38th line. 78901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 012345678901234567890123456 this is the 47th line. 4567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 789012345678901234567890123456789012345678901234567 50th 7890123456789012345 |
Added testsuite/data/bigfile.partial8000.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | this is the big data file. it has to be over 1 page size in length. 0123456789 these lines are all 80 long. this is the second line. 012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 012345678901 this is the seventh line. 12345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 456789 this is the 13th line, and there 127 lines in total. 67890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 901234567890123456789012345 this is the 18th line. 456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 78901234567890123456 this is the 31st line. 345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 90123456789012345678901234567890123456789 this is the 38th line. 78901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 012345678901234567890123456 this is the 47th line. 4567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 789012345678901234567890123456789012345678901234567 50th 7890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 56789012 this is the 52nd line. 1234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012 54th 1234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345 this is the 60th line. 2345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 678901234 this is the 71st line. 12345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567 this is the 80th line. 567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789012345678901234 5678901234567890123456789012345678901234567890123456789012345678901234567890123 4567890123456 this is the 93th line. 3456789012345678901234567890123456789012 3456789012345678901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123456 7890123456789012345678901234567890123456789012345678901234567890123456789012345 |
Added testsuite/data/file.
> > > > | 1 2 3 4 | 123456781234567 345678903456789 234567892345678 012345670123456 |
Added testsuite/data/index.html.
> | 1 | this is the bozohttpd testsuite ./data/index.html file |
Added testsuite/html_cmp.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #! /bin/sh # # $eterna: html_cmp,v 1.9 2011/11/17 22:18:02 mrg Exp $ # # like cmp(1)/diff(1) but compares to files after making their # `Date: ' headers the same, to allow `now' and `then' to work properly. # it also tries to find servername's that might be the local host and # converts those as well.. # # it must be called like `html_cmp cmp|diff file1 file1' *only*. if [ "cmp" = "$1" ]; then cmd="cmp -s" elif [ "diff" = "$1" ]; then cmd="diff -u" else exit 77 fi h=`hostname || uname -n` sedcmd="s/^Date: .*/Date: nowish/; s/^Last-Modified: .*/Last-Modified: nowish/; s/[a-zA-Z0-9-]*\.eterna\.com\.au/$h/g; s/^Server: .*/^Server: bozotic HTTP server version 5.08/; s/^Content-Length: .*/Content-Length: 223/;" sed -e "$sedcmd" < "$2" > "f1.tmp.$$" sed -e "$sedcmd" < "$3" > "f2.tmp.$$" ${cmd} "f1.tmp.$$" "f2.tmp.$$" rv=$? rm -f "f1.tmp.$$" "f2.tmp.$$" exit $rv |
Added testsuite/t1.in.
> | 1 | get / |
Added testsuite/t1.out.
> > | 1 2 | HTTP/0.9 200 OK this is the bozohttpd testsuite ./data/index.html file |
Added testsuite/t10.in.
> | 1 | GET /xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx HTTP/1.0 |
Added testsuite/t10.out.
> > > > > > > > | 1 2 3 4 5 6 7 8 | HTTP/1.0 404 Not Found Content-Type: text/html Content-Length: 1024 Server: bozohttpd/20140708 <html><head><title>404 Not Found</title></head> <body><h1>404 Not Found</h1> /xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
Added testsuite/t11.in.
> > > | 1 2 3 | GET /cgi-bin/echo.bat?&dir+c:\\ HTTP/1.1 Host: |
Added testsuite/t11.out.
> | 1 | HTTP/1.1 200 OK |
Added testsuite/t2.in.
> | 1 | GET / HTTP/1.0 |
Added testsuite/t2.out.
> > > > > > > > > | 1 2 3 4 5 6 7 8 9 | HTTP/1.0 200 OK Date: Tue, 10 Jul 2001 15:45:36 GMT Server: bozotic HTTP server version 5.08 Accept-Ranges: bytes Last-Modified: Tue, 10 Jul 2001 15:50:43 GMT Content-Type: text/html Content-Length: 55 this is the bozohttpd testsuite ./data/index.html file |
Added testsuite/t3.in.
> | 1 | GET / HTTP/1.1 |
Added testsuite/t3.out.
> > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 | HTTP/1.1 400 Bad Request Content-Type: text/html Content-Length: 229 Server: bozotic HTTP server version 5.08 Allow: GET, HEAD, POST <html><head><title>400 Bad Request</title></head> <body><h1>400 Bad Request</h1> /: <pre>The request was not valid</pre> <hr><address><a href="http://madrugada.eterna.com.au/">madrugada.eterna.com.au</a></address> </body></html> |
Added testsuite/t4.in.
> > | 1 2 | GET / HTTP/1.1 Host: |
Added testsuite/t4.out.
> > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 | HTTP/1.1 200 OK Date: Tue, 10 Jul 2001 15:49:21 GMT Server: bozotic HTTP server version 5.08 Accept-Ranges: bytes Last-Modified: Tue, 10 Jul 2001 15:34:33 GMT Content-Type: text/html Content-Length: 55 Connection: close this is the bozohttpd testsuite ./data/index.html file |
Added testsuite/t5.in.
> > | 1 2 | GET /cgi-bin/..M-@M-/..M-@M-/..M-@M-/..M-@M-/..M-@M-/../winnt/system32/cmd.exe?/c+dir+c:\\ HTTP/1.0 |
Added testsuite/t5.out.
> > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 | HTTP/1.0 403 Forbidden Content-Type: text/html Content-Length: 336 Server: bozohttpd/20030206 <html><head><title>403 Forbidden</title></head> <body><h1>403 Forbidden</h1> /cgi-bin/..M-@M-/..M-@M-/..M-@M-/..M-@M-/..M-@M-/../winnt/system32/cmd.exe: <pre>Access to this item has been denied</pre> <hr><address><a href="http://what-time-is-love.eterna.com.au/">what-time-is-love.eterna.com.au</a></address> </body></html> |
Added testsuite/t6.in.
> > | 1 2 | GET /xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx HTTP/1.0 |
Added testsuite/t6.out.
> > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 | HTTP/1.0 404 Not Found Content-Type: text/html Content-Length: 335 Server: bozohttpd/5.15 <html><head><title>404 Not Found</title></head> <body><h1>404 Not Found</h1> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: <pre>This item has not been found</pre> <hr><address><a href="http://splode.eterna.com.au/">splode.eterna.com.au</a></address> </body></html> |
Added testsuite/t7.in.
> > > > | 1 2 3 4 | GET /file HTTP/1.1 Host: Range: bytes=0-63 |
Added testsuite/t7.out.
> > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | HTTP/1.1 206 Partial Content Date: Sun, 02 Mar 2008 08:52:03 GMT Server: bozohttpd/20060710 Accept-Ranges: bytes Last-Modified: Sun, 02 Mar 2008 08:44:38 GMT Content-Type: text/plain Content-Range: bytes 0-63/64 Content-Length: 64 Connection: close 123456781234567 345678903456789 234567892345678 012345670123456 |
Added testsuite/t8.in.
> > > > | 1 2 3 4 | GET /file HTTP/1.1 Host: Range: bytes=0-31 |
Added testsuite/t8.out.
> > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | HTTP/1.1 206 Partial Content Date: Sun, 02 Mar 2008 08:52:03 GMT Server: bozohttpd/20060710 Accept-Ranges: bytes Last-Modified: Sun, 02 Mar 2008 08:44:38 GMT Content-Type: text/plain Content-Range: bytes 0-31/64 Content-Length: 32 Connection: close 123456781234567 345678903456789 |
Added testsuite/t9.in.
> > > > | 1 2 3 4 | GET /file HTTP/1.1 Host: Range: bytes=32-63 |
Added testsuite/t9.out.
> > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | HTTP/1.1 206 Partial Content Date: Sun, 02 Mar 2008 08:52:03 GMT Server: bozohttpd/20060710 Accept-Ranges: bytes Last-Modified: Sun, 02 Mar 2008 08:44:38 GMT Content-Type: text/plain Content-Range: bytes 32-63/64 Content-Length: 32 Connection: close 234567892345678 012345670123456 |
Added testsuite/test-bigfile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #! /bin/sh # $NetBSD: test-bigfile,v 1.4 2017/01/31 14:33:54 mrg Exp $ test="$1" # partial4000 or partial8000 bozohttpd="$2" wget="$3" datadir="$4" verbose="$5" tmperr="tmp.$test.err" if [ "yes" = "$verbose" ]; then echo "Running test $test" else exec 2>"$tmperr" fi bozotestport=11111 # copy beginning file cp "${datadir}/bigfile.${test}" ./bigfile # fire up bozohttpd ${bozohttpd} -b -b -I ${bozotestport} -n -s -f "${datadir}" & bozopid=$! "${wget}" -c http://localhost:${bozotestport}/bigfile kill -9 $bozopid if cmp ./bigfile "${datadir}/bigfile"; then rm -f ./bigfile exit 0 else rm -f ./bigfile if [ "yes" = "$verbose" ]; then echo "Failed test $test:" cat "$tmperr" fi exit 1 fi |
Added testsuite/test-simple.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #! /bin/sh # $NetBSD: test-simple,v 1.4 2017/01/31 14:33:54 mrg Exp $ test="$1"; shift bozohttpd="$1"; shift datadir="$1"; shift curdir="$1"; shift verbose="$1"; shift in="$curdir/$test.in" out="$curdir/$test.out" tmpout="tmp.$test.out" tmperr="tmp.$test.err" if [ "yes" = "$verbose" ]; then echo "Running test $test" else exec 2>"$tmperr" fi bozotestport=11111 ${bozohttpd} "$@" "${datadir}" < "$in" > "$tmpout" if "$curdir/html_cmp" cmp "$out" "$tmpout"; then exit 0 else if [ "yes" = "$verbose" ]; then echo "Failed test $test:" cat "$tmperr" $curdir/html_cmp diff "$out" "$tmpout" fi exit 1 fi |
Added tilde-luzah-bozo.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | /* $NetBSD: tilde-luzah-bozo.c,v 1.14 2015/12/28 07:37:59 mrg Exp $ */ /* $eterna: tilde-luzah-bozo.c,v 1.16 2011/11/18 09:21:15 mrg Exp $ */ /* * Copyright (c) 1997-2014 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer and * dedication in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* this code implements ~user support for bozohttpd */ #ifndef NO_USER_SUPPORT #include <sys/param.h> #include <assert.h> #include <errno.h> #include <pwd.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "bozohttpd.h" /* * bozo_user_transform does this: * - chdir's /~user/public_html * - returns the rest of the file, index.html appended if required * - returned malloced file to serve in request->hr_file, * ala transform_request(). * * transform_request() is supposed to check that we have user support * enabled. */ int bozo_user_transform(bozo_httpreq_t *request) { bozohttpd_t *httpd = request->hr_httpd; char *s, *file = NULL, *user; struct passwd *pw; /* find username */ user = strchr(request->hr_file + 1, '~'); /* this shouldn't happen, but "better paranoid than sorry" */ assert(user != NULL); user++; if ((s = strchr(user, '/')) != NULL) { *s++ = '\0'; } debug((httpd, DEBUG_OBESE, "looking for user %s", user)); pw = getpwnam(user); request->hr_user = bozostrdup(httpd, request, user); /* fix this up immediately */ if (s) { s[-1] = '/'; /* omit additional slashes at the beginning */ while (*s == '/') s++; } if (pw == NULL) { free(request->hr_user); request->hr_user = NULL; (void)bozo_http_error(httpd, 404, request, "no such user"); return 0; } debug((httpd, DEBUG_OBESE, "user %s dir %s/%s uid %d gid %d", pw->pw_name, pw->pw_dir, httpd->public_html, pw->pw_uid, pw->pw_gid)); if (chdir(pw->pw_dir) < 0) { bozowarn(httpd, "chdir1 error: %s: %s", pw->pw_dir, strerror(errno)); (void)bozo_http_error(httpd, 404, request, "can't chdir to homedir"); return 0; } if (chdir(httpd->public_html) < 0) { bozowarn(httpd, "chdir2 error: %s: %s", httpd->public_html, strerror(errno)); (void)bozo_http_error(httpd, 404, request, "can't chdir to public_html"); return 0; } if (s == NULL || *s == '\0') { file = bozostrdup(httpd, request, "/"); } else { file = bozomalloc(httpd, strlen(s) + 2); strcpy(file, "/"); strcat(file, s); } free(request->hr_file); request->hr_file = file; debug((httpd, DEBUG_FAT, "transform_user returning %s under %s", file, pw->pw_dir)); return 1; } #endif /* NO_USER_SUPPORT */ |