Module Name: src Committed By: martin Date: Wed Jun 12 10:32:00 UTC 2019
Modified Files: src/libexec/httpd [netbsd-8]: CHANGES Makefile auth-bozo.c bozohttpd.8 bozohttpd.c bozohttpd.h cgi-bozo.c daemon-bozo.c dir-index-bozo.c ssl-bozo.c src/libexec/httpd/testsuite [netbsd-8]: Makefile t11.out test-bigfile test-simple Log Message: Pull up the following revisions (via patch) requested by mrg in ticket #1281: libexec/httpd/CHANGES 1.31-1.40 libexec/httpd/Makefile 1.28 libexec/httpd/auth-bozo.c 1.23-1.24 libexec/httpd/bozohttpd.8 1.75-1.79 libexec/httpd/bozohttpd.c 1.100-1.113 libexec/httpd/bozohttpd.h 1.58-1.60 libexec/httpd/cgi-bozo.c 1.46-1.48 libexec/httpd/daemon-bozo.c 1.20-1.21 libexec/httpd/dir-index-bozo.c 1.29-1.32 libexec/httpd/ssl-bozo.c 1.26 libexec/httpd/testsuite/Makefile 1.12-1.13 libexec/httpd/testsuite/t11.out 1.2 libexec/httpd/testsuite/test-bigfile 1.6 libexec/httpd/testsuite/test-simple 1.6 Don't display special files in the directory index. They aren't served, but links to them are generated. --- All from "Rajeev V. Pillai" <rajeev_v_pil...@yahoo.com>: - use html tables for directory index. - don't include "index.html" in html headers - additional escaping of names - re-add top/bottom borders - adds an aquamarine table header - Zebra-stripes table rows using CSS instead of code - fix CGI '+' param and error handling. - remove unused parameter to daemon_poll_err(). - avoid sign extension in % handling fix a few problems pointed out by clang static analyzer: - bozostrnsep() may return with "in = NULL", so check for it. - nul terminating in bozo_escape_rfc3986() can be simpler - don't use uniinit variables in check_remap() - don't use re-used freed data in check_virtual(). - fix bozoprefs->size setting when increasing the size (new total was being added to the prior total.) however, bozostrdup() may reference request->hr_file. --- Add ssl specific timeout value (30s). If SSL_accept() doesn't work with in this timeout value, ssl setup now fails. --- Fix handling of bozo_set_timeout() timeouts (and `-T' option parsing) --- Avoid .htpasswd exposure to authenticated users when .htpasswd is in the slashdir too. --- Avoid possible NULL dereference when sending a big request that timeout. --- Use strings.h for strcasecmp (on linux) --- Account for cgihandler being set when counting the number of CGI environment headers we are about to set. Avoids an assertion failure (and overruninng the array) later. To generate a diff of this commit: cvs rdiff -u -r1.25.4.2 -r1.25.4.3 src/libexec/httpd/CHANGES cvs rdiff -u -r1.27 -r1.27.2.1 src/libexec/httpd/Makefile cvs rdiff -u -r1.18.8.1 -r1.18.8.2 src/libexec/httpd/auth-bozo.c cvs rdiff -u -r1.65.4.1 -r1.65.4.2 src/libexec/httpd/bozohttpd.8 cvs rdiff -u -r1.86.4.3 -r1.86.4.4 src/libexec/httpd/bozohttpd.c cvs rdiff -u -r1.47.4.2 -r1.47.4.3 src/libexec/httpd/bozohttpd.h cvs rdiff -u -r1.37.4.3 -r1.37.4.4 src/libexec/httpd/cgi-bozo.c cvs rdiff -u -r1.17.8.1 -r1.17.8.2 src/libexec/httpd/daemon-bozo.c cvs rdiff -u -r1.25.8.1 -r1.25.8.2 src/libexec/httpd/dir-index-bozo.c cvs rdiff -u -r1.22.8.1 -r1.22.8.2 src/libexec/httpd/ssl-bozo.c cvs rdiff -u -r1.7.4.1 -r1.7.4.2 src/libexec/httpd/testsuite/Makefile cvs rdiff -u -r1.1 -r1.1.20.1 src/libexec/httpd/testsuite/t11.out cvs rdiff -u -r1.4.4.1 -r1.4.4.2 src/libexec/httpd/testsuite/test-bigfile cvs rdiff -u -r1.4.10.1 -r1.4.10.2 src/libexec/httpd/testsuite/test-simple Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/libexec/httpd/CHANGES diff -u src/libexec/httpd/CHANGES:1.25.4.2 src/libexec/httpd/CHANGES:1.25.4.3 --- src/libexec/httpd/CHANGES:1.25.4.2 Wed Nov 28 19:50:37 2018 +++ src/libexec/httpd/CHANGES Wed Jun 12 10:32:00 2019 @@ -1,4 +1,24 @@ -$NetBSD: CHANGES,v 1.25.4.2 2018/11/28 19:50:37 martin Exp $ +$NetBSD: CHANGES,v 1.25.4.3 2019/06/12 10:32:00 martin Exp $ + +changes in bozohttpd 20190228: + o extend timeout facility to ssl and stop servers hanging forever + if the client never sends anything. reported by Steffen in netbsd + PR#50655. + o don't display special files in the directory index. they aren't + served, but links to them are generated. + o fix CGI '+' parameter handling, some error checking, and a double + free. from rajeev_v_pil...@yahoo.com + o more directory indexing clean up. from rajeev_v_pil...@yahoo.com + +changes in bozohttpd 20181215: + o fix .htpasswd bypass for authenticated users. reported by JP, + from l...@netbsd.org + o avoid possible null dereference when receiving a big request that + timeout. reported by m...@netbsd.org, from l...@netbsd.org + o fix handling of -T option, from l...@netbsd.org + o cleanups and portability improvements, from m...@netbsd.org + o change directory indexing to use html tables, from + rajeev_v_pil...@yahoo.com changes in bozohttpd 20181125: o fixes for option parsing introduced in bozohttpd 20181123 @@ -293,7 +313,7 @@ changes in bozohttpd 5.07 (20010610): - add many new content-types, now support most common ones changes in bozohttpd 5.06 (20000825): - - add IPv6 suppor from ito...@iijlab.net + - add IPv6 support from ito...@iijlab.net - man page fixes from j...@netbsd.org changes in bozohttpd 5.05 (20000815): Index: src/libexec/httpd/Makefile diff -u src/libexec/httpd/Makefile:1.27 src/libexec/httpd/Makefile:1.27.2.1 --- src/libexec/httpd/Makefile:1.27 Sun May 21 15:28:41 2017 +++ src/libexec/httpd/Makefile Wed Jun 12 10:32:00 2019 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.27 2017/05/21 15:28:41 riastradh Exp $ +# $NetBSD: Makefile,v 1.27.2.1 2019/06/12 10:32:00 martin Exp $ # # $eterna: Makefile,v 1.30 2010/07/11 00:34:27 mrg Exp $ # @@ -77,6 +77,9 @@ bozohttpd.8.txt: bozohttpd.8 CLEANFILES+= bozohttpd.8.html bozohttpd.8.txt +check: + cd ${.CURDIR}/testsuite && ${MAKE} check + # Create a distfile: uses /tmp BASE=bozohttpd-${BOZOVER} TAR=${BASE}.tar Index: src/libexec/httpd/auth-bozo.c diff -u src/libexec/httpd/auth-bozo.c:1.18.8.1 src/libexec/httpd/auth-bozo.c:1.18.8.2 --- src/libexec/httpd/auth-bozo.c:1.18.8.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/auth-bozo.c Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: auth-bozo.c,v 1.18.8.1 2018/11/24 17:13:51 martin Exp $ */ +/* $NetBSD: auth-bozo.c,v 1.18.8.2 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,7 +64,7 @@ bozo_auth_check(bozo_httpreq_t *request, strcpy(dir, "."); else { *basename++ = '\0'; - if (bozo_check_special_files(request, basename)) + if (bozo_check_special_files(request, basename, true)) return 1; } request->hr_authrealm = bozostrdup(httpd, request, dir); Index: src/libexec/httpd/bozohttpd.8 diff -u src/libexec/httpd/bozohttpd.8:1.65.4.1 src/libexec/httpd/bozohttpd.8:1.65.4.2 --- src/libexec/httpd/bozohttpd.8:1.65.4.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/bozohttpd.8 Wed Jun 12 10:32:00 2019 @@ -1,8 +1,8 @@ -.\" $NetBSD: bozohttpd.8,v 1.65.4.1 2018/11/24 17:13:51 martin Exp $ +.\" $NetBSD: bozohttpd.8,v 1.65.4.2 2019/06/12 10:32:00 martin Exp $ .\" .\" $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $ .\" -.\" Copyright (c) 1997-2018 Matthew R. Green +.\" Copyright (c) 1997-2019 Matthew R. Green .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 19, 2018 +.Dd February 27, 2019 .Dt BOZOHTTPD 8 .Os .Sh NAME @@ -245,11 +245,13 @@ to The valid values of .Ar type are +.Dq ssl timeout , .Dq initial timeout , .Dq header timeout , and .Dq request timeout . -The default values are 30 seconds, 10 seconds and 600 seconds, respectively. +The default values are 30 seconds, 30 seconds, 10 seconds and 600 seconds, +respectively. .It Fl t Ar chrootdir Makes .Nm @@ -477,9 +479,7 @@ if a .Pa .bzdirect file is found (contents are irrelevant) .Nm -will allow direct access even with the -.Fl r -option. +will allow direct access. If a .Pa .bzredirect symbolic link is found, @@ -599,7 +599,7 @@ The focus has always been simplicity and and regular code audits. This manual documents .Nm -version 20181123. +version 20190116. .Sh AUTHORS .An -nosplit .Nm @@ -610,14 +610,14 @@ was written by The large list of contributors includes: .Bl -dash .It -.An Marc Balmer -.Aq Mt mbal...@netbsd.org -added Lua support for dynamic content creation -.It .An Christoph Badura .Aq Mt b...@bsd.de provided Range: header support .It +.An Marc Balmer +.Aq Mt mbal...@netbsd.org +added Lua support for dynamic content creation +.It .An Sean Boudreau .Aq Mt se...@netbsd.org provided a security fix for virtual hosting @@ -634,7 +634,7 @@ provided cgi-bin support fixes, and more .Aq Mt a...@netbsd.org cleaned up many internal interfaces, made .Nm -linkable as a library and provided the Lua binding. +linkable as a library and provided the Lua binding .It .An DEGROOTE Arnaud .Aq Mt degro...@netbsd.org @@ -644,14 +644,14 @@ provided a fix for daemon mode .Aq Mt a...@netbsd.org provided directory indexing support .It -.An Per Ekman -.Aq Mt p...@pdc.kth.se -provided a fix for a minor (non-security) buffer overflow condition -.It .An Roland Dowdeswell .Aq Mt el...@netbsd.org added support for serving gzipped files and better SSL handling .It +.An Per Ekman +.Aq Mt p...@pdc.kth.se +provided a fix for a minor (non-security) buffer overflow condition +.It .An Jun-ichiro itojun Hagino, KAME .Aq Mt ito...@iijlab.net provided initial IPv6 support @@ -690,7 +690,7 @@ provided many fixes and enhancements for 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. +various other fixes .It .An Arnaud Lacombe .Aq Mt a...@netbsd.org @@ -708,7 +708,7 @@ provided a cgi-bin fix .Aq Mt j...@netbsd.org Added the .Fl P -option (pidfile support) and provided some man page fixes. +option (pidfile support) and provided some man page fixes .It .An Luke Mewburn .Aq Mt lu...@netbsd.org @@ -717,7 +717,8 @@ HTTP basic authorization support and muc .It .An Rajeev V. Pillai .Aq Mt rajeev_v_pil...@yahoo.com -provided several fixes for virtual hosting +provided several fixes for virtual hosting and directory indexing and +fixes for CGI .It .An Jeremy C. Reed .Aq Mt r...@netbsd.org @@ -739,11 +740,11 @@ provided minor compile fixes and a CGI c .Aq Mt rum...@ephemeral.org provided the .Fl V -option. +option .It .An Thor Lancelot Simon .Aq Mt t...@netbsd.org -enhanced cgi-bin support. +enhanced cgi-bin support .It .An Joerg Sonnenberger .Aq Mt jo...@netbsd.org @@ -760,7 +761,7 @@ provided http authorization fixes .Aq Mt x...@kittenz.org provided chroot and change-to-user support, and other various fixes .It -Coyote Point provided various CGI fixes. +Coyote Point provided various CGI fixes .El .Pp There are probably others I have forgotten (let me know if you care) Index: src/libexec/httpd/bozohttpd.c diff -u src/libexec/httpd/bozohttpd.c:1.86.4.3 src/libexec/httpd/bozohttpd.c:1.86.4.4 --- src/libexec/httpd/bozohttpd.c:1.86.4.3 Wed Nov 28 19:50:37 2018 +++ src/libexec/httpd/bozohttpd.c Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: bozohttpd.c,v 1.86.4.3 2018/11/28 19:50:37 martin Exp $ */ +/* $NetBSD: bozohttpd.c,v 1.86.4.4 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,7 +109,7 @@ #define INDEX_HTML "index.html" #endif #ifndef SERVER_SOFTWARE -#define SERVER_SOFTWARE "bozohttpd/20181125" +#define SERVER_SOFTWARE "bozohttpd/20190228" #endif #ifndef PUBLIC_HTML #define PUBLIC_HTML "public_html" @@ -137,10 +137,9 @@ #include <netdb.h> #include <pwd.h> #include <grp.h> -#include <signal.h> #include <stdarg.h> #include <stdlib.h> -#include <stdbool.h> +#include <strings.h> #include <string.h> #include <syslog.h> #include <time.h> @@ -148,6 +147,9 @@ #include "bozohttpd.h" +#ifndef SSL_TIMEOUT +#define SSL_TIMEOUT "30" /* wait for 30 seconds for ssl handshake */ +#endif #ifndef INITIAL_TIMEOUT #define INITIAL_TIMEOUT "30" /* wait for 30 seconds initially */ #endif @@ -183,39 +185,27 @@ struct { { NULL, NULL }, }; -volatile sig_atomic_t timeout_hit; +volatile sig_atomic_t bozo_timeout_hit; /* * check there's enough space in the prefs and names arrays. */ static int -size_arrays(bozoprefs_t *bozoprefs, size_t needed) +size_arrays(bozohttpd_t *httpd, bozoprefs_t *bozoprefs, size_t needed) { - char **temp; + size_t len = sizeof(char *) * needed; 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; + bozoprefs->name = bozomalloc(httpd, len); + bozoprefs->value = bozomalloc(httpd, len); } 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; + bozoprefs->name = bozorealloc(httpd, bozoprefs->name, len); + bozoprefs->value = bozorealloc(httpd, bozoprefs->value, len); } + + bozoprefs->size = needed; return 1; } @@ -238,16 +228,13 @@ bozo_set_pref(bozohttpd_t *httpd, bozopr if ((i = findvar(bozoprefs, name)) < 0) { /* add the element to the array */ - if (!size_arrays(bozoprefs, bozoprefs->size + 15)) + if (!size_arrays(httpd, 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; - } + free(bozoprefs->value[i]); } bozoprefs->value[i] = bozostrdup(httpd, NULL, value); return 1; @@ -296,7 +283,7 @@ parse_request(bozohttpd_t *httpd, char * len = (ssize_t)strlen(in); val = bozostrnsep(&in, " \t\n\r", &len); - if (len < 1 || val == NULL) + if (len < 1 || val == NULL || in == NULL) return; *method = val; @@ -386,18 +373,19 @@ bozo_clean_request(bozo_httpreq_t *reque static void alarmer(int sig) { - timeout_hit = 1; + bozo_timeout_hit = 1; } /* - * set a timeout for "initial", "header", or "request". + * set a timeout for "ssl", "initial", "header", or "request". */ int bozo_set_timeout(bozohttpd_t *httpd, bozoprefs_t *prefs, const char *target, const char *val) { - const char *cur, *timeouts[] = { + const char **cur, *timeouts[] = { + "ssl timeout", "initial timeout", "header timeout", "request timeout", @@ -407,9 +395,9 @@ bozo_set_timeout(bozohttpd_t *httpd, boz const size_t minlen = 1; size_t len = strlen(target); - for (cur = timeouts[0]; len >= minlen && *cur; cur++) { - if (strncmp(target, cur, len) == 0) { - bozo_set_pref(httpd, prefs, cur, val); + for (cur = timeouts; len >= minlen && *cur; cur++) { + if (strncmp(target, *cur, len) == 0) { + bozo_set_pref(httpd, prefs, *cur, val); return 0; } } @@ -585,12 +573,14 @@ process_method(bozo_httpreq_t *request, static int bozo_got_header_length(bozo_httpreq_t *request, size_t len) { + + if (len > BOZO_HEADERS_MAX_SIZE - request->hr_header_bytes) + return bozo_http_error(request->hr_httpd, 413, request, + "too many headers"); + request->hr_header_bytes += len; - if (request->hr_header_bytes < BOZO_HEADERS_MAX_SIZE) - return 0; - return bozo_http_error(request->hr_httpd, 413, request, - "too many headers"); + return 0; } /* @@ -615,14 +605,10 @@ bozo_read_request(bozohttpd_t *httpd) /* * 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. + * parent, returning 1 for each child. */ if (bozo_daemon_fork(httpd)) return NULL; - if (bozo_ssl_accept(httpd)) - return NULL; request = bozomalloc(httpd, sizeof(*request)); memset(request, 0, sizeof(*request)); @@ -698,6 +684,14 @@ bozo_read_request(bozohttpd_t *httpd) goto cleanup; } + /* + * now to try to setup SSL, and upon failure parent can signal the + * caller there was no request to process and it will wait for + * another. + */ + if (bozo_ssl_accept(httpd)) + return NULL; + alarm(httpd->initial_timeout); while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) { alarm(0); @@ -720,9 +714,9 @@ bozo_read_request(bozohttpd_t *httpd) if (ts.tv_sec > ots.tv_sec && ts.tv_sec > httpd->request_timeout && ts.tv_sec - httpd->request_timeout > ots.tv_sec) - timeout_hit = 1; + bozo_timeout_hit = 1; - if (timeout_hit) { + if (bozo_timeout_hit) { bozo_http_error(httpd, 408, NULL, "request timed out"); goto cleanup; } @@ -993,7 +987,7 @@ bozo_escape_rfc3986(bozohttpd_t *httpd, buf = bozorealloc(httpd, buf, buflen); } - for (len = 0, s = url, d = buf; *s;) { + for (s = url, d = buf; *s;) { if (*s & 0x80) goto encode_it; switch (*s) { @@ -1023,18 +1017,16 @@ bozo_escape_rfc3986(bozohttpd_t *httpd, case '\r': case ' ': encode_it: - snprintf(d, 4, "%%%02X", *s++); + snprintf(d, 4, "%%%02X", (unsigned char)*s++); d += 3; - len += 3; break; default: leave_it: *d++ = *s++; - len++; break; } } - buf[len] = 0; + *d = 0; return buf; } @@ -1192,7 +1184,7 @@ check_remap(bozo_httpreq_t *request) bozohttpd_t *httpd = request->hr_httpd; char *file = request->hr_file, *newfile; void *fmap; - const char *replace, *map_to, *p; + const char *replace = NULL, *map_to = NULL, *p; struct stat st; int mapfile; size_t avail, len, rlen, reqlen, num_esc = 0; @@ -1321,6 +1313,9 @@ check_virtual(bozo_httpreq_t *request) debug((httpd, DEBUG_OBESE, "checking for http:// virtual host in '%s'", file)); if (strncasecmp(file, "http://", 7) == 0) { + /* bozostrdup() might access it. */ + char *old_file = request->hr_file; + /* we would do virtual hosting here? */ file += 7; /* RFC 2616 (HTTP/1.1), 5.2: URI takes precedence over Host: */ @@ -1329,8 +1324,8 @@ check_virtual(bozo_httpreq_t *request) if ((s = strchr(request->hr_host, '/')) != NULL) *s = '\0'; s = strchr(file, '/'); - free(request->hr_file); request->hr_file = bozostrdup(httpd, request, s ? s : "/"); + free(old_file); debug((httpd, DEBUG_OBESE, "got host '%s' file is now '%s'", request->hr_host, request->hr_file)); } else if (!request->hr_host) @@ -1354,7 +1349,10 @@ check_virtual(bozo_httpreq_t *request) if (request->hr_host) { s = strrchr(request->hr_host, ':'); if (s != NULL) - /* truncate Host: as we want to copy it without port part */ + /* + * truncate Host: as we want to copy it + * without port part + */ *s = '\0'; request->hr_virthostname = bozostrdup(httpd, request, request->hr_host); @@ -1441,7 +1439,7 @@ 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]; + path[MAXPATHLEN + 1]; char *basename, *finalredir; int rv, absolute; @@ -1464,12 +1462,12 @@ check_bzredirect(bozo_httpreq_t *request } else if (basename == NULL) { strcpy(path, "."); strcpy(dir, ""); - basename = dir; + basename = request->hr_file + 1; } else { *basename++ = '\0'; strcpy(path, dir); } - if (bozo_check_special_files(request, basename)) + if (bozo_check_special_files(request, basename, true)) return -1; debug((httpd, DEBUG_FAT, "check_bzredirect: path %s", path)); @@ -1921,17 +1919,24 @@ bozo_process_request(bozo_httpreq_t *req /* make sure we're not trying to access special files */ int -bozo_check_special_files(bozo_httpreq_t *request, const char *name) +bozo_check_special_files(bozo_httpreq_t *request, const char *name, bool doerror) { bozohttpd_t *httpd = request->hr_httpd; size_t i; + int error = 0; - for (i = 0; specials[i].file; i++) - if (strcmp(name, specials[i].file) == 0) - return bozo_http_error(httpd, 403, request, + for (i = 0; specials[i].file; i++) { + if (strcmp(name, specials[i].file) == 0) { + if (doerror) { + error = bozo_http_error(httpd, 403, request, specials[i].name); + } else { + error = -1; + } + } + } - return 0; + return error; } /* generic header printing routine */ @@ -2076,6 +2081,9 @@ bozo_escape_html(bozohttpd_t *httpd, con case '&': j += 5; break; + case '"': + j += 6; + break; } } @@ -2106,6 +2114,10 @@ bozo_escape_html(bozohttpd_t *httpd, con memcpy(tmp + j, "&", 5); j += 5; break; + case '"': + memcpy(tmp + j, """, 6); + j += 6; + break; default: tmp[j++] = url[i]; } @@ -2250,7 +2262,8 @@ bozo_http_error(bozohttpd_t *httpd, int if (request && request->hr_allow) bozo_printf(httpd, "Allow: %s\r\n", request->hr_allow); /* RFC 7231 (HTTP/1.1) 6.5.7 */ - if (code == 408 && request->hr_proto == httpd->consts.http_11) + if (code == 408 && request && + request->hr_proto == httpd->consts.http_11) bozo_printf(httpd, "Connection: close\r\n"); bozo_printf(httpd, "\r\n"); /* According to the RFC 2616 sec. 9.4 HEAD method MUST NOT return a @@ -2458,6 +2471,8 @@ bozo_init_prefs(bozohttpd_t *httpd, bozo rv = 1; if (!bozo_set_pref(httpd, prefs, "public_html", PUBLIC_HTML)) rv = 1; + if (!bozo_set_pref(httpd, prefs, "ssl timeout", SSL_TIMEOUT)) + rv = 1; if (!bozo_set_pref(httpd, prefs, "initial timeout", INITIAL_TIMEOUT)) rv = 1; if (!bozo_set_pref(httpd, prefs, "header timeout", HEADER_WAIT_TIME)) @@ -2558,6 +2573,9 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs if ((cp = bozo_get_pref(prefs, "public_html")) != NULL) { httpd->public_html = bozostrdup(httpd, NULL, cp); } + if ((cp = bozo_get_pref(prefs, "ssl timeout")) != NULL) { + httpd->ssl_timeout = atoi(cp); + } if ((cp = bozo_get_pref(prefs, "initial timeout")) != NULL) { httpd->initial_timeout = atoi(cp); } Index: src/libexec/httpd/bozohttpd.h diff -u src/libexec/httpd/bozohttpd.h:1.47.4.2 src/libexec/httpd/bozohttpd.h:1.47.4.3 --- src/libexec/httpd/bozohttpd.h:1.47.4.2 Wed Nov 28 19:50:37 2018 +++ src/libexec/httpd/bozohttpd.h Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: bozohttpd.h,v 1.47.4.2 2018/11/28 19:50:37 martin Exp $ */ +/* $NetBSD: bozohttpd.h,v 1.47.4.3 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,9 @@ #include "netbsd_queue.h" +#include <stdbool.h> +#include <signal.h> + #include <sys/stat.h> #ifndef NO_LUA_SUPPORT @@ -117,6 +120,7 @@ typedef struct bozohttpd_t { int hide_dots; /* hide .* */ int process_cgi; /* use the cgi handler */ char *cgibin; /* cgi-bin directory */ + unsigned ssl_timeout; /* ssl timeout */ unsigned initial_timeout;/* first line timeout */ unsigned header_timeout; /* header lines timeout */ unsigned request_timeout;/* total session timeout */ @@ -195,6 +199,16 @@ typedef struct bozoprefs_t { char **value; /* values for the name entries */ } bozoprefs_t; +/* sun2 has a tiny VA range */ +#ifdef __mc68010__ +#ifndef BOZO_WRSZ +#define BOZO_WRSZ (16 * 1024) +#endif +#ifndef BOZO_MMAPSZ +#define BOZO_MMAPSZ (BOZO_WRSZ * 4) +#endif +#endif + /* by default write in upto 64KiB chunks, and mmap in upto 64MiB chunks */ #ifndef BOZO_WRSZ #define BOZO_WRSZ (64 * 1024) @@ -259,7 +273,7 @@ void debug__(bozohttpd_t *, int, const c /* be sure to always return this error up */ int bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *); -int bozo_check_special_files(bozo_httpreq_t *, const char *) BOZO_CHECKRET; +int bozo_check_special_files(bozo_httpreq_t *, const char *, bool) BOZO_CHECKRET; char *bozo_http_date(char *, size_t); void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, const char *); @@ -432,4 +446,6 @@ char *bozo_get_pref(bozoprefs_t *, const int bozo_get_version(char */*buf*/, size_t /*size*/); +extern volatile sig_atomic_t bozo_timeout_hit; + #endif /* BOZOHTTOPD_H_ */ Index: src/libexec/httpd/cgi-bozo.c diff -u src/libexec/httpd/cgi-bozo.c:1.37.4.3 src/libexec/httpd/cgi-bozo.c:1.37.4.4 --- src/libexec/httpd/cgi-bozo.c:1.37.4.3 Wed Nov 28 19:50:37 2018 +++ src/libexec/httpd/cgi-bozo.c Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: cgi-bozo.c,v 1.37.4.3 2018/11/28 19:50:37 martin Exp $ */ +/* $NetBSD: cgi-bozo.c,v 1.37.4.4 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -241,10 +241,10 @@ parse_search_string(bozo_httpreq_t *requ args[0] = str; args[*args_len] = NULL; - for (s = str, i = 0; (s = strchr(s, '+')) != NULL;) { + for (s = str, i = 1; (s = strchr(s, '+')) != NULL; i++) { *s = '\0'; s++; - args[i++] = s; + args[i] = s; } /* @@ -333,8 +333,7 @@ parse_search_string(bozo_httpreq_t *requ parse_err: - free (str); - free (*args); + free(str); free(args); *args_len = 0; @@ -494,6 +493,7 @@ bozo_process_cgi(bozo_httpreq_t *request (clen && *clen ? 1 : 0) + (request->hr_remotehost && *request->hr_remotehost ? 1 : 0) + (request->hr_remoteaddr && *request->hr_remoteaddr ? 1 : 0) + + (cgihandler ? 1 : 0) + bozo_auth_cgi_count(request) + (request->hr_serverport && *request->hr_serverport ? 1 : 0); @@ -610,9 +610,12 @@ bozo_process_cgi(bozo_httpreq_t *request closelog(); bozo_daemon_closefds(httpd); - if (-1 == execve(path, argv, envp)) + if (-1 == execve(path, argv, envp)) { + bozo_http_error(httpd, 404, request, + "Cannot execute CGI"); bozoerr(httpd, 1, "child exec failed: %s: %s", path, strerror(errno)); + } /* NOT REACHED */ bozoerr(httpd, 1, "child execve returned?!"); } Index: src/libexec/httpd/daemon-bozo.c diff -u src/libexec/httpd/daemon-bozo.c:1.17.8.1 src/libexec/httpd/daemon-bozo.c:1.17.8.2 --- src/libexec/httpd/daemon-bozo.c:1.17.8.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/daemon-bozo.c Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: daemon-bozo.c,v 1.17.8.1 2018/11/24 17:13:51 martin Exp $ */ +/* $NetBSD: daemon-bozo.c,v 1.17.8.2 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -205,7 +205,7 @@ daemon_runchild(bozohttpd_t *httpd, int } static int -daemon_poll_err(bozohttpd_t *httpd, int fd, int idx) +daemon_poll_err(bozohttpd_t *httpd, int idx) { if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0) return 0; @@ -284,7 +284,7 @@ again: } for (i = 0; i < httpd->nsock; i++) { - if (daemon_poll_err(httpd, fd, i)) + if (daemon_poll_err(httpd, i)) break; if (httpd->fds[i].revents == 0) continue; Index: src/libexec/httpd/dir-index-bozo.c diff -u src/libexec/httpd/dir-index-bozo.c:1.25.8.1 src/libexec/httpd/dir-index-bozo.c:1.25.8.2 --- src/libexec/httpd/dir-index-bozo.c:1.25.8.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/dir-index-bozo.c Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: dir-index-bozo.c,v 1.25.8.1 2018/11/24 17:13:51 martin Exp $ */ +/* $NetBSD: dir-index-bozo.c,v 1.25.8.2 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: dir-index-bozo.c,v 1.20 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,14 +45,6 @@ #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.. */ @@ -62,12 +54,10 @@ bozo_dir_index(bozo_httpreq_t *request, 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; + char *file = NULL, *printname = NULL, *p; + int k, j; if (!isindex || !httpd->dir_indexing) return 0; @@ -116,21 +106,36 @@ bozo_dir_index(bozo_httpreq_t *request, #else printname = bozostrdup(httpd, request, request->hr_file); #endif /* !NO_USER_SUPPORT */ + if ((p = strstr(printname, httpd->index_html)) != NULL) { + if (strcmp(printname, httpd->index_html) == 0) + strcpy(printname, "/"); /* is ``slashdir'' */ + else + *p = '\0'; /* strip unwanted ``index_html'' */ + } + if ((p = bozo_escape_html(httpd, printname)) != NULL) { + free(printname); + printname = p; + } bozo_printf(httpd, - "<html><head><title>Index of %s</title></head>\r\n", + "<!DOCTYPE html>\r\n" + "<html><head><meta charset=\"utf-8\"/>\r\n" + "<style type=\"text/css\">\r\n" + "table {\r\n" + "\tborder-top: 1px solid black;\r\n" + "\tborder-bottom: 1px solid black;\r\n" + "}\r\n" + "th { background: aquamarine; }\r\n" + "tr:nth-child(even) { background: lavender; }\r\n" + "</style>\r\n"); + bozo_printf(httpd, "<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>"); + bozo_printf(httpd, + "<table cols=3>\r\n<thead>\r\n" + "<tr><th>Name<th>Last modified<th align=right>Size\r\n" + "<tbody>\r\n"); for (j = k = scandir(dirpath, &de, NULL, alphasort), deo = de; j--; de++) { @@ -143,66 +148,46 @@ bozo_dir_index(bozo_httpreq_t *request, httpd->hide_dots && name[0] == '.')) continue; + if (bozo_check_special_files(request, name, false)) + 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; + bozo_printf(httpd, "<tr><td>"); if (strcmp(name, "..") == 0) { bozo_printf(httpd, "<a href=\"../\">"); - l += bozo_printf(httpd, "Parent Directory"); + bozo_printf(httpd, "Parent Directory"); } else if (!nostat && S_ISDIR(sb.st_mode)) { bozo_printf(httpd, "<a href=\"%s/\">", urlname); - l += bozo_printf(httpd, "%s/", htmlname); + 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); + bozo_printf(httpd, "%s", htmlname); } else { bozo_printf(httpd, "<a href=\"%s\">", urlname); - l += bozo_printf(httpd, "%s", htmlname); + 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, "? ?"); + bozo_printf(httpd, "<td>?<td>?\r\n"); else { unsigned long long len; - len = ((unsigned long long)sb.st_size + 1023) / 1024; - - 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); + strftime(buf, sizeof buf, "%d-%b-%Y %R", gmtime(&sb.st_mtime)); + bozo_printf(httpd, "<td>%s", buf); - bozo_printf(httpd, "%12llukB", len); + len = ((unsigned long long)sb.st_size + 1023) / 1024; + bozo_printf(httpd, "<td align=right>%llukB", len); } bozo_printf(httpd, "\r\n"); } @@ -211,8 +196,7 @@ bozo_dir_index(bozo_httpreq_t *request, while (k--) free(deo[k]); free(deo); - bozo_printf(httpd, "</pre>"); - directory_hr(httpd); + bozo_printf(httpd, "</table>\r\n"); bozo_printf(httpd, "</body></html>\r\n\r\n"); bozo_flush(httpd, stdout); @@ -222,4 +206,3 @@ done: return 1; } #endif /* NO_DIRINDEX_SUPPORT */ - Index: src/libexec/httpd/ssl-bozo.c diff -u src/libexec/httpd/ssl-bozo.c:1.22.8.1 src/libexec/httpd/ssl-bozo.c:1.22.8.2 --- src/libexec/httpd/ssl-bozo.c:1.22.8.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/ssl-bozo.c Wed Jun 12 10:32:00 2019 @@ -1,9 +1,9 @@ -/* $NetBSD: ssl-bozo.c,v 1.22.8.1 2018/11/24 17:13:51 martin Exp $ */ +/* $NetBSD: ssl-bozo.c,v 1.22.8.2 2019/06/12 10:32:00 martin Exp $ */ /* $eterna: ssl-bozo.c,v 1.15 2011/11/18 09:21:15 mrg Exp $ */ /* - * Copyright (c) 1997-2018 Matthew R. Green + * Copyright (c) 1997-2019 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -263,6 +263,8 @@ bozo_ssl_accept(bozohttpd_t *httpd) if (sslinfo == NULL || !sslinfo->ssl_context) return 0; + alarm(httpd->ssl_timeout); + sslinfo->bozossl = SSL_new(sslinfo->ssl_context); if (sslinfo->bozossl == NULL) bozoerr(httpd, 1, "SSL_new failed"); @@ -273,6 +275,14 @@ bozo_ssl_accept(bozohttpd_t *httpd) const int ret = SSL_accept(sslinfo->bozossl); bozo_check_error_queue(httpd, "accept", ret); + alarm(0); + + if (bozo_timeout_hit) { + SSL_free(sslinfo->bozossl); + sslinfo->bozossl = NULL; + return 1; + } + return ret != 1; } Index: src/libexec/httpd/testsuite/Makefile diff -u src/libexec/httpd/testsuite/Makefile:1.7.4.1 src/libexec/httpd/testsuite/Makefile:1.7.4.2 --- src/libexec/httpd/testsuite/Makefile:1.7.4.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/testsuite/Makefile Wed Jun 12 10:32:00 2019 @@ -1,3 +1,4 @@ +# $NetBSD: Makefile,v 1.7.4.2 2019/06/12 10:32:00 martin Exp $ # $eterna: Makefile,v 1.14 2009/05/22 21:51:39 mrg Exp $ SIMPLETESTS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t12 t13 t14 t15 @@ -9,7 +10,6 @@ BOZOHTTPD?= ../debug/bozohttpd-debug WGET?= wget DATA?= $(.CURDIR)/data VERBOSE?= yes -HOST?= test.eterna .if ${VERBOSE} != "yes" SILENT= @ @@ -28,17 +28,17 @@ check: check-simple check-cgi check-bigf check-simple: .for a in $(SIMPLETESTS) - ${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}" "${HOST}" + ${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}" "${HOST}" -c "${.CURDIR}/cgi-bin" + ${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}" "${HOST}" + ${SILENT}$(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "${DATA}" "${VERBOSE}" .endfor .include <bsd.obj.mk> Index: src/libexec/httpd/testsuite/t11.out diff -u src/libexec/httpd/testsuite/t11.out:1.1 src/libexec/httpd/testsuite/t11.out:1.1.20.1 --- src/libexec/httpd/testsuite/t11.out:1.1 Tue Jan 31 14:33:54 2017 +++ src/libexec/httpd/testsuite/t11.out Wed Jun 12 10:32:00 2019 @@ -1 +1,11 @@ HTTP/1.1 200 OK +Content-Type: text/html +Content-Length: 194 +Server: bozohttpd/20181215 +Allow: GET, HEAD, POST + +<html><head><title>404 Not Found</title></head> +<body><h1>404 Not Found</h1> +cgi-bin/echo.bat: <pre>This item has not been found</pre> +<hr><address><a href="// /"> </a></address> +</body></html> Index: src/libexec/httpd/testsuite/test-bigfile diff -u src/libexec/httpd/testsuite/test-bigfile:1.4.4.1 src/libexec/httpd/testsuite/test-bigfile:1.4.4.2 --- src/libexec/httpd/testsuite/test-bigfile:1.4.4.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/testsuite/test-bigfile Wed Jun 12 10:32:00 2019 @@ -1,12 +1,11 @@ #! /bin/sh -# $NetBSD: test-bigfile,v 1.4.4.1 2018/11/24 17:13:51 martin Exp $ +# $NetBSD: test-bigfile,v 1.4.4.2 2019/06/12 10:32:00 martin Exp $ test="$1"; shift # partial4000 or partial8000 bozohttpd="$1"; shift wget="$1"; shift datadir="$1"; shift verbose="$1"; shift -host="$1"; shift tmperr="tmp.$test.err" Index: src/libexec/httpd/testsuite/test-simple diff -u src/libexec/httpd/testsuite/test-simple:1.4.10.1 src/libexec/httpd/testsuite/test-simple:1.4.10.2 --- src/libexec/httpd/testsuite/test-simple:1.4.10.1 Sat Nov 24 17:13:51 2018 +++ src/libexec/httpd/testsuite/test-simple Wed Jun 12 10:32:00 2019 @@ -1,12 +1,11 @@ #! /bin/sh -# $NetBSD: test-simple,v 1.4.10.1 2018/11/24 17:13:51 martin Exp $ +# $NetBSD: test-simple,v 1.4.10.2 2019/06/12 10:32:00 martin Exp $ test="$1"; shift bozohttpd="$1"; shift datadir="$1"; shift curdir="$1"; shift verbose="$1"; shift -host="$1"; shift in="$curdir/$test.in" out="$curdir/$test.out" @@ -21,7 +20,7 @@ fi bozotestport=11111 -${bozohttpd} "$@" "${datadir}" "${host}" < "$in" > "$tmpout" +${bozohttpd} "$@" "${datadir}" < "$in" > "$tmpout" if "$curdir/html_cmp" cmp "$out" "$tmpout"; then exit 0 else