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
"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...
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