Module Name: src
Committed By: mrg
Date: Sat Apr 18 07:28:24 UTC 2009
Modified Files:
src/libexec/httpd: auth-bozo.c bozohttpd.8 bozohttpd.c bozohttpd.h
cgi-bozo.c content-bozo.c daemon-bozo.c dir-index-bozo.c ssl-bozo.c
tilde-luzah-bozo.c
Log Message:
merge bozohttpd 20090417
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/libexec/httpd/auth-bozo.c \
src/libexec/httpd/daemon-bozo.c src/libexec/httpd/ssl-bozo.c \
src/libexec/httpd/tilde-luzah-bozo.c
cvs rdiff -u -r1.10 -r1.11 src/libexec/httpd/bozohttpd.8
cvs rdiff -u -r1.11 -r1.12 src/libexec/httpd/bozohttpd.c \
src/libexec/httpd/cgi-bozo.c
cvs rdiff -u -r1.7 -r1.8 src/libexec/httpd/bozohttpd.h
cvs rdiff -u -r1.3 -r1.4 src/libexec/httpd/content-bozo.c
cvs rdiff -u -r1.5 -r1.6 src/libexec/httpd/dir-index-bozo.c
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/auth-bozo.c
diff -u src/libexec/httpd/auth-bozo.c:1.4 src/libexec/httpd/auth-bozo.c:1.5
--- src/libexec/httpd/auth-bozo.c:1.4 Mon Mar 3 22:15:08 2008
+++ src/libexec/httpd/auth-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: auth-bozo.c,v 1.4 2008/03/03 22:15:08 mrg Exp $ */
+/* $NetBSD: auth-bozo.c,v 1.5 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: auth-bozo.c,v 1.8 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: auth-bozo.c,v 1.12 2009/04/17 22:52:19 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -53,7 +51,7 @@
/*
* Check if HTTP authentication is required
*/
-void
+int
auth_check(http_req *request, const char *file)
{
struct stat sb;
@@ -69,9 +67,10 @@
else {
*basename++ = '\0';
/* ensure basename(file) != AUTH_FILE */
- check_special_files(request, basename);
+ if (check_special_files(request, basename))
+ return 1;
}
- request->hr_authrealm = dir;
+ request->hr_authrealm = bozostrdup(dir);
snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE);
if (stat(authfile, &sb) < 0) {
@@ -81,7 +80,8 @@
return;
}
if ((fp = fopen(authfile, "r")) == NULL)
- http_error(403, request, "no permission to open authfile");
+ return http_error(403, request, "no permission to open "
+ "authfile");
debug((DEBUG_NORMAL,
"auth_check realm `%s' dir `%s' authfile `%s' open",
dir, file, authfile));
@@ -106,7 +106,21 @@
}
}
fclose(fp);
- http_error(401, request, "bad auth");
+ return http_error(401, request, "bad auth");
+}
+
+void
+auth_cleanup(http_req *request)
+{
+
+ if (request == NULL)
+ return;
+ if (request->hr_authuser)
+ free(request->hr_authuser);
+ if (request->hr_authpass)
+ free(request->hr_authpass);
+ if (request->hr_authrealm)
+ free(request->hr_authrealm);
}
int
@@ -124,7 +138,7 @@
authbuf[alen] = '\0';
if (alen == -1 ||
(pass = strchr(authbuf, ':')) == NULL)
- http_error(400, request,
+ return http_error(400, request,
"bad authorization field");
*pass++ = '\0';
request->hr_authuser = bozostrdup(authbuf);
@@ -138,11 +152,12 @@
return 0;
}
-void
+int
auth_check_special_files(http_req *request, const char *name)
{
if (strcmp(name, AUTH_FILE) == 0)
- http_error(403, request, "no permission to open authfile");
+ return http_error(403, request, "no permission to open authfile");
+ return 0;
}
void
@@ -160,7 +175,7 @@
{
if (request->hr_authuser && *request->hr_authuser) {
spsetenv("AUTH_TYPE", "Basic", (*curenvpp)++);
- spsetenv("REMOTEUSER", request->hr_authuser, (*curenvpp)++);
+ spsetenv("REMOTE_USER", request->hr_authuser, (*curenvpp)++);
}
}
Index: src/libexec/httpd/daemon-bozo.c
diff -u src/libexec/httpd/daemon-bozo.c:1.4 src/libexec/httpd/daemon-bozo.c:1.5
--- src/libexec/httpd/daemon-bozo.c:1.4 Fri May 2 19:14:03 2008
+++ src/libexec/httpd/daemon-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: daemon-bozo.c,v 1.4 2008/05/02 19:14:03 degroote Exp $ */
+/* $NetBSD: daemon-bozo.c,v 1.5 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: daemon-bozo.c,v 1.9 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: daemon-bozo.c,v 1.13 2009/04/17 22:52:20 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -116,7 +114,7 @@
/*
* the parent never returns from this function, only children that
- * are ready to run...
+ * are ready to run... XXXMRG - still true in fork-lesser bozo?
*/
void
daemon_fork()
Index: src/libexec/httpd/ssl-bozo.c
diff -u src/libexec/httpd/ssl-bozo.c:1.4 src/libexec/httpd/ssl-bozo.c:1.5
--- src/libexec/httpd/ssl-bozo.c:1.4 Sat May 10 19:25:20 2008
+++ src/libexec/httpd/ssl-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,6 +1,6 @@
-/* $NetBSD: ssl-bozo.c,v 1.4 2008/05/10 19:25:20 mlelstv Exp $ */
+/* $NetBSD: ssl-bozo.c,v 1.5 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: ssl-bozo.c,v 1.7 2008/03/03 03:36:12 mrg Exp $ */
+/* $eterna: ssl-bozo.c,v 1.9 2008/11/06 05:08:11 mrg Exp $ */
/*
* Copyright (c) 1997-2008 Matthew R. Green
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Index: src/libexec/httpd/tilde-luzah-bozo.c
diff -u src/libexec/httpd/tilde-luzah-bozo.c:1.4 src/libexec/httpd/tilde-luzah-bozo.c:1.5
--- src/libexec/httpd/tilde-luzah-bozo.c:1.4 Wed Feb 4 22:55:58 2009
+++ src/libexec/httpd/tilde-luzah-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: tilde-luzah-bozo.c,v 1.4 2009/02/04 22:55:58 tls Exp $ */
+/* $NetBSD: tilde-luzah-bozo.c,v 1.5 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: tilde-luzah-bozo.c,v 1.5 2008/03/03 03:36:12 mrg Exp $ */
+/* $eterna: tilde-luzah-bozo.c,v 1.10 2009/04/18 05:36:04 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -40,6 +38,7 @@
#include <errno.h>
#include <pwd.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -56,11 +55,13 @@
* user_transform does this:
* - chdir's /~user/public_html
* - returns the rest of the file, index.html appended if required
+ * - returned malloced file to serve in request->hr_file,
+ * ala transform_request().
*
* transform_request() is supposed to check that we have user support
* enabled.
*/
-char *
+int
user_transform(request, isindex)
http_req *request;
int *isindex;
@@ -81,19 +82,23 @@
/* fix this up immediately */
if (s)
s[-1] = '/';
- if (pw == NULL)
- http_error(404, request, "no such user");
+ if (pw == NULL) {
+ (void)http_error(404, request, "no such user");
+ return 0;
+ }
debug((DEBUG_OBESE, "user %s home dir %s uid %d gid %d", pw->pw_name,
pw->pw_dir, pw->pw_uid, pw->pw_gid));
if (chdir(pw->pw_dir) < 0) {
warning("chdir1 error: %s: %s", pw->pw_dir, strerror(errno));
- http_error(403, request, "can't chdir to homedir");
+ (void)http_error(403, request, "can't chdir to homedir");
+ return 0;
}
if (chdir(public_html) < 0) {
warning("chdir2 error: %s: %s", public_html, strerror(errno));
- http_error(403, request, "can't chdir to public_html");
+ (void)http_error(403, request, "can't chdir to public_html");
+ return 0;
}
if (s == NULL || *s == '\0') {
file = bozostrdup(index_html);
@@ -107,13 +112,22 @@
/* see transform_request() */
if (*file == '/' || strcmp(file, "..") == 0 ||
- strstr(file, "/..") || strstr(file, "../"))
- http_error(403, request, "illegal request");
+ strstr(file, "/..") || strstr(file, "../")) {
+ (void)http_error(403, request, "illegal request");
+ free(file);
+ return 0;
+ }
+
+ if (auth_check(request, file)) {
+ free(file);
+ return 0;
+ }
- auth_check(request, file);
+ free(request->hr_file);
+ request->hr_file = file;
debug((DEBUG_FAT, "transform_user returning %s under %s", file,
pw->pw_dir));
- return (file);
+ return 1;
}
#endif /* NO_USER_SUPPORT */
Index: src/libexec/httpd/bozohttpd.8
diff -u src/libexec/httpd/bozohttpd.8:1.10 src/libexec/httpd/bozohttpd.8:1.11
--- src/libexec/httpd/bozohttpd.8:1.10 Thu Apr 16 21:26:57 2009
+++ src/libexec/httpd/bozohttpd.8 Sat Apr 18 07:28:24 2009
@@ -1,8 +1,8 @@
-.\" $NetBSD: bozohttpd.8,v 1.10 2009/04/16 21:26:57 snj Exp $
+.\" $NetBSD: bozohttpd.8,v 1.11 2009/04/18 07:28:24 mrg Exp $
.\"
-.\" $eterna: bozohttpd.8,v 1.78 2008/03/03 03:36:11 mrg Exp $
+.\" $eterna: bozohttpd.8,v 1.84 2009/04/18 01:48:18 mrg Exp $
.\"
-.\" Copyright (c) 1997-2008 Matthew R. Green
+.\" Copyright (c) 1997-2009 Matthew R. Green
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -13,8 +13,6 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -28,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 6, 2008
+.Dd April 17, 2009
.Dt HTTPD 8
.Os
.Sh NAME
@@ -363,7 +361,7 @@
distributed with
.Nx
has support for HTTP Basic Authorisation enabled by default,
-the portable distribution it is excluded.
+in the portable distribution it is excluded.
Compile
.Nm
with
@@ -425,6 +423,30 @@
.Pp
To use
.Nm
+has support for SSLv2, SSLv3, and TLSv1 protocols that is included by
+default. It requires linking with the crypto and ssl library, using
+.Dq -lcrypto -lssl .
+To disable SSL SUPPORT compile
+.Nm
+with
+.Dq -DNO_SSL_SUPPORT
+on the compiler command line.
+.Sh EXAMPLES
+To configure set of virtual hosts, one would use an
+.Xr inetd.conf 5
+entry like:
+.Bd -literal
+http stream tcp nowait:600 httpd /usr/pkg/libexec/bozohttpd bozohttpd -v /var/vroot /var/www
+.Ed
+.Pp
+and inside
+.Pa /var/vroot
+create a directory (or a symlink to a directory) with the same name as
+the virtual host, for each virtual host.
+Lookups for these names are done in a case-insensitive manner.
+.Pp
+To use
+.Nm
with PHP, one must use the
.Fl C
option to specify a CGI handler for a particular file type.
@@ -438,22 +460,21 @@
.Sh HISTORY
The
.Nm
-program was first written in perl, based on another perl http server
+program is actually called
+.Dq bozohttpd .
+It 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.
-It was known for many years as
-.Dq bozohttpd .
+From
.Dq bozohttpd
-version 20060517 was integrated into
-.Nx 5.0
-as
-.Nm .
+version 20060517, it has been integrated into
+.Nx .
The focus has always been simplicity and security, with minimal features
and regular code audits.
This manual documents
.Nm
-version 20080303.
+version 20090417.
.Sh AUTHORS
.Nm
was written by Matthew R. Green
@@ -478,6 +499,10 @@
.Aq [email protected]
provided cgi-bin support fixes, and more
.It
+DEGROOTE Arnaud
+.Aq [email protected]
+provided a fix for daemon mode
+.It
Andrew Doran
.Aq [email protected]
provided directory indexing support
@@ -486,10 +511,6 @@
.Aq [email protected]
provided a fix for a minor (non-security) buffer overflow condition
.It
-Zak Johnson
-.Aq [email protected]
-provided cgi-bin enhancements
-.It
Jun-ichiro itojun Hagino, KAME
.Aq [email protected]
provided initial IPv6 support
@@ -498,10 +519,18 @@
.Aq [email protected]
provided .bzabsredirect support
.It
+Arto Huusko
+.Aq [email protected]
+provided fixes cgi-bin
+.It
Roland Illig
.Aq [email protected]
provided some off-by-one fixes
.It
+Zak Johnson
+.Aq [email protected]
+provided cgi-bin enhancements
+.It
Nicolas Jombart
.Aq [email protected]
provided fixes for HTTP basic authorisation support
@@ -537,15 +566,31 @@
.Fl V
option.
.It
+Joerg Sonnenberger
+.Aq [email protected]
+implemented If-Modified-Since support
+.It
ISIHARA Takanori
.Aq [email protected]
provided a man page fix
.It
+Holger Weiss
+.Aq [email protected]
+provided http authorisation fixes
+.It
.Aq [email protected]
provided chroot and change-to-user support, and other various fixes
+.It
+Coyote Point provided various CGI fixes
.El
.Pp
There are probably others I have forgotten (let me know if you care)
+.Pp
+Please send all updates to
+.Nm
+to
+.Aq [email protected]
+for inclusion in future releaases.
.Sh BUGS
.Nm
does not handled HTTP/1.1 chunked input from the client yet.
Index: src/libexec/httpd/bozohttpd.c
diff -u src/libexec/httpd/bozohttpd.c:1.11 src/libexec/httpd/bozohttpd.c:1.12
--- src/libexec/httpd/bozohttpd.c:1.11 Mon Mar 23 12:49:28 2009
+++ src/libexec/httpd/bozohttpd.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: bozohttpd.c,v 1.11 2009/03/23 12:49:28 reinoud Exp $ */
+/* $NetBSD: bozohttpd.c,v 1.12 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: bozohttpd.c,v 1.142 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: bozohttpd.c,v 1.152 2009/04/18 05:36:04 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -111,7 +109,7 @@
#define INDEX_HTML "index.html"
#endif
#ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE "bozohttpd/20080303"
+#define SERVER_SOFTWARE "bozohttpd/20090417"
#endif
#ifndef DIRECT_ACCESS_FILE
#define DIRECT_ACCESS_FILE ".bzdirect"
@@ -195,29 +193,26 @@
volatile sig_atomic_t alarmhit;
static void parse_request(char *, char **, char **, char **, char **);
+static void clean_request(http_req *request);
static http_req *read_request(void);
-static struct headers *addmerge_header(http_req *request, char *val,
- char *str, ssize_t len);
+static struct headers *addmerge_header(http_req *, char *, char *, ssize_t);
+static int mmap_and_write_part(int, off_t, size_t);
static void process_request(http_req *);
static int check_direct_access(http_req *request);
-static char *transform_request(http_req *, int *);
+static int transform_request(http_req *, int *);
static void handle_redirect(http_req *, const char *, int);
-static void check_virtual(http_req *);
+static int check_virtual(http_req *);
static void check_bzredirect(http_req *);
static void fix_url_percent(http_req *);
-static void process_method(http_req *, const char *);
-static void process_proto(http_req *, const char *);
+static int process_proto(http_req *, const char *);
+static int process_method(http_req *, const char *);
static void escape_html(http_req *);
static const char *http_errors_short(int);
static const char *http_errors_long(int);
-void *bozomalloc(size_t);
-void *bozorealloc(void *, size_t);
-char *bozostrdup(const char *);
-
/* bozotic io */
int (*bozoprintf)(const char *, ...) = printf;
ssize_t (*bozoread)(int, void *, size_t) = read;
@@ -277,7 +272,7 @@
int
main(int argc, char **argv)
{
- http_req *http_request;
+ http_req *request;
extern char **environ;
char *cleanenv[1];
uid_t uid;
@@ -531,9 +526,10 @@
* read and process the HTTP request.
*/
do {
- http_request = read_request();
- if (http_request) {
- process_request(http_request);
+ request = read_request();
+ if (request) {
+ process_request(request);
+ clean_request(request);
return (0);
}
} while (bflag);
@@ -556,7 +552,9 @@
}
/*
- * convert "in" into the three parts of a request (first line)
+ * convert "in" into the three parts of a request (first line).
+ * we allocate into file and query, but return pointers into
+ * "in" for proto and method.
*/
static void
parse_request(char *in, char **method, char **file, char **query, char **proto)
@@ -564,13 +562,15 @@
ssize_t len;
char *val;
- *method = *file = *query = *proto = NULL; /* set them up */
+ debug((DEBUG_EXPLODING, "parse in: %s", in));
+ *method = *file = *query = *proto = NULL;
len = (ssize_t)strlen(in);
val = bozostrnsep(&in, " \t\n\r", &len);
if (len < 1 || val == NULL)
return;
*method = val;
+
while (*in == ' ' || *in == '\t')
in++;
val = bozostrnsep(&in, " \t\n\r", &len);
@@ -581,23 +581,26 @@
*file = in;
return;
}
-
*file = val;
+
*query = strchr(*file, '?');
- if (*query) {
- *query = *query + 1;
- *(*query - 1) = '\0';
- }
+ if (*query)
+ *(*query)++ = '\0';
if (in) {
while (*in && (*in == ' ' || *in == '\t'))
in++;
if (*in)
*proto = in;
- }
- debug((DEBUG_FAT, "URL INFO: |m: %s |f: %s |q: %s |p: %s |",
- *method, *file, *query, *proto));
+ }
+ /* allocate private copies */
+ *file = strdup(*file);
+ if (*query)
+ *query = strdup(*query);
+
+ debug((DEBUG_FAT, "url: method: \"%s\" file: \"%s\" query: \"%s\" proto: \"%s\"",
+ *method, *file, *query, *proto));
}
/*
@@ -611,6 +614,40 @@
}
/*
+ * cleanup a http_req after use
+ */
+static void
+clean_request(http_req *request)
+{
+ struct headers *hdr, *ohdr = NULL;
+
+ if (request == NULL)
+ return;
+
+ /* clean up request */
+#define MF(x) if (request->x) free(request->x)
+ MF(hr_remotehost);
+ MF(hr_remoteaddr);
+ MF(hr_serverport);
+ MF(hr_file);
+ MF(hr_query);
+#undef MF
+ auth_cleanup(request);
+ for (hdr = SIMPLEQ_FIRST(&request->hr_headers); hdr;
+ hdr = SIMPLEQ_NEXT(hdr, h_next)) {
+ free(hdr->h_value);
+ free(hdr->h_header);
+ if (ohdr)
+ free(ohdr);
+ ohdr = hdr;
+ }
+ if (ohdr)
+ free(ohdr);
+
+ free(request);
+}
+
+/*
* This function reads a http request from stdin, returning a pointer to a
* http_req structure, describing the request.
*/
@@ -640,8 +677,9 @@
request->hr_allow = request->hr_host = NULL;
request->hr_content_type = request->hr_content_length = NULL;
request->hr_range = NULL;
- request->hr_if_modified_since = NULL;
request->hr_last_byte_pos = -1;
+ request->hr_if_modified_since = NULL;
+ request->hr_file = NULL;
slen = sizeof(ss);
if (getpeername(0, (struct sockaddr *)&ss, &slen) < 0)
@@ -687,38 +725,54 @@
alarm(MAX_WAIT_TIME);
while ((str = bozodgetln(STDIN_FILENO, &len, bozoread)) != NULL) {
alarm(0);
- if (alarmhit)
- http_error(408, NULL, "request timed out");
+ if (alarmhit) {
+ (void)http_error(408, NULL, "request timed out");
+ goto cleanup;
+ }
line++;
if (line == 1) {
- str = bozostrdup(str); /* we use this copy */
- if (len < 1)
- http_error(404, NULL, "null method");
+ if (len < 1) {
+ (void)http_error(404, NULL, "null method");
+ goto cleanup;
+ }
+
warning("got request ``%s'' from host %s to port %s",
str,
host ? host : addr ? addr : "<local>",
port ? port : "<stdin>");
+#if 0
debug((DEBUG_FAT, "read_req, getting request: ``%s''",
str));
+#endif
+ /* we allocate return space in file and query only */
parse_request(str, &method, &file, &query, &proto);
-
- if (method == NULL)
- http_error(404, NULL, "null method");
- if (file == NULL)
- http_error(404, NULL, "null file");
+ request->hr_file = file;
+ request->hr_query = query;
+ if (method == NULL) {
+ (void)http_error(404, NULL, "null method");
+ goto cleanup;
+ }
+ if (file == NULL) {
+ (void)http_error(404, NULL, "null file");
+ goto cleanup;
+ }
/*
* note that we parse the proto first, so that we
* can more properly parse the method and the url.
*/
- request->hr_file = file;
- request->hr_query = query;
- process_proto(request, proto);
- process_method(request, method);
+ if (process_proto(request, proto) ||
+ process_method(request, method)) {
+ goto cleanup;
+ }
+
+ debug((DEBUG_FAT, "got file \"%s\" query \"%s\"",
+ request->hr_file,
+ request->hr_query ? request->hr_query : "<none>"));
/* http/0.9 has no header processing */
if (request->hr_proto == http_09)
@@ -733,8 +787,10 @@
debug((DEBUG_EXPLODING,
"read_req2: after bozostrnsep: str ``%s'' val ``%s''",
str, val));
- if (val == NULL || len == -1)
- http_error(404, request, "no header");
+ if (val == NULL || len == -1) {
+ (void)http_error(404, request, "no header");
+ goto cleanup;
+ }
while (*str == ' ' || *str == '\t')
len--, str++;
while (*val == ' ' || *val == '\t')
@@ -752,8 +808,10 @@
else if (strcasecmp(hdr->h_header, "host") == 0)
request->hr_host = hdr->h_value;
/* HTTP/1.1 rev06 draft spec: 14.20 */
- else if (strcasecmp(hdr->h_header, "expect") == 0)
- http_error(417, request, "we don't support Expect:");
+ else if (strcasecmp(hdr->h_header, "expect") == 0) {
+ (void)http_error(417, request, "we don't support Expect:");
+ goto cleanup;
+ }
else if (strcasecmp(hdr->h_header, "referrer") == 0 ||
strcasecmp(hdr->h_header, "referer") == 0)
request->hr_referrer = hdr->h_value;
@@ -774,12 +832,44 @@
signal(SIGALRM, SIG_DFL);
/* RFC1945, 8.3 */
- if (request->hr_method == HTTP_POST && request->hr_content_length == NULL)
- http_error(400, request, "missing content length");
+ if (request->hr_method == HTTP_POST && request->hr_content_length == NULL) {
+ (void)http_error(400, request, "missing content length");
+ goto cleanup;
+ }
/* HTTP/1.1 draft rev-06, 14.23 & 19.6.1.1 */
- if (request->hr_proto == http_11 && request->hr_host == NULL)
- http_error(400, request, "missing Host header");
+ if (request->hr_proto == http_11 && request->hr_host == NULL) {
+ (void)http_error(400, request, "missing Host header");
+ goto cleanup;
+ }
+
+ if (request->hr_range != NULL) {
+ debug((DEBUG_FAT, "hr_range: %s", request->hr_range));
+ /* support only simple ranges %d- and %d-%d */
+ if (strchr(request->hr_range, ',') == NULL) {
+ const char *rstart, *dash;
+
+ rstart = strchr(request->hr_range, '=');
+ if (rstart != NULL) {
+ rstart++;
+ dash = strchr(rstart, '-');
+ if (dash != NULL && dash != rstart) {
+ dash++;
+ request->hr_have_range = 1;
+ request->hr_first_byte_pos =
+ strtoll(rstart, NULL, 10);
+ if (request->hr_first_byte_pos < 0)
+ request->hr_first_byte_pos = 0;
+ if (*dash != '\0') {
+ request->hr_last_byte_pos =
+ strtoll(dash, NULL, 10);
+ if (request->hr_last_byte_pos < 0)
+ request->hr_last_byte_pos = -1;
+ }
+ }
+ }
+ }
+ }
if (request->hr_range != NULL) {
debug((DEBUG_FAT, "hr_range: %s", request->hr_range));
@@ -812,6 +902,14 @@
debug((DEBUG_FAT, "read_request returns url %s in request",
request->hr_file));
return (request);
+
+cleanup:
+ clean_request(request);
+
+ /* If SSL enabled cleanup SSL structure. */
+ ssl_destroy();
+
+ return NULL;
}
/*
@@ -821,7 +919,6 @@
addmerge_header(http_req *request, char *val, char *str, ssize_t len)
{
struct headers *hdr;
- static char space[2] = { ' ', 0 };
/* do we exist already? */
SIMPLEQ_FOREACH(hdr, &request->hr_headers, h_next) {
@@ -831,17 +928,15 @@
if (hdr) {
/* yup, merge it in */
- if (hdr->h_value == space)
- hdr->h_value = bozostrdup(str);
- else {
- char *nval;
+ char *nval;
- if (asprintf(&nval, "%s, %s", hdr->h_value, str) == -1)
- http_error(500, NULL,
- "memory allocation failure");
- free(hdr->h_value);
- hdr->h_value = nval;
+ if (asprintf(&nval, "%s, %s", hdr->h_value, str) == -1) {
+ (void)http_error(500, NULL,
+ "memory allocation failure");
+ return NULL;
}
+ free(hdr->h_value);
+ hdr->h_value = nval;
} else {
/* nope, create a new one */
@@ -850,7 +945,7 @@
if (str && *str)
hdr->h_value = bozostrdup(str);
else
- hdr->h_value = space;
+ hdr->h_value = bozostrdup(" ");
SIMPLEQ_INSERT_TAIL(&request->hr_headers, hdr, h_next);
request->hr_nheaders++;
@@ -860,6 +955,47 @@
}
static int
+mmap_and_write_part(int fd, off_t first_byte_pos, size_t sz)
+{
+ size_t mappedsz;
+ char *addr;
+ void *oaddr;
+
+ addr = mmap(0, sz, PROT_READ, MAP_SHARED, fd, first_byte_pos);
+ if (addr == (char *)-1) {
+ warning("mmap failed: %s", strerror(errno));
+ return -1;
+ }
+ oaddr = addr;
+ mappedsz = sz;
+
+#ifdef MADV_SEQUENTIAL
+ (void)madvise(addr, sz, MADV_SEQUENTIAL);
+#endif
+ while (sz > WRSZ) {
+ if (bozowrite(STDOUT_FILENO, addr, WRSZ) != WRSZ) {
+ warning("write failed: %s", strerror(errno));
+ goto out;
+ }
+ debug((DEBUG_OBESE, "wrote %d bytes", WRSZ));
+ sz -= WRSZ;
+ addr += WRSZ;
+ }
+ if (sz && (size_t)bozowrite(STDOUT_FILENO, addr, sz) != sz) {
+ warning("final write failed: %s", strerror(errno));
+ goto out;
+ }
+ debug((DEBUG_OBESE, "wrote %d bytes", (int)sz));
+ out:
+ if (munmap(oaddr, mappedsz) < 0) {
+ warning("munmap failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
parse_http_date(const char *val, time_t *timestamp)
{
char *remainder;
@@ -895,30 +1031,37 @@
/*
* note that transform_request chdir()'s if required. also note
- * that cgi is handed here, and a cgi request will never return
- * back here.
+ * that cgi is handed here. if transform_request() returns 0
+ * then the request has been handled already.
*/
- file = transform_request(request, &isindex);
- if (file == NULL)
- http_error(404, request, "empty file after transform");
+ if (transform_request(request, &isindex) == 0)
+ return;
+
+ file = request->hr_file;
fd = open(file, O_RDONLY);
if (fd < 0) {
debug((DEBUG_FAT, "open failed: %s", strerror(errno)));
if (errno == EPERM)
- http_error(403, request, "no permission to open file");
+ (void)http_error(403, request, "no permission to open file");
else if (errno == ENOENT) {
- if (directory_index(request, file, isindex))
- return;
- http_error(404, request, "no file");
+ if (directory_index(request, file, isindex))
+ ;
+ else
+ (void)http_error(404, request, "no file");
} else
- http_error(500, request, "open file");
+ (void)http_error(500, request, "open file");
+ return;
+ }
+ if (fstat(fd, &sb) < 0) {
+ (void)http_error(500, request, "can't fstat");
+ goto cleanup;
}
- if (fstat(fd, &sb) < 0)
- http_error(500, request, "can't fstat");
- if (S_ISDIR(sb.st_mode))
+ if (S_ISDIR(sb.st_mode)) {
handle_redirect(request, NULL, 0);
- /* NOTREACHED */
+ goto cleanup;
+ }
+
if (request->hr_if_modified_since &&
parse_http_date(request->hr_if_modified_since, ×tamp) &&
timestamp >= sb.st_mtime) {
@@ -926,7 +1069,7 @@
bozoprintf("%s 304 Not Modified\r\n", request->hr_proto);
bozoprintf("\r\n");
bozoflush(stdout);
- exit(0);
+ goto cleanup;
}
/* validate requested range */
@@ -957,37 +1100,27 @@
bozoflush(stdout);
if (request->hr_method != HTTP_HEAD) {
- char *addr;
- void *oaddr;
- size_t mappedsz;
- size_t sz;
-
- sz = mappedsz = request->hr_last_byte_pos - request->hr_first_byte_pos + 1;
- oaddr = addr = mmap(0, mappedsz, PROT_READ,
- MAP_SHARED, fd, request->hr_first_byte_pos);
- if (addr == (char *)-1)
- error(1, "mmap failed: %s", strerror(errno));
+ off_t szleft, cur_byte_pos;
-#ifdef MADV_SEQUENTIAL
- madvise(addr, sz, MADV_SEQUENTIAL);
-#endif
- while (sz > WRSZ) {
- if (bozowrite(STDOUT_FILENO, addr, WRSZ) != WRSZ)
- error(1, "write failed: %s", strerror(errno));
- debug((DEBUG_OBESE, "wrote %d bytes", WRSZ));
- sz -= WRSZ;
- addr += WRSZ;
- }
- if (sz && (size_t)bozowrite(STDOUT_FILENO, addr, sz) != sz)
- error(1, "final write failed: %s", strerror(errno));
- debug((DEBUG_OBESE, "wrote %d bytes", (int)sz));
- if (munmap(oaddr, mappedsz) < 0)
- warning("munmap failed");
+ szleft =
+ request->hr_last_byte_pos - request->hr_first_byte_pos + 1;
+ cur_byte_pos = request->hr_first_byte_pos;
+
+ while (szleft) {
+ size_t sz;
+
+ if (MMAPSZ < szleft)
+ sz = MMAPSZ;
+ else
+ sz = szleft;
+ if (mmap_and_write_part(fd, cur_byte_pos, sz))
+ goto cleanup;
+ cur_byte_pos += sz;
+ szleft -= sz;
+ }
}
- /* If SSL enabled cleanup SSL structure. */
- ssl_destroy();
+cleanup:
close(fd);
- free(file);
}
/*
@@ -997,7 +1130,7 @@
* directory exists under vpath. if it does, use this as the
# new slashdir.
*/
-static void
+static int
check_virtual(http_req *request)
{
char *file = request->hr_file, *s;
@@ -1052,7 +1185,7 @@
if (s == 0) {
if (Vflag)
goto use_slashdir;
- http_error(404, request, "unknown URL");
+ return http_error(404, request, "unknown URL");
}
} else
use_slashdir:
@@ -1062,24 +1195,25 @@
* ok, nailed the correct slashdir, chdir to it
*/
if (chdir(s) < 0)
- error(1, "can't chdir %s: %s", s, strerror(errno));
+ return http_error(404, request, "can't chdir to slashdir");
+ return 0;
}
/* make sure we're not trying to access special files */
-void
+int
check_special_files(http_req *request, const char *name)
{
/* ensure basename(name) != special files */
if (strcmp(name, DIRECT_ACCESS_FILE) == 0)
- http_error(403, request,
+ return http_error(403, request,
"no permission to open direct access file");
if (strcmp(name, REDIRECT_FILE) == 0)
- http_error(403, request,
+ return http_error(403, request,
"no permission to open redirect file");
if (strcmp(name, ABSREDIRECT_FILE) == 0)
- http_error(403, request,
+ return http_error(403, request,
"no permission to open redirect file");
- auth_check_special_files(request, name);
+ return auth_check_special_files(request, name);
}
/*
@@ -1190,23 +1324,27 @@
* - disallow anything ending up with a file starting
* at "/" or having ".." in it.
* - anything else is a really weird internal error
+ * - returns malloced file to serve, if unhandled
*/
-static char *
+int
transform_request(http_req *request, int *isindex)
{
- char *new_file; // the new file name we're going to fetch
- char *req_file; // the original file in the request
+ char *file, *newfile = NULL;
size_t len;
- new_file = NULL;
+ file = NULL;
*isindex = 0;
- debug((DEBUG_FAT, "tf_req: url %s", request->hr_file));
+ debug((DEBUG_FAT, "tf_req: file %s", request->hr_file));
fix_url_percent(request);
- check_virtual(request);
- req_file = request->hr_file;
+ if (check_virtual(request)) {
+ goto bad_done;
+ }
+ file = request->hr_file;
- if (req_file[0] != '/')
- http_error(404, request, "unknown URL");
+ if (file[0] != '/') {
+ (void)http_error(404, request, "unknown URL");
+ goto bad_done;
+ }
check_bzredirect(request);
@@ -1233,14 +1371,14 @@
"checking referrer \"%s\" vs myname %s", r, myname));
if (strncmp(r, "http://", 7) != 0 ||
(strncasecmp(r + 7, myname, strlen(myname)) != 0 &&
- !TOP_PAGE(req_file)))
+ !TOP_PAGE(file)))
to_indexhtml = 1;
} else {
const char *h = request->hr_host;
debug((DEBUG_FAT, "url has no referrer at all"));
/* if there's no referrer, let / or /index.html past */
- if (!TOP_PAGE(req_file) ||
+ if (!TOP_PAGE(file) ||
(h && strncasecmp(h, myname, strlen(myname)) != 0))
to_indexhtml = 1;
}
@@ -1250,43 +1388,52 @@
if (asprintf(&slashindexhtml, "/%s", index_html) < 0)
error(1, "asprintf");
- debug((DEBUG_FAT, "rflag: redirecting %s to %s", req_file, slashindexhtml));
+ debug((DEBUG_FAT, "rflag: redirecting %s to %s", file, slashindexhtml));
handle_redirect(request, slashindexhtml, 0);
- /* NOTREACHED */
+ free(slashindexhtml);
+ return 0;
}
}
- len = strlen(req_file);
+ len = strlen(file);
if (0) {
#ifndef NO_USER_SUPPORT
- } else if (len > 1 && uflag && req_file[1] == '~') {
- if (req_file[2] == '\0')
- http_error(404, request, "missing username");
- if (strchr(req_file + 2, '/') == NULL)
+ } else if (len > 1 && uflag && file[1] == '~') {
+ if (file[2] == '\0') {
+ (void)http_error(404, request, "missing username");
+ goto bad_done;
+ }
+ if (strchr(file + 2, '/') == NULL) {
handle_redirect(request, NULL, 0);
- /* NOTREACHED */
+ return 0;
+ }
debug((DEBUG_FAT, "calling user_transform"));
+
return (user_transform(request, isindex));
#endif /* NO_USER_SUPPORT */
} else if (len > 1) {
- debug((DEBUG_FAT, "url[len-1] == %c", req_file[len-1]));
- if (req_file[len-1] == '/') { /* append index.html */
+ debug((DEBUG_FAT, "file[len-1] == %c", file[len-1]));
+ if (file[len-1] == '/') { /* append index.html */
*isindex = 1;
debug((DEBUG_FAT, "appending index.html"));
- new_file = bozomalloc(len + strlen(index_html) + 1);
- strcpy(new_file, req_file + 1);
- strcat(new_file, index_html);
+ newfile = bozomalloc(len + strlen(index_html) + 1);
+ strcpy(newfile, file + 1);
+ strcat(newfile, index_html);
} else
- new_file = bozostrdup(req_file + 1);
+ newfile = bozostrdup(file + 1);
} else if (len == 1) {
debug((DEBUG_EXPLODING, "tf_req: len == 1"));
- new_file = bozostrdup(index_html);
+ newfile = bozostrdup(index_html);
*isindex = 1;
- } else /* len == 0 ? */
- http_error(500, request, "request->hr_file is nul?");
+ } else { /* len == 0 ? */
+ (void)http_error(500, request, "request->hr_file is nul?");
+ goto bad_done;
+ }
- if (new_file == NULL)
- http_error(500, request, "internal failure");
+ if (newfile == NULL) {
+ (void)http_error(500, request, "internal failure");
+ goto bad_done;
+ }
/*
* look for "http://myname/" and deal with it as necessary.
@@ -1298,21 +1445,28 @@
* XXX true security only comes from our parent using chroot(2)
* before execve(2)'ing us. or our own built in chroot(2) support.
*/
- if (*new_file == '/' || strcmp(new_file, "..") == 0 ||
- strstr(new_file, "/..") || strstr(new_file, "../"))
- http_error(403, request, "illegal request");
+ if (*newfile == '/' || strcmp(newfile, "..") == 0 ||
+ strstr(newfile, "/..") || strstr(newfile, "../")) {
+ (void)http_error(403, request, "illegal request");
+ goto bad_done;
+ }
- auth_check(request, new_file);
+ if (auth_check(request, newfile))
+ goto bad_done;
- if (new_file && strlen(new_file)) {
- free(request->hr_file);
- request->hr_file = new_file;
- }
+ if (strlen(newfile))
+ request->hr_file = newfile;
- process_cgi(request);
-
- debug((DEBUG_FAT, "transform_request returned: %s", new_file));
- return (new_file);
+ if (process_cgi(request))
+ return 0;
+
+ debug((DEBUG_FAT, "transform_request set: %s", newfile));
+ return 1;
+bad_done:
+ debug((DEBUG_FAT, "transform_request returning: 0"));
+ if (newfile)
+ free(newfile);
+ return 0;
}
/*
@@ -1325,15 +1479,16 @@
char *urlbuf;
char portbuf[20];
int query = 0;
-
+
if (url == NULL) {
if (asprintf(&urlbuf, "/%s/", request->hr_file) < 0)
error(1, "asprintf");
url = urlbuf;
- }
-
+ } else
+ urlbuf = NULL;
+
if (request->hr_query && strlen(request->hr_query)) {
- query = 1;
+ query = 1;
}
if (request->hr_serverport && strcmp(request->hr_serverport, "80") != 0)
@@ -1377,7 +1532,8 @@
bozoprintf("</body></html>\n");
head:
bozoflush(stdout);
- exit(0);
+ if (urlbuf)
+ free(urlbuf);
}
/* generic header printing routine */
@@ -1471,10 +1627,7 @@
}
tmp[j] = 0;
- /*
- * original "url" is a substring of an allocation, so we
- * can't touch it. so, ignore it and replace the request.
- */
+ free(request->hr_file);
request->hr_file = tmp;
}
@@ -1503,22 +1656,30 @@
}
debug((DEBUG_EXPLODING, "fu_%%: got s == %%, s[1]s[2] == %c%c",
s[1], s[2]));
- if (s[1] == '\0' || s[2] == '\0')
- http_error(400, request,
+ if (s[1] == '\0' || s[2] == '\0') {
+ (void)http_error(400, request,
"percent hack missing two chars afterwards");
- if (s[1] == '0' && s[2] == '0')
- http_error(404, request, "percent hack was %00");
- if (s[1] == '2' && s[2] == 'f')
- http_error(404, request, "percent hack was %2f (/)");
+ goto copy_rest;
+ }
+ if (s[1] == '0' && s[2] == '0') {
+ (void)http_error(404, request, "percent hack was %00");
+ goto copy_rest;
+ }
+ if (s[1] == '2' && s[2] == 'f') {
+ (void)http_error(404, request, "percent hack was %2f (/)");
+ goto copy_rest;
+ }
buf[0] = *++s;
buf[1] = *++s;
buf[2] = '\0';
s++;
*t = (char)strtol(buf, NULL, 16);
- debug((DEBUG_EXPLODING, "fu_%%: strtol put '%c' into *t", *t));
- if (*t++ == '\0')
- http_error(400, request, "percent hack got a 0 back");
+ debug((DEBUG_EXPLODING, "fu_%%: strtol put '%02x' into *t", *t));
+ if (*t++ == '\0') {
+ (void)http_error(400, request, "percent hack got a 0 back");
+ goto copy_rest;
+ }
while (*s && *s != '%') {
if (end && s >= end)
@@ -1526,6 +1687,12 @@
*t++ = *s++;
}
} while (*s);
+copy_rest:
+ while (*s) {
+ if (s >= end)
+ break;
+ *t++ = *s++;
+ }
*t = '\0';
debug((DEBUG_FAT, "fix_url_percent returns %s in url", request->hr_file));
}
@@ -1551,28 +1718,29 @@
{ NULL, 0, },
};
-static void
+static int
process_method(http_req *request, const char *method)
{
struct method_map *mmp;
+ if (request->hr_proto == http_11)
+ request->hr_allow = "GET, HEAD, POST";
+
for (mmp = method_map; mmp->name; mmp++)
if (strcasecmp(method, mmp->name) == 0) {
request->hr_method = mmp->type;
request->hr_methodstr = mmp->name;
- return;
+ return 0;
}
- if (request->hr_proto == http_11)
- request->hr_allow = "GET, HEAD, POST";
- http_error(404, request, "unknown method");
+ return http_error(404, request, "unknown method");
}
/*
* as the prototype string is not constant (eg, "HTTP/1.1" is equivalent
* to "HTTP/001.01"), we MUST parse this.
*/
-static void
+static int
process_proto(http_req *request, const char *proto)
{
char majorstr[16], *minorstr;
@@ -1582,7 +1750,7 @@
got_proto_09:
request->hr_proto = http_09;
debug((DEBUG_FAT, "request %s is http/0.9", request->hr_file));
- return;
+ return 0;
}
if (strncasecmp(proto, "HTTP/", 5) != 0)
@@ -1614,10 +1782,10 @@
request->hr_proto));
SIMPLEQ_INIT(&request->hr_headers);
request->hr_nheaders = 0;
- return;
+ return 0;
}
bad:
- http_error(404, NULL, "unknown prototype");
+ return http_error(404, NULL, "unknown prototype");
}
#ifdef DEBUG
@@ -1675,7 +1843,7 @@
/* the follow functions and variables are used in handling HTTP errors */
/* ARGSUSED */
-void
+int
http_error(int code, http_req *request, const char *msg)
{
static char buf[BUFSIZ];
@@ -1686,9 +1854,11 @@
int size;
debug((DEBUG_FAT, "http_error %d: %s", code, msg));
- if (header == NULL || reason == NULL)
+ if (header == NULL || reason == NULL) {
error(1, "http_error() failed (short = %p, long = %p)",
header, reason);
+ return code;
+ }
if (request && request->hr_serverport &&
strcmp(request->hr_serverport, "80") != 0)
@@ -1706,8 +1876,10 @@
"</body></html>\n",
header, header, request->hr_file, reason,
myname, portbuf, myname, portbuf);
- if (size >= (int)sizeof buf)
+ if (size >= (int)sizeof buf) {
warning("http_error buffer too small, truncated");
+ size = (int)sizeof buf;
+ }
} else
size = 0;
@@ -1724,7 +1896,7 @@
bozoprintf("%s", buf);
bozoflush(stdout);
- exit(1);
+ return code;
}
/* short map between error code, and short/long messages */
@@ -1885,8 +2057,10 @@
void *p;
p = realloc(ptr, size);
- if (p == NULL)
- http_error(500, NULL, "memory allocation failure");
+ if (p == NULL) {
+ (void)http_error(500, NULL, "memory allocation failure");
+ exit(1);
+ }
return (p);
}
@@ -1896,8 +2070,10 @@
void *p;
p = malloc(size);
- if (p == NULL)
- http_error(500, NULL, "memory allocation failure");
+ if (p == NULL) {
+ (void)http_error(500, NULL, "memory allocation failure");
+ exit(1);
+ }
return (p);
}
@@ -1907,7 +2083,9 @@
char *p;
p = strdup(str);
- if (p == NULL)
- http_error(500, NULL, "memory allocation failure");
+ if (p == NULL) {
+ (void)http_error(500, NULL, "memory allocation failure");
+ exit(1);
+ }
return (p);
}
Index: src/libexec/httpd/cgi-bozo.c
diff -u src/libexec/httpd/cgi-bozo.c:1.11 src/libexec/httpd/cgi-bozo.c:1.12
--- src/libexec/httpd/cgi-bozo.c:1.11 Wed Mar 11 06:53:25 2009
+++ src/libexec/httpd/cgi-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: cgi-bozo.c,v 1.11 2009/03/11 06:53:25 mrg Exp $ */
+/* $NetBSD: cgi-bozo.c,v 1.12 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: cgi-bozo.c,v 1.18 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: cgi-bozo.c,v 1.28 2009/04/18 05:36:04 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -85,9 +83,10 @@
/*
* Checks if the request has asked for a cgi-bin. Should only be called if
* cgibin is set. If it starts CGIBIN_PREFIX or has a ncontent handler,
- * process the cgi, otherwise just return.
+ * process the cgi, otherwise just return. Returns 0 if it did not handle
+ * the request.
*/
-void
+int
process_cgi(http_req *request)
{
char buf[WRSZ];
@@ -102,16 +101,19 @@
int sv[2];
if (!cgibin && !Cflag)
- return;
+ return 0;
asprintf(&file, "/%s", request->hr_file);
- if (request->hr_query && strlen(request->hr_query)) {
- query = bozostrdup(request->hr_query);
- } else {
- query = NULL;
- }
-
- asprintf(&url, "%s%c%s", file, query?'?':0, query);
+ if (file == NULL)
+ return 0;
+ if (request->hr_query && strlen(request->hr_query))
+ query = bozostrdup(request->hr_query);
+ else
+ query = NULL;
+
+ asprintf(&url, "%s%s%s", file, query ? "?" : "", query ? query : "");
+ if (url == NULL)
+ goto out;
debug((DEBUG_NORMAL, "process_cgi: url `%s'", url));
path = NULL;
@@ -121,14 +123,14 @@
info = NULL;
len = strlen(url);
- auth_check(request, url + 1);
+ if (auth_check(request, url + 1))
+ goto out;
+
if (!cgibin || strncmp(url + 1, CGIBIN_PREFIX, CGIBIN_PREFIX_LEN) != 0) {
cgihandler = content_cgihandler(request, file + 1);
if (cgihandler == NULL) {
- debug((DEBUG_FAT, "process_cgi: no handler, returning"));
- free(file);
- free(url);
- return;
+ debug((DEBUG_FAT, "process_cgi: no handler, returning"));
+ goto out;
}
if (len == 0 || file[len - 1] == '/')
append_index_html(&file);
@@ -136,6 +138,7 @@
cgihandler));
} else if (len - 1 == CGIBIN_PREFIX_LEN) /* url is "/cgi-bin/" */
append_index_html(&file);
+
ix = 0;
if (cgihandler) {
command = file + 1;
@@ -220,7 +223,7 @@
spsetenv("SCRIPT_NAME", file, curenvp++);
spsetenv("SCRIPT_FILENAME", file + 1, curenvp++);
spsetenv("SERVER_SOFTWARE", server_software, curenvp++);
- spsetenv("REQUEST_URI", url, curenvp++);
+ spsetenv("REQUEST_URI", request->hr_file, curenvp++);
spsetenv("DATE_GMT", http_date(), curenvp++);
if (query && *query)
spsetenv("QUERY_STRING", query, curenvp++);
@@ -241,6 +244,9 @@
free(file);
free(url);
+ debug((DEBUG_FAT, "process_cgi: going exec %s, %s %s %s",
+ path, argv[0], strornull(argv[1]), strornull(argv[2])));
+
if (-1 == socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv))
error(1, "child socketpair failed: %s", strerror(errno));
@@ -302,6 +308,15 @@
}
debug((DEBUG_FAT, "done processing cgi input"));
exit(0);
+
+ out:
+ if (query)
+ free(query);
+ if (file)
+ free(file);
+ if (url)
+ free(url);
+ return 0;
}
/*
@@ -323,7 +338,7 @@
SIMPLEQ_INIT(&headers);
write_header = nph == 0;
while (nph == 0 && (str = bozodgetln(in, &len, read)) != NULL) {
- char * hdr_name, * hdr_value;
+ char *hdr_name, *hdr_value;
if (parse_header(str, len, &hdr_name, &hdr_value))
break;
@@ -393,15 +408,15 @@
}
static int
-parse_header(const char * str, ssize_t len, char ** hdr_str, char ** hdr_val)
+parse_header(const char *str, ssize_t len, char **hdr_str, char **hdr_val)
{
- char * name, * value;
+ char *name, *value;
/* if the string passed is zero-length bail out */
if (*str == '\0')
return -1;
- name = value = bozostrdup(str);
+ value = bozostrdup(str);
/* locate the ':' separator in the header/value */
name = bozostrnsep(&value, ":", &len);
@@ -430,7 +445,6 @@
struct content_map *map;
debug((DEBUG_FAT, "content_cgihandler: trying file %s", file));
-
map = match_content_map(file, 0);
if (map)
return (map->cgihandler);
Index: src/libexec/httpd/bozohttpd.h
diff -u src/libexec/httpd/bozohttpd.h:1.7 src/libexec/httpd/bozohttpd.h:1.8
--- src/libexec/httpd/bozohttpd.h:1.7 Mon Feb 9 17:06:11 2009
+++ src/libexec/httpd/bozohttpd.h Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: bozohttpd.h,v 1.7 2009/02/09 17:06:11 joerg Exp $ */
+/* $NetBSD: bozohttpd.h,v 1.8 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: bozohttpd.h,v 1.18 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: bozohttpd.h,v 1.25 2009/04/18 05:36:04 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -36,6 +34,8 @@
#include <stdio.h>
+/* lots of "const" but gets free()'ed etc at times, sigh */
+
/* headers */
struct headers {
/*const*/ char *h_header;
@@ -55,8 +55,8 @@
#define HTTP_TRACE 0x07 /* not supported */
#define HTTP_CONNECT 0x08 /* not supported */
const char *hr_methodstr;
- char *hr_file;
- char *hr_query;
+ char *hr_file;
+ char *hr_query;
const char *hr_proto;
const char *hr_content_type;
const char *hr_content_length;
@@ -68,9 +68,9 @@
int hr_have_range;
off_t hr_first_byte_pos;
off_t hr_last_byte_pos;
- const char *hr_remotehost;
- const char *hr_remoteaddr;
- const char *hr_serverport;
+ /*const*/ char *hr_remotehost;
+ /*const*/ char *hr_remoteaddr;
+ /*const*/ char *hr_serverport;
#ifdef DO_HTPASSWD
const char *hr_authrealm;
const char *hr_authuser;
@@ -88,7 +88,9 @@
const char *cgihandler; /* optional CGI handler */
};
+/* write in upto 64KiB chunks, and mmap in upto 64MiB chunks */
#define WRSZ (64 * 1024)
+#define MMAPSZ (WRSZ * 1024)
/* debug flags */
#define DEBUG_NORMAL 1
@@ -114,11 +116,12 @@
void warning(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
void error(int, const char *, ...)
- __attribute__((__format__(__printf__, 2, 3)));
-void http_error(int, http_req *, const char *)
+ __attribute__((__format__(__printf__, 2, 3)))
+ __attribute__((__noreturn__));
+int http_error(int, http_req *, const char *)
__attribute__((__noreturn__));
-void check_special_files(http_req *, const char *);
+int check_special_files(http_req *, const char *);
char *http_date(void);
void print_header(http_req *, struct stat *, const char *, const char *);
@@ -161,16 +164,18 @@
/* auth-bozo.c */
#ifdef DO_HTPASSWD
-extern void auth_check(http_req *, const char *);
+extern int auth_check(http_req *, const char *);
+extern void auth_cleanup(http_req *);
extern int auth_check_headers(http_req *, char *, char *, ssize_t);
-extern void auth_check_special_files(http_req *, const char *);
+extern int auth_check_special_files(http_req *, const char *);
extern void auth_check_401(http_req *, int);
extern void auth_cgi_setenv(http_req *, char ***);
extern int auth_cgi_count(http_req *);
#else
-#define auth_check(x, y) /* nothing */
+#define auth_check(x, y) 0
+#define auth_cleanup(x) /* nothing */
#define auth_check_headers(x, y, z, a) 0
-#define auth_check_special_files(x, y) /* nothing */
+#define auth_check_special_files(x, y) 0
#define auth_check_401(x, y) /* nothing */
#define auth_cgi_setenv(x, y) /* nothing */
#define auth_cgi_count(x) 0
@@ -179,12 +184,12 @@
/* cgi-bozo.c */
#ifndef NO_CGIBIN_SUPPORT
-void set_cgibin(char *);
-void spsetenv(const char *env, const char *val, char **envp);
-void process_cgi(http_req *);
-void add_content_map_cgi(char *, char *);
+extern void set_cgibin(char *);
+extern void spsetenv(const char *env, const char *val, char **envp);
+extern int process_cgi(http_req *);
+extern void add_content_map_cgi(char *, char *);
#else
-#define process_cgi(r) /* nothing */
+#define process_cgi(r) 0
#endif /* NO_CGIBIN_SUPPORT */
@@ -194,8 +199,8 @@
#ifndef NO_DAEMON_MODE
extern char *iflag;
-void daemon_init(void);
-void daemon_fork(void);
+extern void daemon_init(void);
+extern void daemon_fork(void);
#else
#define daemon_init() /* nothing */
#define daemon_fork() /* nothing */
@@ -207,7 +212,9 @@
extern int uflag;
extern const char *public_html;
-char * user_transform(http_req *, int *);
+int user_transform(http_req *, int *);
+#else
+#define user_transform(a, b) 0
#endif /* NO_USER_SUPPORT */
@@ -222,10 +229,10 @@
/* content-bozo.c */
-const char *content_type(http_req *, const char *);
-const char *content_encoding(http_req *, const char *);
-struct content_map *match_content_map(const char *, int);
-struct content_map *get_content_map(const char *);
+extern const char *content_type(http_req *, const char *);
+extern const char *content_encoding(http_req *, const char *);
+extern struct content_map *match_content_map(const char *, int);
+extern struct content_map *get_content_map(const char *);
#ifndef NO_DYNAMIC_CONTENT
void add_content_map_mime(char *, char *, char *, char *);
#endif
Index: src/libexec/httpd/content-bozo.c
diff -u src/libexec/httpd/content-bozo.c:1.3 src/libexec/httpd/content-bozo.c:1.4
--- src/libexec/httpd/content-bozo.c:1.3 Mon Mar 3 22:15:09 2008
+++ src/libexec/httpd/content-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: content-bozo.c,v 1.3 2008/03/03 22:15:09 mrg Exp $ */
+/* $NetBSD: content-bozo.c,v 1.4 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: content-bozo.c,v 1.9 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: content-bozo.c,v 1.12 2009/04/17 22:52:20 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -36,6 +34,7 @@
#include <sys/param.h>
+#include <errno.h>
#include <string.h>
#include "bozohttpd.h"
@@ -242,6 +241,8 @@
dynamic_content_map_size++;
dynamic_content_map = bozorealloc(dynamic_content_map,
(dynamic_content_map_size + 1) * sizeof *map);
+ if (dynamic_content_map == NULL)
+ error(1, "out of memory allocating content map");
map = &dynamic_content_map[dynamic_content_map_size];
map->name = map->type = map->encoding = map->encoding11 =
map->cgihandler = NULL;
Index: src/libexec/httpd/dir-index-bozo.c
diff -u src/libexec/httpd/dir-index-bozo.c:1.5 src/libexec/httpd/dir-index-bozo.c:1.6
--- src/libexec/httpd/dir-index-bozo.c:1.5 Wed Feb 4 22:55:58 2009
+++ src/libexec/httpd/dir-index-bozo.c Sat Apr 18 07:28:24 2009
@@ -1,9 +1,9 @@
-/* $NetBSD: dir-index-bozo.c,v 1.5 2009/02/04 22:55:58 tls Exp $ */
+/* $NetBSD: dir-index-bozo.c,v 1.6 2009/04/18 07:28:24 mrg Exp $ */
-/* $eterna: dir-index-bozo.c,v 1.10 2008/03/03 03:36:11 mrg Exp $ */
+/* $eterna: dir-index-bozo.c,v 1.14 2009/04/18 01:48:18 mrg Exp $ */
/*
- * Copyright (c) 1997-2008 Matthew R. Green
+ * Copyright (c) 1997-2009 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,8 +15,6 @@
* notice, this list of conditions and the following disclaimer and
* dedication in the documentation and/or other materials provided
* with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -41,6 +39,7 @@
#include <dirent.h>
#include <errno.h>
#include <string.h>
+#include <stdlib.h>
#include <time.h>
#include <assert.h>
@@ -68,6 +67,7 @@
DIR *dp;
char buf[MAXPATHLEN];
char spacebuf[48];
+ char *file = NULL;
int l, i;
if (!isindex || !Xflag)
@@ -76,7 +76,7 @@
if (strlen(dirname) <= strlen(index_html))
dirname = ".";
else {
- char *file = bozostrdup(dirname);
+ file = bozostrdup(dirname);
file[strlen(file) - strlen(index_html)] = '\0';
dirname = file;
@@ -85,12 +85,13 @@
if (stat(dirname, &sb) < 0 ||
(dp = opendir(dirname)) == NULL) {
if (errno == EPERM)
- http_error(403, request,
+ (void)http_error(403, request,
"no permission to open directory");
else if (errno == ENOENT)
- http_error(404, request, "no file");
+ (void)http_error(404, request, "no file");
else
- http_error(500, request, "open directory");
+ (void)http_error(500, request, "open directory");
+ goto done;
/* NOTREACHED */
}
@@ -104,7 +105,7 @@
if (request->hr_method == HTTP_HEAD) {
closedir(dp);
- return 1;
+ goto done;
}
bozoprintf("<html><head><title>Index of %s</title></head>\r\n",
@@ -182,6 +183,9 @@
bozoprintf("</body></html>\r\n\r\n");
bozoflush(stdout);
+done:
+ if (file)
+ free(file);
return 1;
}
#endif /* NO_DIRINDEX_SUPPORT */