Module Name: src
Committed By: snj
Date: Fri Apr 15 19:38:13 UTC 2016
Modified Files:
src/libexec/httpd [netbsd-6-0]: 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/lua [netbsd-6-0]: bozo.lua glue.c
src/libexec/httpd/testsuite [netbsd-6-0]: Makefile t10.out test-bigfile
Log Message:
Pull up following revision(s) (requested by mrg in ticket #1377):
libexec/httpd/CHANGES: up to 1.22
libexec/httpd/Makefile: up to 1.26 via patch
libexec/httpd/auth-bozo.c: up to 1.18
libexec/httpd/bozohttpd.8: up to 1.59
libexec/httpd/bozohttpd.c: up to 1.80 via patch
libexec/httpd/bozohttpd.h: up to 1.45
libexec/httpd/cgi-bozo.c: up to 1.33
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/lua/bozo.lua: up to 1.2
libexec/httpd/lua/glue.c: up to 1.2
libexec/httpd/main.c: up to 1.13
libexec/httpd/printenv.lua: up to 1.3
libexec/httpd/ssl-bozo.c: up to 1.22
libexec/httpd/testsuite/Makefile: up to 1.5
libexec/httpd/testsuite/t10.out: up to 1.2
libexec/httpd/testsuite/test-bigfile: up to 1.2
libexec/httpd/tilde-luzah-bozo.c: up to 1.14
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
--
updates and bozohttpd 20160415:
o add search-word support for CGI
o fix a security issue in CGI suffix handler support which would
allow remote code execution, from [email protected]
o -C option supports now CGI scripts only
To generate a diff of this commit:
cvs rdiff -u -r1.11.6.1 -r1.11.6.2 src/libexec/httpd/CHANGES
cvs rdiff -u -r1.12.14.1 -r1.12.14.2 src/libexec/httpd/Makefile
cvs rdiff -u -r1.10.8.1 -r1.10.8.2 src/libexec/httpd/auth-bozo.c
cvs rdiff -u -r1.32.6.1 -r1.32.6.2 src/libexec/httpd/bozohttpd.8
cvs rdiff -u -r1.30.6.1 -r1.30.6.2 src/libexec/httpd/bozohttpd.c
cvs rdiff -u -r1.20.6.1 -r1.20.6.2 src/libexec/httpd/bozohttpd.h
cvs rdiff -u -r1.20.8.1 -r1.20.8.2 src/libexec/httpd/cgi-bozo.c
cvs rdiff -u -r1.7.8.1 -r1.7.8.2 src/libexec/httpd/content-bozo.c
cvs rdiff -u -r1.15.8.1 -r1.15.8.2 src/libexec/httpd/daemon-bozo.c
cvs rdiff -u -r1.13.2.1.4.1 -r1.13.2.1.4.2 src/libexec/httpd/dir-index-bozo.c
cvs rdiff -u -r1.9.10.2 -r1.9.10.3 src/libexec/httpd/lua-bozo.c
cvs rdiff -u -r1.5.8.1 -r1.5.8.2 src/libexec/httpd/main.c
cvs rdiff -u -r1.2.10.2 -r1.2.10.3 src/libexec/httpd/printenv.lua
cvs rdiff -u -r1.13.6.1 -r1.13.6.2 src/libexec/httpd/ssl-bozo.c
cvs rdiff -u -r1.9.8.1 -r1.9.8.2 src/libexec/httpd/tilde-luzah-bozo.c
cvs rdiff -u -r1.1.1.1 -r1.1.1.1.14.1 src/libexec/httpd/lua/bozo.lua \
src/libexec/httpd/lua/glue.c
cvs rdiff -u -r1.4 -r1.4.14.1 src/libexec/httpd/testsuite/Makefile
cvs rdiff -u -r1.1.1.1 -r1.1.1.1.16.1 src/libexec/httpd/testsuite/t10.out
cvs rdiff -u -r1.1.1.1 -r1.1.1.1.14.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.11.6.1 src/libexec/httpd/CHANGES:1.11.6.2
--- src/libexec/httpd/CHANGES:1.11.6.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/CHANGES Fri Apr 15 19:38:13 2016
@@ -1,5 +1,29 @@
$eterna: CHANGES,v 1.78 2011/11/18 01:25:11 mrg Exp $
+changes in bozohttpd 20160415:
+ o add search-word support for CGI
+ o fix a security issue in CGI suffix handler support which would
+ allow remote code execution, from [email protected]
+ o -C option supports now CGI scripts only
+
+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
+ o directory listings show correct file sizes for large files
+
+changes in bozohttpd 20140717:
+ o properly handle SSL errors
+
changes in bozohttpd 20140708:
o fixes for virtual host support, from [email protected]
o avoid printing double errors, from [email protected]
Index: src/libexec/httpd/Makefile
diff -u src/libexec/httpd/Makefile:1.12.14.1 src/libexec/httpd/Makefile:1.12.14.2
--- src/libexec/httpd/Makefile:1.12.14.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/Makefile Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.12.14.1 2014/07/09 09:47:10 msaitoh Exp $
+# $NetBSD: Makefile,v 1.12.14.2 2016/04/15 19:38:13 snj 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"
@@ -32,6 +36,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.10.8.1 src/libexec/httpd/auth-bozo.c:1.10.8.2
--- src/libexec/httpd/auth-bozo.c:1.10.8.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/auth-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: auth-bozo.c,v 1.10.8.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: auth-bozo.c,v 1.10.8.2 2016/04/15 19:38:13 snj 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");
}
@@ -118,6 +118,13 @@ bozo_auth_check(bozo_httpreq_t *request,
}
void
+bozo_auth_init(bozo_httpreq_t *request)
+{
+ request->hr_authuser = NULL;
+ request->hr_authpass = NULL;
+}
+
+void
bozo_auth_cleanup(bozo_httpreq_t *request)
{
@@ -129,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;
@@ -150,8 +158,10 @@ bozo_auth_check_headers(bozo_httpreq_t *
return bozo_http_error(httpd, 400, request,
"bad authorization field");
*pass++ = '\0';
- request->hr_authuser = bozostrdup(httpd, authbuf);
- request->hr_authpass = bozostrdup(httpd, pass);
+ free(request->hr_authuser);
+ free(request->hr_authpass);
+ 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));
@@ -181,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
@@ -229,6 +239,12 @@ base64_decode(const unsigned char *in, s
unsigned char *cp;
size_t i;
+ if (ilen == 0) {
+ if (olen)
+ *out = '\0';
+ return 0;
+ }
+
cp = out;
for (i = 0; i < ilen; i += 4) {
if (cp + 3 > out + olen)
@@ -250,7 +266,7 @@ base64_decode(const unsigned char *in, s
| decodetable[in[i + 3]];
#undef IN_CHECK
}
- while (in[i - 1] == '=')
+ while (i > 0 && in[i - 1] == '=')
cp--,i--;
return (cp - out);
}
Index: src/libexec/httpd/bozohttpd.8
diff -u src/libexec/httpd/bozohttpd.8:1.32.6.1 src/libexec/httpd/bozohttpd.8:1.32.6.2
--- src/libexec/httpd/bozohttpd.8:1.32.6.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/bozohttpd.8 Fri Apr 15 19:38:13 2016
@@ -1,8 +1,8 @@
-.\" $NetBSD: bozohttpd.8,v 1.32.6.1 2014/07/09 09:47:10 msaitoh Exp $
+.\" $NetBSD: bozohttpd.8,v 1.32.6.2 2016/04/15 19:38:13 snj Exp $
.\"
.\" $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $
.\"
-.\" Copyright (c) 1997-2014 Matthew R. Green
+.\" Copyright (c) 1997-2015 Matthew R. Green
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -26,21 +26,22 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 9, 2014
-.Dt HTTPD 8
+.Dd December 12, 2015
+.Dt BOZOHTTPD 8
.Os
.Sh NAME
-.Nm httpd
+.Nm bozohttpd
.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
@@ -491,17 +507,14 @@ with PHP, one must use the
option to specify a CGI handler for a particular file type.
Typically this will be like:
.Bd -literal
-httpd -C .php /usr/pkg/bin/php /var/www
+httpd -C .php /usr/pkg/bin/php-cgi /var/www
.Ed
.Sh SEE ALSO
.Xr inetd.conf 5 ,
.Xr inetd 8
.Sh HISTORY
-The
.Nm
-program is actually called
-.Dq bozohttpd .
-It was first written in perl, based on another perl http server
+was first written in perl, based on another perl http server
called
.Dq tinyhttpd .
It was then rewritten from scratch in perl, and then once again in C.
@@ -513,7 +526,7 @@ The focus has always been simplicity and
and regular code audits.
This manual documents
.Nm
-version 20140201.
+version 20150501.
.Sh AUTHORS
.An -nosplit
.Nm
@@ -546,8 +559,9 @@ provided cgi-bin support fixes, and more
.It
.An Alistair G. Crooks
.Aq Mt [email protected]
-cleaned up many internal interfaces, made bozohttpd linkable as a
-library and provided the Lua binding.
+cleaned up many internal interfaces, made
+.Nm
+linkable as a library and provided the Lua binding.
.It
.An DEGROOTE Arnaud
.Aq Mt [email protected]
@@ -597,6 +611,13 @@ provided fixes for HTTP basic authorisat
.Aq Mt [email protected]
provided many fixes and enhancements for the man page
.It
+.An Mateusz Kocielski
+.Aq Mt [email protected]
+fixed memory leaks, various issues with userdir support,
+information disclosure issues, added support for using CGI handlers
+with directory indexing, found several security issues and provided
+various other fixes.
+.It
.An Arnaud Lacombe
.Aq Mt [email protected]
provided some clean up for memory leaks
@@ -609,7 +630,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]
@@ -662,9 +683,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.30.6.1 src/libexec/httpd/bozohttpd.c:1.30.6.2
--- src/libexec/httpd/bozohttpd.c:1.30.6.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/bozohttpd.c Fri Apr 15 19:38:13 2016
@@ -1,9 +1,9 @@
-/* $NetBSD: bozohttpd.c,v 1.30.6.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: bozohttpd.c,v 1.30.6.2 2016/04/15 19:38:13 snj Exp $ */
/* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */
/*
- * Copyright (c) 1997-2014 Matthew R. Green
+ * Copyright (c) 1997-2015 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -109,7 +109,7 @@
#define INDEX_HTML "index.html"
#endif
#ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE "bozohttpd/20140708"
+#define SERVER_SOFTWARE "bozohttpd/20160415"
#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)) {
@@ -350,6 +348,15 @@ bozo_clean_request(bozo_httpreq_t *reque
ohdr = hdr;
}
free(ohdr);
+ ohdr = NULL;
+ for (hdr = SIMPLEQ_FIRST(&request->hr_replheaders); hdr;
+ hdr = SIMPLEQ_NEXT(hdr, h_next)) {
+ free(hdr->h_value);
+ free(hdr->h_header);
+ free(ohdr);
+ ohdr = hdr;
+ }
+ free(ohdr);
free(request);
}
@@ -365,49 +372,76 @@ alarmer(int sig)
}
/*
+ * a list of header quirks: currently, a list of headers that
+ * can't be folded into a single line.
+ */
+const char *header_quirks[] = { "WWW-Authenticate", NULL };
+
+/*
* add or merge this header (val: str) into the requests list
*/
static bozoheaders_t *
-addmerge_header(bozo_httpreq_t *request, char *val,
- char *str, ssize_t len)
+addmerge_header(bozo_httpreq_t *request, struct qheaders *headers,
+ const char *val, const char *str, ssize_t len)
{
- struct bozoheaders *hdr;
+ struct bozohttpd_t *httpd = request->hr_httpd;
+ struct bozoheaders *hdr = NULL;
+ const char **quirk;
USE_ARG(len);
- /* do we exist already? */
- SIMPLEQ_FOREACH(hdr, &request->hr_headers, h_next) {
- if (strcasecmp(val, hdr->h_header) == 0)
+ for (quirk = header_quirks; *quirk; quirk++)
+ if (strcasecmp(*quirk, val) == 0)
break;
+
+ if (*quirk == NULL) {
+ /* do we exist already? */
+ SIMPLEQ_FOREACH(hdr, headers, h_next) {
+ if (strcasecmp(val, hdr->h_header) == 0)
+ break;
+ }
}
if (hdr) {
/* 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);
+ SIMPLEQ_INSERT_TAIL(headers, hdr, h_next);
request->hr_nheaders++;
}
return hdr;
}
+bozoheaders_t *
+addmerge_reqheader(bozo_httpreq_t *request, const char *val, const char *str,
+ ssize_t len)
+{
+
+ return addmerge_header(request, &request->hr_headers, val, str, len);
+}
+
+bozoheaders_t *
+addmerge_replheader(bozo_httpreq_t *request, const char *val, const char *str,
+ ssize_t len)
+{
+
+ return addmerge_header(request, &request->hr_replheaders,
+ val, str, len);
+}
+
/*
* as the prototype string is not constant (eg, "HTTP/1.1" is equivalent
* to "HTTP/001.01"), we MUST parse this.
@@ -415,13 +449,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 +480,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 +520,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 +533,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");
}
/*
@@ -527,7 +563,8 @@ bozo_read_request(bozohttpd_t *httpd)
*/
if (bozo_daemon_fork(httpd))
return NULL;
- bozo_ssl_accept(httpd);
+ if (bozo_ssl_accept(httpd))
+ return NULL;
request = bozomalloc(httpd, sizeof(*request));
memset(request, 0, sizeof(*request));
@@ -540,6 +577,8 @@ bozo_read_request(bozohttpd_t *httpd)
request->hr_virthostname = NULL;
request->hr_file = NULL;
request->hr_oldfile = NULL;
+ SIMPLEQ_INIT(&request->hr_replheaders);
+ bozo_auth_init(request);
slen = sizeof(ss);
if (getpeername(0, (struct sockaddr *)(void *)&ss, &slen) < 0)
@@ -558,9 +597,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);
/*
@@ -576,15 +615,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
@@ -593,7 +633,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) {
@@ -612,11 +652,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);
@@ -673,14 +713,15 @@ bozo_read_request(bozohttpd_t *httpd)
if (bozo_auth_check_headers(request, val, str, len))
goto next_header;
- hdr = addmerge_header(request, val, str, len);
+ hdr = addmerge_reqheader(request, val, str, len);
if (strcasecmp(hdr->h_header, "content-type") == 0)
request->hr_content_type = hdr->h_value;
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,
@@ -795,7 +836,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;
@@ -806,7 +847,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));
@@ -815,13 +856,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;
}
@@ -849,10 +890,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;
@@ -866,17 +908,11 @@ 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;
switch (*s) {
case ':':
- case '/':
case '?':
case '#':
case '[':
@@ -894,11 +930,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++;
@@ -911,115 +954,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 (request->hr_serverport && strcmp(request->hr_serverport, "80") != 0)
- snprintf(portbuf, sizeof(portbuf), ":%s",
- request->hr_serverport);
- else
+ if (absolute) {
+ char *sep = NULL;
+ const char *s;
+
+ /*
+ * 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 */
}
/*
@@ -1036,9 +1082,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
*/
@@ -1049,12 +1092,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)
@@ -1068,6 +1111,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
@@ -1092,15 +1158,14 @@ check_virtual(bozo_httpreq_t *request)
}
debug((httpd, DEBUG_OBESE, "looking at dir``%s''",
d->d_name));
- if (strncasecmp(d->d_name, request->hr_host,
- len) == 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;
}
}
@@ -1137,6 +1202,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];
@@ -1149,27 +1215,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) {
@@ -1177,9 +1247,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;
}
@@ -1187,16 +1257,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);
@@ -1204,37 +1272,33 @@ 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;
}
/* this fixes the %HH hack that RFC2396 requires. */
-static int
-fix_url_percent(bozo_httpreq_t *request)
+int
+bozo_decode_url_percent(bozo_httpreq_t *request, char *str)
{
bozohttpd_t *httpd = request->hr_httpd;
- char *s, *t, buf[3], *url;
+ char *s, *t, buf[3];
char *end; /* if end is not-zero, we don't translate beyond that */
- url = request->hr_file;
-
- end = url + strlen(url);
+ end = str + strlen(str);
/* fast forward to the first % */
- if ((s = strchr(url, '%')) == NULL)
+ if ((s = strchr(str, '%')) == NULL)
return 0;
t = s;
@@ -1286,7 +1350,7 @@ fix_url_percent(bozo_httpreq_t *request)
} while (*s);
*t = '\0';
- debug((httpd, DEBUG_FAT, "fix_url_percent returns %s in url",
+ debug((httpd, DEBUG_FAT, "bozo_decode_url_percent returns `%s'",
request->hr_file));
return 0;
@@ -1296,7 +1360,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
@@ -1314,12 +1377,11 @@ 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;
debug((httpd, DEBUG_FAT, "tf_req: file %s", request->hr_file));
- if (fix_url_percent(request)) {
+ if (bozo_decode_url_percent(request, request->hr_file)) {
goto bad_done;
}
if (check_virtual(request)) {
@@ -1332,84 +1394,49 @@ transform_request(bozo_httpreq_t *reques
goto bad_done;
}
- switch(check_bzredirect(request)) {
- case -1:
- goto bad_done;
- case 1:
- return 0;
- }
-
- if (httpd->untrustedref) {
- int to_indexhtml = 0;
+ /* omit additional slashes at the beginning */
+ while (file[1] == '/')
+ file++;
-#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;
@@ -1419,10 +1446,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,
@@ -1436,15 +1463,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");
@@ -1548,7 +1574,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";
@@ -1562,7 +1588,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:
(void)bozo_http_error(httpd, 403, request,
"no permission to open file");
@@ -1640,9 +1666,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
@@ -1694,6 +1717,12 @@ bozo_print_header(bozo_httpreq_t *reques
bozohttpd_t *httpd = request->hr_httpd;
off_t len;
char date[40];
+ bozoheaders_t *hdr;
+
+ SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) {
+ bozo_printf(httpd, "%s: %s\r\n", hdr->h_header,
+ hdr->h_value);
+ }
bozo_printf(httpd, "Date: %s\r\n", bozo_http_date(date, sizeof(date)));
bozo_printf(httpd, "Server: %s\r\n", httpd->server_software);
@@ -1724,7 +1753,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);
}
@@ -1754,7 +1783,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;
@@ -1769,7 +1798,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;
@@ -1784,6 +1813,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
@@ -1859,6 +1902,7 @@ static struct errors_map {
{ 404, "404 Not Found", "This item has not been found", },
{ 408, "408 Request Timeout", "This request took too long", },
{ 417, "417 Expectation Failed","Expectations not available", },
+ { 420, "420 Enhance Your Calm","Chill, Winston", },
{ 500, "500 Internal Error", "An error occured on the server", },
{ 501, "501 Not Implemented", "This request is not available", },
{ 0, NULL, NULL, },
@@ -1900,10 +1944,11 @@ bozo_http_error(bozohttpd_t *httpd, int
const char *proto = (request && request->hr_proto) ?
request->hr_proto : httpd->consts.http_11;
int size;
+ bozoheaders_t *hdr;
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;
@@ -1917,32 +1962,59 @@ 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;
bozo_printf(httpd, "%s %s\r\n", proto, header);
- if (request)
+
+ if (request) {
bozo_auth_check_401(request, code);
+ SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) {
+ bozo_printf(httpd, "%s: %s\r\n", hdr->h_header,
+ hdr->h_value);
+ }
+ }
bozo_printf(httpd, "Content-Type: text/html\r\n");
bozo_printf(httpd, "Content-Length: %d\r\n", size);
@@ -2075,12 +2147,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 *
@@ -2089,26 +2160,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 */
@@ -2141,15 +2213,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;
}
@@ -2158,7 +2231,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 */
@@ -2169,7 +2242,7 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs
struct passwd *pw;
extern char **environ;
static char *cleanenv[1] = { NULL };
- uid_t uid;
+ uid_t uid = 0;
char *chrootdir;
char *username;
char *portnum;
@@ -2180,16 +2253,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 */
@@ -2197,16 +2269,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);
@@ -2216,19 +2284,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;
@@ -2242,11 +2314,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.
@@ -2254,39 +2327,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.20.6.1 src/libexec/httpd/bozohttpd.h:1.20.6.2
--- src/libexec/httpd/bozohttpd.h:1.20.6.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/bozohttpd.h Fri Apr 15 19:38:13 2016
@@ -1,9 +1,9 @@
-/* $NetBSD: bozohttpd.h,v 1.20.6.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: bozohttpd.h,v 1.20.6.2 2016/04/15 19:38:13 snj Exp $ */
/* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */
/*
- * Copyright (c) 1997-2014 Matthew R. Green
+ * Copyright (c) 1997-2015 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -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 */
@@ -49,6 +54,7 @@ typedef struct bozoheaders {
/*const*/ char *h_value; /* this gets free()'ed etc at times */
SIMPLEQ_ENTRY(bozoheaders) h_next;
} bozoheaders_t;
+SIMPLEQ_HEAD(qheaders, bozoheaders);
#ifndef NO_LUA_SUPPORT
typedef struct lua_handler {
@@ -68,7 +74,6 @@ typedef struct lua_state_map {
typedef struct bozo_content_map_t {
const char *name; /* postfix of file */
- size_t namelen; /* length of postfix */
const char *type; /* matching content-type */
const char *encoding; /* matching content-encoding */
const char *encoding11; /* matching content-encoding (HTTP/1.1) */
@@ -86,11 +91,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 */
@@ -105,6 +108,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 */
@@ -147,6 +151,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;
@@ -166,8 +173,9 @@ typedef struct bozo_httpreq_t {
/*const*/ char *hr_authuser;
/*const*/ char *hr_authpass;
#endif
- SIMPLEQ_HEAD(, bozoheaders) hr_headers;
- int hr_nheaders;
+ struct qheaders hr_headers;
+ struct qheaders hr_replheaders;
+ int hr_nheaders;
} bozo_httpreq_t;
/* helper to access the "active" host name from a httpd/request pair */
@@ -177,8 +185,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;
@@ -211,42 +219,52 @@ 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);
+int bozo_decode_url_percent(bozo_httpreq_t *, char *);
-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_accept(x) do { /* nothing */ } while (0)
-#define bozo_ssl_destroy(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) 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 *);
-void bozo_ssl_accept(bozohttpd_t *);
+int bozo_ssl_accept(bozohttpd_t *);
void bozo_ssl_destroy(bozohttpd_t *);
#endif
/* auth-bozo.c */
#ifdef DO_HTPASSWD
+void bozo_auth_init(bozo_httpreq_t *);
int bozo_auth_check(bozo_httpreq_t *, const char *);
void bozo_auth_cleanup(bozo_httpreq_t *);
int bozo_auth_check_headers(bozo_httpreq_t *, char *, char *, ssize_t);
@@ -255,12 +273,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) 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 */
@@ -287,9 +306,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 *);
@@ -299,9 +318,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 */
@@ -319,7 +340,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 */
@@ -330,15 +352,19 @@ 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 *);
void bozo_process_request(bozo_httpreq_t *);
void bozo_clean_request(bozo_httpreq_t *);
+bozoheaders_t *addmerge_reqheader(bozo_httpreq_t *, const char *,
+ const char *, ssize_t);
+bozoheaders_t *addmerge_replheader(bozo_httpreq_t *, const char *,
+ const char *, ssize_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.20.8.1 src/libexec/httpd/cgi-bozo.c:1.20.8.2
--- src/libexec/httpd/cgi-bozo.c:1.20.8.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/cgi-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,9 +1,9 @@
-/* $NetBSD: cgi-bozo.c,v 1.20.8.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: cgi-bozo.c,v 1.20.8.2 2016/04/15 19:38:13 snj Exp $ */
/* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */
/*
- * Copyright (c) 1997-2014 Matthew R. Green
+ * Copyright (c) 1997-2015 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -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));
}
@@ -211,10 +212,140 @@ append_index_html(bozohttpd_t *httpd, ch
"append_index_html: url adjusted to `%s'", *url));
}
+/* This function parse search-string according to section 4.4 of RFC3875 */
+static char **
+parse_search_string(bozo_httpreq_t *request, const char *query, size_t *args_len)
+{
+ struct bozohttpd_t *httpd = request->hr_httpd;
+ size_t i;
+ char *s, *str, **args;
+
+ *args_len = 0;
+
+ /* URI MUST not contain any unencoded '=' - RFC3875, section 4.4 */
+ if (strchr(query, '=')) {
+ return NULL;
+ }
+
+ str = bozostrdup(httpd, request, query);
+
+ /*
+ * there's no more arguments than '+' chars in the query string as it's
+ * the separator
+ */
+ *args_len = 1;
+ /* count '+' in str */
+ for (s = str; (s = strchr(s, '+')); (*args_len)++);
+
+ args = bozomalloc(httpd, sizeof(*args) * (*args_len + 1));
+
+ args[0] = str;
+ args[*args_len] = NULL;
+ for (s = str, i = 0; (s = strchr(s, '+'));) {
+ *s = '\0';
+ s++;
+ args[i++] = s;
+ }
+
+ /*
+ * check if search-strings are valid:
+ *
+ * RFC3875, section 4.4:
+ *
+ * search-string = search-word *( "+" search-word )
+ * search-word = 1*schar
+ * schar = unreserved | escaped | xreserved
+ * xreserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," |
+ * "$"
+ *
+ * section 2.3:
+ *
+ * hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" |
+ * "b" | "c" | "d" | "e" | "f"
+ * escaped = "%" hex hex
+ * unreserved = alpha | digit | mark
+ * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+ *
+ * section 2.2:
+ *
+ * alpha = lowalpha | hialpha
+ * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" |
+ * "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" |
+ * "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" |
+ * "y" | "z"
+ * hialpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" |
+ * "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" |
+ * "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" |
+ * "Y" | "Z"
+ * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+ * "8" | "9"
+ */
+#define UNRESERVED_CHAR "-_.!~*'()"
+#define XRESERVED_CHAR ";/?:@&=,$"
+
+ for (i = 0; i < *args_len; i++) {
+ s = args[i];
+ /* search-word MUST have at least one schar */
+ if (*s == '\0')
+ goto parse_err;
+ while(*s) {
+ /* check if it's unreserved */
+ if (isalpha((int)*s) || isdigit((int)*s) ||
+ strchr(UNRESERVED_CHAR, *s)) {
+ s++;
+ continue;
+ }
+
+ /* check if it's escaped */
+ if (*s == '%') {
+ if (s[1] == '\0' || s[2] == '\0')
+ goto parse_err;
+ if (!isxdigit((int)s[1]) ||
+ !isxdigit((int)s[2]))
+ goto parse_err;
+ s += 3;
+ continue;
+ }
+
+ /* check if it's xreserved */
+
+ if (strchr(XRESERVED_CHAR, *s)) {
+ s++;
+ continue;
+ }
+
+ goto parse_err;
+ }
+ }
+
+ /* decode percent encoding */
+ for (i = 0; i < *args_len; i++) {
+ if (bozo_decode_url_percent(request, args[i]))
+ goto parse_err;
+ }
+
+ /* allocate each arg separately */
+ for (i = 0; i < *args_len; i++)
+ args[i] = bozostrdup(httpd, request, args[i]);
+ free(str);
+
+ return args;
+
+parse_err:
+
+ free (*args);
+ free (str);
+ *args = NULL;
+ *args_len = 0;
+
+ return 0;
+
+}
+
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));
}
@@ -248,9 +379,9 @@ bozo_process_cgi(bozo_httpreq_t *request
bozoheaders_t *headp;
const char *type, *clen, *info, *cgihandler;
char *query, *s, *t, *path, *env, *command, *file, *url;
- char **envp, **curenvp, *argv[4];
+ char **envp, **curenvp, **argv, **search_string_argv = NULL;
char *uri;
- size_t len;
+ size_t i, len, search_string_argc = 0;
ssize_t rbytes;
pid_t pid;
int envpsize, ix, nph;
@@ -259,26 +390,30 @@ 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;
@@ -307,16 +442,29 @@ bozo_process_cgi(bozo_httpreq_t *request
} else if (len - 1 == CGIBIN_PREFIX_LEN) /* url is "/cgi-bin/" */
append_index_html(httpd, &file);
+ /* RFC3875 sect. 4.4. - search-string support */
+ if (query != NULL) {
+ search_string_argv = parse_search_string(request, query,
+ &search_string_argc);
+ }
+
+ debug((httpd, DEBUG_NORMAL, "parse_search_string args no: %lu",
+ search_string_argc));
+ for (i = 0; i < search_string_argc; i++) {
+ debug((httpd, DEBUG_FAT,
+ "search_string[%lu]: `%s'", i, search_string_argv[i]));
+ }
+
+ argv = bozomalloc(httpd, sizeof(*argv) * (3 + search_string_argc));
+
ix = 0;
if (cgihandler) {
command = file + 1;
- path = bozostrdup(httpd, cgihandler);
- argv[ix++] = path;
- /* argv[] = [ path, command, query, NULL ] */
+ path = bozostrdup(httpd, request, cgihandler);
} else {
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,
@@ -324,12 +472,15 @@ bozo_process_cgi(bozo_httpreq_t *request
strcpy(path, httpd->cgibin);
strcat(path, "/");
strcat(path, command);
- /* argv[] = [ command, query, NULL ] */
}
- argv[ix++] = command;
- argv[ix++] = query;
- argv[ix++] = NULL;
+ argv[ix++] = path;
+
+ /* copy search-string args */
+ for (i = 0; i < search_string_argc; i++)
+ argv[ix++] = search_string_argv[i];
+
+ argv[ix++] = NULL;
nph = strncmp(command, "nph-", 4) == 0;
type = request->hr_content_type;
@@ -395,8 +546,11 @@ bozo_process_cgi(bozo_httpreq_t *request
bozo_setenv(httpd, "REQUEST_URI", uri, curenvp++);
bozo_setenv(httpd, "DATE_GMT", bozo_http_date(date, sizeof(date)),
curenvp++);
+ /* RFC3875 section 4.1.7 says that QUERY_STRING MUST be defined. */
if (query && *query)
bozo_setenv(httpd, "QUERY_STRING", query, curenvp++);
+ else
+ bozo_setenv(httpd, "QUERY_STRING", "", curenvp++);
if (info && *info)
bozo_setenv(httpd, "PATH_INFO", info, curenvp++);
if (type && *type)
@@ -413,21 +567,23 @@ 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 with args:",
+ path));
- debug((httpd, DEBUG_FAT, "bozo_process_cgi: going exec %s, %s %s %s",
- path, argv[0], strornull(argv[1]), strornull(argv[2])));
+ for (i = 0; argv[i] != NULL; i++) {
+ debug((httpd, DEBUG_FAT, "bozo_process_cgi: argv[%lu] = `%s'",
+ i, argv[i]));
+ }
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));
/*
@@ -438,7 +594,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]);
@@ -450,19 +606,26 @@ 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);
+ for (i = 0; i < search_string_argc; i++)
+ free(search_string_argv[i]);
+ free(search_string_argv);
+
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);
@@ -486,7 +649,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));
}
}
@@ -494,6 +657,10 @@ bozo_process_cgi(bozo_httpreq_t *request
exit(0);
out:
+
+ for (i = 0; i < search_string_argc; i++)
+ free(search_string_argv[i]);
+ free(search_string_argv);
free(query);
free(file);
free(url);
@@ -503,7 +670,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;
@@ -514,7 +682,6 @@ bozo_add_content_map_cgi(bozohttpd_t *ht
map = bozo_get_content_map(httpd, arg);
map->name = arg;
- map->namelen = strlen(map->name);
map->type = map->encoding = map->encoding11 = NULL;
map->cgihandler = cgihandler;
}
Index: src/libexec/httpd/content-bozo.c
diff -u src/libexec/httpd/content-bozo.c:1.7.8.1 src/libexec/httpd/content-bozo.c:1.7.8.2
--- src/libexec/httpd/content-bozo.c:1.7.8.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/content-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,9 +1,9 @@
-/* $NetBSD: content-bozo.c,v 1.7.8.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: content-bozo.c,v 1.7.8.2 2016/04/15 19:38:13 snj Exp $ */
/* $eterna: content-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $ */
/*
- * Copyright (c) 1997-2014 Matthew R. Green
+ * Copyright (c) 1997-2015 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,141 +47,145 @@
*/
static bozo_content_map_t static_content_map[] = {
- { ".html", 5, "text/html", "", "", NULL },
- { ".htm", 4, "text/html", "", "", NULL },
- { ".gif", 4, "image/gif", "", "", NULL },
- { ".jpeg", 5, "image/jpeg", "", "", NULL },
- { ".jpg", 4, "image/jpeg", "", "", NULL },
- { ".jpe", 4, "image/jpeg", "", "", NULL },
- { ".png", 4, "image/png", "", "", NULL },
- { ".mp3", 4, "audio/mpeg", "", "", NULL },
- { ".css", 4, "text/css", "", "", NULL },
- { ".txt", 4, "text/plain", "", "", NULL },
- { ".swf", 4, "application/x-shockwave-flash","", "", NULL },
- { ".dcr", 4, "application/x-director", "", "", NULL },
- { ".pac", 4, "application/x-ns-proxy-autoconfig", "", "", NULL },
- { ".pa", 3, "application/x-ns-proxy-autoconfig", "", "", NULL },
- { ".tar", 4, "multipart/x-tar", "", "", NULL },
- { ".gtar", 5, "multipart/x-gtar", "", "", NULL },
- { ".tar.Z", 6, "multipart/x-tar", "x-compress", "compress", NULL },
- { ".tar.gz", 7, "multipart/x-tar", "x-gzip", "gzip", NULL },
- { ".taz", 4, "multipart/x-tar", "x-gzip", "gzip", NULL },
- { ".tgz", 4, "multipart/x-tar", "x-gzip", "gzip", NULL },
- { ".tar.z", 6, "multipart/x-tar", "x-pack", "x-pack", NULL },
- { ".Z", 2, "application/x-compress", "x-compress", "compress", NULL },
- { ".gz", 3, "application/x-gzip", "x-gzip", "gzip", NULL },
- { ".z", 2, "unknown", "x-pack", "x-pack", NULL },
- { ".bz2", 4, "application/x-bzip2", "x-bzip2", "x-bzip2", NULL },
- { ".ogg", 4, "application/x-ogg", "", "", NULL },
- { ".mkv", 4, "video/x-matroska", "", "", NULL },
- { ".xbel", 5, "text/xml", "", "", NULL },
- { ".xml", 4, "text/xml", "", "", NULL },
- { ".xsl", 4, "text/xml", "", "", NULL },
- { ".hqx", 4, "application/mac-binhex40", "", "", NULL },
- { ".cpt", 4, "application/mac-compactpro","", "", NULL },
- { ".doc", 4, "application/msword", "", "", NULL },
- { ".bin", 4, "application/octet-stream", "", "", NULL },
- { ".dms", 4, "application/octet-stream", "", "", NULL },
- { ".lha", 4, "application/octet-stream", "", "", NULL },
- { ".lzh", 4, "application/octet-stream", "", "", NULL },
- { ".exe", 4, "application/octet-stream", "", "", NULL },
- { ".class", 6, "application/octet-stream", "", "", NULL },
- { ".oda", 4, "application/oda", "", "", NULL },
- { ".pdf", 4, "application/pdf", "", "", NULL },
- { ".ai", 3, "application/postscript", "", "", NULL },
- { ".eps", 4, "application/postscript", "", "", NULL },
- { ".ps", 3, "application/postscript", "", "", NULL },
- { ".ppt", 4, "application/powerpoint", "", "", NULL },
- { ".rtf", 4, "application/rtf", "", "", NULL },
- { ".bcpio", 6, "application/x-bcpio", "", "", NULL },
- { ".torrent", 8, "application/x-bittorrent", "", "", NULL },
- { ".vcd", 4, "application/x-cdlink", "", "", NULL },
- { ".cpio", 5, "application/x-cpio", "", "", NULL },
- { ".csh", 4, "application/x-csh", "", "", NULL },
- { ".dir", 4, "application/x-director", "", "", NULL },
- { ".dxr", 4, "application/x-director", "", "", NULL },
- { ".dvi", 4, "application/x-dvi", "", "", NULL },
- { ".hdf", 4, "application/x-hdf", "", "", NULL },
- { ".cgi", 4, "application/x-httpd-cgi", "", "", NULL },
- { ".skp", 4, "application/x-koan", "", "", NULL },
- { ".skd", 4, "application/x-koan", "", "", NULL },
- { ".skt", 4, "application/x-koan", "", "", NULL },
- { ".skm", 4, "application/x-koan", "", "", NULL },
- { ".latex", 6, "application/x-latex", "", "", NULL },
- { ".mif", 4, "application/x-mif", "", "", NULL },
- { ".nc", 3, "application/x-netcdf", "", "", NULL },
- { ".cdf", 4, "application/x-netcdf", "", "", NULL },
- { ".patch", 6, "application/x-patch", "", "", NULL },
- { ".sh", 3, "application/x-sh", "", "", NULL },
- { ".shar", 5, "application/x-shar", "", "", NULL },
- { ".sit", 4, "application/x-stuffit", "", "", NULL },
- { ".sv4cpio", 8, "application/x-sv4cpio", "", "", NULL },
- { ".sv4crc", 7, "application/x-sv4crc", "", "", NULL },
- { ".tar", 4, "application/x-tar", "", "", NULL },
- { ".tcl", 4, "application/x-tcl", "", "", NULL },
- { ".tex", 4, "application/x-tex", "", "", NULL },
- { ".texinfo", 8, "application/x-texinfo", "", "", NULL },
- { ".texi", 5, "application/x-texinfo", "", "", NULL },
- { ".t", 2, "application/x-troff", "", "", NULL },
- { ".tr", 3, "application/x-troff", "", "", NULL },
- { ".roff", 5, "application/x-troff", "", "", NULL },
- { ".man", 4, "application/x-troff-man", "", "", NULL },
- { ".me", 3, "application/x-troff-me", "", "", NULL },
- { ".ms", 3, "application/x-troff-ms", "", "", NULL },
- { ".ustar", 6, "application/x-ustar", "", "", NULL },
- { ".src", 4, "application/x-wais-source", "", "", NULL },
- { ".zip", 4, "application/zip", "", "", NULL },
- { ".au", 3, "audio/basic", "", "", NULL },
- { ".snd", 4, "audio/basic", "", "", NULL },
- { ".mpga", 5, "audio/mpeg", "", "", NULL },
- { ".mp2", 4, "audio/mpeg", "", "", NULL },
- { ".aif", 4, "audio/x-aiff", "", "", NULL },
- { ".aiff", 5, "audio/x-aiff", "", "", NULL },
- { ".aifc", 5, "audio/x-aiff", "", "", NULL },
- { ".ram", 4, "audio/x-pn-realaudio", "", "", NULL },
- { ".rpm", 4, "audio/x-pn-realaudio-plugin","", "", NULL },
- { ".ra", 3, "audio/x-realaudio", "", "", NULL },
- { ".wav", 4, "audio/x-wav", "", "", NULL },
- { ".pdb", 4, "chemical/x-pdb", "", "", NULL },
- { ".xyz", 4, "chemical/x-pdb", "", "", NULL },
- { ".ief", 4, "image/ief", "", "", NULL },
- { ".tiff", 5, "image/tiff", "", "", NULL },
- { ".tif", 4, "image/tiff", "", "", NULL },
- { ".ras", 4, "image/x-cmu-raster", "", "", NULL },
- { ".pnm", 4, "image/x-portable-anymap", "", "", NULL },
- { ".pbm", 4, "image/x-portable-bitmap", "", "", NULL },
- { ".pgm", 4, "image/x-portable-graymap", "", "", NULL },
- { ".ppm", 4, "image/x-portable-pixmap", "", "", NULL },
- { ".rgb", 4, "image/x-rgb", "", "", NULL },
- { ".xbm", 4, "image/x-xbitmap", "", "", NULL },
- { ".xpm", 4, "image/x-xpixmap", "", "", NULL },
- { ".xwd", 4, "image/x-xwindowdump", "", "", NULL },
- { ".rtx", 4, "text/richtext", "", "", NULL },
- { ".tsv", 4, "text/tab-separated-values", "", "", NULL },
- { ".etx", 4, "text/x-setext", "", "", NULL },
- { ".sgml", 5, "text/x-sgml", "", "", NULL },
- { ".sgm", 4, "text/x-sgml", "", "", NULL },
- { ".mpeg", 5, "video/mpeg", "", "", NULL },
- { ".mpg", 4, "video/mpeg", "", "", NULL },
- { ".mpe", 4, "video/mpeg", "", "", NULL },
- { ".mp4", 4, "video/mp4", "", "", NULL },
- { ".qt", 3, "video/quicktime", "", "", NULL },
- { ".mov", 4, "video/quicktime", "", "", NULL },
- { ".avi", 4, "video/x-msvideo", "", "", NULL },
- { ".movie", 6, "video/x-sgi-movie", "", "", NULL },
- { ".ice", 4, "x-conference/x-cooltalk", "", "", NULL },
- { ".wrl", 4, "x-world/x-vrml", "", "", NULL },
- { ".vrml", 5, "x-world/x-vrml", "", "", NULL },
- { ".svg", 5, "image/svg+xml", "", "", NULL },
- { NULL, 0, NULL, NULL, NULL, NULL }
+ { ".html", "text/html", "", "", NULL },
+ { ".htm", "text/html", "", "", NULL },
+ { ".gif", "image/gif", "", "", NULL },
+ { ".jpeg", "image/jpeg", "", "", NULL },
+ { ".jpg", "image/jpeg", "", "", NULL },
+ { ".jpe", "image/jpeg", "", "", NULL },
+ { ".png", "image/png", "", "", NULL },
+ { ".mp3", "audio/mpeg", "", "", NULL },
+ { ".css", "text/css", "", "", NULL },
+ { ".txt", "text/plain", "", "", NULL },
+ { ".swf", "application/x-shockwave-flash","", "", NULL },
+ { ".dcr", "application/x-director", "", "", NULL },
+ { ".pac", "application/x-ns-proxy-autoconfig", "", "", NULL },
+ { ".pa", "application/x-ns-proxy-autoconfig", "", "", NULL },
+ { ".tar", "multipart/x-tar", "", "", NULL },
+ { ".gtar", "multipart/x-gtar", "", "", NULL },
+ { ".tar.Z", "multipart/x-tar", "x-compress", "compress", NULL },
+ { ".tar.gz", "multipart/x-tar", "x-gzip", "gzip", NULL },
+ { ".taz", "multipart/x-tar", "x-gzip", "gzip", NULL },
+ { ".tgz", "multipart/x-tar", "x-gzip", "gzip", NULL },
+ { ".tar.z", "multipart/x-tar", "x-pack", "x-pack", NULL },
+ { ".Z", "application/x-compress", "x-compress", "compress", NULL },
+ { ".gz", "application/x-gzip", "x-gzip", "gzip", NULL },
+ { ".z", "unknown", "x-pack", "x-pack", NULL },
+ { ".bz2", "application/x-bzip2", "x-bzip2", "x-bzip2", NULL },
+ { ".ogg", "application/x-ogg", "", "", NULL },
+ { ".mkv", "video/x-matroska", "", "", NULL },
+ { ".xbel", "text/xml", "", "", NULL },
+ { ".xml", "text/xml", "", "", NULL },
+ { ".xsl", "text/xml", "", "", NULL },
+ { ".hqx", "application/mac-binhex40", "", "", NULL },
+ { ".cpt", "application/mac-compactpro", "", "", NULL },
+ { ".doc", "application/msword", "", "", NULL },
+ { ".bin", "application/octet-stream", "", "", NULL },
+ { ".dms", "application/octet-stream", "", "", NULL },
+ { ".lha", "application/octet-stream", "", "", NULL },
+ { ".lzh", "application/octet-stream", "", "", NULL },
+ { ".exe", "application/octet-stream", "", "", NULL },
+ { ".class", "application/octet-stream", "", "", NULL },
+ { ".oda", "application/oda", "", "", NULL },
+ { ".pdf", "application/pdf", "", "", NULL },
+ { ".ai", "application/postscript", "", "", NULL },
+ { ".eps", "application/postscript", "", "", NULL },
+ { ".ps", "application/postscript", "", "", NULL },
+ { ".ppt", "application/powerpoint", "", "", NULL },
+ { ".rtf", "application/rtf", "", "", NULL },
+ { ".bcpio", "application/x-bcpio", "", "", NULL },
+ { ".torrent", "application/x-bittorrent", "", "", NULL },
+ { ".vcd", "application/x-cdlink", "", "", NULL },
+ { ".cpio", "application/x-cpio", "", "", NULL },
+ { ".csh", "application/x-csh", "", "", NULL },
+ { ".dir", "application/x-director", "", "", NULL },
+ { ".dxr", "application/x-director", "", "", NULL },
+ { ".dvi", "application/x-dvi", "", "", NULL },
+ { ".hdf", "application/x-hdf", "", "", NULL },
+ { ".cgi", "application/x-httpd-cgi", "", "", NULL },
+ { ".skp", "application/x-koan", "", "", NULL },
+ { ".skd", "application/x-koan", "", "", NULL },
+ { ".skt", "application/x-koan", "", "", NULL },
+ { ".skm", "application/x-koan", "", "", NULL },
+ { ".latex", "application/x-latex", "", "", NULL },
+ { ".mif", "application/x-mif", "", "", NULL },
+ { ".nc", "application/x-netcdf", "", "", NULL },
+ { ".cdf", "application/x-netcdf", "", "", NULL },
+ { ".patch", "application/x-patch", "", "", NULL },
+ { ".sh", "application/x-sh", "", "", NULL },
+ { ".shar", "application/x-shar", "", "", NULL },
+ { ".sit", "application/x-stuffit", "", "", NULL },
+ { ".sv4cpio", "application/x-sv4cpio", "", "", NULL },
+ { ".sv4crc", "application/x-sv4crc", "", "", NULL },
+ { ".tar", "application/x-tar", "", "", NULL },
+ { ".tcl", "application/x-tcl", "", "", NULL },
+ { ".tex", "application/x-tex", "", "", NULL },
+ { ".texinfo", "application/x-texinfo", "", "", NULL },
+ { ".texi", "application/x-texinfo", "", "", NULL },
+ { ".t", "application/x-troff", "", "", NULL },
+ { ".tr", "application/x-troff", "", "", NULL },
+ { ".roff", "application/x-troff", "", "", NULL },
+ { ".man", "application/x-troff-man", "", "", NULL },
+ { ".me", "application/x-troff-me", "", "", NULL },
+ { ".ms", "application/x-troff-ms", "", "", NULL },
+ { ".ustar", "application/x-ustar", "", "", NULL },
+ { ".src", "application/x-wais-source", "", "", NULL },
+ { ".zip", "application/zip", "", "", NULL },
+ { ".au", "audio/basic", "", "", NULL },
+ { ".snd", "audio/basic", "", "", NULL },
+ { ".mpga", "audio/mpeg", "", "", NULL },
+ { ".mp2", "audio/mpeg", "", "", NULL },
+ { ".aif", "audio/x-aiff", "", "", NULL },
+ { ".aiff", "audio/x-aiff", "", "", NULL },
+ { ".aifc", "audio/x-aiff", "", "", NULL },
+ { ".ram", "audio/x-pn-realaudio", "", "", NULL },
+ { ".rpm", "audio/x-pn-realaudio-plugin", "", "", NULL },
+ { ".ra", "audio/x-realaudio", "", "", NULL },
+ { ".wav", "audio/x-wav", "", "", NULL },
+ { ".pdb", "chemical/x-pdb", "", "", NULL },
+ { ".xyz", "chemical/x-pdb", "", "", NULL },
+ { ".ief", "image/ief", "", "", NULL },
+ { ".tiff", "image/tiff", "", "", NULL },
+ { ".tif", "image/tiff", "", "", NULL },
+ { ".ras", "image/x-cmu-raster", "", "", NULL },
+ { ".pnm", "image/x-portable-anymap", "", "", NULL },
+ { ".pbm", "image/x-portable-bitmap", "", "", NULL },
+ { ".pgm", "image/x-portable-graymap", "", "", NULL },
+ { ".ppm", "image/x-portable-pixmap", "", "", NULL },
+ { ".rgb", "image/x-rgb", "", "", NULL },
+ { ".xbm", "image/x-xbitmap", "", "", NULL },
+ { ".xpm", "image/x-xpixmap", "", "", NULL },
+ { ".xwd", "image/x-xwindowdump", "", "", NULL },
+ { ".rtx", "text/richtext", "", "", NULL },
+ { ".tsv", "text/tab-separated-values", "", "", NULL },
+ { ".etx", "text/x-setext", "", "", NULL },
+ { ".sgml", "text/x-sgml", "", "", NULL },
+ { ".sgm", "text/x-sgml", "", "", NULL },
+ { ".mpeg", "video/mpeg", "", "", NULL },
+ { ".mpg", "video/mpeg", "", "", NULL },
+ { ".mpe", "video/mpeg", "", "", NULL },
+ { ".ts", "video/mpeg", "", "", NULL },
+ { ".vob", "video/mpeg", "", "", NULL },
+ { ".mp4", "video/mp4", "", "", NULL },
+ { ".qt", "video/quicktime", "", "", NULL },
+ { ".mov", "video/quicktime", "", "", NULL },
+ { ".avi", "video/x-msvideo", "", "", NULL },
+ { ".movie", "video/x-sgi-movie", "", "", NULL },
+ { ".ice", "x-conference/x-cooltalk", "", "", NULL },
+ { ".wrl", "x-world/x-vrml", "", "", NULL },
+ { ".vrml", "x-world/x-vrml", "", "", NULL },
+ { ".svg", "image/svg+xml", "", "", NULL },
+ { NULL, NULL, NULL, NULL, NULL }
};
static bozo_content_map_t *
search_map(bozo_content_map_t *map, const char *name, size_t len)
{
for ( ; map && map->name; map++) {
- if (map->namelen < len &&
- strcasecmp(map->name, name + (len - map->namelen)) == 0)
+ const size_t namelen = strlen(map->name);
+
+ if (namelen < len &&
+ strcasecmp(map->name, name + (len - namelen)) == 0)
return map;
}
return NULL;
@@ -254,11 +258,10 @@ 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;
- map->namelen = 0;
map--;
return map;
@@ -289,7 +292,6 @@ bozo_add_content_map_mime(bozohttpd_t *h
map = bozo_get_content_map(httpd, cmap0);
#define CHECKMAP(s) (!s || ((s)[0] == '-' && (s)[1] == '\0') ? "" : (s))
map->name = CHECKMAP(cmap0);
- map->namelen = strlen(map->name);
map->type = CHECKMAP(cmap1);
map->encoding = CHECKMAP(cmap2);
map->encoding11 = CHECKMAP(cmap3);
Index: src/libexec/httpd/daemon-bozo.c
diff -u src/libexec/httpd/daemon-bozo.c:1.15.8.1 src/libexec/httpd/daemon-bozo.c:1.15.8.2
--- src/libexec/httpd/daemon-bozo.c:1.15.8.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/daemon-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: daemon-bozo.c,v 1.15.8.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: daemon-bozo.c,v 1.15.8.2 2016/04/15 19:38:13 snj 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.13.2.1.4.1 src/libexec/httpd/dir-index-bozo.c:1.13.2.1.4.2
--- src/libexec/httpd/dir-index-bozo.c:1.13.2.1.4.1 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/dir-index-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dir-index-bozo.c,v 1.13.2.1.4.1 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: dir-index-bozo.c,v 1.13.2.1.4.2 2016/04/15 19:38:13 snj 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;
@@ -189,8 +199,8 @@ bozo_dir_index(bozo_httpreq_t *request,
spacebuf[i] = '\0';
bozo_printf(httpd, "%s", spacebuf);
- bozo_printf(httpd, "%7ukB",
- ((unsigned)((unsigned)(sb.st_size) >> 10)));
+ bozo_printf(httpd, "%12llukB",
+ (unsigned long long)sb.st_size >> 10);
}
bozo_printf(httpd, "\r\n");
}
@@ -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.9.10.2 src/libexec/httpd/lua-bozo.c:1.9.10.3
--- src/libexec/httpd/lua-bozo.c:1.9.10.2 Wed Jul 9 09:47:10 2014
+++ src/libexec/httpd/lua-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: lua-bozo.c,v 1.9.10.2 2014/07/09 09:47:10 msaitoh Exp $ */
+/* $NetBSD: lua-bozo.c,v 1.9.10.3 2016/04/15 19:38:13 snj 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,28 +184,28 @@ 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
luaL_openlibs(map->L);
- lua_getglobal(L, "package");
- lua_getfield(L, -1, "preload");
- lua_pushcfunction(L, luaopen_httpd);
- lua_setfield(L, -2, "httpd");
- lua_pop(L, 2);
+ lua_getglobal(map->L, "package");
+ lua_getfield(map->L, -1, "preload");
+ lua_pushcfunction(map->L, luaopen_httpd);
+ lua_setfield(map->L, -2, "httpd");
+ lua_pop(map->L, 2);
#else
lua_openlib(map->L, "", luaopen_base);
lua_openlib(map->L, LUA_LOADLIBNAME, luaopen_package);
@@ -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);
}
@@ -276,6 +276,7 @@ lua_url_decode(lua_State *L, char *s)
*q++ = *p;
}
}
+ *q = '\0';
lua_pushstring(L, val);
lua_setfield(L, -2, s);
free(val);
@@ -310,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.5.8.1 src/libexec/httpd/main.c:1.5.8.2
--- src/libexec/httpd/main.c:1.5.8.1 Wed Jul 9 09:47:11 2014
+++ src/libexec/httpd/main.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.5.8.1 2014/07/09 09:47:11 msaitoh Exp $ */
+/* $NetBSD: main.c,v 1.5.8.2 2016/04/15 19:38:13 snj 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,43 +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(&httpd, &prefs, "chroot dir", optarg);
+ break;
+
#ifdef NO_USER_SUPPORT
case 'p':
- case 't':
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);
- break;
-
- case 't':
- bozo_set_pref(&prefs, "chroot dir", 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.10.2 src/libexec/httpd/printenv.lua:1.2.10.3
--- src/libexec/httpd/printenv.lua:1.2.10.2 Wed Jul 9 09:47:11 2014
+++ src/libexec/httpd/printenv.lua Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
--- $NetBSD: printenv.lua,v 1.2.10.2 2014/07/09 09:47:11 msaitoh Exp $
+-- $NetBSD: printenv.lua,v 1.2.10.3 2016/04/15 19:38:13 snj 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.13.6.1 src/libexec/httpd/ssl-bozo.c:1.13.6.2
--- src/libexec/httpd/ssl-bozo.c:1.13.6.1 Wed Jul 9 09:47:11 2014
+++ src/libexec/httpd/ssl-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ssl-bozo.c,v 1.13.6.1 2014/07/09 09:47:11 msaitoh Exp $ */
+/* $NetBSD: ssl-bozo.c,v 1.13.6.2 2016/04/15 19:38:13 snj Exp $ */
/* $eterna: ssl-bozo.c,v 1.15 2011/11/18 09:21:15 mrg Exp $ */
@@ -30,7 +30,7 @@
*
*/
-/* this code implements SSL for bozohttpd */
+/* this code implements SSL and backend IO for bozohttpd */
#include <stdarg.h>
#include <stdio.h>
@@ -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,29 +74,17 @@ typedef struct sslinfo_t {
SSL *bozossl;
char *certificate_file;
char *privatekey_file;
+ char *ciphers;
} sslinfo_t;
/*
- * bozo_ssl_err
- *
- * bozo_ssl_err works just like bozo_err except in addition to printing
- * the error provided by the caller at the point of error it pops and
- * prints all errors from the SSL error queue.
+ * bozo_clear_ssl_queue: print the contents of the SSL error queue
*/
-BOZO_PRINTFLIKE(3, 4) BOZO_DEAD static void
-bozo_ssl_err(bozohttpd_t *httpd, int code, const char *fmt, ...)
+static void
+bozo_clear_ssl_queue(bozohttpd_t *httpd)
{
- va_list ap;
-
- va_start(ap, fmt);
- if (httpd->logstderr || isatty(STDERR_FILENO)) {
- vfprintf(stderr, fmt, ap);
- fputs("\n", stderr);
- } else
- vsyslog(LOG_ERR, fmt, ap);
- va_end(ap);
+ unsigned long sslcode = ERR_get_error();
- unsigned int sslcode = ERR_get_error();
do {
static const char sslfmt[] = "SSL Error: %s:%s:%s";
@@ -93,20 +100,77 @@ bozo_ssl_err(bozohttpd_t *httpd, int cod
ERR_reason_error_string(sslcode));
}
} while (0 != (sslcode = ERR_get_error()));
+}
+
+/*
+ * 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, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (httpd->logstderr || isatty(STDERR_FILENO)) {
+ vfprintf(stderr, fmt, ap);
+ fputs("\n", stderr);
+ } else
+ vsyslog(LOG_ERR, fmt, ap);
+ va_end(ap);
+
+ bozo_clear_ssl_queue(httpd);
+}
+
+
+/*
+ * 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, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (httpd->logstderr || isatty(STDERR_FILENO)) {
+ vfprintf(stderr, fmt, ap);
+ fputs("\n", stderr);
+ } else
+ vsyslog(LOG_ERR, fmt, ap);
+ va_end(ap);
+
+ bozo_clear_ssl_queue(httpd);
exit(code);
}
+/*
+ * bozo_check_error_queue: print warnings if the error isn't expected
+ */
+static void
+bozo_check_error_queue(bozohttpd_t *httpd, const char *tag, int ret)
+{
+ if (ret > 0)
+ return;
+
+ const sslinfo_t *sslinfo = httpd->sslinfo;
+ const int sslerr = SSL_get_error(sslinfo->bozossl, ret);
+
+ if (sslerr != SSL_ERROR_ZERO_RETURN &&
+ sslerr != SSL_ERROR_SYSCALL &&
+ sslerr != SSL_ERROR_NONE)
+ bozo_ssl_warn(httpd, "%s: SSL_ERROR %d", tag, sslerr);
+}
+
static BOZO_PRINTFLIKE(2, 0) int
bozo_ssl_printf(bozohttpd_t *httpd, const char * fmt, va_list ap)
{
- sslinfo_t *sslinfo;
- char *buf;
- int nbytes;
-
- sslinfo = httpd->sslinfo;
- /* XXX we need more elegant/proper handling of SSL_write return */
- if ((nbytes = vasprintf(&buf, fmt, ap)) != -1)
- SSL_write(sslinfo->bozossl, buf, nbytes);
+ char *buf;
+ int nbytes;
+
+ if ((nbytes = vasprintf(&buf, fmt, ap)) != -1) {
+ const sslinfo_t *sslinfo = httpd->sslinfo;
+ int ret = SSL_write(sslinfo->bozossl, buf, nbytes);
+ bozo_check_error_queue(httpd, "write", ret);
+ }
free(buf);
@@ -116,53 +180,35 @@ bozo_ssl_printf(bozohttpd_t *httpd, cons
static ssize_t
bozo_ssl_read(bozohttpd_t *httpd, int fd, void *buf, size_t nbytes)
{
- sslinfo_t *sslinfo;
- ssize_t rbytes;
+ const sslinfo_t *sslinfo = httpd->sslinfo;
+ int ret;
USE_ARG(fd);
- sslinfo = httpd->sslinfo;
- /* XXX we need elegant/proper handling of SSL_read return */
- rbytes = (ssize_t)SSL_read(sslinfo->bozossl, buf, (int)nbytes);
- if (rbytes < 1) {
- if (SSL_get_error(sslinfo->bozossl, rbytes) ==
- SSL_ERROR_WANT_READ)
- bozo_warn(httpd, "SSL_ERROR_WANT_READ");
- else
- bozo_warn(httpd, "SSL_ERROR OTHER");
- }
+ ret = SSL_read(sslinfo->bozossl, buf, (int)nbytes);
+ bozo_check_error_queue(httpd, "read", ret);
- return rbytes;
+ return (ssize_t)ret;
}
static ssize_t
bozo_ssl_write(bozohttpd_t *httpd, int fd, const void *buf, size_t nbytes)
{
- sslinfo_t *sslinfo;
- ssize_t wbytes;
+ const sslinfo_t *sslinfo = httpd->sslinfo;
+ int ret;
USE_ARG(fd);
- sslinfo = httpd->sslinfo;
- /* XXX we need elegant/proper handling of SSL_write return */
- wbytes = (ssize_t)SSL_write(sslinfo->bozossl, buf, (int)nbytes);
+ ret = SSL_write(sslinfo->bozossl, buf, (int)nbytes);
+ bozo_check_error_queue(httpd, "write", ret);
- return wbytes;
-}
-
-static int
-bozo_ssl_flush(bozohttpd_t *httpd, FILE *fp)
-{
- USE_ARG(httpd);
- USE_ARG(fp);
- /* nothing to see here, move right along */
- return 0;
+ return (ssize_t)ret;
}
void
bozo_ssl_init(bozohttpd_t *httpd)
{
- sslinfo_t *sslinfo;
+ sslinfo_t *sslinfo = httpd->sslinfo;
+ long options;
- sslinfo = httpd->sslinfo;
if (sslinfo == NULL || !sslinfo->certificate_file)
return;
SSL_library_init();
@@ -171,11 +217,22 @@ bozo_ssl_init(bozohttpd_t *httpd)
sslinfo->ssl_method = SSLv23_server_method();
sslinfo->ssl_context = SSL_CTX_new(sslinfo->ssl_method);
- /* XXX we need to learn how to check the SSL stack for more info */
if (NULL == sslinfo->ssl_context)
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,
@@ -194,50 +251,73 @@ bozo_ssl_init(bozohttpd_t *httpd)
"Check private key failed");
}
-void
+/*
+ * returns non-zero for failure
+ */
+int
bozo_ssl_accept(bozohttpd_t *httpd)
{
- sslinfo_t *sslinfo;
+ sslinfo_t *sslinfo = httpd->sslinfo;
- sslinfo = httpd->sslinfo;
- if (sslinfo != NULL && sslinfo->ssl_context) {
- sslinfo->bozossl = SSL_new(sslinfo->ssl_context);
- SSL_set_rfd(sslinfo->bozossl, 0);
- SSL_set_wfd(sslinfo->bozossl, 1);
- SSL_accept(sslinfo->bozossl);
- }
+ if (sslinfo == NULL || !sslinfo->ssl_context)
+ return 0;
+
+ sslinfo->bozossl = SSL_new(sslinfo->ssl_context);
+ if (sslinfo->bozossl == NULL)
+ bozoerr(httpd, 1, "SSL_new failed");
+
+ SSL_set_rfd(sslinfo->bozossl, 0);
+ SSL_set_wfd(sslinfo->bozossl, 1);
+
+ const int ret = SSL_accept(sslinfo->bozossl);
+ bozo_check_error_queue(httpd, "accept", ret);
+
+ return ret != 1;
}
void
bozo_ssl_destroy(bozohttpd_t *httpd)
{
- sslinfo_t *sslinfo;
+ const sslinfo_t *sslinfo = httpd->sslinfo;
- sslinfo = httpd->sslinfo;
if (sslinfo && sslinfo->bozossl)
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;
+ sslinfo_t *sslinfo = bozo_get_sslinfo(httpd);
- if ((sslinfo = httpd->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));
- if (!httpd->bindport) {
- httpd->bindport = strdup("https");
- }
+ sslinfo->certificate_file,
+ sslinfo->privatekey_file));
+ if (!httpd->bindport)
+ 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 */
@@ -250,13 +330,11 @@ bozo_printf(bozohttpd_t *httpd, const ch
va_start(args, fmt);
#ifndef NO_SSL_SUPPORT
- if (httpd->sslinfo) {
+ if (httpd->sslinfo)
cc = bozo_ssl_printf(httpd, fmt, args);
- va_end(args);
- return cc;
- }
+ else
#endif
- cc = vprintf(fmt, args);
+ cc = vprintf(fmt, args);
va_end(args);
return cc;
}
@@ -265,9 +343,8 @@ ssize_t
bozo_read(bozohttpd_t *httpd, int fd, void *buf, size_t len)
{
#ifndef NO_SSL_SUPPORT
- if (httpd->sslinfo) {
+ if (httpd->sslinfo)
return bozo_ssl_read(httpd, fd, buf, len);
- }
#endif
return read(fd, buf, len);
}
@@ -276,9 +353,8 @@ ssize_t
bozo_write(bozohttpd_t *httpd, int fd, const void *buf, size_t len)
{
#ifndef NO_SSL_SUPPORT
- if (httpd->sslinfo) {
+ if (httpd->sslinfo)
return bozo_ssl_write(httpd, fd, buf, len);
- }
#endif
return write(fd, buf, len);
}
@@ -287,9 +363,8 @@ int
bozo_flush(bozohttpd_t *httpd, FILE *fp)
{
#ifndef NO_SSL_SUPPORT
- if (httpd->sslinfo) {
- return bozo_ssl_flush(httpd, fp);
- }
+ if (httpd->sslinfo)
+ return 0;
#endif
return fflush(fp);
}
Index: src/libexec/httpd/tilde-luzah-bozo.c
diff -u src/libexec/httpd/tilde-luzah-bozo.c:1.9.8.1 src/libexec/httpd/tilde-luzah-bozo.c:1.9.8.2
--- src/libexec/httpd/tilde-luzah-bozo.c:1.9.8.1 Wed Jul 9 09:47:11 2014
+++ src/libexec/httpd/tilde-luzah-bozo.c Fri Apr 15 19:38:13 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: tilde-luzah-bozo.c,v 1.9.8.1 2014/07/09 09:47:11 msaitoh Exp $ */
+/* $NetBSD: tilde-luzah-bozo.c,v 1.9.8.2 2016/04/15 19:38:13 snj 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/lua/bozo.lua
diff -u src/libexec/httpd/lua/bozo.lua:1.1.1.1 src/libexec/httpd/lua/bozo.lua:1.1.1.1.14.1
--- src/libexec/httpd/lua/bozo.lua:1.1.1.1 Mon May 10 03:30:04 2010
+++ src/libexec/httpd/lua/bozo.lua Fri Apr 15 19:38:13 2016
@@ -35,6 +35,7 @@ dofile "optparse.lua"
opt = OptionParser{usage="%prog [options] root [vhost]", version="20091105"}
opt.add_option{"-C", "--cgimap", action="store", dest="cgimap", help="--cgimap 's t'"}
+opt.add_option{"-E", "--enable-user-cgibin", action="store_true", dest="enableusercgibin", help="--enable-user-cgibin"}
opt.add_option{"-H", "--hide-dots", action="store_true", dest="hidedots", help="--hide-dots"}
opt.add_option{"-I", "--portnum", action="store", dest="portnum", help="--portnum number"}
opt.add_option{"-M", "--dynamicmime", action="store", dest="dynmime", help="--dynamicmime 'suffix type a b'"}
@@ -50,7 +51,6 @@ opt.add_option{"-f", "--foreground", act
opt.add_option{"-i", "--bindaddr", action="store", dest="bindaddress", help="--bindaddr address"}
opt.add_option{"-n", "--numeric", action="store_true", dest="numeric", help="--numeric"}
opt.add_option{"-p", "--public-html", action="store", dest="public_html", help="--public-html dir"}
-opt.add_option{"-r", "--trusted-referal", action="store_true", dest="trustedref", help="trusted referal"}
opt.add_option{"-s", "--logtostderr", action="store_true", dest="logstderr", help="log to stderr"}
opt.add_option{"-t", "--chroot", action="store", dest="chroot", help="--chroot dir"}
opt.add_option{"-u", "--enable-users", action="store_true", dest="enableusers", help="--enable-users"}
@@ -141,6 +141,9 @@ end
if options.hidedots then
bozohttpd.set_pref(prefs, "hide dots", "true")
end
+if options.enableusercgibin then
+ bozohttpd.set_pref(prefs, "enable user cgibin", "true")
+end
if options.dirindex then
bozohttpd.set_pref(prefs, "directory indexing", "true")
end
Index: src/libexec/httpd/lua/glue.c
diff -u src/libexec/httpd/lua/glue.c:1.1.1.1 src/libexec/httpd/lua/glue.c:1.1.1.1.14.1
--- src/libexec/httpd/lua/glue.c:1.1.1.1 Mon May 10 03:30:04 2010
+++ src/libexec/httpd/lua/glue.c Fri Apr 15 19:38:13 2016
@@ -92,11 +92,13 @@ l_init_httpd(lua_State *L)
static int
l_init_prefs(lua_State *L)
{
+ bozohttpd_t *httpd;
bozoprefs_t *prefs;
prefs = lua_newuserdata(L, sizeof(*prefs));
(void) memset(prefs, 0x0, sizeof(*prefs));
- (void) bozo_init_prefs(prefs);
+ httpd = lua_touserdata(L, 1);
+ (void) bozo_init_prefs(httpd, prefs);
return 1;
}
Index: src/libexec/httpd/testsuite/Makefile
diff -u src/libexec/httpd/testsuite/Makefile:1.4 src/libexec/httpd/testsuite/Makefile:1.4.14.1
--- src/libexec/httpd/testsuite/Makefile:1.4 Sat May 23 02:26:03 2009
+++ src/libexec/httpd/testsuite/Makefile Fri Apr 15 19:38:13 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/t10.out
diff -u src/libexec/httpd/testsuite/t10.out:1.1.1.1 src/libexec/httpd/testsuite/t10.out:1.1.1.1.16.1
--- src/libexec/httpd/testsuite/t10.out:1.1.1.1 Sat Apr 18 07:09:27 2009
+++ src/libexec/httpd/testsuite/t10.out Fri Apr 15 19:38:13 2016
@@ -1,8 +1,8 @@
-HTTP/1.0 500 Internal Error
+HTTP/1.0 404 Not Found
Content-Type: text/html
-Content-Length: 10296
-Server: bozohttpd/20090417
+Content-Length: 1024
+Server: bozohttpd/20140708
-<html><head><title>500 Internal Error</title></head>
-<body><h1>500 Internal Error</h1>
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\ No newline at end of file
+<html><head><title>404 Not Found</title></head>
+<body><h1>404 Not Found</h1>
+/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\ No newline at end of file
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.14.1
--- src/libexec/httpd/testsuite/test-bigfile:1.1.1.1 Sat May 23 02:21:19 2009
+++ src/libexec/httpd/testsuite/test-bigfile Fri Apr 15 19:38:13 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