Module Name:    src
Committed By:   mrg
Date:           Wed Nov 21 09:37:02 UTC 2018

Modified Files:
        src/libexec/httpd: CHANGES auth-bozo.c bozohttpd.c bozohttpd.h
        src/libexec/httpd/testsuite: Makefile html_cmp test-bigfile test-simple

Log Message:
- 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.


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/libexec/httpd/CHANGES
cvs rdiff -u -r1.20 -r1.21 src/libexec/httpd/auth-bozo.c
cvs rdiff -u -r1.90 -r1.91 src/libexec/httpd/bozohttpd.c
cvs rdiff -u -r1.54 -r1.55 src/libexec/httpd/bozohttpd.h
cvs rdiff -u -r1.10 -r1.11 src/libexec/httpd/testsuite/Makefile
cvs rdiff -u -r1.5 -r1.6 src/libexec/httpd/testsuite/html_cmp
cvs rdiff -u -r1.4 -r1.5 src/libexec/httpd/testsuite/test-bigfile \
    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.27 src/libexec/httpd/CHANGES:1.28
--- src/libexec/httpd/CHANGES:1.27	Tue Nov 20 01:06:46 2018
+++ src/libexec/httpd/CHANGES	Wed Nov 21 09:37:02 2018
@@ -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 mar...@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

Index: src/libexec/httpd/auth-bozo.c
diff -u src/libexec/httpd/auth-bozo.c:1.20 src/libexec/httpd/auth-bozo.c:1.21
--- src/libexec/httpd/auth-bozo.c:1.20	Tue Nov 20 01:06:46 2018
+++ src/libexec/httpd/auth-bozo.c	Wed Nov 21 09:37:02 2018
@@ -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,
 		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 *
 	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)
 {

Index: src/libexec/httpd/bozohttpd.c
diff -u src/libexec/httpd/bozohttpd.c:1.90 src/libexec/httpd/bozohttpd.c:1.91
--- src/libexec/httpd/bozohttpd.c:1.90	Tue Nov 20 01:06:46 2018
+++ src/libexec/httpd/bozohttpd.c	Wed Nov 21 09:37:02 2018
@@ -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,26 +109,9 @@
 #define INDEX_HTML		"index.html"
 #endif
 #ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE		"bozohttpd/20181119"
-#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"
+#define SERVER_SOFTWARE		"bozohttpd/20181121"
 #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"
 #endif
@@ -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 *
 		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 *
 		*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 *reques
 	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 
 	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 */

Index: src/libexec/httpd/bozohttpd.h
diff -u src/libexec/httpd/bozohttpd.h:1.54 src/libexec/httpd/bozohttpd.h:1.55
--- src/libexec/httpd/bozohttpd.h:1.54	Tue Nov 20 01:23:06 2018
+++ src/libexec/httpd/bozohttpd.h	Wed Nov 21 09:37:02 2018
@@ -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 c
 #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)

Index: src/libexec/httpd/testsuite/Makefile
diff -u src/libexec/httpd/testsuite/Makefile:1.10 src/libexec/httpd/testsuite/Makefile:1.11
--- src/libexec/httpd/testsuite/Makefile:1.10	Tue Nov 20 01:06:46 2018
+++ src/libexec/httpd/testsuite/Makefile	Wed Nov 21 09:37:02 2018
@@ -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-bigf
 
 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>

Index: src/libexec/httpd/testsuite/html_cmp
diff -u src/libexec/httpd/testsuite/html_cmp:1.5 src/libexec/httpd/testsuite/html_cmp:1.6
--- src/libexec/httpd/testsuite/html_cmp:1.5	Tue Dec 27 12:09:19 2016
+++ src/libexec/httpd/testsuite/html_cmp	Wed Nov 21 09:37:02 2018
@@ -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/;"
 

Index: src/libexec/httpd/testsuite/test-bigfile
diff -u src/libexec/httpd/testsuite/test-bigfile:1.4 src/libexec/httpd/testsuite/test-bigfile:1.5
--- src/libexec/httpd/testsuite/test-bigfile:1.4	Tue Jan 31 14:33:54 2017
+++ src/libexec/httpd/testsuite/test-bigfile	Wed Nov 21 09:37:02 2018
@@ -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
Index: src/libexec/httpd/testsuite/test-simple
diff -u src/libexec/httpd/testsuite/test-simple:1.4 src/libexec/httpd/testsuite/test-simple:1.5
--- src/libexec/httpd/testsuite/test-simple:1.4	Tue Jan 31 14:33:54 2017
+++ src/libexec/httpd/testsuite/test-simple	Wed Nov 21 09:37:02 2018
@@ -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

Reply via email to