NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bin/58880: bozohttpd(8): set custom header field in responses



The following reply was made to PR bin/58880; it has been noted by GNATS.

From: Sunil Nimmagadda <sunil%nimmagadda.net@localhost>
To: "Taylor R Campbell via gnats" <gnats-admin%NetBSD.org@localhost>
Cc: mrg%netbsd.org@localhost,  netbsd-bugs%netbsd.org@localhost,  campbell+netbsd%mumble.net@localhost,
  gnats-bugs%netbsd.org@localhost
Subject: Re: bin/58880: bozohttpd(8): set custom header field in responses
Date: Mon, 16 Dec 2024 17:58:59 +0530

 --=-=-=
 Content-Type: text/plain
 
 "Taylor R Campbell via gnats" <gnats-admin%NetBSD.org@localhost> writes:
 
 > The following reply was made to PR bin/58880; it has been noted by GNATS.
 >
 > From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
 > To: Sunil Nimmagadda <sunil%nimmagadda.net@localhost>
 > Cc: gnats-admin%netbsd.org@localhost,
 > 	netbsd-bugs%netbsd.org@localhost, gnats-bugs%netbsd.org@localhost
 > Subject: Re: bin/58880: bozohttpd(8): set custom header field in responses
 > Date: Fri, 13 Dec 2024 14:57:03 +0000
 >
 >  > Date: Fri, 13 Dec 2024 13:03:05 +0530
 >  > From: Sunil Nimmagadda <sunil%nimmagadda.net@localhost>
 >  >=20
 >  > This diff allows custom headers to be specified in a .bzcustomheaders fil=
 >  e at
 >  > the root of the server. The lines from it are included verbatim as
 >  > headers in all of the responses...
 >  
 >  Awesome!  Can I interest you in writing some automatic tests for this
 >  too, including the edge cases martin@ mentioned?
 
 Sure, updated diff with atf test case. For now, this diff only supports
 static text and no variable substitutions...
 
 --=-=-=
 Content-Type: text/x-patch
 Content-Disposition: inline;
  filename=0001-Implement-custom-headers-for-httpd.patch
 Content-Description: Custom headers for bozohttpd
 
 >From 7f8f1ab04076f7a276fd3fec892450880ac388e1 Mon Sep 17 00:00:00 2001
 From: Sunil Nimmagadda <sunil%nimmagadda.net@localhost>
 Date: Sat, 14 Dec 2024 09:00:05 +0530
 Subject: [PATCH] Implement custom headers for httpd.
 
 ---
  libexec/httpd/bozohttpd.8               |  5 ++
  libexec/httpd/bozohttpd.c               | 36 ++++++++++++++
  libexec/httpd/bozohttpd.h               | 10 ++++
  tests/libexec/httpd/.bzcustomheaders    |  2 +
  tests/libexec/httpd/Makefile            |  6 +++
  tests/libexec/httpd/custom_headers.awk  | 51 ++++++++++++++++++++
  tests/libexec/httpd/index.html          |  4 ++
  tests/libexec/httpd/t_custom_headers.sh | 62 +++++++++++++++++++++++++
  8 files changed, 176 insertions(+)
  create mode 100644 tests/libexec/httpd/.bzcustomheaders
  create mode 100644 tests/libexec/httpd/Makefile
  create mode 100644 tests/libexec/httpd/custom_headers.awk
  create mode 100644 tests/libexec/httpd/index.html
  create mode 100644 tests/libexec/httpd/t_custom_headers.sh
 
 diff --git a/libexec/httpd/bozohttpd.8 b/libexec/httpd/bozohttpd.8
 index 196fcb52acc7..b37cfb50de6c 100644
 --- a/libexec/httpd/bozohttpd.8
 +++ b/libexec/httpd/bozohttpd.8
 @@ -640,6 +640,11 @@ with a backslash
  .Pq Ql \e
  The right hand side of the colon is always used verbatim, no escape sequences
  are interpreted.
 +.Ss CUSTOM RESPONSE HEADERS
 +If a
 +.Pa .bzcustomheaders
 +file is found at the root of the server, it is expected to contain
 +custom headers to be included verbatim in all of the responses.
  .Sh EXAMPLES
  To configure set of virtual hosts, one would use an
  .Xr inetd.conf 5
 diff --git a/libexec/httpd/bozohttpd.c b/libexec/httpd/bozohttpd.c
 index 656bdf073af3..a488f8b4fa5f 100644
 --- a/libexec/httpd/bozohttpd.c
 +++ b/libexec/httpd/bozohttpd.c
 @@ -181,6 +181,7 @@ struct {
  	{ ABSREDIRECT_FILE,   "rejected absredirect request" },
  	{ REMAP_FILE,         "rejected remap request" },
  	{ AUTH_FILE,          "rejected authfile request" },
 +	{ CUSTOMHEADERS_FILE, "rejected customheaders request" },
  	{ NULL,               NULL },
  };
  
 @@ -1974,12 +1975,17 @@ bozo_print_header(bozo_httpreq_t *request,
  	off_t len;
  	char	date[40];
  	bozoheaders_t *hdr;
 +	bozocustomheaders_t *chdr;
  
  	SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) {
  		bozo_printf(httpd, "%s: %s\r\n", hdr->h_header,
  				hdr->h_value);
  	}
  
 +        SIMPLEQ_FOREACH(chdr, &httpd->customheaders, h_next) {
 +		bozo_printf(httpd, "%s\r\n", chdr->h_header);
 +        }
 +
  	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");
 @@ -2524,6 +2530,8 @@ bozo_init_httpd(bozohttpd_t *httpd)
  #ifndef NO_LUA_SUPPORT
  	SIMPLEQ_INIT(&httpd->lua_states);
  #endif
 +
 +        SIMPLEQ_INIT(&httpd->customheaders);
  	return 1;
  }
  
 @@ -2562,6 +2570,33 @@ bozo_set_defaults(bozohttpd_t *httpd, bozoprefs_t *prefs)
  	return bozo_init_httpd(httpd) && bozo_init_prefs(httpd, prefs);
  }
  
 +static void
 +bozo_setup_customheaders(bozohttpd_t *httpd)
 +{
 +	struct bozocustomheaders *hdr;
 +	FILE *fp;
 +	char *fn, *line = NULL;
 +	size_t linecap = 0;
 +	ssize_t linelen;
 +
 +	bozoasprintf(httpd, &fn, "%s/%s", httpd->slashdir, CUSTOMHEADERS_FILE);
 +	fp = fopen(fn, "r");
 +	if (fp == NULL) {
 +		free(fn);
 +		return;
 +	}
 +
 +	free(fn);
 +	while ((linelen = getline(&line, &linecap, fp)) > 0) {
 +		line[strcspn(line, "\n")] = '\0';
 +		hdr = bozomalloc(httpd, sizeof *hdr);
 +		hdr->h_header = bozostrdup(httpd, NULL, line);
 +		SIMPLEQ_INSERT_TAIL(&httpd->customheaders, hdr, h_next);
 +	}
 +	free(line);
 +	fclose(fp);
 +}
 +
  /* set the virtual host name, port and root */
  int
  bozo_setup(bozohttpd_t *httpd, bozoprefs_t *prefs, const char *vhost,
 @@ -2674,6 +2709,7 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs_t *prefs, const char *vhost,
  	 */
  	bozo_ssl_init(httpd);
  	bozo_daemon_init(httpd);
 +	bozo_setup_customheaders(httpd);
  
  	username = bozo_get_pref(prefs, "username");
  	if (username != NULL) {
 diff --git a/libexec/httpd/bozohttpd.h b/libexec/httpd/bozohttpd.h
 index cdfec757793e..811b891215da 100644
 --- a/libexec/httpd/bozohttpd.h
 +++ b/libexec/httpd/bozohttpd.h
 @@ -64,6 +64,12 @@ typedef struct bozoheaders {
  } bozoheaders_t;
  SIMPLEQ_HEAD(qheaders, bozoheaders);
  
 +typedef struct bozocustomheaders {
 +	const char *h_header;
 +	SIMPLEQ_ENTRY(bozocustomheaders)	h_next;
 +} bozocustomheaders_t;
 +SIMPLEQ_HEAD(cheaders, bozocustomheaders);
 +
  #ifndef NO_LUA_SUPPORT
  typedef struct lua_handler {
  	const char	*name;
 @@ -144,6 +150,7 @@ typedef struct bozohttpd_t {
  	ssize_t		 getln_buflen;	/* length of allocated space */
  	char		*errorbuf;	/* no dynamic allocation allowed */
  	bozo_consts_t	 consts;	/* various constants */
 +	struct cheaders	customheaders;	/* Headers read from .bzcustomheaders */
  } bozohttpd_t;
  
  /* bozo_httpreq_t */
 @@ -280,6 +287,9 @@ void	debug__(bozohttpd_t *, int, const char *, ...) BOZO_PRINTFLIKE(3, 4);
  #ifndef AUTH_FILE
  #define AUTH_FILE		".htpasswd"
  #endif
 +#ifndef CUSTOMHEADERS_FILE
 +#define CUSTOMHEADERS_FILE	".bzcustomheaders"
 +#endif
  
  /* be sure to always return this error up */
  int	bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *);
 diff --git a/tests/libexec/httpd/.bzcustomheaders b/tests/libexec/httpd/.bzcustomheaders
 new file mode 100644
 index 000000000000..3e2ca829597f
 --- /dev/null
 +++ b/tests/libexec/httpd/.bzcustomheaders
 @@ -0,0 +1,2 @@
 +Strict-Transport-Security: max-age=31536000
 +Content-Security-Policy: default-src https:
 diff --git a/tests/libexec/httpd/Makefile b/tests/libexec/httpd/Makefile
 new file mode 100644
 index 000000000000..936f616997c2
 --- /dev/null
 +++ b/tests/libexec/httpd/Makefile
 @@ -0,0 +1,6 @@
 +.include <bsd.own.mk>
 +
 +TESTSDIR=	${TESTSBASE}/libexec/httpd
 +TESTS_SH=	t_custom_headers
 +
 +.include <bsd.test.mk>
 diff --git a/tests/libexec/httpd/custom_headers.awk b/tests/libexec/httpd/custom_headers.awk
 new file mode 100644
 index 000000000000..a7e00cb1847b
 --- /dev/null
 +++ b/tests/libexec/httpd/custom_headers.awk
 @@ -0,0 +1,51 @@
 +# Copyright (c) 2024 The NetBSD Foundation, Inc.
 +# All rights reserved.
 +#
 +# This code is derived from software contributed to The NetBSD Foundation
 +# by Sunil Nimmagadda.
 +#
 +# 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.
 +#
 +
 +BEGIN {
 +    in_headers = 1
 +    while (getline <".bzcustomheaders" > 0) {
 +	custom_headers[$0] = 0
 +    }
 +}
 +
 +/^$/ { in_headers = 0 }
 +
 +{
 +    if (in_headers && $0 in custom_headers) {
 +	custom_headers[$0] += 1
 +    }
 +}
 +
 +END {
 +    for (h in custom_headers) {
 +	if (custom_headers[h] == 0) {
 +	    printf("\'%s\' header not found\n", h)
 +	    exit 1
 +	}
 +    }
 +}
 diff --git a/tests/libexec/httpd/index.html b/tests/libexec/httpd/index.html
 new file mode 100644
 index 000000000000..b0941bbd5809
 --- /dev/null
 +++ b/tests/libexec/httpd/index.html
 @@ -0,0 +1,4 @@
 +<!DOCTYPE html>
 +<html lang="en">
 +<head><title>hello world!</title></head>
 +</html>
 diff --git a/tests/libexec/httpd/t_custom_headers.sh b/tests/libexec/httpd/t_custom_headers.sh
 new file mode 100644
 index 000000000000..666af720accc
 --- /dev/null
 +++ b/tests/libexec/httpd/t_custom_headers.sh
 @@ -0,0 +1,62 @@
 +# Copyright (c) 2024 The NetBSD Foundation, Inc.
 +# All rights reserved.
 +#
 +# This code is derived from software contributed to The NetBSD Foundation
 +# by Sunil Nimmagadda.
 +#
 +# 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.
 +#
 +
 +atf_test_case custom_headers cleanup
 +custom_headers_head()
 +{
 +	atf_set "descr" "Check for custom HTTP headers"
 +}
 +
 +HTTPD_PID=./.__httpd.pid
 +custom_headers_body()
 +{
 +	# start httpd in daemon mode
 +	atf_check -s exit:0 \
 +	    /usr/libexec/httpd -P $HTTPD_PID -I 8080 -b .
 +
 +	atf_check -s exit:0 \
 +	    printf "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n" | \
 +	    nc 127.0.0.1 8080 | \
 +	    tr -d '\r' | \
 +	    awk -f $(atf_get_srcdir)/custom_headers.awk
 +}
 +
 +custom_headers_cleanup()
 +{
 +	if [ -f "$HTTPD_PID" ]; then
 +		echo kill -9 "$(cat $HTTPD_PID)"
 +		kill -9 "$(cat $HTTPD_PID)"
 +		echo '# wait for httpd to exit'
 +		sleep 1
 +	fi
 +}
 +
 +atf_init_test_cases()
 +{
 +	atf_add_test_case custom_headers
 +}
 -- 
 2.47.0
 
 
 --=-=-=--
 


Home | Main Index | Thread Index | Old Index