Module Name: src
Committed By: martin
Date: Sun Apr 10 10:33:11 UTC 2016
Modified Files:
src/libexec/httpd [netbsd-7]: CHANGES Makefile auth-bozo.c bozohttpd.8
bozohttpd.c bozohttpd.h cgi-bozo.c content-bozo.c daemon-bozo.c
dir-index-bozo.c lua-bozo.c main.c printenv.lua ssl-bozo.c
tilde-luzah-bozo.c
src/libexec/httpd/testsuite [netbsd-7]: Makefile test-bigfile
Log Message:
Catch up to -current (via patch), requested by mspo in #1141:
libexec/httpd/CHANGES up to 1.21
libexec/httpd/Makefile up to 1.26
libexec/httpd/auth-bozo.c up to 1.18
libexec/httpd/bozohttpd.8 up to 1.58
libexec/httpd/bozohttpd.c up to 1.79
libexec/httpd/bozohttpd.h up to 1.44
libexec/httpd/cgi-bozo.c up to 1.32
libexec/httpd/content-bozo.c up to 1.13
libexec/httpd/daemon-bozo.c up to 1.17
libexec/httpd/dir-index-bozo.c up to 1.25
libexec/httpd/lua-bozo.c up to 1.14
libexec/httpd/main.c up to 1.13
libexec/httpd/netbsd_queue.h up to 1.1
libexec/httpd/printenv.lua up to 1.3
libexec/httpd/ssl-bozo.c up to 1.22
libexec/httpd/tilde-luzah-bozo.c up to 1.14
libexec/httpd/testsuite/Makefile up to 1.5
libexec/httpd/testsuite/test-bigfile up to 1.2
Import bozohttpd 20151028:
o add CGI support for ~user translation (-E switch)
o add redirects to ~user translation
o fix bugs around ~user translation
o add schema detection for absolute redirects
o fixed few memory leaks
o bunch of minor tweaks
o removed -r support
o smarter redirects
Changes in 20150320:
o fix redirection handling
o support transport stream (.ts) and video object (.vob) files
o directory listings show correct file sizes for large files
To generate a diff of this commit:
cvs rdiff -u -r1.19.2.1 -r1.19.2.2 src/libexec/httpd/CHANGES
cvs rdiff -u -r1.22.2.1 -r1.22.2.2 src/libexec/httpd/Makefile
cvs rdiff -u -r1.13.2.1 -r1.13.2.2 src/libexec/httpd/auth-bozo.c
cvs rdiff -u -r1.46.4.4 -r1.46.4.5 src/libexec/httpd/bozohttpd.8
cvs rdiff -u -r1.56.2.4 -r1.56.2.5 src/libexec/httpd/bozohttpd.c
cvs rdiff -u -r1.33.2.2 -r1.33.2.3 src/libexec/httpd/bozohttpd.h
cvs rdiff -u -r1.25.2.2 -r1.25.2.3 src/libexec/httpd/cgi-bozo.c
cvs rdiff -u -r1.10.2.2 -r1.10.2.3 src/libexec/httpd/content-bozo.c
cvs rdiff -u -r1.16 -r1.16.4.1 src/libexec/httpd/daemon-bozo.c
cvs rdiff -u -r1.19.4.1 -r1.19.4.2 src/libexec/httpd/dir-index-bozo.c
cvs rdiff -u -r1.10.2.1 -r1.10.2.2 src/libexec/httpd/lua-bozo.c
cvs rdiff -u -r1.8 -r1.8.2.1 src/libexec/httpd/main.c
cvs rdiff -u -r1.2 -r1.2.18.1 src/libexec/httpd/printenv.lua
cvs rdiff -u -r1.18 -r1.18.2.1 src/libexec/httpd/ssl-bozo.c
cvs rdiff -u -r1.10 -r1.10.4.1 src/libexec/httpd/tilde-luzah-bozo.c
cvs rdiff -u -r1.4 -r1.4.24.1 src/libexec/httpd/testsuite/Makefile
cvs rdiff -u -r1.1.1.1 -r1.1.1.1.30.1 \
src/libexec/httpd/testsuite/test-bigfile
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.19.2.1 src/libexec/httpd/CHANGES:1.19.2.2
--- src/libexec/httpd/CHANGES:1.19.2.1 Sun Apr 19 04:44:03 2015
+++ src/libexec/httpd/CHANGES Sun Apr 10 10:33:11 2016
@@ -1,5 +1,15 @@
$eterna: CHANGES,v 1.78 2011/11/18 01:25:11 mrg Exp $
+changes in bozohttpd 20151028:
+ o add CGI support for ~user translation (-E switch)
+ o add redirects to ~user translation
+ o fix bugs around ~user translation
+ o add schema detection for absolute redirects
+ o fixed few memory leaks
+ o bunch of minor tweaks
+ o removed -r support
+ o smarter redirects
+
changes in bozohttpd 20150320:
o fix redirection handling
o support transport stream (.ts) and video object (.vob) files
Index: src/libexec/httpd/Makefile
diff -u src/libexec/httpd/Makefile:1.22.2.1 src/libexec/httpd/Makefile:1.22.2.2
--- src/libexec/httpd/Makefile:1.22.2.1 Thu Apr 23 19:38:11 2015
+++ src/libexec/httpd/Makefile Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.22.2.1 2015/04/23 19:38:11 snj Exp $
+# $NetBSD: Makefile,v 1.22.2.2 2016/04/10 10:33:11 martin Exp $
#
# $eterna: Makefile,v 1.30 2010/07/11 00:34:27 mrg Exp $
#
@@ -15,6 +15,10 @@
# DO_HTPASSWD /* support .htpasswd files */
# NO_LUA_SUPPORT /* don't support Lua for dynamic content */
#
+# other system specific defines:
+# HAVE_NBUTIL_H /* netbsd compat is in <nbutil.h>
+# (don't forget to also enable -lnbutil)
+#
# these are usually set via the "COPTS" variable, or some other method
# for setting CFLAGS relevant to your make, eg
# % make COPTS="-DDO_HTPASSWD"
@@ -33,6 +37,17 @@ DPADD= ${LIBCRYPT} ${LIBLUA} ${LIBM}
WARNS?= 4
+.if defined(.OS.MAKE)
+OPSYS= ${.OS.MAKE}
+.else
+OPSYS:= ${:!uname -s!:S/-//g:S/\///g}
+.endif
+
+.if ${OPSYS} == "QNX"
+CPPFLAGS+= -DHAVE_NBUTIL_H
+LDADD+= -lnbutil
+.endif
+
.include <bsd.own.mk>
.if ${MKCRYPTO} != "no"
Index: src/libexec/httpd/auth-bozo.c
diff -u src/libexec/httpd/auth-bozo.c:1.13.2.1 src/libexec/httpd/auth-bozo.c:1.13.2.2
--- src/libexec/httpd/auth-bozo.c:1.13.2.1 Mon Jan 12 10:02:29 2015
+++ src/libexec/httpd/auth-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: auth-bozo.c,v 1.13.2.1 2015/01/12 10:02:29 martin Exp $ */
+/* $NetBSD: auth-bozo.c,v 1.13.2.2 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */
@@ -72,10 +72,10 @@ bozo_auth_check(bozo_httpreq_t *request,
if (bozo_check_special_files(request, basename))
return 1;
}
- request->hr_authrealm = bozostrdup(httpd, dir);
+ request->hr_authrealm = bozostrdup(httpd, request, dir);
- if ((size_t)snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE) >=
- sizeof(authfile)) {
+ if ((size_t)snprintf(authfile, sizeof(authfile), "%s/%s", dir,
+ AUTH_FILE) >= sizeof(authfile)) {
return bozo_http_error(httpd, 404, request,
"authfile path too long");
}
@@ -136,7 +136,8 @@ bozo_auth_cleanup(bozo_httpreq_t *reques
}
int
-bozo_auth_check_headers(bozo_httpreq_t *request, char *val, char *str, ssize_t len)
+bozo_auth_check_headers(bozo_httpreq_t *request, char *val, char *str,
+ ssize_t len)
{
bozohttpd_t *httpd = request->hr_httpd;
@@ -159,8 +160,8 @@ bozo_auth_check_headers(bozo_httpreq_t *
*pass++ = '\0';
free(request->hr_authuser);
free(request->hr_authpass);
- request->hr_authuser = bozostrdup(httpd, authbuf);
- request->hr_authpass = bozostrdup(httpd, pass);
+ request->hr_authuser = bozostrdup(httpd, request, authbuf);
+ request->hr_authpass = bozostrdup(httpd, request, pass);
debug((httpd, DEBUG_FAT,
"decoded authorization `%s' as `%s':`%s'",
str, request->hr_authuser, request->hr_authpass));
@@ -190,8 +191,8 @@ bozo_auth_check_401(bozo_httpreq_t *requ
if (code == 401)
bozo_printf(httpd,
"WWW-Authenticate: Basic realm=\"%s\"\r\n",
- (request && request->hr_authrealm) ?
- request->hr_authrealm : "default realm");
+ request->hr_authrealm ?
+ request->hr_authrealm : "default realm");
}
#ifndef NO_CGIBIN_SUPPORT
Index: src/libexec/httpd/bozohttpd.8
diff -u src/libexec/httpd/bozohttpd.8:1.46.4.4 src/libexec/httpd/bozohttpd.8:1.46.4.5
--- src/libexec/httpd/bozohttpd.8:1.46.4.4 Sat May 9 08:50:42 2015
+++ src/libexec/httpd/bozohttpd.8 Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: bozohttpd.8,v 1.46.4.4 2015/05/09 08:50:42 snj Exp $
+.\" $NetBSD: bozohttpd.8,v 1.46.4.5 2016/04/10 10:33:11 martin Exp $
.\"
.\" $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $
.\"
@@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 1, 2015
+.Dd December 12, 2015
.Dt BOZOHTTPD 8
.Os
.Sh NAME
@@ -34,13 +34,14 @@
.Nd hyper text transfer protocol version 1.1 daemon
.Sh SYNOPSIS
.Nm
-.Op Fl CIMPSZciptvx
+.Op Fl EHVXefhnsu
.Op Fl C Ar suffix cgihandler
.Op Fl I Ar port
.Op Fl L Ar prefix script
.Op Fl M Ar suffix type encoding encoding11
.Op Fl P Ar pidfile
.Op Fl S Ar server_software
+.Op Fl U Ar username
.Op Fl Z Ar cert privkey
.Op Fl c Ar cgibin
.Op Fl i Ar address
@@ -48,6 +49,7 @@
.Op Fl t Ar chrootdir
.Op Fl v Ar virtualroot
.Op Fl x Ar index
+.Op Fl z Ar ciphers
.Ar slashdir
.Op Ar myname
.Sh DESCRIPTION
@@ -111,9 +113,11 @@ is a valid CGI program in the
directory.
In other words, all CGI URL's must begin with
.Em \%/cgi-bin/ .
-Note that the CGI/1.1 interface is not available with
+Note that the CGI/1.1 interface is available with
.Em ~user
-translation.
+translation using
+.Fl E
+switch.
.It Fl e
Causes
.Nm
@@ -223,15 +227,6 @@ translations from
.Dq public_html
to
.Ar pubdir .
-.It Fl r
-Forces pages besides the
-.Dq index.html
-(see the
-.Fl X
-option) page to require that the Referrer: header be present and
-refer to this web server, otherwise a redirect to the
-.Dq index.html
-page will be returned instead.
.It Fl S Ar server_software
Sets the internal server version to
.Ar server_software .
@@ -270,6 +265,12 @@ into the directory
(but see the
.Fl p
option above).
+.It Fl E
+Enables CGI/1.1 interface for
+.Em ~user
+translation.
+Note that enabling this support implies that users can run
+commands as web server user, this may have security implications.
.It Fl V
Sets the default virtual host directory to
.Ar slashdir .
@@ -303,6 +304,9 @@ Changes the default file read for direct
.Dq index.html
to
.Ar index .
+.It Fl z Ar ciphers
+Sets the list of SSL ciphers (see
+.Xr SSL_CTX_set_cipher_list 3 ) .
.It Fl Z Ar certificate_path privatekey_path
Sets the path to the server certificate file and the private key file
in pem format.
@@ -333,7 +337,8 @@ by default to process incoming TCP conne
option),
.Nm
has little internal networking knowledge.
-(Indeed, you can run it on the command line with little change of functionality.)
+(Indeed, you can run it on the command line with little change of
+functionality.)
A typical
.Xr inetd.conf 5
entry would be:
@@ -425,7 +430,7 @@ It may require linking with the crypt li
.Dq -lcrypt .
.Ss SSL SUPPORT
.Nm
-has support for SSLv2, SSLv3, and TLSv1 protocols that is included by
+has support for TLSv1.1 and TLSv1.2 protocols that are included by
default.
It requires linking with the crypto and ssl library, using
.Dq -lcrypto -lssl .
@@ -462,12 +467,23 @@ symbolic link is found,
.Nm
will perform a smart redirect to the target of this symlink.
The target is assumed to live on the same server.
+If target starts with slash then absolute redirection is performed,
+otherwise it's handled as relative.
If a
.Pa .bzabsredirect
symbolic link is found,
.Nm
will redirect to the absolute url pointed to by this symlink.
This is useful to redirect to different servers.
+Two forms of redirection are supported - symbolic link without schema will use
+.Em http://
+as default i.e. link to
+.Em NetBSD.org
+will redirect to
+.Em http://NetBSD.org/
+Otherwise provided schema will be used i.e. symbolic link to
+.Em ftp://NetBSD.org/
+will redirect to provided the URL.
.Sh EXAMPLES
To configure set of virtual hosts, one would use an
.Xr inetd.conf 5
@@ -597,8 +613,9 @@ provided many fixes and enhancements for
.It
.An Mateusz Kocielski
.Aq Mt [email protected]
-fixed memory leaks, information disclosure issues and added support
-for using CGI handlers with directory indexing.
+fixed memory leaks, various issues with userdir support,
+information disclosure issues, added support for using CGI handlers
+with directory indexing and provided various other fixes.
.It
.An Arnaud Lacombe
.Aq Mt [email protected]
@@ -612,7 +629,7 @@ provided man page fixes
.Aq Mt [email protected]
Added the
.Fl P
-option.
+option (pidfile support) and provided some man page fixes.
.It
.An Luke Mewburn
.Aq Mt [email protected]
@@ -665,9 +682,6 @@ provided http authorisation fixes
provided chroot and change-to-user support, and other various fixes
.It
Coyote Point provided various CGI fixes.
-.It
-.An Julio Merino
-added pidfile support and provided some man page fixes.
.El
.Pp
There are probably others I have forgotten (let me know if you care)
Index: src/libexec/httpd/bozohttpd.c
diff -u src/libexec/httpd/bozohttpd.c:1.56.2.4 src/libexec/httpd/bozohttpd.c:1.56.2.5
--- src/libexec/httpd/bozohttpd.c:1.56.2.4 Sat May 9 08:50:42 2015
+++ src/libexec/httpd/bozohttpd.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: bozohttpd.c,v 1.56.2.4 2015/05/09 08:50:42 snj Exp $ */
+/* $NetBSD: bozohttpd.c,v 1.56.2.5 2016/04/10 10:33:11 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/20150501"
+#define SERVER_SOFTWARE "bozohttpd/20151231"
#endif
#ifndef DIRECT_ACCESS_FILE
#define DIRECT_ACCESS_FILE ".bzdirect"
@@ -171,61 +171,59 @@ volatile sig_atomic_t alarmhit;
* check there's enough space in the prefs and names arrays.
*/
static int
-size_arrays(bozoprefs_t *bozoprefs, unsigned needed)
+size_arrays(bozoprefs_t *bozoprefs, size_t needed)
{
char **temp;
if (bozoprefs->size == 0) {
/* only get here first time around */
- bozoprefs->size = needed;
- if ((bozoprefs->name = calloc(sizeof(char *), needed)) == NULL) {
- (void) fprintf(stderr, "size_arrays: bad alloc\n");
+ bozoprefs->name = calloc(sizeof(char *), needed);
+ if (bozoprefs->name == NULL)
return 0;
- }
- if ((bozoprefs->value = calloc(sizeof(char *), needed)) == NULL) {
+ bozoprefs->value = calloc(sizeof(char *), needed);
+ if (bozoprefs->value == NULL) {
free(bozoprefs->name);
- (void) fprintf(stderr, "size_arrays: bad alloc\n");
return 0;
}
- } else if (bozoprefs->c == bozoprefs->size) {
+ bozoprefs->size = needed;
+ } else if (bozoprefs->count == bozoprefs->size) {
/* only uses 'needed' when filled array */
- bozoprefs->size += needed;
temp = realloc(bozoprefs->name, sizeof(char *) * needed);
- if (temp == NULL) {
- (void) fprintf(stderr, "size_arrays: bad alloc\n");
+ if (temp == NULL)
return 0;
- }
bozoprefs->name = temp;
temp = realloc(bozoprefs->value, sizeof(char *) * needed);
- if (temp == NULL) {
- (void) fprintf(stderr, "size_arrays: bad alloc\n");
+ if (temp == NULL)
return 0;
- }
bozoprefs->value = temp;
+ bozoprefs->size += needed;
}
return 1;
}
-static int
+static ssize_t
findvar(bozoprefs_t *bozoprefs, const char *name)
{
- unsigned i;
+ size_t i;
- for (i = 0 ; i < bozoprefs->c && strcmp(bozoprefs->name[i], name) != 0; i++)
- ;
- return (i == bozoprefs->c) ? -1 : (int)i;
+ for (i = 0; i < bozoprefs->count; i++)
+ if (strcmp(bozoprefs->name[i], name) == 0)
+ return (ssize_t)i;
+ return -1;
}
int
-bozo_set_pref(bozoprefs_t *bozoprefs, const char *name, const char *value)
+bozo_set_pref(bozohttpd_t *httpd, bozoprefs_t *bozoprefs,
+ const char *name, const char *value)
{
- int i;
+ ssize_t i;
if ((i = findvar(bozoprefs, name)) < 0) {
/* add the element to the array */
- if (size_arrays(bozoprefs, bozoprefs->size + 15)) {
- bozoprefs->name[i = bozoprefs->c++] = strdup(name);
- }
+ if (!size_arrays(bozoprefs, bozoprefs->size + 15))
+ return 0;
+ i = bozoprefs->count++;
+ bozoprefs->name[i] = bozostrdup(httpd, NULL, name);
} else {
/* replace the element in the array */
if (bozoprefs->value[i]) {
@@ -233,8 +231,7 @@ bozo_set_pref(bozoprefs_t *bozoprefs, co
bozoprefs->value[i] = NULL;
}
}
- /* sanity checks for range of values go here */
- bozoprefs->value[i] = strdup(value);
+ bozoprefs->value[i] = bozostrdup(httpd, NULL, value);
return 1;
}
@@ -244,10 +241,10 @@ bozo_set_pref(bozoprefs_t *bozoprefs, co
char *
bozo_get_pref(bozoprefs_t *bozoprefs, const char *name)
{
- int i;
+ ssize_t i;
- return ((i = findvar(bozoprefs, name)) < 0) ? NULL :
- bozoprefs->value[i];
+ i = findvar(bozoprefs, name);
+ return i < 0 ? NULL : bozoprefs->value[i];
}
char *
@@ -309,9 +306,9 @@ parse_request(bozohttpd_t *httpd, char *
}
/* allocate private copies */
- *file = bozostrdup(httpd, *file);
+ *file = bozostrdup(httpd, NULL, *file);
if (*query)
- *query = bozostrdup(httpd, *query);
+ *query = bozostrdup(httpd, NULL, *query);
debug((httpd, DEBUG_FAT,
"url: method: \"%s\" file: \"%s\" query: \"%s\" proto: \"%s\"",
@@ -341,6 +338,7 @@ bozo_clean_request(bozo_httpreq_t *reque
free(request->hr_oldfile);
free(request->hr_query);
free(request->hr_host);
+ bozo_user_free(request->hr_user);
bozo_auth_cleanup(request);
for (hdr = SIMPLEQ_FIRST(&request->hr_headers); hdr;
hdr = SIMPLEQ_NEXT(hdr, h_next)) {
@@ -371,6 +369,7 @@ static bozoheaders_t *
addmerge_header(bozo_httpreq_t *request, char *val,
char *str, ssize_t len)
{
+ struct bozohttpd_t *httpd = request->hr_httpd;
struct bozoheaders *hdr;
USE_ARG(len);
@@ -384,22 +383,18 @@ addmerge_header(bozo_httpreq_t *request,
/* yup, merge it in */
char *nval;
- if (asprintf(&nval, "%s, %s", hdr->h_value, str) == -1) {
- (void)bozo_http_error(request->hr_httpd, 500, NULL,
- "memory allocation failure");
- return NULL;
- }
+ bozoasprintf(httpd, &nval, "%s, %s", hdr->h_value, str);
free(hdr->h_value);
hdr->h_value = nval;
} else {
/* nope, create a new one */
- hdr = bozomalloc(request->hr_httpd, sizeof *hdr);
- hdr->h_header = bozostrdup(request->hr_httpd, val);
+ hdr = bozomalloc(httpd, sizeof *hdr);
+ hdr->h_header = bozostrdup(httpd, request, val);
if (str && *str)
- hdr->h_value = bozostrdup(request->hr_httpd, str);
+ hdr->h_value = bozostrdup(httpd, request, str);
else
- hdr->h_value = bozostrdup(request->hr_httpd, " ");
+ hdr->h_value = bozostrdup(httpd, request, " ");
SIMPLEQ_INSERT_TAIL(&request->hr_headers, hdr, h_next);
request->hr_nheaders++;
@@ -415,13 +410,14 @@ addmerge_header(bozo_httpreq_t *request,
static int
process_proto(bozo_httpreq_t *request, const char *proto)
{
+ struct bozohttpd_t *httpd = request->hr_httpd;
char majorstr[16], *minorstr;
int majorint, minorint;
if (proto == NULL) {
got_proto_09:
- request->hr_proto = request->hr_httpd->consts.http_09;
- debug((request->hr_httpd, DEBUG_FAT, "request %s is http/0.9",
+ request->hr_proto = httpd->consts.http_09;
+ debug((httpd, DEBUG_FAT, "request %s is http/0.9",
request->hr_file));
return 0;
}
@@ -445,25 +441,25 @@ got_proto_09:
goto got_proto_09;
case 1:
if (minorint == 0)
- request->hr_proto = request->hr_httpd->consts.http_10;
+ request->hr_proto = httpd->consts.http_10;
else if (minorint == 1)
- request->hr_proto = request->hr_httpd->consts.http_11;
+ request->hr_proto = httpd->consts.http_11;
else
break;
- debug((request->hr_httpd, DEBUG_FAT, "request %s is %s",
+ debug((httpd, DEBUG_FAT, "request %s is %s",
request->hr_file, request->hr_proto));
SIMPLEQ_INIT(&request->hr_headers);
request->hr_nheaders = 0;
return 0;
}
bad:
- return bozo_http_error(request->hr_httpd, 404, NULL, "unknown prototype");
+ return bozo_http_error(httpd, 404, NULL, "unknown prototype");
}
/*
* process each type of HTTP method, setting this HTTP requests
- # method type.
+ * method type.
*/
static struct method_map {
const char *name;
@@ -485,9 +481,10 @@ static struct method_map {
static int
process_method(bozo_httpreq_t *request, const char *method)
{
+ struct bozohttpd_t *httpd = request->hr_httpd;
struct method_map *mmp;
- if (request->hr_proto == request->hr_httpd->consts.http_11)
+ if (request->hr_proto == httpd->consts.http_11)
request->hr_allow = "GET, HEAD, POST";
for (mmp = method_map; mmp->name; mmp++)
@@ -497,7 +494,7 @@ process_method(bozo_httpreq_t *request,
return 0;
}
- return bozo_http_error(request->hr_httpd, 404, request, "unknown method");
+ return bozo_http_error(httpd, 404, request, "unknown method");
}
/*
@@ -560,9 +557,9 @@ bozo_read_request(bozohttpd_t *httpd)
host = NULL;
}
if (host != NULL)
- request->hr_remotehost = bozostrdup(request->hr_httpd, host);
+ request->hr_remotehost = bozostrdup(httpd, request, host);
if (addr != NULL)
- request->hr_remoteaddr = bozostrdup(request->hr_httpd, addr);
+ request->hr_remoteaddr = bozostrdup(httpd, request, addr);
slen = sizeof(ss);
/*
@@ -578,15 +575,16 @@ bozo_read_request(bozohttpd_t *httpd)
if (getsockname(0, (struct sockaddr *)(void *)&ss, &slen) < 0)
port = NULL;
else {
- if (getnameinfo((struct sockaddr *)(void *)&ss, slen, NULL, 0,
- bufport, sizeof bufport, NI_NUMERICSERV) == 0)
+ if (getnameinfo((struct sockaddr *)(void *)&ss, slen,
+ NULL, 0, bufport, sizeof bufport,
+ NI_NUMERICSERV) == 0)
port = bufport;
else
port = NULL;
}
}
if (port != NULL)
- request->hr_serverport = bozostrdup(request->hr_httpd, port);
+ request->hr_serverport = bozostrdup(httpd, request, port);
/*
* setup a timer to make sure the request is not hung
@@ -595,7 +593,7 @@ bozo_read_request(bozohttpd_t *httpd)
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGALRM);
sa.sa_flags = 0;
- sigaction(SIGALRM, &sa, NULL); /* XXX */
+ sigaction(SIGALRM, &sa, NULL);
alarm(MAX_WAIT_TIME);
while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) {
@@ -614,11 +612,11 @@ bozo_read_request(bozohttpd_t *httpd)
"null method");
goto cleanup;
}
-
- bozo_warn(httpd, "got request ``%s'' from host %s to port %s",
- str,
- host ? host : addr ? addr : "<local>",
- port ? port : "<stdin>");
+ bozowarn(httpd,
+ "got request ``%s'' from host %s to port %s",
+ str,
+ host ? host : addr ? addr : "<local>",
+ port ? port : "<stdin>");
/* we allocate return space in file and query only */
parse_request(httpd, str, &method, &file, &query, &proto);
@@ -682,7 +680,8 @@ bozo_read_request(bozohttpd_t *httpd)
else if (strcasecmp(hdr->h_header, "content-length") == 0)
request->hr_content_length = hdr->h_value;
else if (strcasecmp(hdr->h_header, "host") == 0)
- request->hr_host = bozostrdup(httpd, hdr->h_value);
+ request->hr_host = bozostrdup(httpd, request,
+ hdr->h_value);
/* RFC 2616 (HTTP/1.1): 14.20 */
else if (strcasecmp(hdr->h_header, "expect") == 0) {
(void)bozo_http_error(httpd, 417, request,
@@ -797,7 +796,7 @@ mmap_and_write_part(bozohttpd_t *httpd,
addr = mmap(0, mappedsz, PROT_READ, MAP_SHARED, fd, mappedoffset);
if (addr == (char *)-1) {
- bozo_warn(httpd, "mmap failed: %s", strerror(errno));
+ bozowarn(httpd, "mmap failed: %s", strerror(errno));
return -1;
}
mappedaddr = addr;
@@ -808,7 +807,7 @@ mmap_and_write_part(bozohttpd_t *httpd,
while (sz > BOZO_WRSZ) {
if (bozo_write(httpd, STDOUT_FILENO, addr + wroffset,
BOZO_WRSZ) != BOZO_WRSZ) {
- bozo_warn(httpd, "write failed: %s", strerror(errno));
+ bozowarn(httpd, "write failed: %s", strerror(errno));
goto out;
}
debug((httpd, DEBUG_OBESE, "wrote %d bytes", BOZO_WRSZ));
@@ -817,13 +816,13 @@ mmap_and_write_part(bozohttpd_t *httpd,
}
if (sz && (size_t)bozo_write(httpd, STDOUT_FILENO, addr + wroffset,
sz) != sz) {
- bozo_warn(httpd, "final write failed: %s", strerror(errno));
+ bozowarn(httpd, "final write failed: %s", strerror(errno));
goto out;
}
debug((httpd, DEBUG_OBESE, "wrote %d bytes", (int)sz));
out:
if (munmap(mappedaddr, mappedsz) < 0) {
- bozo_warn(httpd, "munmap failed");
+ bozowarn(httpd, "munmap failed");
return -1;
}
@@ -851,10 +850,11 @@ parse_http_date(const char *val, time_t
/*
* given an url, encode it ala rfc 3986. ie, escape ? and friends.
* note that this function returns a static buffer, and thus needs
- * to be updated for any sort of parallel processing.
+ * to be updated for any sort of parallel processing. escape only
+ * chosen characters for absolute redirects
*/
char *
-bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url)
+bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute)
{
static char *buf;
static size_t buflen = 0;
@@ -868,11 +868,6 @@ bozo_escape_rfc3986(bozohttpd_t *httpd,
buf = bozorealloc(httpd, buf, buflen);
}
- if (url == NULL) {
- buf[0] = 0;
- return buf;
- }
-
for (len = 0, s = url, d = buf; *s;) {
if (*s & 0x80)
goto encode_it;
@@ -895,11 +890,18 @@ bozo_escape_rfc3986(bozohttpd_t *httpd,
case ';':
case '=':
case '%':
+ case '"':
+ if (absolute)
+ goto leave_it;
+ case '\n':
+ case '\r':
+ case ' ':
encode_it:
- snprintf(d, 4, "%%%2X", *s++);
+ snprintf(d, 4, "%%%02X", *s++);
d += 3;
len += 3;
break;
+ leave_it:
default:
*d++ = *s++;
len++;
@@ -912,115 +914,118 @@ bozo_escape_rfc3986(bozohttpd_t *httpd,
}
/*
- * checks to see if this request has a valid .bzdirect file. returns
- * 0 on failure and 1 on success.
- */
-static int
-check_direct_access(bozo_httpreq_t *request)
-{
- FILE *fp;
- struct stat sb;
- char dir[MAXPATHLEN], dirfile[MAXPATHLEN], *basename;
-
- snprintf(dir, sizeof(dir), "%s", request->hr_file + 1);
- debug((request->hr_httpd, DEBUG_FAT, "check_direct_access: dir %s", dir));
- basename = strrchr(dir, '/');
-
- if ((!basename || basename[1] != '\0') &&
- lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode))
- /* nothing */;
- else if (basename == NULL)
- strcpy(dir, ".");
- else {
- *basename++ = '\0';
- bozo_check_special_files(request, basename);
- }
-
- if ((size_t)snprintf(dirfile, sizeof(dirfile), "%s/%s", dir,
- DIRECT_ACCESS_FILE) >= sizeof(dirfile)) {
- bozo_http_error(request->hr_httpd, 404, request,
- "directfile path too long");
- return 0;
- }
- if (stat(dirfile, &sb) < 0 ||
- (fp = fopen(dirfile, "r")) == NULL)
- return 0;
- fclose(fp);
- return 1;
-}
-
-/*
- * do automatic redirection -- if there are query parameters for the URL
- * we will tack these on to the new (redirected) URL.
+ * do automatic redirection -- if there are query parameters or userdir for
+ * the URL we will tack these on to the new (redirected) URL.
*/
static void
-handle_redirect(bozo_httpreq_t *request,
- const char *url, int absolute)
+handle_redirect(bozo_httpreq_t *request, const char *url, int absolute)
{
bozohttpd_t *httpd = request->hr_httpd;
- char *urlbuf;
+ char *finalurl, *urlbuf;
+#ifndef NO_USER_SUPPORT
+ char *userbuf;
+#endif /* !NO_USER_SUPPORT */
char portbuf[20];
+ const char *scheme, *query, *quest;
const char *hostname = BOZOHOST(httpd, request);
- int query = 0;
+ int absproto = 0; /* absolute redirect provides own schema */
if (url == NULL) {
- if (asprintf(&urlbuf, "/%s/", request->hr_file) < 0)
- bozo_err(httpd, 1, "asprintf");
+ bozoasprintf(httpd, &urlbuf, "/%s/", request->hr_file);
url = urlbuf;
} else
urlbuf = NULL;
- url = bozo_escape_rfc3986(request->hr_httpd, url);
- if (request->hr_query && strlen(request->hr_query))
- query = 1;
+#ifndef NO_USER_SUPPORT
+ if (request->hr_user && !absolute) {
+ bozoasprintf(httpd, &userbuf, "/~%s%s", request->hr_user, url);
+ url = userbuf;
+ } else
+ userbuf = NULL;
+#endif /* !NO_USER_SUPPORT */
+
+ if (absolute) {
+ char *sep = NULL;
+ const char *s;
- if (request->hr_serverport && strcmp(request->hr_serverport, "80") != 0)
- snprintf(portbuf, sizeof(portbuf), ":%s",
- request->hr_serverport);
- else
+ /*
+ * absolute redirect may specify own protocol i.e. to redirect
+ * to another schema like https:// or ftp://.
+ * Details: RFC 3986, section 3.
+ */
+
+ /* 1. check if url contains :// */
+ sep = strstr(url, "://");
+
+ /*
+ * RFC 3986, section 3.1:
+ * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+ if (sep) {
+ for (s = url; s != sep;) {
+ if (!isalnum((int)*s) &&
+ *s != '+' && *s != '-' && *s != '.')
+ break;
+ if (++s == sep) {
+ absproto = 1;
+ }
+ }
+ }
+ }
+
+ /* construct final redirection url */
+
+ scheme = absproto ? "" : httpd->sslinfo ? "https://" : "http://";
+
+ if (absolute) {
+ hostname = "";
portbuf[0] = '\0';
- if (absolute)
- bozo_warn(httpd, "redirecting %s", url);
- else
- bozo_warn(httpd, "redirecting %s%s%s", hostname, portbuf, url);
- debug((httpd, DEBUG_FAT, "redirecting %s", url));
+ } else {
+ const char *defport = httpd->sslinfo ? "443" : "80";
+
+ if (request->hr_serverport &&
+ strcmp(request->hr_serverport, defport) != 0)
+ snprintf(portbuf, sizeof(portbuf), ":%s",
+ request->hr_serverport);
+ else
+ portbuf[0] = '\0';
+ }
+
+ url = bozo_escape_rfc3986(httpd, url, absolute);
+
+ if (request->hr_query && strlen(request->hr_query)) {
+ query = request->hr_query;
+ quest = "?";
+ } else {
+ query = quest = "";
+ }
+
+ bozoasprintf(httpd, &finalurl, "%s%s%s%s%s%s",
+ scheme, hostname, portbuf, url, quest, query);
+
+ bozowarn(httpd, "redirecting %s", finalurl);
+ debug((httpd, DEBUG_FAT, "redirecting %s", finalurl));
+
bozo_printf(httpd, "%s 301 Document Moved\r\n", request->hr_proto);
if (request->hr_proto != httpd->consts.http_09)
bozo_print_header(request, NULL, "text/html", NULL);
- if (request->hr_proto != httpd->consts.http_09) {
- bozo_printf(httpd, "Location: http://");
- if (absolute == 0)
- bozo_printf(httpd, "%s%s", hostname, portbuf);
- if (query) {
- bozo_printf(httpd, "%s?%s\r\n", url, request->hr_query);
- } else {
- bozo_printf(httpd, "%s\r\n", url);
- }
- }
+ if (request->hr_proto != httpd->consts.http_09)
+ bozo_printf(httpd, "Location: %s\r\n", finalurl);
bozo_printf(httpd, "\r\n");
if (request->hr_method == HTTP_HEAD)
goto head;
bozo_printf(httpd, "<html><head><title>Document Moved</title></head>\n");
bozo_printf(httpd, "<body><h1>Document Moved</h1>\n");
- bozo_printf(httpd, "This document had moved <a href=\"http://");
- if (query) {
- if (absolute)
- bozo_printf(httpd, "%s?%s", url, request->hr_query);
- else
- bozo_printf(httpd, "%s%s%s?%s", hostname,
- portbuf, url, request->hr_query);
- } else {
- if (absolute)
- bozo_printf(httpd, "%s", url);
- else
- bozo_printf(httpd, "%s%s%s", hostname,
- portbuf, url);
- }
- bozo_printf(httpd, "\">here</a>\n");
+ bozo_printf(httpd, "This document had moved <a href=\"%s\">here</a>\n",
+ finalurl);
bozo_printf(httpd, "</body></html>\n");
head:
bozo_flush(httpd, stdout);
free(urlbuf);
+ free(finalurl);
+#ifndef NO_USER_SUPPORT
+ free(userbuf);
+#endif /* !NO_USER_SUPPORT */
}
/*
@@ -1037,9 +1042,6 @@ check_virtual(bozo_httpreq_t *request)
char *file = request->hr_file, *s;
size_t len;
- if (!httpd->virtbase)
- goto use_slashdir;
-
/*
* convert http://virtual.host/ to request->hr_host
*/
@@ -1050,12 +1052,12 @@ check_virtual(bozo_httpreq_t *request)
file += 7;
/* RFC 2616 (HTTP/1.1), 5.2: URI takes precedence over Host: */
free(request->hr_host);
- request->hr_host = bozostrdup(request->hr_httpd, file);
+ request->hr_host = bozostrdup(httpd, request, file);
if ((s = strchr(request->hr_host, '/')) != NULL)
*s = '\0';
s = strchr(file, '/');
free(request->hr_file);
- request->hr_file = bozostrdup(request->hr_httpd, s ? s : "/");
+ request->hr_file = bozostrdup(httpd, request, s ? s : "/");
debug((httpd, DEBUG_OBESE, "got host ``%s'' file is now ``%s''",
request->hr_host, request->hr_file));
} else if (!request->hr_host)
@@ -1069,6 +1071,29 @@ check_virtual(bozo_httpreq_t *request)
request->hr_host[len - 3] = '\0';
len = strlen(request->hr_host);
}
+
+ if (!httpd->virtbase) {
+
+ /*
+ * if we don't use vhost support, then set virthostname if
+ * user supplied Host header. It will be used for possible
+ * redirections
+ */
+
+ if (request->hr_host) {
+ s = strrchr(request->hr_host, ':');
+ if (s != NULL)
+ /* truncate Host: as we want to copy it without port part */
+ *s = '\0';
+ request->hr_virthostname = bozostrdup(httpd, request,
+ request->hr_host);
+ if (s != NULL)
+ /* fix Host: again, if we truncated it */
+ *s = ':';
+ }
+
+ goto use_slashdir;
+ }
/*
* ok, we have a virtual host, use opendir(3) to find a case
@@ -1093,15 +1118,14 @@ check_virtual(bozo_httpreq_t *request)
}
debug((httpd, DEBUG_OBESE, "looking at dir``%s''",
d->d_name));
- if (d->d_namlen == len && strcmp(d->d_name,
- request->hr_host) == 0) {
+ if (strcmp(d->d_name, request->hr_host) == 0) {
/* found it, punch it */
debug((httpd, DEBUG_OBESE, "found it punch it"));
request->hr_virthostname =
- bozostrdup(httpd, d->d_name);
- if (asprintf(&s, "%s/%s", httpd->virtbase,
- request->hr_virthostname) < 0)
- bozo_err(httpd, 1, "asprintf");
+ bozostrdup(httpd, request, d->d_name);
+ bozoasprintf(httpd, &s, "%s/%s",
+ httpd->virtbase,
+ request->hr_virthostname);
break;
}
}
@@ -1138,6 +1162,7 @@ use_slashdir:
static int
check_bzredirect(bozo_httpreq_t *request)
{
+ bozohttpd_t *httpd = request->hr_httpd;
struct stat sb;
char dir[MAXPATHLEN], redir[MAXPATHLEN], redirpath[MAXPATHLEN + 1],
path[MAXPATHLEN];
@@ -1150,27 +1175,31 @@ check_bzredirect(bozo_httpreq_t *request
*/
if((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >=
sizeof(dir)) {
- bozo_http_error(request->hr_httpd, 404, request,
+ bozo_http_error(httpd, 404, request,
"file path too long");
return -1;
}
- debug((request->hr_httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir));
+ 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))
- /* nothing */;
- else if (basename == NULL)
- strcpy(dir, ".");
- else {
+ lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+ strcpy(path, dir);
+ } else if (basename == NULL) {
+ strcpy(path, ".");
+ strcpy(dir, "");
+ } else {
*basename++ = '\0';
bozo_check_special_files(request, basename);
+ strcpy(path, dir);
}
- if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", dir,
+ 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(request->hr_httpd, 404, request,
- "redirectfile path too long");
+ bozo_http_error(httpd, 404, request,
+ "redirectfile path too long");
return -1;
}
if (lstat(redir, &sb) == 0) {
@@ -1178,9 +1207,9 @@ check_bzredirect(bozo_httpreq_t *request
return 0;
absolute = 0;
} else {
- if((size_t)snprintf(redir, sizeof(redir), "%s/%s", dir,
+ if((size_t)snprintf(redir, sizeof(redir), "%s/%s", path,
ABSREDIRECT_FILE) >= sizeof(redir)) {
- bozo_http_error(request->hr_httpd, 404, request,
+ bozo_http_error(httpd, 404, request,
"redirectfile path too long");
return -1;
}
@@ -1188,16 +1217,14 @@ check_bzredirect(bozo_httpreq_t *request
return 0;
absolute = 1;
}
- debug((request->hr_httpd, DEBUG_FAT,
- "check_bzredirect: calling readlink"));
+ debug((httpd, DEBUG_FAT, "check_bzredirect: calling readlink"));
rv = readlink(redir, redirpath, sizeof redirpath - 1);
if (rv == -1 || rv == 0) {
- debug((request->hr_httpd, DEBUG_FAT, "readlink failed"));
+ debug((httpd, DEBUG_FAT, "readlink failed"));
return 0;
}
redirpath[rv] = '\0';
- debug((request->hr_httpd, DEBUG_FAT,
- "readlink returned \"%s\"", redirpath));
+ debug((httpd, DEBUG_FAT, "readlink returned \"%s\"", redirpath));
/* check if we need authentication */
snprintf(path, sizeof(path), "%s/", dir);
@@ -1205,19 +1232,17 @@ check_bzredirect(bozo_httpreq_t *request
return 1;
/* now we have the link pointer, redirect to the real place */
- if (absolute)
- finalredir = redirpath;
- else {
- if ((size_t)snprintf(finalredir = redir, sizeof(redir), "/%s/%s",
- dir, redirpath) >= sizeof(redir)) {
- bozo_http_error(request->hr_httpd, 404, 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,
"redirect path too long");
return -1;
}
- }
+ } else
+ finalredir = redirpath;
- debug((request->hr_httpd, DEBUG_FAT,
- "check_bzredirect: new redir %s", finalredir));
+ debug((httpd, DEBUG_FAT, "check_bzredirect: new redir %s", finalredir));
handle_redirect(request, finalredir, absolute);
return 1;
}
@@ -1297,7 +1322,6 @@ fix_url_percent(bozo_httpreq_t *request)
* transform_request does this:
* - ``expand'' %20 crapola
* - punt if it doesn't start with /
- * - check httpd->untrustedref / referrer
* - look for "http://myname/" and deal with it.
* - maybe call bozo_process_cgi()
* - check for ~user and call bozo_user_transform() if so
@@ -1315,7 +1339,6 @@ transform_request(bozo_httpreq_t *reques
bozohttpd_t *httpd = request->hr_httpd;
char *file, *newfile = NULL;
size_t len;
- const char *hostname = BOZOHOST(httpd, request);
file = NULL;
*isindex = 0;
@@ -1333,84 +1356,49 @@ transform_request(bozo_httpreq_t *reques
goto bad_done;
}
- switch(check_bzredirect(request)) {
- case -1:
- goto bad_done;
- case 1:
- return 0;
- }
+ /* omit additional slashes at the beginning */
+ while (file[1] == '/')
+ file++;
- if (httpd->untrustedref) {
- int to_indexhtml = 0;
-
-#define TOP_PAGE(x) (strcmp((x), "/") == 0 || \
- strcmp((x) + 1, httpd->index_html) == 0 || \
- strcmp((x) + 1, "favicon.ico") == 0)
-
- debug((httpd, DEBUG_EXPLODING, "checking httpd->untrustedref"));
- /*
- * first check that this path isn't allowed via .bzdirect file,
- * and then check referrer; make sure that people come via the
- * real name... otherwise if we aren't looking at / or
- * /index.html, redirect... we also special case favicon.ico.
- */
- if (check_direct_access(request))
- /* nothing */;
- else if (request->hr_referrer) {
- const char *r = request->hr_referrer;
-
- debug((httpd, DEBUG_FAT,
- "checking referrer \"%s\" vs virthostname %s",
- r, hostname));
- if (strncmp(r, "http://", 7) != 0 ||
- (strncasecmp(r + 7, hostname,
- strlen(hostname)) != 0 &&
- !TOP_PAGE(file)))
- to_indexhtml = 1;
- } else {
- const char *h = request->hr_host;
-
- debug((httpd, DEBUG_FAT, "url has no referrer at all"));
- /* if there's no referrer, let / or /index.html past */
- if (!TOP_PAGE(file) ||
- (h && strncasecmp(h, hostname,
- strlen(hostname)) != 0))
- to_indexhtml = 1;
- }
-
- if (to_indexhtml) {
- char *slashindexhtml;
-
- if (asprintf(&slashindexhtml, "/%s",
- httpd->index_html) < 0)
- bozo_err(httpd, 1, "asprintf");
- debug((httpd, DEBUG_FAT,
- "httpd->untrustedref: redirecting %s to %s",
- file, slashindexhtml));
- handle_redirect(request, slashindexhtml, 0);
- free(slashindexhtml);
- return 0;
- }
- }
+ /* fix file provided by user as it's used in other handlers */
+ request->hr_file = file;
len = strlen(file);
- if (/*CONSTCOND*/0) {
+
#ifndef NO_USER_SUPPORT
- } else if (len > 1 && httpd->enable_users && file[1] == '~') {
+ /* first of all expand user path */
+ if (len > 1 && httpd->enable_users && file[1] == '~') {
if (file[2] == '\0') {
(void)bozo_http_error(httpd, 404, request,
"missing username");
goto bad_done;
}
if (strchr(file + 2, '/') == NULL) {
- handle_redirect(request, NULL, 0);
+ char *userredirecturl;
+ bozoasprintf(httpd, &userredirecturl, "%s/", file);
+ handle_redirect(request, userredirecturl, 0);
+ free(userredirecturl);
return 0;
}
debug((httpd, DEBUG_FAT, "calling bozo_user_transform"));
- return bozo_user_transform(request, isindex);
+ if (!bozo_user_transform(request))
+ return 0;
+
+ file = request->hr_file;
+ len = strlen(file);
+ }
#endif /* NO_USER_SUPPORT */
- } else if (len > 1) {
+
+
+ switch (check_bzredirect(request)) {
+ case -1:
+ goto bad_done;
+ case 1:
+ return 0;
+ }
+
+ if (len > 1) {
debug((httpd, DEBUG_FAT, "file[len-1] == %c", file[len-1]));
if (file[len-1] == '/') { /* append index.html */
*isindex = 1;
@@ -1420,10 +1408,10 @@ transform_request(bozo_httpreq_t *reques
strcpy(newfile, file + 1);
strcat(newfile, httpd->index_html);
} else
- newfile = bozostrdup(request->hr_httpd, file + 1);
+ newfile = bozostrdup(httpd, request, file + 1);
} else if (len == 1) {
debug((httpd, DEBUG_EXPLODING, "tf_req: len == 1"));
- newfile = bozostrdup(request->hr_httpd, httpd->index_html);
+ newfile = bozostrdup(httpd, request, httpd->index_html);
*isindex = 1;
} else { /* len == 0 ? */
(void)bozo_http_error(httpd, 500, request,
@@ -1437,15 +1425,14 @@ transform_request(bozo_httpreq_t *reques
}
/*
- * look for "http://myname/" and deal with it as necessary.
- */
-
- /*
* stop traversing outside our domain
*
* XXX true security only comes from our parent using chroot(2)
* before execve(2)'ing us. or our own built in chroot(2) support.
*/
+
+ debug((httpd, DEBUG_FAT, "newfile: %s", newfile));
+
if (*newfile == '/' || strcmp(newfile, "..") == 0 ||
strstr(newfile, "/..") || strstr(newfile, "../")) {
(void)bozo_http_error(httpd, 403, request, "illegal request");
@@ -1549,7 +1536,7 @@ bozo_process_request(bozo_httpreq_t *req
fd = -1;
encoding = NULL;
if (can_gzip(request)) {
- asprintf(&file, "%s.gz", request->hr_file);
+ bozoasprintf(httpd, &file, "%s.gz", request->hr_file);
fd = open(file, O_RDONLY);
if (fd >= 0)
encoding = "gzip";
@@ -1563,7 +1550,7 @@ bozo_process_request(bozo_httpreq_t *req
if (fd < 0) {
debug((httpd, DEBUG_FAT, "open failed: %s", strerror(errno)));
- switch(errno) {
+ switch (errno) {
case EPERM:
case EACCES:
(void)bozo_http_error(httpd, 403, request,
@@ -1642,9 +1629,6 @@ bozo_process_request(bozo_httpreq_t *req
while (szleft) {
size_t sz;
- /* This should take care of the first unaligned chunk */
- if ((cur_byte_pos & (httpd->page_size - 1)) != 0)
- sz = (size_t)(cur_byte_pos & ~httpd->page_size);
if ((off_t)httpd->mmapsz < szleft)
sz = httpd->mmapsz;
else
@@ -1726,7 +1710,7 @@ bozo_print_header(bozo_httpreq_t *reques
len = sbp->st_size;
bozo_printf(httpd, "Content-Length: %qd\r\n", (long long)len);
}
- if (request && request->hr_proto == httpd->consts.http_11)
+ if (request->hr_proto == httpd->consts.http_11)
bozo_printf(httpd, "Connection: close\r\n");
bozo_flush(httpd, stdout);
}
@@ -1756,7 +1740,7 @@ debug__(bozohttpd_t *httpd, int level, c
/* these are like warn() and err(), except for syslog not stderr */
void
-bozo_warn(bozohttpd_t *httpd, const char *fmt, ...)
+bozowarn(bozohttpd_t *httpd, const char *fmt, ...)
{
va_list ap;
@@ -1771,7 +1755,7 @@ bozo_warn(bozohttpd_t *httpd, const char
}
void
-bozo_err(bozohttpd_t *httpd, int code, const char *fmt, ...)
+bozoerr(bozohttpd_t *httpd, int code, const char *fmt, ...)
{
va_list ap;
@@ -1786,6 +1770,20 @@ bozo_err(bozohttpd_t *httpd, int code, c
exit(code);
}
+void
+bozoasprintf(bozohttpd_t *httpd, char **str, const char *fmt, ...)
+{
+ va_list ap;
+ int e;
+
+ va_start(ap, fmt);
+ e = vasprintf(str, fmt, ap);
+ va_end(ap);
+
+ if (e < 0)
+ bozoerr(httpd, EXIT_FAILURE, "asprintf");
+}
+
/*
* this escapes HTML tags. returns allocated escaped
* string if needed, or NULL on allocation failure or
@@ -1906,7 +1904,7 @@ bozo_http_error(bozohttpd_t *httpd, int
debug((httpd, DEBUG_FAT, "bozo_http_error %d: %s", code, msg));
if (header == NULL || reason == NULL) {
- bozo_err(httpd, 1,
+ bozoerr(httpd, 1,
"bozo_http_error() failed (short = %p, long = %p)",
header, reason);
return code;
@@ -1920,26 +1918,47 @@ bozo_http_error(bozohttpd_t *httpd, int
portbuf[0] = '\0';
if (request && request->hr_file) {
- char *file = NULL;
+ char *file = NULL, *user = NULL, *user_escaped = NULL;
+ int file_alloc = 0;
const char *hostname = BOZOHOST(httpd, request);
/* bozo_escape_html() failure here is just too bad. */
file = bozo_escape_html(NULL, request->hr_file);
- if (file == NULL)
+ if (file == NULL)
file = request->hr_file;
+ else
+ file_alloc = 1;
+
+#ifndef NO_USER_SUPPORT
+ if (request->hr_user != NULL) {
+ user_escaped = bozo_escape_html(NULL, request->hr_user);
+ if (user_escaped == NULL)
+ user_escaped = request->hr_user;
+ /* expand username to ~user/ */
+ bozoasprintf(httpd, &user, "~%s/", user_escaped);
+ if (user_escaped != request->hr_user)
+ free(user_escaped);
+ }
+#endif /* !NO_USER_SUPPORT */
+
size = snprintf(httpd->errorbuf, BUFSIZ,
"<html><head><title>%s</title></head>\n"
"<body><h1>%s</h1>\n"
- "%s: <pre>%s</pre>\n"
+ "%s%s: <pre>%s</pre>\n"
"<hr><address><a href=\"http://%s%s/\">%s%s</a></address>\n"
"</body></html>\n",
- header, header, file, reason,
- hostname, portbuf, hostname, portbuf);
+ header, header,
+ user ? user : "", file,
+ reason, hostname, portbuf, hostname, portbuf);
+ free(user);
if (size >= (int)BUFSIZ) {
- bozo_warn(httpd,
+ bozowarn(httpd,
"bozo_http_error buffer too small, truncated");
size = (int)BUFSIZ;
}
+
+ if (file_alloc)
+ free(file);
} else
size = 0;
@@ -2078,12 +2097,11 @@ bozorealloc(bozohttpd_t *httpd, void *pt
void *p;
p = realloc(ptr, size);
- if (p == NULL) {
- (void)bozo_http_error(httpd, 500, NULL,
- "memory allocation failure");
- exit(1);
- }
- return (p);
+ if (p)
+ return p;
+
+ (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure");
+ exit(EXIT_FAILURE);
}
void *
@@ -2092,26 +2110,27 @@ bozomalloc(bozohttpd_t *httpd, size_t si
void *p;
p = malloc(size);
- if (p == NULL) {
- (void)bozo_http_error(httpd, 500, NULL,
- "memory allocation failure");
- exit(1);
- }
- return (p);
+ if (p)
+ return p;
+
+ (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure");
+ exit(EXIT_FAILURE);
}
char *
-bozostrdup(bozohttpd_t *httpd, const char *str)
+bozostrdup(bozohttpd_t *httpd, bozo_httpreq_t *request, const char *str)
{
char *p;
p = strdup(str);
- if (p == NULL) {
- (void)bozo_http_error(httpd, 500, NULL,
- "memory allocation failure");
- exit(1);
- }
- return (p);
+ if (p)
+ return p;
+
+ if (!request)
+ bozoerr(httpd, EXIT_FAILURE, "strdup");
+
+ (void)bozo_http_error(httpd, 500, request, "memory allocation failure");
+ exit(EXIT_FAILURE);
}
/* set default values in bozohttpd_t struct */
@@ -2144,15 +2163,16 @@ bozo_init_httpd(bozohttpd_t *httpd)
/* set default values in bozoprefs_t struct */
int
-bozo_init_prefs(bozoprefs_t *prefs)
+bozo_init_prefs(bozohttpd_t *httpd, bozoprefs_t *prefs)
{
/* make sure everything is clean */
(void) memset(prefs, 0x0, sizeof(*prefs));
/* set up default values */
- bozo_set_pref(prefs, "server software", SERVER_SOFTWARE);
- bozo_set_pref(prefs, "index.html", INDEX_HTML);
- bozo_set_pref(prefs, "public_html", PUBLIC_HTML);
+ if (!bozo_set_pref(httpd, prefs, "server software", SERVER_SOFTWARE) ||
+ !bozo_set_pref(httpd, prefs, "index.html", INDEX_HTML) ||
+ !bozo_set_pref(httpd, prefs, "public_html", PUBLIC_HTML))
+ return 0;
return 1;
}
@@ -2161,7 +2181,7 @@ bozo_init_prefs(bozoprefs_t *prefs)
int
bozo_set_defaults(bozohttpd_t *httpd, bozoprefs_t *prefs)
{
- return bozo_init_httpd(httpd) && bozo_init_prefs(prefs);
+ return bozo_init_httpd(httpd) && bozo_init_prefs(httpd, prefs);
}
/* set the virtual host name, port and root */
@@ -2183,16 +2203,15 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs
if (vhost == NULL) {
httpd->virthostname = bozomalloc(httpd, MAXHOSTNAMELEN+1);
- /* XXX we do not check for FQDN here */
if (gethostname(httpd->virthostname, MAXHOSTNAMELEN+1) < 0)
- bozo_err(httpd, 1, "gethostname");
+ bozoerr(httpd, 1, "gethostname");
httpd->virthostname[MAXHOSTNAMELEN] = '\0';
} else {
- httpd->virthostname = strdup(vhost);
+ httpd->virthostname = bozostrdup(httpd, NULL, vhost);
}
- httpd->slashdir = strdup(root);
+ httpd->slashdir = bozostrdup(httpd, NULL, root);
if ((portnum = bozo_get_pref(prefs, "port number")) != NULL) {
- httpd->bindport = strdup(portnum);
+ httpd->bindport = bozostrdup(httpd, NULL, portnum);
}
/* go over preferences now */
@@ -2200,16 +2219,12 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs
strcmp(cp, "true") == 0) {
httpd->numeric = 1;
}
- if ((cp = bozo_get_pref(prefs, "trusted referal")) != NULL &&
- strcmp(cp, "true") == 0) {
- httpd->untrustedref = 1;
- }
if ((cp = bozo_get_pref(prefs, "log to stderr")) != NULL &&
strcmp(cp, "true") == 0) {
httpd->logstderr = 1;
}
if ((cp = bozo_get_pref(prefs, "bind address")) != NULL) {
- httpd->bindaddress = strdup(cp);
+ httpd->bindaddress = bozostrdup(httpd, NULL, cp);
}
if ((cp = bozo_get_pref(prefs, "background")) != NULL) {
httpd->background = atoi(cp);
@@ -2219,19 +2234,23 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs
httpd->foreground = 1;
}
if ((cp = bozo_get_pref(prefs, "pid file")) != NULL) {
- httpd->pidfile = strdup(cp);
+ httpd->pidfile = bozostrdup(httpd, NULL, cp);
}
if ((cp = bozo_get_pref(prefs, "unknown slash")) != NULL &&
strcmp(cp, "true") == 0) {
httpd->unknown_slash = 1;
}
if ((cp = bozo_get_pref(prefs, "virtual base")) != NULL) {
- httpd->virtbase = strdup(cp);
+ httpd->virtbase = bozostrdup(httpd, NULL, cp);
}
if ((cp = bozo_get_pref(prefs, "enable users")) != NULL &&
strcmp(cp, "true") == 0) {
httpd->enable_users = 1;
}
+ if ((cp = bozo_get_pref(prefs, "enable user cgibin")) != NULL &&
+ strcmp(cp, "true") == 0) {
+ httpd->enable_cgi_users = 1;
+ }
if ((cp = bozo_get_pref(prefs, "dirty environment")) != NULL &&
strcmp(cp, "true") == 0) {
dirtyenv = 1;
@@ -2245,11 +2264,12 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs
httpd->dir_indexing = 1;
}
if ((cp = bozo_get_pref(prefs, "public_html")) != NULL) {
- httpd->public_html = strdup(cp);
+ httpd->public_html = bozostrdup(httpd, NULL, cp);
}
httpd->server_software =
- strdup(bozo_get_pref(prefs, "server software"));
- httpd->index_html = strdup(bozo_get_pref(prefs, "index.html"));
+ bozostrdup(httpd, NULL, bozo_get_pref(prefs, "server software"));
+ httpd->index_html =
+ bozostrdup(httpd, NULL, bozo_get_pref(prefs, "index.html"));
/*
* initialise ssl and daemon mode if necessary.
@@ -2257,39 +2277,33 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs
bozo_ssl_init(httpd);
bozo_daemon_init(httpd);
- if ((username = bozo_get_pref(prefs, "username")) == NULL) {
- if ((pw = getpwuid(uid = 0)) == NULL)
- bozo_err(httpd, 1, "getpwuid(0): %s", strerror(errno));
- httpd->username = strdup(pw->pw_name);
- } else {
- httpd->username = strdup(username);
- if ((pw = getpwnam(httpd->username)) == NULL)
- bozo_err(httpd, 1, "getpwnam(%s): %s", httpd->username,
- strerror(errno));
+ username = bozo_get_pref(prefs, "username");
+ if (username != NULL) {
+ if ((pw = getpwnam(username)) == NULL)
+ bozoerr(httpd, 1, "getpwnam(%s): %s", username,
+ strerror(errno));
if (initgroups(pw->pw_name, pw->pw_gid) == -1)
- bozo_err(httpd, 1, "initgroups: %s", strerror(errno));
+ bozoerr(httpd, 1, "initgroups: %s", strerror(errno));
if (setgid(pw->pw_gid) == -1)
- bozo_err(httpd, 1, "setgid(%u): %s", pw->pw_gid,
- strerror(errno));
+ bozoerr(httpd, 1, "setgid(%u): %s", pw->pw_gid,
+ strerror(errno));
uid = pw->pw_uid;
}
/*
* handle chroot.
*/
if ((chrootdir = bozo_get_pref(prefs, "chroot dir")) != NULL) {
- httpd->rootdir = strdup(chrootdir);
+ httpd->rootdir = bozostrdup(httpd, NULL, chrootdir);
if (chdir(httpd->rootdir) == -1)
- bozo_err(httpd, 1, "chdir(%s): %s", httpd->rootdir,
+ bozoerr(httpd, 1, "chdir(%s): %s", httpd->rootdir,
strerror(errno));
if (chroot(httpd->rootdir) == -1)
- bozo_err(httpd, 1, "chroot(%s): %s", httpd->rootdir,
+ bozoerr(httpd, 1, "chroot(%s): %s", httpd->rootdir,
strerror(errno));
}
- if (username != NULL)
- if (setuid(uid) == -1)
- bozo_err(httpd, 1, "setuid(%d): %s", uid,
- strerror(errno));
+ if (username != NULL && setuid(uid) == -1)
+ bozoerr(httpd, 1, "setuid(%d): %s", uid, strerror(errno));
/*
* prevent info leakage between different compartments.
Index: src/libexec/httpd/bozohttpd.h
diff -u src/libexec/httpd/bozohttpd.h:1.33.2.2 src/libexec/httpd/bozohttpd.h:1.33.2.3
--- src/libexec/httpd/bozohttpd.h:1.33.2.2 Sat May 9 08:50:42 2015
+++ src/libexec/httpd/bozohttpd.h Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: bozohttpd.h,v 1.33.2.2 2015/05/09 08:50:42 snj Exp $ */
+/* $NetBSD: bozohttpd.h,v 1.33.2.3 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */
@@ -41,6 +41,11 @@
#endif
#include <stdio.h>
+/* QNX provides a lot of NetBSD things in nbutil.h */
+#ifdef HAVE_NBUTIL_H
+#include <nbutil.h>
+#endif
+
/* lots of "const" but gets free()'ed etc at times, sigh */
/* headers */
@@ -85,11 +90,9 @@ typedef struct bozo_consts_t {
/* this structure encapsulates all the bozo flags and control vars */
typedef struct bozohttpd_t {
char *rootdir; /* root directory */
- char *username; /* username to switch to */
int numeric; /* avoid gethostby*() */
char *virtbase; /* virtual directory base */
int unknown_slash; /* unknown vhosts go to normal slashdir */
- int untrustedref; /* make sure referrer = me unless url = / */
int logstderr; /* log to stderr (even if not tty) */
int background; /* drop into daemon mode */
int foreground; /* keep daemon mode in foreground */
@@ -104,6 +107,7 @@ typedef struct bozohttpd_t {
const char *index_html; /* our home page */
const char *public_html; /* ~user/public_html page */
int enable_users; /* enable public_html */
+ int enable_cgi_users; /* use the cgi handler */
int *sock; /* bound sockets */
int nsock; /* number of above */
struct pollfd *fds; /* current poll fd set */
@@ -146,6 +150,9 @@ typedef struct bozo_httpreq_t {
char *hr_query;
char *hr_host; /* HTTP/1.1 Host: or virtual hostname,
possibly including a port number */
+#ifndef NO_USER_SUPPORT
+ char *hr_user; /* username if we hit userdir request */
+#endif /* !NO_USER_SUPPORT */
const char *hr_proto;
const char *hr_content_type;
const char *hr_content_length;
@@ -176,8 +183,8 @@ typedef struct bozo_httpreq_t {
/* structure to hold string based (name, value) pairs with preferences */
typedef struct bozoprefs_t {
- unsigned size; /* size of the two arrays */
- unsigned c; /* # of entries in arrays */
+ size_t size; /* size of the two arrays */
+ size_t count; /* # of entries in arrays */
char **name; /* names of each entry */
char **value; /* values for the name entries */
} bozoprefs_t;
@@ -210,34 +217,42 @@ void debug__(bozohttpd_t *, int, const c
#define debug(x)
#endif /* NO_DEBUG */
-void bozo_warn(bozohttpd_t *, const char *, ...)
- BOZO_PRINTFLIKE(2, 3);
-void bozo_err(bozohttpd_t *, int, const char *, ...)
- BOZO_PRINTFLIKE(3, 4)
- BOZO_DEAD;
int bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *);
int bozo_check_special_files(bozo_httpreq_t *, const char *);
char *bozo_http_date(char *, size_t);
-void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, const char *);
-char *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url);
+void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *,
+ const char *);
+char *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute);
char *bozo_escape_html(bozohttpd_t *httpd, const char *url);
-char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *, int, void *, size_t));
+/* these are similar to libc functions, no underscore here */
+void bozowarn(bozohttpd_t *, const char *, ...)
+ BOZO_PRINTFLIKE(2, 3);
+void bozoerr(bozohttpd_t *, int, const char *, ...)
+ BOZO_PRINTFLIKE(3, 4)
+ BOZO_DEAD;
+void bozoasprintf(bozohttpd_t *, char **, const char *, ...)
+ BOZO_PRINTFLIKE(3, 4);
+char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *,
+ int, void *, size_t));
char *bozostrnsep(char **, const char *, ssize_t *);
-
void *bozomalloc(bozohttpd_t *, size_t);
void *bozorealloc(bozohttpd_t *, void *, size_t);
-char *bozostrdup(bozohttpd_t *, const char *);
+char *bozostrdup(bozohttpd_t *, bozo_httpreq_t *, const char *);
+
+#define bozo_noop do { /* nothing */ } while (/*CONSTCOND*/0)
/* ssl-bozo.c */
#ifdef NO_SSL_SUPPORT
-#define bozo_ssl_set_opts(w, x, y) do { /* nothing */ } while (0)
-#define bozo_ssl_init(x) do { /* nothing */ } while (0)
+#define bozo_ssl_set_opts(w, x, y) bozo_noop
+#define bozo_ssl_set_ciphers(w, x, y) bozo_noop
+#define bozo_ssl_init(x) bozo_noop
#define bozo_ssl_accept(x) (0)
-#define bozo_ssl_destroy(x) do { /* nothing */ } while (0)
+#define bozo_ssl_destroy(x) bozo_noop
#else
void bozo_ssl_set_opts(bozohttpd_t *, const char *, const char *);
+void bozo_ssl_set_ciphers(bozohttpd_t *, const char *);
void bozo_ssl_init(bozohttpd_t *);
int bozo_ssl_accept(bozohttpd_t *);
void bozo_ssl_destroy(bozohttpd_t *);
@@ -255,13 +270,13 @@ void bozo_auth_check_401(bozo_httpreq_t
void bozo_auth_cgi_setenv(bozo_httpreq_t *, char ***);
int bozo_auth_cgi_count(bozo_httpreq_t *);
#else
-#define bozo_auth_init(x) do { /* nothing */ } while (0)
+#define bozo_auth_init(x) bozo_noop
#define bozo_auth_check(x, y) 0
-#define bozo_auth_cleanup(x) do { /* nothing */ } while (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) do { /* nothing */ } while (0)
-#define bozo_auth_cgi_setenv(x, y) do { /* nothing */ } while (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
#endif /* DO_HTPASSWD */
@@ -288,9 +303,9 @@ int bozo_process_lua(bozo_httpreq_t *);
/* daemon-bozo.c */
#ifdef NO_DAEMON_MODE
-#define bozo_daemon_init(x) do { /* nothing */ } while (0)
+#define bozo_daemon_init(x) bozo_noop
#define bozo_daemon_fork(x) 0
-#define bozo_daemon_closefds(x) do { /* nothing */ } while (0)
+#define bozo_daemon_closefds(x) bozo_noop
#else
void bozo_daemon_init(bozohttpd_t *);
int bozo_daemon_fork(bozohttpd_t *);
@@ -300,9 +315,11 @@ void bozo_daemon_closefds(bozohttpd_t *)
/* tilde-luzah-bozo.c */
#ifdef NO_USER_SUPPORT
-#define bozo_user_transform(a, c) 0
+#define bozo_user_transform(x) 0
+#define bozo_user_free(x) 0
#else
-int bozo_user_transform(bozo_httpreq_t *, int *);
+int bozo_user_transform(bozo_httpreq_t *);
+#define bozo_user_free(x) free(x)
#endif /* NO_USER_SUPPORT */
@@ -320,7 +337,8 @@ const char *bozo_content_encoding(bozo_h
bozo_content_map_t *bozo_match_content_map(bozohttpd_t *, const char *, int);
bozo_content_map_t *bozo_get_content_map(bozohttpd_t *, const char *);
#ifndef NO_DYNAMIC_CONTENT
-void bozo_add_content_map_mime(bozohttpd_t *, const char *, const char *, const char *, const char *);
+void bozo_add_content_map_mime(bozohttpd_t *, const char *, const char *,
+ const char *, const char *);
#endif
/* I/O */
@@ -331,7 +349,7 @@ int bozo_flush(bozohttpd_t *, FILE *);
/* misc */
int bozo_init_httpd(bozohttpd_t *);
-int bozo_init_prefs(bozoprefs_t *);
+int bozo_init_prefs(bozohttpd_t *, bozoprefs_t *);
int bozo_set_defaults(bozohttpd_t *, bozoprefs_t *);
int bozo_setup(bozohttpd_t *, bozoprefs_t *, const char *, const char *);
bozo_httpreq_t *bozo_read_request(bozohttpd_t *);
@@ -339,7 +357,7 @@ void bozo_process_request(bozo_httpreq_t
void bozo_clean_request(bozo_httpreq_t *);
/* variables */
-int bozo_set_pref(bozoprefs_t *, const char *, const char *);
+int bozo_set_pref(bozohttpd_t *, bozoprefs_t *, const char *, const char *);
char *bozo_get_pref(bozoprefs_t *, const char *);
#endif /* BOZOHTTOPD_H_ */
Index: src/libexec/httpd/cgi-bozo.c
diff -u src/libexec/httpd/cgi-bozo.c:1.25.2.2 src/libexec/httpd/cgi-bozo.c:1.25.2.3
--- src/libexec/httpd/cgi-bozo.c:1.25.2.2 Sat May 9 08:50:42 2015
+++ src/libexec/httpd/cgi-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: cgi-bozo.c,v 1.25.2.2 2015/05/09 08:50:42 snj Exp $ */
+/* $NetBSD: cgi-bozo.c,v 1.25.2.3 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */
@@ -75,22 +75,23 @@ content_cgihandler(bozohttpd_t *httpd, b
}
static int
-parse_header(bozohttpd_t *httpd, const char *str, ssize_t len, char **hdr_str,
- char **hdr_val)
+parse_header(bozo_httpreq_t *request, const char *str, ssize_t len,
+ char **hdr_str, char **hdr_val)
{
+ struct bozohttpd_t *httpd = request->hr_httpd;
char *name, *value;
/* if the string passed is zero-length bail out */
if (*str == '\0')
return -1;
- value = bozostrdup(httpd, str);
+ value = bozostrdup(httpd, request, str);
/* locate the ':' separator in the header/value */
name = bozostrnsep(&value, ":", &len);
if (NULL == name || -1 == len) {
- free(name);
+ free(value);
return -1;
}
@@ -127,7 +128,7 @@ finish_cgi_output(bozohttpd_t *httpd, bo
(str = bozodgetln(httpd, in, &len, bozo_read)) != NULL) {
char *hdr_name, *hdr_value;
- if (parse_header(httpd, str, len, &hdr_name, &hdr_value))
+ if (parse_header(request, str, len, &hdr_name, &hdr_value))
break;
/*
@@ -194,7 +195,7 @@ finish_cgi_output(bozohttpd_t *httpd, bo
rbytes -= wbytes;
bp += wbytes;
} else
- bozo_err(httpd, 1,
+ bozoerr(httpd, 1,
"cgi output write failed: %s",
strerror(errno));
}
@@ -214,7 +215,7 @@ append_index_html(bozohttpd_t *httpd, ch
void
bozo_cgi_setbin(bozohttpd_t *httpd, const char *path)
{
- httpd->cgibin = strdup(path);
+ httpd->cgibin = bozostrdup(httpd, NULL, path);
debug((httpd, DEBUG_OBESE, "cgibin (cgi-bin directory) is %s",
httpd->cgibin));
}
@@ -247,8 +248,7 @@ bozo_process_cgi(bozo_httpreq_t *request
char date[40];
bozoheaders_t *headp;
const char *type, *clen, *info, *cgihandler;
- char *query, *s, *t, *path, *env, *file, *url;
- char command[MAXPATHLEN];
+ char *query, *s, *t, *path, *env, *command, *file, *url;
char **envp, **curenvp, *argv[4];
char *uri;
size_t len;
@@ -260,31 +260,36 @@ bozo_process_cgi(bozo_httpreq_t *request
if (!httpd->cgibin && !httpd->process_cgi)
return 0;
+#ifndef NO_USER_SUPPORT
+ if (request->hr_user && !httpd->enable_cgi_users)
+ return 0;
+#endif /* !NO_USER_SUPPORT */
+
if (request->hr_oldfile && strcmp(request->hr_oldfile, "/") != 0)
uri = request->hr_oldfile;
else
uri = request->hr_file;
if (uri[0] == '/')
- file = bozostrdup(httpd, uri);
+ file = bozostrdup(httpd, request, uri);
else
- asprintf(&file, "/%s", uri);
- if (file == NULL)
- return 0;
+ bozoasprintf(httpd, &file, "/%s", uri);
if (request->hr_query && strlen(request->hr_query))
- query = bozostrdup(httpd, request->hr_query);
+ query = bozostrdup(httpd, request, request->hr_query);
else
query = NULL;
- asprintf(&url, "%s%s%s", file, query ? "?" : "", query ? query : "");
- if (url == NULL)
- goto out;
+ bozoasprintf(httpd, &url, "%s%s%s",
+ file,
+ query ? "?" : "",
+ query ? query : "");
debug((httpd, DEBUG_NORMAL, "bozo_process_cgi: url `%s'", url));
path = NULL;
envp = NULL;
cgihandler = NULL;
+ command = NULL;
info = NULL;
len = strlen(url);
@@ -309,15 +314,14 @@ bozo_process_cgi(bozo_httpreq_t *request
ix = 0;
if (cgihandler) {
- snprintf(command, sizeof(command), "%s", file + 1);
- path = bozostrdup(httpd, cgihandler);
+ command = file + 1;
+ path = bozostrdup(httpd, request, cgihandler);
argv[ix++] = path;
/* argv[] = [ path, command, query, NULL ] */
} else {
- snprintf(command, sizeof(command), "%s",
- file + CGIBIN_PREFIX_LEN + 1);
+ command = file + CGIBIN_PREFIX_LEN + 1;
if ((s = strchr(command, '/')) != NULL) {
- info = bozostrdup(httpd, s);
+ info = bozostrdup(httpd, request, s);
*s = '\0';
}
path = bozomalloc(httpd,
@@ -414,21 +418,18 @@ bozo_process_cgi(bozo_httpreq_t *request
bozo_setenv(httpd, "REMOTE_ADDR", request->hr_remoteaddr,
curenvp++);
/*
- * XXX Apache does this when invoking content handlers, and PHP
- * XXX 5.3 requires it as a "security" measure.
+ * Apache does this when invoking content handlers, and PHP
+ * 5.3 requires it as a "security" measure.
*/
if (cgihandler)
bozo_setenv(httpd, "REDIRECT_STATUS", "200", curenvp++);
bozo_auth_cgi_setenv(request, &curenvp);
- free(file);
- free(url);
-
debug((httpd, DEBUG_FAT, "bozo_process_cgi: going exec %s, %s %s %s",
path, argv[0], strornull(argv[1]), strornull(argv[2])));
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1)
- bozo_err(httpd, 1, "child socketpair failed: %s",
+ bozoerr(httpd, 1, "child socketpair failed: %s",
strerror(errno));
/*
@@ -439,7 +440,7 @@ bozo_process_cgi(bozo_httpreq_t *request
*/
switch (fork()) {
case -1: /* eep, failure */
- bozo_err(httpd, 1, "child fork failed: %s", strerror(errno));
+ bozoerr(httpd, 1, "child fork failed: %s", strerror(errno));
/*NOTREACHED*/
case 0:
close(sv[0]);
@@ -451,19 +452,23 @@ bozo_process_cgi(bozo_httpreq_t *request
bozo_daemon_closefds(httpd);
if (-1 == execve(path, argv, envp))
- bozo_err(httpd, 1, "child exec failed: %s: %s",
+ bozoerr(httpd, 1, "child exec failed: %s: %s",
path, strerror(errno));
/* NOT REACHED */
- bozo_err(httpd, 1, "child execve returned?!");
+ bozoerr(httpd, 1, "child execve returned?!");
}
+ free(query);
+ free(file);
+ free(url);
+
close(sv[1]);
/* parent: read from stdin (bozo_read()) write to sv[0] */
/* child: read from sv[0] (bozo_write()) write to stdout */
pid = fork();
if (pid == -1)
- bozo_err(httpd, 1, "io child fork failed: %s", strerror(errno));
+ bozoerr(httpd, 1, "io child fork failed: %s", strerror(errno));
else if (pid == 0) {
/* child reader/writer */
close(STDIN_FILENO);
@@ -487,7 +492,7 @@ bozo_process_cgi(bozo_httpreq_t *request
rbytes -= wbytes;
bp += wbytes;
} else
- bozo_err(httpd, 1, "write failed: %s",
+ bozoerr(httpd, 1, "write failed: %s",
strerror(errno));
}
}
@@ -504,7 +509,8 @@ bozo_process_cgi(bozo_httpreq_t *request
#ifndef NO_DYNAMIC_CONTENT
/* cgi maps are simple ".postfix /path/to/prog" */
void
-bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg, const char *cgihandler)
+bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg,
+ const char *cgihandler)
{
bozo_content_map_t *map;
Index: src/libexec/httpd/content-bozo.c
diff -u src/libexec/httpd/content-bozo.c:1.10.2.2 src/libexec/httpd/content-bozo.c:1.10.2.3
--- src/libexec/httpd/content-bozo.c:1.10.2.2 Sat May 9 08:50:42 2015
+++ src/libexec/httpd/content-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: content-bozo.c,v 1.10.2.2 2015/05/09 08:50:42 snj Exp $ */
+/* $NetBSD: content-bozo.c,v 1.10.2.3 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: content-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */
@@ -258,7 +258,7 @@ bozo_get_content_map(bozohttpd_t *httpd,
httpd->dynamic_content_map,
(httpd->dynamic_content_map_size + 1) * sizeof *map);
if (httpd->dynamic_content_map == NULL)
- bozo_err(httpd, 1, "out of memory allocating content map");
+ bozoerr(httpd, 1, "out of memory allocating content map");
map = &httpd->dynamic_content_map[httpd->dynamic_content_map_size];
map->name = map->type = map->encoding = map->encoding11 =
map->cgihandler = NULL;
Index: src/libexec/httpd/daemon-bozo.c
diff -u src/libexec/httpd/daemon-bozo.c:1.16 src/libexec/httpd/daemon-bozo.c:1.16.4.1
--- src/libexec/httpd/daemon-bozo.c:1.16 Thu Jan 2 08:21:38 2014
+++ src/libexec/httpd/daemon-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: daemon-bozo.c,v 1.16 2014/01/02 08:21:38 mrg Exp $ */
+/* $NetBSD: daemon-bozo.c,v 1.16.4.1 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $ */
@@ -105,10 +105,10 @@ create_pidfile(bozohttpd_t *httpd)
return;
if (atexit(remove_pidfile) == -1)
- bozo_err(httpd, 1, "Failed to install pidfile handler");
+ bozoerr(httpd, 1, "Failed to install pidfile handler");
if ((file = fopen(httpd->pidfile, "w")) == NULL)
- bozo_err(httpd, 1, "Failed to create pidfile '%s'",
+ bozoerr(httpd, 1, "Failed to create pidfile '%s'",
httpd->pidfile);
(void)fprintf(file, "%d\n", getpid());
(void)fclose(file);
@@ -138,7 +138,7 @@ bozo_daemon_init(bozohttpd_t *httpd)
h.ai_flags = AI_PASSIVE;
e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0);
if (e)
- bozo_err(httpd, 1, "getaddrinfo([%s]:%s): %s",
+ bozoerr(httpd, 1, "getaddrinfo([%s]:%s): %s",
httpd->bindaddress ? httpd->bindaddress : "*",
portnum, gai_strerror(e));
for (r = r0; r != NULL; r = r->ai_next)
@@ -151,7 +151,7 @@ bozo_daemon_init(bozohttpd_t *httpd)
continue;
if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) == -1)
- bozo_warn(httpd, "setsockopt SO_REUSEADDR: %s",
+ bozowarn(httpd, "setsockopt SO_REUSEADDR: %s",
strerror(errno));
if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1)
continue;
@@ -163,7 +163,7 @@ bozo_daemon_init(bozohttpd_t *httpd)
i++;
}
if (i == 0)
- bozo_err(httpd, 1, "could not find any addresses to bind");
+ bozoerr(httpd, 1, "could not find any addresses to bind");
httpd->nsock = i;
freeaddrinfo(r0);
@@ -172,7 +172,7 @@ bozo_daemon_init(bozohttpd_t *httpd)
create_pidfile(httpd);
- bozo_warn(httpd, "started in daemon mode as `%s' port `%s' root `%s'",
+ bozowarn(httpd, "started in daemon mode as `%s' port `%s' root `%s'",
httpd->virthostname, portnum, httpd->slashdir);
signal(SIGHUP, controlled_exit);
@@ -209,13 +209,13 @@ daemon_poll_err(bozohttpd_t *httpd, int
if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0)
return 0;
- bozo_warn(httpd, "poll on fd %d pid %d revents %d: %s",
+ bozowarn(httpd, "poll on fd %d pid %d revents %d: %s",
httpd->fds[idx].fd, getpid(), httpd->fds[idx].revents,
strerror(errno));
- bozo_warn(httpd, "nsock = %d", httpd->nsock);
+ bozowarn(httpd, "nsock = %d", httpd->nsock);
close(httpd->sock[idx]);
httpd->nsock--;
- bozo_warn(httpd, "nsock now = %d", httpd->nsock);
+ bozowarn(httpd, "nsock now = %d", httpd->nsock);
/* no sockets left */
if (httpd->nsock == 0)
exit(0);
@@ -271,7 +271,7 @@ again:
/* fail on programmer errors */
if (errno == EFAULT ||
errno == EINVAL)
- bozo_err(httpd, 1, "poll: %s",
+ bozoerr(httpd, 1, "poll: %s",
strerror(errno));
/* sleep on some temporary kernel failures */
@@ -294,7 +294,7 @@ again:
if (fd == -1) {
if (errno == EFAULT ||
errno == EINVAL)
- bozo_err(httpd, 1, "accept: %s",
+ bozoerr(httpd, 1, "accept: %s",
strerror(errno));
if (errno == ENOMEM ||
@@ -317,7 +317,7 @@ again:
switch (fork()) {
case -1: /* eep, failure */
- bozo_warn(httpd, "fork() failed, sleeping for "
+ bozowarn(httpd, "fork() failed, sleeping for "
"10 seconds: %s", strerror(errno));
close(fd);
sleep(10);
Index: src/libexec/httpd/dir-index-bozo.c
diff -u src/libexec/httpd/dir-index-bozo.c:1.19.4.1 src/libexec/httpd/dir-index-bozo.c:1.19.4.2
--- src/libexec/httpd/dir-index-bozo.c:1.19.4.1 Mon Jan 12 10:02:29 2015
+++ src/libexec/httpd/dir-index-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dir-index-bozo.c,v 1.19.4.1 2015/01/12 10:02:29 martin Exp $ */
+/* $NetBSD: dir-index-bozo.c,v 1.19.4.2 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: dir-index-bozo.c,v 1.20 2011/11/18 09:21:15 mrg Exp $ */
@@ -57,7 +57,7 @@ directory_hr(bozohttpd_t *httpd)
* output a directory index. return 1 if it actually did something..
*/
int
-bozo_dir_index(bozo_httpreq_t *request, const char *dirname, int isindex)
+bozo_dir_index(bozo_httpreq_t *request, const char *dirpath, int isindex)
{
bozohttpd_t *httpd = request->hr_httpd;
struct stat sb;
@@ -66,23 +66,23 @@ bozo_dir_index(bozo_httpreq_t *request,
DIR *dp;
char buf[MAXPATHLEN];
char spacebuf[48];
- char *file = NULL;
+ char *file = NULL, *printname = NULL;
int l, k, j, i;
if (!isindex || !httpd->dir_indexing)
return 0;
- if (strlen(dirname) <= strlen(httpd->index_html))
- dirname = ".";
+ if (strlen(dirpath) <= strlen(httpd->index_html))
+ dirpath = ".";
else {
- file = bozostrdup(httpd, dirname);
+ file = bozostrdup(httpd, request, dirpath);
file[strlen(file) - strlen(httpd->index_html)] = '\0';
- dirname = file;
+ dirpath = file;
}
- debug((httpd, DEBUG_FAT, "bozo_dir_index: dirname ``%s''", dirname));
- if (stat(dirname, &sb) < 0 ||
- (dp = opendir(dirname)) == NULL) {
+ debug((httpd, DEBUG_FAT, "bozo_dir_index: dirpath ``%s''", dirpath));
+ if (stat(dirpath, &sb) < 0 ||
+ (dp = opendir(dirpath)) == NULL) {
if (errno == EPERM)
(void)bozo_http_error(httpd, 403, request,
"no permission to open directory");
@@ -108,11 +108,21 @@ bozo_dir_index(bozo_httpreq_t *request,
goto done;
}
+#ifndef NO_USER_SUPPORT
+ if (request->hr_user) {
+ bozoasprintf(httpd, &printname, "~%s/%s",
+ request->hr_user, request->hr_file);
+ } else
+ printname = bozostrdup(httpd, request, request->hr_file);
+#else
+ printname = bozostrdup(httpd, request, request->hr_file);
+#endif /* !NO_USER_SUPPORT */
+
bozo_printf(httpd,
"<html><head><title>Index of %s</title></head>\r\n",
- request->hr_file);
+ printname);
bozo_printf(httpd, "<body><h1>Index of %s</h1>\r\n",
- request->hr_file);
+ printname);
bozo_printf(httpd, "<pre>\r\n");
#define NAMELEN 40
#define LMODLEN 19
@@ -123,7 +133,7 @@ bozo_dir_index(bozo_httpreq_t *request,
directory_hr(httpd);
bozo_printf(httpd, "<pre>");
- for (j = k = scandir(dirname, &de, NULL, alphasort), deo = de;
+ for (j = k = scandir(dirpath, &de, NULL, alphasort), deo = de;
j--; de++) {
int nostat = 0;
char *name = (*de)->d_name;
@@ -134,13 +144,13 @@ bozo_dir_index(bozo_httpreq_t *request,
httpd->hide_dots && name[0] == '.'))
continue;
- snprintf(buf, sizeof buf, "%s/%s", dirname, name);
+ snprintf(buf, sizeof buf, "%s/%s", dirpath, name);
if (stat(buf, &sb))
nostat = 1;
l = 0;
- urlname = bozo_escape_rfc3986(httpd, name);
+ urlname = bozo_escape_rfc3986(httpd, name, 0);
htmlname = bozo_escape_html(httpd, name);
if (htmlname == NULL)
htmlname = name;
@@ -206,6 +216,7 @@ bozo_dir_index(bozo_httpreq_t *request,
done:
free(file);
+ free(printname);
return 1;
}
#endif /* NO_DIRINDEX_SUPPORT */
Index: src/libexec/httpd/lua-bozo.c
diff -u src/libexec/httpd/lua-bozo.c:1.10.2.1 src/libexec/httpd/lua-bozo.c:1.10.2.2
--- src/libexec/httpd/lua-bozo.c:1.10.2.1 Mon Jan 12 10:02:29 2015
+++ src/libexec/httpd/lua-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: lua-bozo.c,v 1.10.2.1 2015/01/12 10:02:29 martin Exp $ */
+/* $NetBSD: lua-bozo.c,v 1.10.2.2 2016/04/10 10:33:11 martin Exp $ */
/*
* Copyright (c) 2013 Marc Balmer <[email protected]>
@@ -123,7 +123,7 @@ lua_register_handler(lua_State *L)
handler = bozomalloc(httpd, sizeof(lua_handler_t));
- handler->name = bozostrdup(httpd, lua_tostring(L, 1));
+ handler->name = bozostrdup(httpd, NULL, lua_tostring(L, 1));
handler->ref = luaL_ref(L, LUA_REGISTRYINDEX);
SIMPLEQ_INSERT_TAIL(&map->handlers, handler, h_next);
httpd->process_lua = 1;
@@ -184,19 +184,19 @@ bozo_add_lua_map(bozohttpd_t *httpd, con
lua_state_map_t *map;
map = bozomalloc(httpd, sizeof(lua_state_map_t));
- map->prefix = bozostrdup(httpd, prefix);
+ map->prefix = bozostrdup(httpd, NULL, prefix);
if (*script == '/')
- map->script = bozostrdup(httpd, script);
+ map->script = bozostrdup(httpd, NULL, script);
else {
char cwd[MAXPATHLEN], *path;
getcwd(cwd, sizeof(cwd) - 1);
- asprintf(&path, "%s/%s", cwd, script);
+ bozoasprintf(httpd, &path, "%s/%s", cwd, script);
map->script = path;
}
map->L = luaL_newstate();
if (map->L == NULL)
- bozo_err(httpd, 1, "can't create Lua state");
+ bozoerr(httpd, 1, "can't create Lua state");
SIMPLEQ_INIT(&map->handlers);
#if LUA_VERSION_NUM >= 502
@@ -225,10 +225,10 @@ bozo_add_lua_map(bozohttpd_t *httpd, con
lua_settable(map->L, LUA_REGISTRYINDEX);
if (luaL_loadfile(map->L, script))
- bozo_err(httpd, 1, "failed to load script %s: %s", script,
+ bozoerr(httpd, 1, "failed to load script %s: %s", script,
lua_tostring(map->L, -1));
if (lua_pcall(map->L, 0, 0, 0))
- bozo_err(httpd, 1, "failed to execute script %s: %s", script,
+ bozoerr(httpd, 1, "failed to execute script %s: %s", script,
lua_tostring(map->L, -1));
SIMPLEQ_INSERT_TAIL(&httpd->lua_states, map, s_next);
}
@@ -311,44 +311,41 @@ bozo_process_lua(bozo_httpreq_t *request
if (!httpd->process_lua)
return 0;
+ info = NULL;
+ query = NULL;
+ prefix = NULL;
uri = request->hr_oldfile ? request->hr_oldfile : request->hr_file;
if (*uri == '/') {
- file = bozostrdup(httpd, uri);
- prefix = bozostrdup(httpd, &uri[1]);
+ file = bozostrdup(httpd, request, uri);
+ if (file == NULL)
+ goto out;
+ prefix = bozostrdup(httpd, request, &uri[1]);
} else {
- prefix = bozostrdup(httpd, uri);
- asprintf(&file, "/%s", uri);
- }
- if (file == NULL) {
- free(prefix);
- return 0;
+ if (asprintf(&file, "/%s", uri) < 0)
+ goto out;
+ prefix = bozostrdup(httpd, request, uri);
}
+ if (prefix == NULL)
+ goto out;
- if (request->hr_query && strlen(request->hr_query))
- query = bozostrdup(httpd, request->hr_query);
- else
- query = NULL;
+ if (request->hr_query && request->hr_query[0])
+ query = bozostrdup(httpd, request, request->hr_query);
p = strchr(prefix, '/');
- if (p == NULL){
- free(prefix);
- return 0;
- }
+ if (p == NULL)
+ goto out;
*p++ = '\0';
handler = p;
- if (!*handler) {
- free(prefix);
- return 0;
- }
+ if (!*handler)
+ goto out;
p = strchr(handler, '/');
if (p != NULL)
*p++ = '\0';
- info = NULL;
command = file + 1;
if ((s = strchr(command, '/')) != NULL) {
- info = bozostrdup(httpd, s);
+ info = bozostrdup(httpd, request, s);
*s = '\0';
}
Index: src/libexec/httpd/main.c
diff -u src/libexec/httpd/main.c:1.8 src/libexec/httpd/main.c:1.8.2.1
--- src/libexec/httpd/main.c:1.8 Wed Jul 16 07:41:43 2014
+++ src/libexec/httpd/main.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.8 2014/07/16 07:41:43 mrg Exp $ */
+/* $NetBSD: main.c,v 1.8.2.1 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: main.c,v 1.6 2011/11/18 09:21:15 mrg Exp $ */
/* from: eterna: bozohttpd.c,v 1.159 2009/05/23 02:14:30 mrg Exp */
@@ -58,65 +58,67 @@
BOZO_DEAD static void
usage(bozohttpd_t *httpd, char *progname)
{
- bozo_warn(httpd, "usage: %s [options] slashdir [virtualhostname]",
+ bozowarn(httpd, "usage: %s [options] slashdir [virtualhostname]",
progname);
- bozo_warn(httpd, "options:");
+ bozowarn(httpd, "options:");
#ifndef NO_DEBUG
- bozo_warn(httpd, " -d\t\t\tenable debug support");
+ bozowarn(httpd, " -d\t\t\tenable debug support");
+#endif
+ bozowarn(httpd, " -s\t\t\talways log to stderr");
+#ifndef NO_DYNAMIC_CONTENT
+ bozowarn(httpd, " -M arg t c c11\tadd this mime extenstion");
#endif
- bozo_warn(httpd, " -s\t\t\talways log to stderr");
#ifndef NO_USER_SUPPORT
- bozo_warn(httpd, " -u\t\t\tenable ~user/public_html support");
- bozo_warn(httpd, " -p dir\t\tchange `public_html' directory name]");
+ bozowarn(httpd, " -u\t\t\tenable ~user/public_html support");
+ bozowarn(httpd, " -p dir\t\tchange `public_html' directory name");
+#ifndef NO_CGIBIN_SUPPORT
+ bozowarn(httpd, " -E\t\t\tenable CGI support for user dirs");
#endif
-#ifndef NO_DYNAMIC_CONTENT
- bozo_warn(httpd, " -M arg t c c11\tadd this mime extenstion");
#endif
#ifndef NO_CGIBIN_SUPPORT
#ifndef NO_DYNAMIC_CONTENT
- bozo_warn(httpd, " -C arg prog\t\tadd this CGI handler");
+ bozowarn(httpd, " -C arg prog\t\tadd this CGI handler");
#endif
- bozo_warn(httpd,
+ bozowarn(httpd,
" -c cgibin\t\tenable cgi-bin support in this directory");
#endif
#ifndef NO_LUA_SUPPORT
- bozo_warn(httpd, " -L arg script\tadd this Lua script");
+ bozowarn(httpd, " -L arg script\tadd this Lua script");
#endif
- bozo_warn(httpd, " -I port\t\tbind or use on this port");
+ bozowarn(httpd, " -I port\t\tbind or use on this port");
#ifndef NO_DAEMON_MODE
- bozo_warn(httpd, " -b\t\t\tbackground and go into daemon mode");
- bozo_warn(httpd, " -f\t\t\tkeep daemon mode in the foreground");
- bozo_warn(httpd,
+ bozowarn(httpd, " -b\t\t\tbackground and go into daemon mode");
+ bozowarn(httpd, " -f\t\t\tkeep daemon mode in the foreground");
+ bozowarn(httpd,
" -i address\t\tbind on this address (daemon mode only)");
- bozo_warn(httpd, " -P pidfile\t\tpath to the pid file to create");
+ bozowarn(httpd, " -P pidfile\t\tpath to the pid file to create");
#endif
- bozo_warn(httpd, " -S version\t\tset server version string");
- bozo_warn(httpd, " -t dir\t\tchroot to `dir'");
- bozo_warn(httpd, " -U username\t\tchange user to `user'");
- bozo_warn(httpd,
+ bozowarn(httpd, " -S version\t\tset server version string");
+ bozowarn(httpd, " -t dir\t\tchroot to `dir'");
+ bozowarn(httpd, " -U username\t\tchange user to `user'");
+ bozowarn(httpd,
" -e\t\t\tdon't clean the environment (-t and -U only)");
- bozo_warn(httpd,
+ bozowarn(httpd,
" -v virtualroot\tenable virtual host support "
"in this directory");
- bozo_warn(httpd,
- " -r\t\t\tmake sure sub-pages come from "
- "this host via referrer");
#ifndef NO_DIRINDEX_SUPPORT
- bozo_warn(httpd,
+ bozowarn(httpd,
" -X\t\t\tenable automatic directory index support");
- bozo_warn(httpd,
+ bozowarn(httpd,
" -H\t\t\thide files starting with a period (.)"
" in index mode");
#endif
- bozo_warn(httpd,
+ bozowarn(httpd,
" -x index\t\tchange default `index.html' file name");
#ifndef NO_SSL_SUPPORT
- bozo_warn(httpd,
+ bozowarn(httpd,
+ " -z ciphers\t\tspecify SSL ciphers");
+ bozowarn(httpd,
" -Z cert privkey\tspecify path to server certificate"
" and private key file\n"
"\t\t\tin pem format and enable bozohttpd in SSL mode");
#endif /* NO_SSL_SUPPORT */
- bozo_err(httpd, 1, "%s failed to start", progname);
+ bozoerr(httpd, 1, "%s failed to start", progname);
}
int
@@ -126,6 +128,7 @@ main(int argc, char **argv)
bozohttpd_t httpd;
bozoprefs_t prefs;
char *progname;
+ const char *val;
int c;
(void) memset(&httpd, 0x0, sizeof(httpd));
@@ -140,13 +143,17 @@ main(int argc, char **argv)
bozo_set_defaults(&httpd, &prefs);
+ /*
+ * -r option was removed, do not reuse it for a while
+ */
+
while ((c = getopt(argc, argv,
- "C:HI:L:M:P:S:U:VXZ:bc:defhi:np:rst:uv:x:z:")) != -1) {
- switch(c) {
+ "C:EHI:L:M:P:S:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) {
+ switch (c) {
case 'L':
#ifdef NO_LUA_SUPPORT
- bozo_err(&httpd, 1,
+ bozoerr(&httpd, 1,
"Lua support is not enabled");
/* NOTREACHED */
#else
@@ -159,7 +166,7 @@ main(int argc, char **argv)
#endif /* NO_LUA_SUPPORT */
case 'M':
#ifdef NO_DYNAMIC_CONTENT
- bozo_err(&httpd, 1,
+ bozoerr(&httpd, 1,
"dynamic mime content support is not enabled");
/* NOTREACHED */
#else
@@ -173,23 +180,20 @@ main(int argc, char **argv)
#endif /* NO_DYNAMIC_CONTENT */
case 'n':
- bozo_set_pref(&prefs, "numeric", "true");
- break;
-
- case 'r':
- bozo_set_pref(&prefs, "trusted referal", "true");
+ bozo_set_pref(&httpd, &prefs, "numeric", "true");
break;
case 's':
- bozo_set_pref(&prefs, "log to stderr", "true");
+ bozo_set_pref(&httpd, &prefs, "log to stderr", "true");
break;
case 'S':
- bozo_set_pref(&prefs, "server software", optarg);
+ bozo_set_pref(&httpd, &prefs, "server software",
+ optarg);
break;
case 'Z':
#ifdef NO_SSL_SUPPORT
- bozo_err(&httpd, 1, "ssl support is not enabled");
+ bozoerr(&httpd, 1, "ssl support is not enabled");
/* NOT REACHED */
#else
/* make sure there's two arguments */
@@ -198,24 +202,34 @@ main(int argc, char **argv)
bozo_ssl_set_opts(&httpd, optarg, argv[optind++]);
break;
#endif /* NO_SSL_SUPPORT */
+
+ case 'z':
+#ifdef NO_SSL_SUPPORT
+ bozoerr(&httpd, 1, "ssl support is not enabled");
+ /* NOT REACHED */
+#else
+ bozo_ssl_set_ciphers(&httpd, optarg);
+ break;
+#endif /* NO_SSL_SUPPORT */
+
case 'U':
- bozo_set_pref(&prefs, "username", optarg);
+ bozo_set_pref(&httpd, &prefs, "username", optarg);
break;
case 'V':
- bozo_set_pref(&prefs, "unknown slash", "true");
+ bozo_set_pref(&httpd, &prefs, "unknown slash", "true");
break;
case 'v':
- bozo_set_pref(&prefs, "virtual base", optarg);
+ bozo_set_pref(&httpd, &prefs, "virtual base", optarg);
break;
case 'x':
- bozo_set_pref(&prefs, "index.html", optarg);
+ bozo_set_pref(&httpd, &prefs, "index.html", optarg);
break;
case 'I':
- bozo_set_pref(&prefs, "port number", optarg);
+ bozo_set_pref(&httpd, &prefs, "port number", optarg);
break;
#ifdef NO_DAEMON_MODE
@@ -224,7 +238,7 @@ main(int argc, char **argv)
case 'f':
case 'i':
case 'P':
- bozo_err(&httpd, 1, "Daemon mode is not enabled");
+ bozoerr(&httpd, 1, "Daemon mode is not enabled");
/* NOTREACHED */
#else
case 'b':
@@ -233,34 +247,33 @@ main(int argc, char **argv)
* background == 2 (aka, -b -b) means to
* only process 1 per kid
*/
- if (bozo_get_pref(&prefs, "background") == NULL) {
- bozo_set_pref(&prefs, "background", "1");
- } else {
- bozo_set_pref(&prefs, "background", "2");
- }
+ val = bozo_get_pref(&prefs, "background") == NULL ?
+ "1" : "2";
+ bozo_set_pref(&httpd, &prefs, "background", val);
break;
case 'e':
- bozo_set_pref(&prefs, "dirty environment", "true");
+ bozo_set_pref(&httpd, &prefs, "dirty environment",
+ "true");
break;
case 'f':
- bozo_set_pref(&prefs, "foreground", "true");
+ bozo_set_pref(&httpd, &prefs, "foreground", "true");
break;
case 'i':
- bozo_set_pref(&prefs, "bind address", optarg);
+ bozo_set_pref(&httpd, &prefs, "bind address", optarg);
break;
case 'P':
- bozo_set_pref(&prefs, "pid file", optarg);
+ bozo_set_pref(&httpd, &prefs, "pid file", optarg);
break;
#endif /* NO_DAEMON_MODE */
#ifdef NO_CGIBIN_SUPPORT
case 'c':
case 'C':
- bozo_err(&httpd, 1, "CGI is not enabled");
+ bozoerr(&httpd, 1, "CGI is not enabled");
/* NOTREACHED */
#else
case 'c':
@@ -269,7 +282,7 @@ main(int argc, char **argv)
case 'C':
# ifdef NO_DYNAMIC_CONTENT
- bozo_err(&httpd, 1,
+ bozoerr(&httpd, 1,
"dynamic CGI handler support is not enabled");
/* NOTREACHED */
# else
@@ -286,42 +299,54 @@ main(int argc, char **argv)
httpd.debug++;
#ifdef NO_DEBUG
if (httpd.debug == 1)
- bozo_warn(&httpd, "Debugging is not enabled");
+ bozowarn(&httpd, "Debugging is not enabled");
#endif /* NO_DEBUG */
break;
case 't':
- bozo_set_pref(&prefs, "chroot dir", optarg);
+ bozo_set_pref(&httpd, &prefs, "chroot dir", optarg);
break;
#ifdef NO_USER_SUPPORT
case 'p':
case 'u':
- bozo_err(&httpd, 1, "User support is not enabled");
+ case 'E':
+ bozoerr(&httpd, 1, "User support is not enabled");
/* NOTREACHED */
#else
case 'p':
- bozo_set_pref(&prefs, "public_html", optarg);
+ bozo_set_pref(&httpd, &prefs, "public_html", optarg);
break;
case 'u':
- bozo_set_pref(&prefs, "enable users", "true");
+ bozo_set_pref(&httpd, &prefs, "enable users", "true");
+ break;
+#ifndef NO_CGIBIN_SUPPORT
+ case 'E':
+ bozo_set_pref(&httpd, &prefs, "enable user cgibin",
+ "true");
break;
+#else
+ case 'E':
+ bozoerr(&httpd, 1, "CGI is not enabled");
+ /* NOTREACHED */
+#endif /* NO_CGIBIN_SPPORT */
#endif /* NO_USER_SUPPORT */
#ifdef NO_DIRINDEX_SUPPORT
case 'H':
case 'X':
- bozo_err(&httpd, 1,
+ bozoerr(&httpd, 1,
"directory indexing is not enabled");
/* NOTREACHED */
#else
case 'H':
- bozo_set_pref(&prefs, "hide dots", "true");
+ bozo_set_pref(&httpd, &prefs, "hide dots", "true");
break;
case 'X':
- bozo_set_pref(&prefs, "directory indexing", "true");
+ bozo_set_pref(&httpd, &prefs, "directory indexing",
+ "true");
break;
#endif /* NO_DIRINDEX_SUPPORT */
Index: src/libexec/httpd/printenv.lua
diff -u src/libexec/httpd/printenv.lua:1.2 src/libexec/httpd/printenv.lua:1.2.18.1
--- src/libexec/httpd/printenv.lua:1.2 Thu Jan 2 08:21:38 2014
+++ src/libexec/httpd/printenv.lua Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
--- $NetBSD: printenv.lua,v 1.2 2014/01/02 08:21:38 mrg Exp $
+-- $NetBSD: printenv.lua,v 1.2.18.1 2016/04/10 10:33:11 martin Exp $
-- this small Lua script demonstrates the use of Lua in (bozo)httpd
-- it will simply output the "environment"
@@ -8,6 +8,10 @@
-- the same value on each invocation. You can not keep state between
-- two calls.
+-- You can test this example by running the following command:
+-- /usr/libexec/httpd -b -f -I 8080 -L test printenv.lua .
+-- and then navigate to: http://127.0.0.1:8080/test/printenv
+
local httpd = require 'httpd'
function printenv(env, headers, query)
@@ -15,12 +19,14 @@ function printenv(env, headers, query)
-- we get the "environment" in the env table, the values are more
-- or less the same as the variable for a CGI program
- if count == nil then
- count = 1
- end
-
- -- output a header
- print([[
+ -- output headers using httpd.write()
+ -- httpd.write() will not append newlines
+ httpd.write("HTTP/1.1 200 Ok\r\n")
+ httpd.write("Content-Type: text/html\r\n\r\n")
+
+ -- output html using httpd.print()
+ -- you can also use print() and io.write() but they will not work with SSL
+ httpd.print([[
<html>
<head>
<title>Bozotic Lua Environment</title>
@@ -29,54 +35,58 @@ function printenv(env, headers, query)
<h1>Bozotic Lua Environment</h1>
]])
- print('module version: ' .. httpd._VERSION .. '<br>')
+ httpd.print('module version: ' .. httpd._VERSION .. '<br>')
- print('<h2>Server Environment</h2>')
+ httpd.print('<h2>Server Environment</h2>')
-- print the list of "environment" variables
for k, v in pairs(env) do
- print(k .. '=' .. v .. '<br/>')
+ httpd.print(k .. '=' .. v .. '<br/>')
end
- print('<h2>Request Headers</h2>')
+ httpd.print('<h2>Request Headers</h2>')
for k, v in pairs(headers) do
- print(k .. '=' .. v .. '<br/>')
+ httpd.print(k .. '=' .. v .. '<br/>')
end
if query ~= nil then
- print('<h2>Query Variables</h2>')
+ httpd.print('<h2>Query Variables</h2>')
for k, v in pairs(query) do
- print(k .. '=' .. v .. '<br/>')
+ httpd.print(k .. '=' .. v .. '<br/>')
end
end
- print('<h2>Form Test</h2>')
+ httpd.print('<h2>Form Test</h2>')
- print([[
- <form method="POST" action="/rest/form?sender=me">
+ httpd.print([[
+ <form method="POST" action="form?sender=me">
<input type="text" name="a_value">
<input type="submit">
</form>
]])
-- output a footer
- print([[
+ httpd.print([[
</body>
</html>
]])
end
function form(env, header, query)
+
+ httpd.write("HTTP/1.1 200 Ok\r\n")
+ httpd.write("Content-Type: text/html\r\n\r\n")
+
if query ~= nil then
- print('<h2>Form Variables</h2>')
+ httpd.print('<h2>Form Variables</h2>')
if env.CONTENT_TYPE ~= nil then
- print('Content-type: ' .. env.CONTENT_TYPE .. '<br>')
+ httpd.print('Content-type: ' .. env.CONTENT_TYPE .. '<br>')
end
for k, v in pairs(query) do
- print(k .. '=' .. v .. '<br/>')
+ httpd.print(k .. '=' .. v .. '<br/>')
end
else
- print('No values')
+ httpd.print('No values')
end
end
Index: src/libexec/httpd/ssl-bozo.c
diff -u src/libexec/httpd/ssl-bozo.c:1.18 src/libexec/httpd/ssl-bozo.c:1.18.2.1
--- src/libexec/httpd/ssl-bozo.c:1.18 Thu Jul 17 06:27:52 2014
+++ src/libexec/httpd/ssl-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ssl-bozo.c,v 1.18 2014/07/17 06:27:52 mrg Exp $ */
+/* $NetBSD: ssl-bozo.c,v 1.18.2.1 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: ssl-bozo.c,v 1.15 2011/11/18 09:21:15 mrg Exp $ */
@@ -48,6 +48,25 @@
#define USE_ARG(x) /*LINTED*/(void)&(x)
#endif
+#ifndef BOZO_SSL_CIPHERS
+#define BOZO_SSL_CIPHERS \
+ "AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:" \
+ "AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:" \
+ "AES:" \
+ "-SHA:" \
+ "!aNULL:!eNULL:" \
+ "!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:" \
+ "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:" \
+ "!KRB5-DES-CBC3-SHA"
+#endif
+
+#ifndef BOZO_SSL_OPTIONS
+#define BOZO_SSL_OPTIONS \
+ (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1)
+#endif
+
+ /* this structure encapsulates the ssl info */
+
/* this structure encapsulates the ssl info */
typedef struct sslinfo_t {
SSL_CTX *ssl_context;
@@ -55,6 +74,7 @@ typedef struct sslinfo_t {
SSL *bozossl;
char *certificate_file;
char *privatekey_file;
+ char *ciphers;
} sslinfo_t;
/*
@@ -83,7 +103,7 @@ bozo_clear_ssl_queue(bozohttpd_t *httpd)
}
/*
- * bozo_ssl_warn works just like bozo_warn, plus the SSL error queue
+ * bozo_ssl_warn works just like bozowarn, plus the SSL error queue
*/
BOZO_PRINTFLIKE(2, 3) static void
bozo_ssl_warn(bozohttpd_t *httpd, const char *fmt, ...)
@@ -103,7 +123,7 @@ bozo_ssl_warn(bozohttpd_t *httpd, const
/*
- * bozo_ssl_err works just like bozo_err, plus the SSL error queue
+ * bozo_ssl_err works just like bozoerr, plus the SSL error queue
*/
BOZO_PRINTFLIKE(3, 4) BOZO_DEAD static void
bozo_ssl_err(bozohttpd_t *httpd, int code, const char *fmt, ...)
@@ -187,6 +207,7 @@ void
bozo_ssl_init(bozohttpd_t *httpd)
{
sslinfo_t *sslinfo = httpd->sslinfo;
+ long options;
if (sslinfo == NULL || !sslinfo->certificate_file)
return;
@@ -200,6 +221,18 @@ bozo_ssl_init(bozohttpd_t *httpd)
bozo_ssl_err(httpd, EXIT_FAILURE,
"SSL context creation failed");
+ options = SSL_CTX_set_options(sslinfo->ssl_context,
+ BOZO_SSL_OPTIONS);
+ if ((options & BOZO_SSL_OPTIONS) != BOZO_SSL_OPTIONS)
+ bozo_ssl_err(httpd, EXIT_FAILURE,
+ "Error setting ssl options requested %#lx, got %#lx",
+ BOZO_SSL_OPTIONS, options);
+
+ if (!SSL_CTX_set_cipher_list(sslinfo->ssl_context,
+ sslinfo->ciphers ? sslinfo->ciphers : BOZO_SSL_CIPHERS))
+ bozo_ssl_err(httpd, EXIT_FAILURE,
+ "Error setting cipher list '%s'", sslinfo->ciphers);
+
if (1 != SSL_CTX_use_certificate_chain_file(sslinfo->ssl_context,
sslinfo->certificate_file))
bozo_ssl_err(httpd, EXIT_FAILURE,
@@ -231,7 +264,7 @@ bozo_ssl_accept(bozohttpd_t *httpd)
sslinfo->bozossl = SSL_new(sslinfo->ssl_context);
if (sslinfo->bozossl == NULL)
- bozo_err(httpd, 1, "SSL_new failed");
+ bozoerr(httpd, 1, "SSL_new failed");
SSL_set_rfd(sslinfo->bozossl, 0);
SSL_set_wfd(sslinfo->bozossl, 1);
@@ -251,24 +284,40 @@ bozo_ssl_destroy(bozohttpd_t *httpd)
SSL_free(sslinfo->bozossl);
}
+static sslinfo_t *
+bozo_get_sslinfo(bozohttpd_t *httpd)
+{
+ sslinfo_t *sslinfo;
+ if (httpd->sslinfo)
+ return httpd->sslinfo;
+ sslinfo = bozomalloc(httpd, sizeof(*sslinfo));
+ if (sslinfo == NULL)
+ bozoerr(httpd, 1, "sslinfo allocation failed");
+ memset(sslinfo, 0, sizeof(*sslinfo));
+ return httpd->sslinfo = sslinfo;
+}
+
void
bozo_ssl_set_opts(bozohttpd_t *httpd, const char *cert, const char *priv)
{
- sslinfo_t *sslinfo = httpd->sslinfo;
+ sslinfo_t *sslinfo = bozo_get_sslinfo(httpd);
- if (sslinfo == NULL) {
- sslinfo = bozomalloc(httpd, sizeof(*sslinfo));
- if (sslinfo == NULL)
- bozo_err(httpd, 1, "sslinfo allocation failed");
- httpd->sslinfo = sslinfo;
- }
- sslinfo->certificate_file = strdup(cert);
- sslinfo->privatekey_file = strdup(priv);
+ sslinfo->certificate_file = bozostrdup(httpd, NULL, cert);
+ sslinfo->privatekey_file = bozostrdup(httpd, NULL, priv);
debug((httpd, DEBUG_NORMAL, "using cert/priv files: %s & %s",
- sslinfo->certificate_file,
- sslinfo->privatekey_file));
+ sslinfo->certificate_file,
+ sslinfo->privatekey_file));
if (!httpd->bindport)
- httpd->bindport = strdup("https");
+ httpd->bindport = bozostrdup(httpd, NULL, "https");
+}
+
+void
+bozo_ssl_set_ciphers(bozohttpd_t *httpd, const char *ciphers)
+{
+ sslinfo_t *sslinfo = bozo_get_sslinfo(httpd);
+
+ sslinfo->ciphers = bozostrdup(httpd, NULL, ciphers);
+ debug((httpd, DEBUG_NORMAL, "using ciphers: %s", sslinfo->ciphers));
}
#endif /* NO_SSL_SUPPORT */
Index: src/libexec/httpd/tilde-luzah-bozo.c
diff -u src/libexec/httpd/tilde-luzah-bozo.c:1.10 src/libexec/httpd/tilde-luzah-bozo.c:1.10.4.1
--- src/libexec/httpd/tilde-luzah-bozo.c:1.10 Thu Jan 2 08:21:38 2014
+++ src/libexec/httpd/tilde-luzah-bozo.c Sun Apr 10 10:33:11 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: tilde-luzah-bozo.c,v 1.10 2014/01/02 08:21:38 mrg Exp $ */
+/* $NetBSD: tilde-luzah-bozo.c,v 1.10.4.1 2016/04/10 10:33:11 martin Exp $ */
/* $eterna: tilde-luzah-bozo.c,v 1.16 2011/11/18 09:21:15 mrg Exp $ */
@@ -36,6 +36,7 @@
#include <sys/param.h>
+#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
@@ -55,27 +56,40 @@
* enabled.
*/
int
-bozo_user_transform(bozo_httpreq_t *request, int *isindex)
+bozo_user_transform(bozo_httpreq_t *request)
{
bozohttpd_t *httpd = request->hr_httpd;
- char c, *s, *file = NULL;
+ char *s, *file = NULL, *user;
struct passwd *pw;
- *isindex = 0;
+ /* find username */
+ user = strchr(request->hr_file + 1, '~');
- if ((s = strchr(request->hr_file + 2, '/')) != NULL) {
+ /* this shouldn't happen, but "better paranoid than sorry" */
+ assert(user != NULL);
+
+ user++;
+
+ if ((s = strchr(user, '/')) != NULL) {
*s++ = '\0';
- c = s[strlen(s)-1];
- *isindex = (c == '/' || c == '\0');
}
debug((httpd, DEBUG_OBESE, "looking for user %s",
- request->hr_file + 2));
- pw = getpwnam(request->hr_file + 2);
+ user));
+ pw = getpwnam(user);
+ request->hr_user = bozostrdup(httpd, request, user);
+
/* fix this up immediately */
- if (s)
+ if (s) {
s[-1] = '/';
+ /* omit additional slashes at the beginning */
+ while (*s == '/')
+ s++;
+ }
+
if (pw == NULL) {
+ free(request->hr_user);
+ request->hr_user = NULL;
(void)bozo_http_error(httpd, 404, request, "no such user");
return 0;
}
@@ -85,40 +99,25 @@ bozo_user_transform(bozo_httpreq_t *requ
pw->pw_uid, pw->pw_gid));
if (chdir(pw->pw_dir) < 0) {
- bozo_warn(httpd, "chdir1 error: %s: %s", pw->pw_dir,
+ bozowarn(httpd, "chdir1 error: %s: %s", pw->pw_dir,
strerror(errno));
(void)bozo_http_error(httpd, 404, request,
"can't chdir to homedir");
return 0;
}
if (chdir(httpd->public_html) < 0) {
- bozo_warn(httpd, "chdir2 error: %s: %s", httpd->public_html,
+ bozowarn(httpd, "chdir2 error: %s: %s", httpd->public_html,
strerror(errno));
(void)bozo_http_error(httpd, 404, request,
"can't chdir to public_html");
return 0;
}
if (s == NULL || *s == '\0') {
- file = bozostrdup(httpd, httpd->index_html);
+ file = bozostrdup(httpd, request, "/");
} else {
- file = bozomalloc(httpd, strlen(s) +
- (*isindex ? strlen(httpd->index_html) + 1 : 1));
- strcpy(file, s);
- if (*isindex)
- strcat(file, httpd->index_html);
- }
-
- /* see transform_request() */
- if (*file == '/' || strcmp(file, "..") == 0 ||
- strstr(file, "/..") || strstr(file, "../")) {
- (void)bozo_http_error(httpd, 403, request, "illegal request");
- free(file);
- return 0;
- }
-
- if (bozo_auth_check(request, file)) {
- free(file);
- return 0;
+ file = bozomalloc(httpd, strlen(s) + 2);
+ strcpy(file, "/");
+ strcat(file, s);
}
free(request->hr_file);
Index: src/libexec/httpd/testsuite/Makefile
diff -u src/libexec/httpd/testsuite/Makefile:1.4 src/libexec/httpd/testsuite/Makefile:1.4.24.1
--- src/libexec/httpd/testsuite/Makefile:1.4 Sat May 23 02:26:03 2009
+++ src/libexec/httpd/testsuite/Makefile Sun Apr 10 10:33:11 2016
@@ -6,7 +6,7 @@ BIGFILETESTS= partial4000 partial8000
BOZOHTTPD?= ../bozohttpd
BOZOHTTPD?= ../debug/bozohttpd-debug
WGET?= wget
-
+DATA?= $(.CURDIR)/data
all:
clean:
@@ -19,14 +19,14 @@ check: check-simple check-bigfile
check-simple:
.for a in $(SIMPLETESTS)
echo "Running test $a"
- $(BOZOHTTPD) ./data < $(.CURDIR)/$a.in > tmp.$a.out || true
+ $(BOZOHTTPD) "$(DATA)" < $(.CURDIR)/$a.in > tmp.$a.out || true
$(.CURDIR)/html_cmp $(.CURDIR)/$a.out tmp.$a.out
.endfor
check-bigfile:
.for a in $(BIGFILETESTS)
echo "Running test $a"
- $(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "./data"
+ $(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "$(DATA)"
.endfor
.include <bsd.obj.mk>
Index: src/libexec/httpd/testsuite/test-bigfile
diff -u src/libexec/httpd/testsuite/test-bigfile:1.1.1.1 src/libexec/httpd/testsuite/test-bigfile:1.1.1.1.30.1
--- src/libexec/httpd/testsuite/test-bigfile:1.1.1.1 Sat May 23 02:21:19 2009
+++ src/libexec/httpd/testsuite/test-bigfile Sun Apr 10 10:33:11 2016
@@ -8,7 +8,7 @@ datadir="$4"
bozotestport=11111
# copy beginning file
-cp ./data/bigfile.${test} ./bigfile
+cp ${datadir}/bigfile.${test} ./bigfile
# fire up bozohttpd
${bozohttpd} -b -b -I ${bozotestport} -n -s -f ${datadir} &
@@ -18,7 +18,7 @@ ${wget} -c http://localhost:${bozotestpo
kill -9 $bozopid
-if cmp ./bigfile ./data/bigfile; then
+if cmp ./bigfile ${datadir}/bigfile; then
rm -f ./bigfile
exit 0
else