Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/httpd Add support for remapping requested paths via ...
details: https://anonhg.NetBSD.org/src/rev/8b614fa5050e
branches: trunk
changeset: 365615:8b614fa5050e
user: martin <martin%NetBSD.org@localhost>
date: Fri Aug 24 11:41:16 2018 +0000
description:
Add support for remapping requested paths via a .bzredirect file.
Fixes PR 52772. Ok: mrg@
diffstat:
libexec/httpd/bozohttpd.8 | 35 ++++++-
libexec/httpd/bozohttpd.c | 171 +++++++++++++++++++++++++++++++++-
libexec/httpd/testsuite/Makefile | 2 +-
libexec/httpd/testsuite/data/.bzremap | 2 +
libexec/httpd/testsuite/t12.in | 2 +
libexec/httpd/testsuite/t12.out | 11 ++
libexec/httpd/testsuite/t13.in | 2 +
libexec/httpd/testsuite/t13.out | 11 ++
8 files changed, 231 insertions(+), 5 deletions(-)
diffs (truncated from 335 to 300 lines):
diff -r 956158934a10 -r 8b614fa5050e libexec/httpd/bozohttpd.8
--- a/libexec/httpd/bozohttpd.8 Fri Aug 24 10:04:41 2018 +0000
+++ b/libexec/httpd/bozohttpd.8 Fri Aug 24 11:41:16 2018 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: bozohttpd.8,v 1.68 2017/11/28 12:22:27 wiz Exp $
+.\" $NetBSD: bozohttpd.8,v 1.69 2018/08/24 11:41:16 martin Exp $
.\"
.\" $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $
.\"
@@ -489,6 +489,37 @@
Otherwise provided schema will be used i.e. symbolic link to
.Em ftp://NetBSD.org/
will redirect to the provided URL.
+If a
+.Pa .bzremap
+file is found at the root of a (virtual) server, it is expected to contain
+rewrite mappings for URLs.
+.Pp
+These remappings are performed internally in the server before authentication
+happens and can be used to hide implementation details, like the CGI handler
+specific suffix for non cgi scripts in authorized directories.
+.Pp
+The map file consists of lines two paths separated by a colon, where the left
+side needs to exactly match a (sub) path of the request and will be replaced
+by the right side.
+.Pp
+The first match always wins.
+.Pp
+A
+.Pa .bzremap
+file could look like this:
+.Bd -literal
+/nic/update:/auth-dir/updipv4.pl
+.Ed
+.Pp
+The remap file should be short, access to it is slow and needs to happen
+on each request.
+If a request path needs to include a colon
+.Pq Li \&:
+character, it can be escaped
+with a backslash
+.Pq Li \e
+The right hand side of the colon is always used verbatim, no escape sequences
+are interpreted.
.Sh EXAMPLES
To configure set of virtual hosts, one would use an
.Xr inetd.conf 5
@@ -554,7 +585,7 @@
and regular code audits.
This manual documents
.Nm
-version 20170201.
+version 20180824.
.Sh AUTHORS
.An -nosplit
.Nm
diff -r 956158934a10 -r 8b614fa5050e libexec/httpd/bozohttpd.c
--- a/libexec/httpd/bozohttpd.c Fri Aug 24 10:04:41 2018 +0000
+++ b/libexec/httpd/bozohttpd.c Fri Aug 24 11:41:16 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bozohttpd.c,v 1.87 2018/01/28 13:37:39 maya Exp $ */
+/* $NetBSD: bozohttpd.c,v 1.88 2018/08/24 11:41:16 martin Exp $ */
/* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */
@@ -109,7 +109,7 @@
#define INDEX_HTML "index.html"
#endif
#ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE "bozohttpd/20170201"
+#define SERVER_SOFTWARE "bozohttpd/20180824"
#endif
#ifndef DIRECT_ACCESS_FILE
#define DIRECT_ACCESS_FILE ".bzdirect"
@@ -120,6 +120,15 @@
#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"
#endif
@@ -149,6 +158,7 @@
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
@@ -1069,6 +1079,154 @@
}
/*
+ * Like strncmp(), but s_esc may contain characters escaped by \.
+ * The len argument does not include the backslashes used for escaping,
+ * that is: it gives the raw len, after unescaping the string.
+ */
+static int
+esccmp(const char *s_plain, const char *s_esc, size_t len)
+{
+ bool esc = false;
+
+ while (len) {
+ if (!esc && *s_esc == '\\') {
+ esc = true;
+ s_esc++;
+ continue;
+ }
+ esc = false;
+ if (*s_plain == 0 || *s_esc == 0 || *s_plain != *s_esc)
+ return *s_esc - *s_plain;
+ s_esc++;
+ s_plain++;
+ len--;
+ }
+ return 0;
+}
+
+/*
+ * Check if the request refers to a uri that is mapped via a .bzremap.
+ * We have /requested/path:/re/mapped/to/this.html lines in there,
+ * and the : separator may be use in the left hand side escaped with
+ * \ to encode a path containig a : character.
+ */
+static void
+check_mapping(bozo_httpreq_t *request)
+{
+ bozohttpd_t *httpd = request->hr_httpd;
+ char *file = request->hr_file, *newfile;
+ void *fmap;
+ const char *replace, *map_to, *p;
+ struct stat st;
+ int mapfile;
+ size_t avail, len, rlen, reqlen, num_esc = 0;
+ bool escaped = false;
+
+ mapfile = open(REMAP_FILE, O_RDONLY, 0);
+ if (mapfile == -1)
+ return;
+ debug((httpd, DEBUG_FAT, "remap file found"));
+ if (fstat(mapfile, &st) == -1) {
+ bozowarn(httpd, "could not stat " REMAP_FILE ", errno: %d",
+ errno);
+ close(mapfile);
+ return;
+ }
+
+ fmap = mmap(NULL, st.st_size, PROT_READ, 0, mapfile, 0);
+ if (fmap == NULL) {
+ bozowarn(httpd, "could not mmap " REMAP_FILE ", error %d",
+ errno);
+ close(mapfile);
+ return;
+ }
+ reqlen = strlen(file);
+ for (p = fmap, avail = st.st_size; avail; ) {
+ /*
+ * We have lines like:
+ * /this/url:/replacement/that/url
+ * If we find a matching left hand side, replace will point
+ * to it and len will be its length. map_to will point to
+ * the right hand side and rlen wil be its length.
+ * If we have no match, both pointers will be NULL.
+ */
+
+ /* skip empty lines */
+ while ((*p == '\r' || *p == '\n') && avail) {
+ p++;
+ avail--;
+ }
+ replace = p;
+ escaped = false;
+ while (avail) {
+ if (*p == '\r' || *p == '\n')
+ break;
+ if (!escaped && *p == ':')
+ break;
+ if (escaped) {
+ escaped = false;
+ num_esc++;
+ } else if (*p == '\\') {
+ escaped = true;
+ }
+ p++;
+ avail--;
+ }
+ if (!avail || *p != ':') {
+ replace = NULL;
+ map_to = NULL;
+ break;
+ }
+ len = p - replace - num_esc;
+ /*
+ * reqlen < len: the left hand side is too long, can't be a
+ * match
+ * reqlen == len: full string has to match
+ * reqlen > len: make sure there is a path separator at 'len'
+ * avail < 2: we are at eof, missing right hand side
+ */
+ if (avail < 2 || reqlen < len ||
+ (reqlen == len && esccmp(file, replace, len) != 0) ||
+ (reqlen > len && (file[len] != '/' ||
+ esccmp(file, replace, len) != 0))) {
+
+ /* non-match, skip to end of line and continue */
+ while (*p != '\r' && *p != '\n' && avail) {
+ p++;
+ avail--;
+ }
+ replace = NULL;
+ map_to = NULL;
+ continue;
+ }
+ p++;
+ avail--;
+
+ /* found a match, parse the target */
+ map_to = p;
+ while (*p != '\r' && *p != '\n' && avail) {
+ p++;
+ avail--;
+ }
+ rlen = p - map_to;
+ break;
+ }
+
+ if (replace && map_to) {
+ newfile = bozomalloc(httpd, strlen(file) + rlen - len + 1);
+ memcpy(newfile, map_to, rlen);
+ strcpy(newfile+rlen, file + len);
+ debug((httpd, DEBUG_NORMAL, "remapping found ``%s'' ",
+ newfile));
+ free(request->hr_file);
+ request->hr_file = newfile;
+ }
+
+ munmap(fmap, st.st_size);
+ close(mapfile);
+}
+
+/*
* deal with virtual host names; we do this:
* if we have a virtual path root (httpd->virtbase), and we are given a
* virtual host spec (Host: ho.st or http://ho.st/), see if this
@@ -1191,6 +1349,12 @@
if (chdir(s) < 0)
return bozo_http_error(httpd, 404, request,
"can't chdir to slashdir");
+
+ /*
+ * is there a mapping for this request?
+ */
+ check_mapping(request);
+
return 0;
}
@@ -1707,6 +1871,9 @@
if (strcmp(name, ABSREDIRECT_FILE) == 0)
return bozo_http_error(httpd, 403, request,
"no permission to open redirect file");
+ 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);
}
diff -r 956158934a10 -r 8b614fa5050e libexec/httpd/testsuite/Makefile
--- a/libexec/httpd/testsuite/Makefile Fri Aug 24 10:04:41 2018 +0000
+++ b/libexec/httpd/testsuite/Makefile Fri Aug 24 11:41:16 2018 +0000
@@ -1,6 +1,6 @@
# $eterna: Makefile,v 1.14 2009/05/22 21:51:39 mrg Exp $
-SIMPLETESTS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10
+SIMPLETESTS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t12 t13
CGITESTS= t11
BIGFILETESTS= partial4000 partial8000
diff -r 956158934a10 -r 8b614fa5050e libexec/httpd/testsuite/data/.bzremap
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libexec/httpd/testsuite/data/.bzremap Fri Aug 24 11:41:16 2018 +0000
@@ -0,0 +1,2 @@
+/nic/update:/auth-dir/updipv4.pl
+/update\:all:/auth-dir/updall.pl
diff -r 956158934a10 -r 8b614fa5050e libexec/httpd/testsuite/t12.in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libexec/httpd/testsuite/t12.in Fri Aug 24 11:41:16 2018 +0000
@@ -0,0 +1,2 @@
+get /nic/update HTTP/1.1
+Host:
diff -r 956158934a10 -r 8b614fa5050e libexec/httpd/testsuite/t12.out
Home |
Main Index |
Thread Index |
Old Index