- move special files defines into bozohttpd.h, so we can ...
- consolidate all the special file checks into bozo_check_special_files() so that all builds check the same list of special files, regardless of build options. - convert "(void)bozo_http_error(...); return -1;" into plain "return bozo_http_error(...);" - fix the call to bozo_check_special_files() to be used on all input types. part of the fixes for failure to reject access to /.htpasswd as reported by JP on tech-security. - use warn_unused_result attribute on bozo_check_special_files(), and fix the failures to return failure. second part of the htpasswd access fix. - update testsuite to use a fixed fake hostname. call this bozohttpd 20181121.
This commit is contained in:
parent
7ea5009dd0
commit
a3912675bc
@ -1,6 +1,6 @@
|
||||
$NetBSD: CHANGES,v 1.27 2018/11/20 01:06:46 mrg Exp $
|
||||
$NetBSD: CHANGES,v 1.28 2018/11/21 09:37:02 mrg Exp $
|
||||
|
||||
changes in bozohttpd 20181118:
|
||||
changes in bozohttpd 20181121:
|
||||
o add url remap support via .bzremap file, from martin@netbsd.org
|
||||
o handle redirections for any protocol, not just http:
|
||||
o fix a denial of service attack against header contents, which
|
||||
@ -9,6 +9,7 @@ changes in bozohttpd 20181118:
|
||||
initial line, each header, and the total time spent
|
||||
o add -T option to expose new timeout settings
|
||||
o minor RFC fixes related to timeout handling
|
||||
o fix special file (.htpasswd, .bz*) bypass. reported by JP.
|
||||
|
||||
changes in bozohttpd 20170201:
|
||||
o fix an infinite loop in cgi processing
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: auth-bozo.c,v 1.20 2018/11/20 01:06:46 mrg Exp $ */
|
||||
/* $NetBSD: auth-bozo.c,v 1.21 2018/11/21 09:37:02 mrg Exp $ */
|
||||
|
||||
/* $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */
|
||||
|
||||
@ -42,10 +42,6 @@
|
||||
|
||||
#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);
|
||||
|
||||
@ -68,7 +64,6 @@ bozo_auth_check(bozo_httpreq_t *request, const char *file)
|
||||
strcpy(dir, ".");
|
||||
else {
|
||||
*basename++ = '\0';
|
||||
/* ensure basename(file) != AUTH_FILE */
|
||||
if (bozo_check_special_files(request, basename))
|
||||
return 1;
|
||||
}
|
||||
@ -173,18 +168,6 @@ bozo_auth_check_headers(bozo_httpreq_t *request, char *val, char *str,
|
||||
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)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bozohttpd.c,v 1.90 2018/11/20 01:06:46 mrg Exp $ */
|
||||
/* $NetBSD: bozohttpd.c,v 1.91 2018/11/21 09:37:02 mrg Exp $ */
|
||||
|
||||
/* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */
|
||||
|
||||
@ -109,25 +109,8 @@
|
||||
#define INDEX_HTML "index.html"
|
||||
#endif
|
||||
#ifndef SERVER_SOFTWARE
|
||||
#define SERVER_SOFTWARE "bozohttpd/20181119"
|
||||
#define SERVER_SOFTWARE "bozohttpd/20181121"
|
||||
#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 REMAP_FILE
|
||||
#define REMAP_FILE ".bzremap"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When you add some .bz* file, make sure to also check it in
|
||||
* bozo_check_special_files()
|
||||
*/
|
||||
|
||||
#ifndef PUBLIC_HTML
|
||||
#define PUBLIC_HTML "public_html"
|
||||
@ -696,7 +679,6 @@ bozo_read_request(bozohttpd_t *httpd)
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGALRM, &sa, NULL);
|
||||
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ots) != 0) {
|
||||
(void)bozo_http_error(httpd, 500, NULL,
|
||||
"clock_gettime failed");
|
||||
@ -1466,32 +1448,33 @@ check_bzredirect(bozo_httpreq_t *request)
|
||||
* 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,
|
||||
if ((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >=
|
||||
sizeof(dir))
|
||||
return 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);
|
||||
basename = dir;
|
||||
} else if (basename == NULL) {
|
||||
strcpy(path, ".");
|
||||
strcpy(dir, "");
|
||||
basename = request->hr_file + 1;
|
||||
} else {
|
||||
*basename++ = '\0';
|
||||
bozo_check_special_files(request, basename);
|
||||
strcpy(path, dir);
|
||||
}
|
||||
if (bozo_check_special_files(request, basename))
|
||||
return -1;
|
||||
|
||||
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,
|
||||
return bozo_http_error(httpd, 404, request,
|
||||
"redirectfile path too long");
|
||||
return -1;
|
||||
}
|
||||
@ -1502,9 +1485,8 @@ check_bzredirect(bozo_httpreq_t *request)
|
||||
} else {
|
||||
if((size_t)snprintf(redir, sizeof(redir), "%s/%s", path,
|
||||
ABSREDIRECT_FILE) >= sizeof(redir)) {
|
||||
bozo_http_error(httpd, 404, request,
|
||||
return bozo_http_error(httpd, 404, request,
|
||||
"redirectfile path too long");
|
||||
return -1;
|
||||
}
|
||||
if (lstat(redir, &sb) < 0 || !S_ISLNK(sb.st_mode))
|
||||
return 0;
|
||||
@ -1528,9 +1510,8 @@ check_bzredirect(bozo_httpreq_t *request)
|
||||
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,
|
||||
return bozo_http_error(httpd, 404, request,
|
||||
"redirect path too long");
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
finalredir = redirpath;
|
||||
@ -1566,21 +1547,15 @@ bozo_decode_url_percent(bozo_httpreq_t *request, char *str)
|
||||
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,
|
||||
if (s[1] == '\0' || s[2] == '\0')
|
||||
return 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;
|
||||
}
|
||||
if (s[1] == '0' && s[2] == '0')
|
||||
return bozo_http_error(httpd, 404, request,
|
||||
"percent hack was %00");
|
||||
if (s[1] == '2' && s[2] == 'f')
|
||||
return bozo_http_error(httpd, 404, request,
|
||||
"percent hack was %2f (/)");
|
||||
|
||||
buf[0] = *++s;
|
||||
buf[1] = *++s;
|
||||
@ -1589,11 +1564,9 @@ bozo_decode_url_percent(bozo_httpreq_t *request, char *str)
|
||||
*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;
|
||||
}
|
||||
if (*t++ == '\0')
|
||||
return bozo_http_error(httpd, 400, request,
|
||||
"percent hack got a 0 back");
|
||||
|
||||
while (*s && *s != '%') {
|
||||
if (end && s >= end)
|
||||
@ -1685,7 +1658,9 @@ transform_request(bozo_httpreq_t *request, int *isindex)
|
||||
switch (check_bzredirect(request)) {
|
||||
case -1:
|
||||
goto bad_done;
|
||||
case 1:
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1963,7 +1938,11 @@ bozo_check_special_files(bozo_httpreq_t *request, const char *name)
|
||||
if (strcmp(name, REMAP_FILE) == 0)
|
||||
return bozo_http_error(httpd, 403, request,
|
||||
"no permission to open redirect file");
|
||||
return bozo_auth_check_special_files(request, name);
|
||||
if (strcmp(name, AUTH_FILE) == 0)
|
||||
return bozo_http_error(httpd, 403, request,
|
||||
"no permission to open authfile");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generic header printing routine */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bozohttpd.h,v 1.54 2018/11/20 01:23:06 mrg Exp $ */
|
||||
/* $NetBSD: bozohttpd.h,v 1.55 2018/11/21 09:37:02 mrg Exp $ */
|
||||
|
||||
/* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */
|
||||
|
||||
@ -217,9 +217,11 @@ typedef struct bozoprefs_t {
|
||||
#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__lint__)
|
||||
#define BOZO_PRINTFLIKE(x,y) __attribute__((__format__(__printf__, x,y)))
|
||||
#define BOZO_DEAD __attribute__((__noreturn__))
|
||||
#define BOZO_CHECKRET __attribute__((__warn_unused_result__))
|
||||
#else
|
||||
#define BOZO_PRINTFLIKE(x,y)
|
||||
#define BOZO_DEAD
|
||||
#define BOZO_CHECKRET
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEBUG
|
||||
@ -231,9 +233,33 @@ void debug__(bozohttpd_t *, int, const char *, ...) BOZO_PRINTFLIKE(3, 4);
|
||||
#define have_debug (1)
|
||||
#endif /* NO_DEBUG */
|
||||
|
||||
/*
|
||||
* bozohttpd special files. avoid serving these out.
|
||||
*
|
||||
* When you add some .bz* file, make sure to also check it in
|
||||
* bozo_check_special_files()
|
||||
*/
|
||||
|
||||
#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 REMAP_FILE
|
||||
#define REMAP_FILE ".bzremap"
|
||||
#endif
|
||||
#ifndef AUTH_FILE
|
||||
#define AUTH_FILE ".htpasswd"
|
||||
#endif
|
||||
|
||||
/* 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 *);
|
||||
int bozo_check_special_files(bozo_httpreq_t *, const char *) BOZO_CHECKRET;
|
||||
char *bozo_http_date(char *, size_t);
|
||||
void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *,
|
||||
const char *);
|
||||
@ -284,7 +310,6 @@ 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 *);
|
||||
@ -293,7 +318,6 @@ int bozo_auth_cgi_count(bozo_httpreq_t *);
|
||||
#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)
|
||||
|
@ -9,6 +9,7 @@ BOZOHTTPD?= ../debug/bozohttpd-debug
|
||||
WGET?= wget
|
||||
DATA?= $(.CURDIR)/data
|
||||
VERBOSE?= yes
|
||||
HOST?= test.eterna
|
||||
|
||||
.if ${VERBOSE} != "yes"
|
||||
SILENT= @
|
||||
@ -27,17 +28,17 @@ check: check-simple check-cgi check-bigfile
|
||||
|
||||
check-simple:
|
||||
.for a in $(SIMPLETESTS)
|
||||
${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}"
|
||||
${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}" "${HOST}"
|
||||
.endfor
|
||||
|
||||
check-cgi:
|
||||
.for a in $(CGITESTS)
|
||||
${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}" -c "${.CURDIR}/cgi-bin"
|
||||
${SILENT}$(.CURDIR)/test-simple "$a" "${BOZOHTTPD}" "${DATA}" "${.CURDIR}" "${VERBOSE}" "${HOST}" -c "${.CURDIR}/cgi-bin"
|
||||
.endfor
|
||||
|
||||
check-bigfile:
|
||||
.for a in $(BIGFILETESTS)
|
||||
${SILENT}$(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "${DATA}" "${VERBOSE}"
|
||||
${SILENT}$(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "${DATA}" "${VERBOSE}" "${HOST}"
|
||||
.endfor
|
||||
|
||||
.include <bsd.obj.mk>
|
||||
|
@ -22,6 +22,7 @@ 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/[a-zA-Z0-9-]*\.eterna23\.net/$h/g;
|
||||
s/^Server: .*/^Server: bozotic HTTP server version 5.08/;
|
||||
s/^Content-Length: .*/Content-Length: 223/;"
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
#! /bin/sh
|
||||
# $NetBSD: test-bigfile,v 1.4 2017/01/31 14:33:54 mrg Exp $
|
||||
# $NetBSD: test-bigfile,v 1.5 2018/11/21 09:37:02 mrg Exp $
|
||||
|
||||
test="$1" # partial4000 or partial8000
|
||||
bozohttpd="$2"
|
||||
wget="$3"
|
||||
datadir="$4"
|
||||
verbose="$5"
|
||||
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"
|
||||
|
||||
@ -21,7 +22,7 @@ bozotestport=11111
|
||||
cp "${datadir}/bigfile.${test}" ./bigfile
|
||||
|
||||
# fire up bozohttpd
|
||||
${bozohttpd} -b -b -I ${bozotestport} -n -s -f "${datadir}" &
|
||||
${bozohttpd} -b -b -I ${bozotestport} -n -s -f "$@" "${datadir}" "${host}" &
|
||||
bozopid=$!
|
||||
|
||||
"${wget}" -c http://localhost:${bozotestport}/bigfile
|
||||
|
@ -1,11 +1,12 @@
|
||||
#! /bin/sh
|
||||
# $NetBSD: test-simple,v 1.4 2017/01/31 14:33:54 mrg Exp $
|
||||
# $NetBSD: test-simple,v 1.5 2018/11/21 09:37:02 mrg 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"
|
||||
@ -20,7 +21,7 @@ fi
|
||||
|
||||
bozotestport=11111
|
||||
|
||||
${bozohttpd} "$@" "${datadir}" < "$in" > "$tmpout"
|
||||
${bozohttpd} "$@" "${datadir}" "${host}" < "$in" > "$tmpout"
|
||||
if "$curdir/html_cmp" cmp "$out" "$tmpout"; then
|
||||
exit 0
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user