Index: CHANGES =================================================================== RCS file: /cvsroot/src/libexec/httpd/CHANGES,v retrieving revision 1.11.2.1 diff -p -u -u -r1.11.2.1 CHANGES --- CHANGES 9 Jul 2014 09:42:39 -0000 1.11.2.1 +++ CHANGES 10 Apr 2016 00:35:18 -0000 @@ -1,5 +1,23 @@ $eterna: CHANGES,v 1.78 2011/11/18 01:25:11 mrg Exp $ +changes in bozohttpd 20151028: + o add CGI support for ~user translation (-E switch) + o add redirects to ~user translation + o fix bugs around ~user translation + o add schema detection for absolute redirects + o fixed few memory leaks + o bunch of minor tweaks + o removed -r support + o smarter redirects + +changes in bozohttpd 20150320: + o fix redirection handling + o support transport stream (.ts) and video object (.vob) files + 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 rajeev_v_pillai@yahoo.com o avoid printing double errors, from shm@netbsd.org Index: Makefile =================================================================== RCS file: /cvsroot/src/libexec/httpd/Makefile,v retrieving revision 1.12.8.1 diff -p -u -u -r1.12.8.1 Makefile --- Makefile 9 Jul 2014 09:42:39 -0000 1.12.8.1 +++ Makefile 10 Apr 2016 00:35:18 -0000 @@ -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 +# (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 .if ${MKCRYPTO} != "no" Index: auth-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/auth-bozo.c,v retrieving revision 1.10.2.1 diff -p -u -u -r1.10.2.1 auth-bozo.c --- auth-bozo.c 9 Jul 2014 09:42:39 -0000 1.10.2.1 +++ auth-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -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: bozohttpd.8 =================================================================== RCS file: /cvsroot/src/libexec/httpd/bozohttpd.8,v retrieving revision 1.32.2.1 diff -p -u -u -r1.32.2.1 bozohttpd.8 --- bozohttpd.8 9 Jul 2014 09:42:39 -0000 1.32.2.1 +++ bozohttpd.8 10 Apr 2016 00:35:18 -0000 @@ -2,7 +2,7 @@ .\" .\" $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 @@ -497,11 +513,8 @@ httpd -C .php /usr/pkg/bin/php /var/www .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 agc@NetBSD.org -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 degroote@NetBSD.org @@ -597,6 +611,12 @@ provided fixes for HTTP basic authorisat .Aq Mt wiz@NetBSD.org provided many fixes and enhancements for the man page .It +.An Mateusz Kocielski +.Aq Mt shm@NetBSD.org +fixed memory leaks, various issues with userdir support, +information disclosure issues, added support for using CGI handlers +with directory indexing and provided various other fixes. +.It .An Arnaud Lacombe .Aq Mt alc@NetBSD.org provided some clean up for memory leaks @@ -609,7 +629,7 @@ provided man page fixes .Aq Mt jmmv@NetBSD.org Added the .Fl P -option. +option (pidfile support) and provided some man page fixes. .It .An Luke Mewburn .Aq Mt lukem@NetBSD.org @@ -662,9 +682,6 @@ provided http authorisation fixes provided chroot and change-to-user support, and other various fixes .It Coyote Point provided various CGI fixes. -.It -.An Julio Merino -added pidfile support and provided some man page fixes. .El .Pp There are probably others I have forgotten (let me know if you care) Index: bozohttpd.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/bozohttpd.c,v retrieving revision 1.30.2.2 diff -p -u -u -r1.30.2.2 bozohttpd.c --- bozohttpd.c 4 Feb 2015 11:37:37 -0000 1.30.2.2 +++ bozohttpd.c 10 Apr 2016 00:35:18 -0000 @@ -3,7 +3,7 @@ /* $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/20151231" #endif #ifndef DIRECT_ACCESS_FILE #define DIRECT_ACCESS_FILE ".bzdirect" @@ -171,61 +171,59 @@ volatile sig_atomic_t alarmhit; * check there's enough space in the prefs and names arrays. */ static int -size_arrays(bozoprefs_t *bozoprefs, unsigned needed) +size_arrays(bozoprefs_t *bozoprefs, size_t needed) { char **temp; if (bozoprefs->size == 0) { /* only get here first time around */ - bozoprefs->size = needed; - if ((bozoprefs->name = calloc(sizeof(char *), needed)) == NULL) { - (void) fprintf(stderr, "size_arrays: bad alloc\n"); + bozoprefs->name = calloc(sizeof(char *), needed); + if (bozoprefs->name == NULL) return 0; - } - if ((bozoprefs->value = calloc(sizeof(char *), needed)) == NULL) { + bozoprefs->value = calloc(sizeof(char *), needed); + if (bozoprefs->value == NULL) { free(bozoprefs->name); - (void) fprintf(stderr, "size_arrays: bad alloc\n"); return 0; } - } else if (bozoprefs->c == bozoprefs->size) { + bozoprefs->size = needed; + } else if (bozoprefs->count == bozoprefs->size) { /* only uses 'needed' when filled array */ - bozoprefs->size += needed; temp = realloc(bozoprefs->name, sizeof(char *) * needed); - if (temp == NULL) { - (void) fprintf(stderr, "size_arrays: bad alloc\n"); + if (temp == NULL) return 0; - } bozoprefs->name = temp; temp = realloc(bozoprefs->value, sizeof(char *) * needed); - if (temp == NULL) { - (void) fprintf(stderr, "size_arrays: bad alloc\n"); + if (temp == NULL) return 0; - } bozoprefs->value = temp; + bozoprefs->size += needed; } return 1; } -static int +static ssize_t findvar(bozoprefs_t *bozoprefs, const char *name) { - unsigned i; + size_t i; - for (i = 0 ; i < bozoprefs->c && strcmp(bozoprefs->name[i], name) != 0; i++) - ; - return (i == bozoprefs->c) ? -1 : (int)i; + for (i = 0; i < bozoprefs->count; i++) + if (strcmp(bozoprefs->name[i], name) == 0) + return (ssize_t)i; + return -1; } int -bozo_set_pref(bozoprefs_t *bozoprefs, const char *name, const char *value) +bozo_set_pref(bozohttpd_t *httpd, bozoprefs_t *bozoprefs, + const char *name, const char *value) { - int i; + ssize_t i; if ((i = findvar(bozoprefs, name)) < 0) { /* add the element to the array */ - if (size_arrays(bozoprefs, bozoprefs->size + 15)) { - bozoprefs->name[i = bozoprefs->c++] = strdup(name); - } + if (!size_arrays(bozoprefs, bozoprefs->size + 15)) + return 0; + i = bozoprefs->count++; + bozoprefs->name[i] = bozostrdup(httpd, NULL, name); } else { /* replace the element in the array */ if (bozoprefs->value[i]) { @@ -233,8 +231,7 @@ bozo_set_pref(bozoprefs_t *bozoprefs, co bozoprefs->value[i] = NULL; } } - /* sanity checks for range of values go here */ - bozoprefs->value[i] = strdup(value); + bozoprefs->value[i] = bozostrdup(httpd, NULL, value); return 1; } @@ -244,10 +241,10 @@ bozo_set_pref(bozoprefs_t *bozoprefs, co char * bozo_get_pref(bozoprefs_t *bozoprefs, const char *name) { - int i; + ssize_t i; - return ((i = findvar(bozoprefs, name)) < 0) ? NULL : - bozoprefs->value[i]; + i = findvar(bozoprefs, name); + return i < 0 ? NULL : bozoprefs->value[i]; } char * @@ -309,9 +306,9 @@ parse_request(bozohttpd_t *httpd, char * } /* allocate private copies */ - *file = bozostrdup(httpd, *file); + *file = bozostrdup(httpd, NULL, *file); if (*query) - *query = bozostrdup(httpd, *query); + *query = bozostrdup(httpd, NULL, *query); debug((httpd, DEBUG_FAT, "url: method: \"%s\" file: \"%s\" query: \"%s\" proto: \"%s\"", @@ -341,6 +338,7 @@ bozo_clean_request(bozo_httpreq_t *reque free(request->hr_oldfile); free(request->hr_query); free(request->hr_host); + bozo_user_free(request->hr_user); bozo_auth_cleanup(request); for (hdr = SIMPLEQ_FIRST(&request->hr_headers); hdr; hdr = SIMPLEQ_NEXT(hdr, h_next)) { @@ -371,6 +369,7 @@ static bozoheaders_t * addmerge_header(bozo_httpreq_t *request, char *val, char *str, ssize_t len) { + struct bozohttpd_t *httpd = request->hr_httpd; struct bozoheaders *hdr; USE_ARG(len); @@ -384,22 +383,18 @@ addmerge_header(bozo_httpreq_t *request, /* yup, merge it in */ char *nval; - if (asprintf(&nval, "%s, %s", hdr->h_value, str) == -1) { - (void)bozo_http_error(request->hr_httpd, 500, NULL, - "memory allocation failure"); - return NULL; - } + bozoasprintf(httpd, &nval, "%s, %s", hdr->h_value, str); free(hdr->h_value); hdr->h_value = nval; } else { /* nope, create a new one */ - hdr = bozomalloc(request->hr_httpd, sizeof *hdr); - hdr->h_header = bozostrdup(request->hr_httpd, val); + hdr = bozomalloc(httpd, sizeof *hdr); + hdr->h_header = bozostrdup(httpd, request, val); if (str && *str) - hdr->h_value = bozostrdup(request->hr_httpd, str); + hdr->h_value = bozostrdup(httpd, request, str); else - hdr->h_value = bozostrdup(request->hr_httpd, " "); + hdr->h_value = bozostrdup(httpd, request, " "); SIMPLEQ_INSERT_TAIL(&request->hr_headers, hdr, h_next); request->hr_nheaders++; @@ -415,13 +410,14 @@ addmerge_header(bozo_httpreq_t *request, static int process_proto(bozo_httpreq_t *request, const char *proto) { + struct bozohttpd_t *httpd = request->hr_httpd; char majorstr[16], *minorstr; int majorint, minorint; if (proto == NULL) { got_proto_09: - request->hr_proto = request->hr_httpd->consts.http_09; - debug((request->hr_httpd, DEBUG_FAT, "request %s is http/0.9", + request->hr_proto = httpd->consts.http_09; + debug((httpd, DEBUG_FAT, "request %s is http/0.9", request->hr_file)); return 0; } @@ -445,25 +441,25 @@ got_proto_09: goto got_proto_09; case 1: if (minorint == 0) - request->hr_proto = request->hr_httpd->consts.http_10; + request->hr_proto = httpd->consts.http_10; else if (minorint == 1) - request->hr_proto = request->hr_httpd->consts.http_11; + request->hr_proto = httpd->consts.http_11; else break; - debug((request->hr_httpd, DEBUG_FAT, "request %s is %s", + debug((httpd, DEBUG_FAT, "request %s is %s", request->hr_file, request->hr_proto)); SIMPLEQ_INIT(&request->hr_headers); request->hr_nheaders = 0; return 0; } bad: - return bozo_http_error(request->hr_httpd, 404, NULL, "unknown prototype"); + return bozo_http_error(httpd, 404, NULL, "unknown prototype"); } /* * process each type of HTTP method, setting this HTTP requests - # method type. + * method type. */ static struct method_map { const char *name; @@ -485,9 +481,10 @@ static struct method_map { static int process_method(bozo_httpreq_t *request, const char *method) { + struct bozohttpd_t *httpd = request->hr_httpd; struct method_map *mmp; - if (request->hr_proto == request->hr_httpd->consts.http_11) + if (request->hr_proto == httpd->consts.http_11) request->hr_allow = "GET, HEAD, POST"; for (mmp = method_map; mmp->name; mmp++) @@ -497,7 +494,7 @@ process_method(bozo_httpreq_t *request, return 0; } - return bozo_http_error(request->hr_httpd, 404, request, "unknown method"); + return bozo_http_error(httpd, 404, request, "unknown method"); } /* @@ -527,7 +524,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 +538,7 @@ bozo_read_request(bozohttpd_t *httpd) request->hr_virthostname = NULL; request->hr_file = NULL; request->hr_oldfile = NULL; + bozo_auth_init(request); slen = sizeof(ss); if (getpeername(0, (struct sockaddr *)(void *)&ss, &slen) < 0) @@ -558,9 +557,9 @@ bozo_read_request(bozohttpd_t *httpd) host = NULL; } if (host != NULL) - request->hr_remotehost = bozostrdup(request->hr_httpd, host); + request->hr_remotehost = bozostrdup(httpd, request, host); if (addr != NULL) - request->hr_remoteaddr = bozostrdup(request->hr_httpd, addr); + request->hr_remoteaddr = bozostrdup(httpd, request, addr); slen = sizeof(ss); /* @@ -576,15 +575,16 @@ bozo_read_request(bozohttpd_t *httpd) if (getsockname(0, (struct sockaddr *)(void *)&ss, &slen) < 0) port = NULL; else { - if (getnameinfo((struct sockaddr *)(void *)&ss, slen, NULL, 0, - bufport, sizeof bufport, NI_NUMERICSERV) == 0) + if (getnameinfo((struct sockaddr *)(void *)&ss, slen, + NULL, 0, bufport, sizeof bufport, + NI_NUMERICSERV) == 0) port = bufport; else port = NULL; } } if (port != NULL) - request->hr_serverport = bozostrdup(request->hr_httpd, port); + request->hr_serverport = bozostrdup(httpd, request, port); /* * setup a timer to make sure the request is not hung @@ -593,7 +593,7 @@ bozo_read_request(bozohttpd_t *httpd) sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGALRM); sa.sa_flags = 0; - sigaction(SIGALRM, &sa, NULL); /* XXX */ + sigaction(SIGALRM, &sa, NULL); alarm(MAX_WAIT_TIME); while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) { @@ -612,11 +612,11 @@ bozo_read_request(bozohttpd_t *httpd) "null method"); goto cleanup; } - - bozo_warn(httpd, "got request ``%s'' from host %s to port %s", - str, - host ? host : addr ? addr : "", - port ? port : ""); + bozowarn(httpd, + "got request ``%s'' from host %s to port %s", + str, + host ? host : addr ? addr : "", + port ? port : ""); /* we allocate return space in file and query only */ parse_request(httpd, str, &method, &file, &query, &proto); @@ -680,7 +680,8 @@ bozo_read_request(bozohttpd_t *httpd) else if (strcasecmp(hdr->h_header, "content-length") == 0) request->hr_content_length = hdr->h_value; else if (strcasecmp(hdr->h_header, "host") == 0) - request->hr_host = bozostrdup(httpd, hdr->h_value); + request->hr_host = bozostrdup(httpd, request, + hdr->h_value); /* RFC 2616 (HTTP/1.1): 14.20 */ else if (strcasecmp(hdr->h_header, "expect") == 0) { (void)bozo_http_error(httpd, 417, request, @@ -795,7 +796,7 @@ mmap_and_write_part(bozohttpd_t *httpd, addr = mmap(0, mappedsz, PROT_READ, MAP_SHARED, fd, mappedoffset); if (addr == (char *)-1) { - bozo_warn(httpd, "mmap failed: %s", strerror(errno)); + bozowarn(httpd, "mmap failed: %s", strerror(errno)); return -1; } mappedaddr = addr; @@ -806,7 +807,7 @@ mmap_and_write_part(bozohttpd_t *httpd, while (sz > BOZO_WRSZ) { if (bozo_write(httpd, STDOUT_FILENO, addr + wroffset, BOZO_WRSZ) != BOZO_WRSZ) { - bozo_warn(httpd, "write failed: %s", strerror(errno)); + bozowarn(httpd, "write failed: %s", strerror(errno)); goto out; } debug((httpd, DEBUG_OBESE, "wrote %d bytes", BOZO_WRSZ)); @@ -815,13 +816,13 @@ mmap_and_write_part(bozohttpd_t *httpd, } if (sz && (size_t)bozo_write(httpd, STDOUT_FILENO, addr + wroffset, sz) != sz) { - bozo_warn(httpd, "final write failed: %s", strerror(errno)); + bozowarn(httpd, "final write failed: %s", strerror(errno)); goto out; } debug((httpd, DEBUG_OBESE, "wrote %d bytes", (int)sz)); out: if (munmap(mappedaddr, mappedsz) < 0) { - bozo_warn(httpd, "munmap failed"); + bozowarn(httpd, "munmap failed"); return -1; } @@ -849,10 +850,11 @@ parse_http_date(const char *val, time_t /* * given an url, encode it ala rfc 3986. ie, escape ? and friends. * note that this function returns a static buffer, and thus needs - * to be updated for any sort of parallel processing. + * to be updated for any sort of parallel processing. escape only + * chosen characters for absolute redirects */ char * -bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url) +bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute) { static char *buf; static size_t buflen = 0; @@ -866,17 +868,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 +890,18 @@ bozo_escape_rfc3986(bozohttpd_t *httpd, case ';': case '=': case '%': + case '"': + if (absolute) + goto leave_it; + case '\n': + case '\r': + case ' ': encode_it: - snprintf(d, 4, "%%%2X", *s++); + snprintf(d, 4, "%%%02X", *s++); d += 3; len += 3; break; + leave_it: default: *d++ = *s++; len++; @@ -911,115 +914,118 @@ bozo_escape_rfc3986(bozohttpd_t *httpd, } /* - * checks to see if this request has a valid .bzdirect file. returns - * 0 on failure and 1 on success. - */ -static int -check_direct_access(bozo_httpreq_t *request) -{ - FILE *fp; - struct stat sb; - char dir[MAXPATHLEN], dirfile[MAXPATHLEN], *basename; - - snprintf(dir, sizeof(dir), "%s", request->hr_file + 1); - debug((request->hr_httpd, DEBUG_FAT, "check_direct_access: dir %s", dir)); - basename = strrchr(dir, '/'); - - if ((!basename || basename[1] != '\0') && - lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) - /* nothing */; - else if (basename == NULL) - strcpy(dir, "."); - else { - *basename++ = '\0'; - bozo_check_special_files(request, basename); - } - - if ((size_t)snprintf(dirfile, sizeof(dirfile), "%s/%s", dir, - DIRECT_ACCESS_FILE) >= sizeof(dirfile)) { - bozo_http_error(request->hr_httpd, 404, request, - "directfile path too long"); - return 0; - } - if (stat(dirfile, &sb) < 0 || - (fp = fopen(dirfile, "r")) == NULL) - return 0; - fclose(fp); - return 1; -} - -/* - * do automatic redirection -- if there are query parameters for the URL - * we will tack these on to the new (redirected) URL. + * do automatic redirection -- if there are query parameters or userdir for + * the URL we will tack these on to the new (redirected) URL. */ static void -handle_redirect(bozo_httpreq_t *request, - const char *url, int absolute) +handle_redirect(bozo_httpreq_t *request, const char *url, int absolute) { bozohttpd_t *httpd = request->hr_httpd; - char *urlbuf; + char *finalurl, *urlbuf; +#ifndef NO_USER_SUPPORT + char *userbuf; +#endif /* !NO_USER_SUPPORT */ char portbuf[20]; + const char *scheme, *query, *quest; const char *hostname = BOZOHOST(httpd, request); - int query = 0; + int absproto = 0; /* absolute redirect provides own schema */ if (url == NULL) { - if (asprintf(&urlbuf, "/%s/", request->hr_file) < 0) - bozo_err(httpd, 1, "asprintf"); + bozoasprintf(httpd, &urlbuf, "/%s/", request->hr_file); url = urlbuf; } else urlbuf = NULL; - url = bozo_escape_rfc3986(request->hr_httpd, url); - if (request->hr_query && strlen(request->hr_query)) - query = 1; +#ifndef NO_USER_SUPPORT + if (request->hr_user && !absolute) { + bozoasprintf(httpd, &userbuf, "/~%s%s", request->hr_user, url); + url = userbuf; + } else + userbuf = NULL; +#endif /* !NO_USER_SUPPORT */ - if (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, "Document Moved\n"); bozo_printf(httpd, "

Document Moved

\n"); - bozo_printf(httpd, "This document had moved 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\n"); + bozo_printf(httpd, "This document had moved here\n", + finalurl); bozo_printf(httpd, "\n"); head: bozo_flush(httpd, stdout); free(urlbuf); + free(finalurl); +#ifndef NO_USER_SUPPORT + free(userbuf); +#endif /* !NO_USER_SUPPORT */ } /* @@ -1036,9 +1042,6 @@ check_virtual(bozo_httpreq_t *request) char *file = request->hr_file, *s; size_t len; - if (!httpd->virtbase) - goto use_slashdir; - /* * convert http://virtual.host/ to request->hr_host */ @@ -1049,12 +1052,12 @@ check_virtual(bozo_httpreq_t *request) file += 7; /* RFC 2616 (HTTP/1.1), 5.2: URI takes precedence over Host: */ free(request->hr_host); - request->hr_host = bozostrdup(request->hr_httpd, file); + request->hr_host = bozostrdup(httpd, request, file); if ((s = strchr(request->hr_host, '/')) != NULL) *s = '\0'; s = strchr(file, '/'); free(request->hr_file); - request->hr_file = bozostrdup(request->hr_httpd, s ? s : "/"); + request->hr_file = bozostrdup(httpd, request, s ? s : "/"); debug((httpd, DEBUG_OBESE, "got host ``%s'' file is now ``%s''", request->hr_host, request->hr_file)); } else if (!request->hr_host) @@ -1068,6 +1071,29 @@ check_virtual(bozo_httpreq_t *request) request->hr_host[len - 3] = '\0'; len = strlen(request->hr_host); } + + if (!httpd->virtbase) { + + /* + * if we don't use vhost support, then set virthostname if + * user supplied Host header. It will be used for possible + * redirections + */ + + if (request->hr_host) { + s = strrchr(request->hr_host, ':'); + if (s != NULL) + /* truncate Host: as we want to copy it without port part */ + *s = '\0'; + request->hr_virthostname = bozostrdup(httpd, request, + request->hr_host); + if (s != NULL) + /* fix Host: again, if we truncated it */ + *s = ':'; + } + + goto use_slashdir; + } /* * ok, we have a virtual host, use opendir(3) to find a case @@ -1092,15 +1118,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 +1162,7 @@ use_slashdir: static int check_bzredirect(bozo_httpreq_t *request) { + bozohttpd_t *httpd = request->hr_httpd; struct stat sb; char dir[MAXPATHLEN], redir[MAXPATHLEN], redirpath[MAXPATHLEN + 1], path[MAXPATHLEN]; @@ -1149,27 +1175,31 @@ check_bzredirect(bozo_httpreq_t *request */ if((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >= sizeof(dir)) { - bozo_http_error(request->hr_httpd, 404, request, + bozo_http_error(httpd, 404, request, "file path too long"); return -1; } - debug((request->hr_httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir)); + debug((httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir)); basename = strrchr(dir, '/'); if ((!basename || basename[1] != '\0') && - lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) - /* nothing */; - else if (basename == NULL) - strcpy(dir, "."); - else { + lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) { + strcpy(path, dir); + } else if (basename == NULL) { + strcpy(path, "."); + strcpy(dir, ""); + } else { *basename++ = '\0'; bozo_check_special_files(request, basename); + strcpy(path, dir); } - if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", dir, + debug((httpd, DEBUG_FAT, "check_bzredirect: path %s", path)); + + if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", path, REDIRECT_FILE) >= sizeof(redir)) { - bozo_http_error(request->hr_httpd, 404, request, - "redirectfile path too long"); + bozo_http_error(httpd, 404, request, + "redirectfile path too long"); return -1; } if (lstat(redir, &sb) == 0) { @@ -1177,9 +1207,9 @@ check_bzredirect(bozo_httpreq_t *request return 0; absolute = 0; } else { - if((size_t)snprintf(redir, sizeof(redir), "%s/%s", dir, + if((size_t)snprintf(redir, sizeof(redir), "%s/%s", path, ABSREDIRECT_FILE) >= sizeof(redir)) { - bozo_http_error(request->hr_httpd, 404, request, + bozo_http_error(httpd, 404, request, "redirectfile path too long"); return -1; } @@ -1187,16 +1217,14 @@ check_bzredirect(bozo_httpreq_t *request return 0; absolute = 1; } - debug((request->hr_httpd, DEBUG_FAT, - "check_bzredirect: calling readlink")); + debug((httpd, DEBUG_FAT, "check_bzredirect: calling readlink")); rv = readlink(redir, redirpath, sizeof redirpath - 1); if (rv == -1 || rv == 0) { - debug((request->hr_httpd, DEBUG_FAT, "readlink failed")); + debug((httpd, DEBUG_FAT, "readlink failed")); return 0; } redirpath[rv] = '\0'; - debug((request->hr_httpd, DEBUG_FAT, - "readlink returned \"%s\"", redirpath)); + debug((httpd, DEBUG_FAT, "readlink returned \"%s\"", redirpath)); /* check if we need authentication */ snprintf(path, sizeof(path), "%s/", dir); @@ -1204,19 +1232,17 @@ check_bzredirect(bozo_httpreq_t *request return 1; /* now we have the link pointer, redirect to the real place */ - if (absolute) - finalredir = redirpath; - else { - if ((size_t)snprintf(finalredir = redir, sizeof(redir), "/%s/%s", - dir, redirpath) >= sizeof(redir)) { - bozo_http_error(request->hr_httpd, 404, request, + if (!absolute && redirpath[0] != '/') { + if ((size_t)snprintf(finalredir = redir, sizeof(redir), "%s%s/%s", + (strlen(dir) > 0 ? "/" : ""), dir, redirpath) >= sizeof(redir)) { + bozo_http_error(httpd, 404, request, "redirect path too long"); return -1; } - } + } else + finalredir = redirpath; - debug((request->hr_httpd, DEBUG_FAT, - "check_bzredirect: new redir %s", finalredir)); + debug((httpd, DEBUG_FAT, "check_bzredirect: new redir %s", finalredir)); handle_redirect(request, finalredir, absolute); return 1; } @@ -1296,7 +1322,6 @@ fix_url_percent(bozo_httpreq_t *request) * transform_request does this: * - ``expand'' %20 crapola * - punt if it doesn't start with / - * - check httpd->untrustedref / referrer * - look for "http://myname/" and deal with it. * - maybe call bozo_process_cgi() * - check for ~user and call bozo_user_transform() if so @@ -1314,7 +1339,6 @@ transform_request(bozo_httpreq_t *reques bozohttpd_t *httpd = request->hr_httpd; char *file, *newfile = NULL; size_t len; - const char *hostname = BOZOHOST(httpd, request); file = NULL; *isindex = 0; @@ -1332,84 +1356,49 @@ transform_request(bozo_httpreq_t *reques goto bad_done; } - switch(check_bzredirect(request)) { - case -1: - goto bad_done; - case 1: - return 0; - } + /* omit additional slashes at the beginning */ + while (file[1] == '/') + file++; - if (httpd->untrustedref) { - int to_indexhtml = 0; - -#define TOP_PAGE(x) (strcmp((x), "/") == 0 || \ - strcmp((x) + 1, httpd->index_html) == 0 || \ - strcmp((x) + 1, "favicon.ico") == 0) - - debug((httpd, DEBUG_EXPLODING, "checking httpd->untrustedref")); - /* - * first check that this path isn't allowed via .bzdirect file, - * and then check referrer; make sure that people come via the - * real name... otherwise if we aren't looking at / or - * /index.html, redirect... we also special case favicon.ico. - */ - if (check_direct_access(request)) - /* nothing */; - else if (request->hr_referrer) { - const char *r = request->hr_referrer; - - debug((httpd, DEBUG_FAT, - "checking referrer \"%s\" vs virthostname %s", - r, hostname)); - if (strncmp(r, "http://", 7) != 0 || - (strncasecmp(r + 7, hostname, - strlen(hostname)) != 0 && - !TOP_PAGE(file))) - to_indexhtml = 1; - } else { - const char *h = request->hr_host; - - debug((httpd, DEBUG_FAT, "url has no referrer at all")); - /* if there's no referrer, let / or /index.html past */ - if (!TOP_PAGE(file) || - (h && strncasecmp(h, hostname, - strlen(hostname)) != 0)) - to_indexhtml = 1; - } - - if (to_indexhtml) { - char *slashindexhtml; - - if (asprintf(&slashindexhtml, "/%s", - httpd->index_html) < 0) - bozo_err(httpd, 1, "asprintf"); - debug((httpd, DEBUG_FAT, - "httpd->untrustedref: redirecting %s to %s", - file, slashindexhtml)); - handle_redirect(request, slashindexhtml, 0); - free(slashindexhtml); - return 0; - } - } + /* fix file provided by user as it's used in other handlers */ + request->hr_file = file; len = strlen(file); - if (/*CONSTCOND*/0) { + #ifndef NO_USER_SUPPORT - } else if (len > 1 && httpd->enable_users && file[1] == '~') { + /* first of all expand user path */ + if (len > 1 && httpd->enable_users && file[1] == '~') { if (file[2] == '\0') { (void)bozo_http_error(httpd, 404, request, "missing username"); goto bad_done; } if (strchr(file + 2, '/') == NULL) { - handle_redirect(request, NULL, 0); + char *userredirecturl; + bozoasprintf(httpd, &userredirecturl, "%s/", file); + handle_redirect(request, userredirecturl, 0); + free(userredirecturl); return 0; } debug((httpd, DEBUG_FAT, "calling bozo_user_transform")); - return bozo_user_transform(request, isindex); + if (!bozo_user_transform(request)) + return 0; + + file = request->hr_file; + len = strlen(file); + } #endif /* NO_USER_SUPPORT */ - } else if (len > 1) { + + + switch (check_bzredirect(request)) { + case -1: + goto bad_done; + case 1: + return 0; + } + + if (len > 1) { debug((httpd, DEBUG_FAT, "file[len-1] == %c", file[len-1])); if (file[len-1] == '/') { /* append index.html */ *isindex = 1; @@ -1419,10 +1408,10 @@ transform_request(bozo_httpreq_t *reques strcpy(newfile, file + 1); strcat(newfile, httpd->index_html); } else - newfile = bozostrdup(request->hr_httpd, file + 1); + newfile = bozostrdup(httpd, request, file + 1); } else if (len == 1) { debug((httpd, DEBUG_EXPLODING, "tf_req: len == 1")); - newfile = bozostrdup(request->hr_httpd, httpd->index_html); + newfile = bozostrdup(httpd, request, httpd->index_html); *isindex = 1; } else { /* len == 0 ? */ (void)bozo_http_error(httpd, 500, request, @@ -1436,15 +1425,14 @@ transform_request(bozo_httpreq_t *reques } /* - * look for "http://myname/" and deal with it as necessary. - */ - - /* * stop traversing outside our domain * * XXX true security only comes from our parent using chroot(2) * before execve(2)'ing us. or our own built in chroot(2) support. */ + + debug((httpd, DEBUG_FAT, "newfile: %s", newfile)); + if (*newfile == '/' || strcmp(newfile, "..") == 0 || strstr(newfile, "/..") || strstr(newfile, "../")) { (void)bozo_http_error(httpd, 403, request, "illegal request"); @@ -1548,7 +1536,7 @@ bozo_process_request(bozo_httpreq_t *req fd = -1; encoding = NULL; if (can_gzip(request)) { - asprintf(&file, "%s.gz", request->hr_file); + bozoasprintf(httpd, &file, "%s.gz", request->hr_file); fd = open(file, O_RDONLY); if (fd >= 0) encoding = "gzip"; @@ -1562,7 +1550,7 @@ bozo_process_request(bozo_httpreq_t *req if (fd < 0) { debug((httpd, DEBUG_FAT, "open failed: %s", strerror(errno))); - switch(errno) { + switch (errno) { case EPERM: case EACCES: (void)bozo_http_error(httpd, 403, request, @@ -1641,9 +1629,6 @@ bozo_process_request(bozo_httpreq_t *req while (szleft) { size_t sz; - /* This should take care of the first unaligned chunk */ - if ((cur_byte_pos & (httpd->page_size - 1)) != 0) - sz = (size_t)(cur_byte_pos & ~httpd->page_size); if ((off_t)httpd->mmapsz < szleft) sz = httpd->mmapsz; else @@ -1725,7 +1710,7 @@ bozo_print_header(bozo_httpreq_t *reques len = sbp->st_size; bozo_printf(httpd, "Content-Length: %qd\r\n", (long long)len); } - if (request && request->hr_proto == httpd->consts.http_11) + if (request->hr_proto == httpd->consts.http_11) bozo_printf(httpd, "Connection: close\r\n"); bozo_flush(httpd, stdout); } @@ -1755,7 +1740,7 @@ debug__(bozohttpd_t *httpd, int level, c /* these are like warn() and err(), except for syslog not stderr */ void -bozo_warn(bozohttpd_t *httpd, const char *fmt, ...) +bozowarn(bozohttpd_t *httpd, const char *fmt, ...) { va_list ap; @@ -1770,7 +1755,7 @@ bozo_warn(bozohttpd_t *httpd, const char } void -bozo_err(bozohttpd_t *httpd, int code, const char *fmt, ...) +bozoerr(bozohttpd_t *httpd, int code, const char *fmt, ...) { va_list ap; @@ -1785,6 +1770,20 @@ bozo_err(bozohttpd_t *httpd, int code, c exit(code); } +void +bozoasprintf(bozohttpd_t *httpd, char **str, const char *fmt, ...) +{ + va_list ap; + int e; + + va_start(ap, fmt); + e = vasprintf(str, fmt, ap); + va_end(ap); + + if (e < 0) + bozoerr(httpd, EXIT_FAILURE, "asprintf"); +} + /* * this escapes HTML tags. returns allocated escaped * string if needed, or NULL on allocation failure or @@ -1860,6 +1859,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, }, @@ -1904,7 +1904,7 @@ bozo_http_error(bozohttpd_t *httpd, int debug((httpd, DEBUG_FAT, "bozo_http_error %d: %s", code, msg)); if (header == NULL || reason == NULL) { - bozo_err(httpd, 1, + bozoerr(httpd, 1, "bozo_http_error() failed (short = %p, long = %p)", header, reason); return code; @@ -1918,26 +1918,47 @@ bozo_http_error(bozohttpd_t *httpd, int portbuf[0] = '\0'; if (request && request->hr_file) { - char *file = NULL; + char *file = NULL, *user = NULL, *user_escaped = NULL; + int file_alloc = 0; const char *hostname = BOZOHOST(httpd, request); /* bozo_escape_html() failure here is just too bad. */ file = bozo_escape_html(NULL, request->hr_file); - if (file == NULL) + if (file == NULL) file = request->hr_file; + else + file_alloc = 1; + +#ifndef NO_USER_SUPPORT + if (request->hr_user != NULL) { + user_escaped = bozo_escape_html(NULL, request->hr_user); + if (user_escaped == NULL) + user_escaped = request->hr_user; + /* expand username to ~user/ */ + bozoasprintf(httpd, &user, "~%s/", user_escaped); + if (user_escaped != request->hr_user) + free(user_escaped); + } +#endif /* !NO_USER_SUPPORT */ + size = snprintf(httpd->errorbuf, BUFSIZ, "%s\n" "

%s

\n" - "%s:
%s
\n" + "%s%s:
%s
\n" "
%s%s
\n" "\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; @@ -2076,12 +2097,11 @@ bozorealloc(bozohttpd_t *httpd, void *pt void *p; p = realloc(ptr, size); - if (p == NULL) { - (void)bozo_http_error(httpd, 500, NULL, - "memory allocation failure"); - exit(1); - } - return (p); + if (p) + return p; + + (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure"); + exit(EXIT_FAILURE); } void * @@ -2090,26 +2110,27 @@ bozomalloc(bozohttpd_t *httpd, size_t si void *p; p = malloc(size); - if (p == NULL) { - (void)bozo_http_error(httpd, 500, NULL, - "memory allocation failure"); - exit(1); - } - return (p); + if (p) + return p; + + (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure"); + exit(EXIT_FAILURE); } char * -bozostrdup(bozohttpd_t *httpd, const char *str) +bozostrdup(bozohttpd_t *httpd, bozo_httpreq_t *request, const char *str) { char *p; p = strdup(str); - if (p == NULL) { - (void)bozo_http_error(httpd, 500, NULL, - "memory allocation failure"); - exit(1); - } - return (p); + if (p) + return p; + + if (!request) + bozoerr(httpd, EXIT_FAILURE, "strdup"); + + (void)bozo_http_error(httpd, 500, request, "memory allocation failure"); + exit(EXIT_FAILURE); } /* set default values in bozohttpd_t struct */ @@ -2142,15 +2163,16 @@ bozo_init_httpd(bozohttpd_t *httpd) /* set default values in bozoprefs_t struct */ int -bozo_init_prefs(bozoprefs_t *prefs) +bozo_init_prefs(bozohttpd_t *httpd, bozoprefs_t *prefs) { /* make sure everything is clean */ (void) memset(prefs, 0x0, sizeof(*prefs)); /* set up default values */ - bozo_set_pref(prefs, "server software", SERVER_SOFTWARE); - bozo_set_pref(prefs, "index.html", INDEX_HTML); - bozo_set_pref(prefs, "public_html", PUBLIC_HTML); + if (!bozo_set_pref(httpd, prefs, "server software", SERVER_SOFTWARE) || + !bozo_set_pref(httpd, prefs, "index.html", INDEX_HTML) || + !bozo_set_pref(httpd, prefs, "public_html", PUBLIC_HTML)) + return 0; return 1; } @@ -2159,7 +2181,7 @@ bozo_init_prefs(bozoprefs_t *prefs) int bozo_set_defaults(bozohttpd_t *httpd, bozoprefs_t *prefs) { - return bozo_init_httpd(httpd) && bozo_init_prefs(prefs); + return bozo_init_httpd(httpd) && bozo_init_prefs(httpd, prefs); } /* set the virtual host name, port and root */ @@ -2170,7 +2192,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; @@ -2181,16 +2203,15 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs if (vhost == NULL) { httpd->virthostname = bozomalloc(httpd, MAXHOSTNAMELEN+1); - /* XXX we do not check for FQDN here */ if (gethostname(httpd->virthostname, MAXHOSTNAMELEN+1) < 0) - bozo_err(httpd, 1, "gethostname"); + bozoerr(httpd, 1, "gethostname"); httpd->virthostname[MAXHOSTNAMELEN] = '\0'; } else { - httpd->virthostname = strdup(vhost); + httpd->virthostname = bozostrdup(httpd, NULL, vhost); } - httpd->slashdir = strdup(root); + httpd->slashdir = bozostrdup(httpd, NULL, root); if ((portnum = bozo_get_pref(prefs, "port number")) != NULL) { - httpd->bindport = strdup(portnum); + httpd->bindport = bozostrdup(httpd, NULL, portnum); } /* go over preferences now */ @@ -2198,16 +2219,12 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs strcmp(cp, "true") == 0) { httpd->numeric = 1; } - if ((cp = bozo_get_pref(prefs, "trusted referal")) != NULL && - strcmp(cp, "true") == 0) { - httpd->untrustedref = 1; - } if ((cp = bozo_get_pref(prefs, "log to stderr")) != NULL && strcmp(cp, "true") == 0) { httpd->logstderr = 1; } if ((cp = bozo_get_pref(prefs, "bind address")) != NULL) { - httpd->bindaddress = strdup(cp); + httpd->bindaddress = bozostrdup(httpd, NULL, cp); } if ((cp = bozo_get_pref(prefs, "background")) != NULL) { httpd->background = atoi(cp); @@ -2217,19 +2234,23 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs httpd->foreground = 1; } if ((cp = bozo_get_pref(prefs, "pid file")) != NULL) { - httpd->pidfile = strdup(cp); + httpd->pidfile = bozostrdup(httpd, NULL, cp); } if ((cp = bozo_get_pref(prefs, "unknown slash")) != NULL && strcmp(cp, "true") == 0) { httpd->unknown_slash = 1; } if ((cp = bozo_get_pref(prefs, "virtual base")) != NULL) { - httpd->virtbase = strdup(cp); + httpd->virtbase = bozostrdup(httpd, NULL, cp); } if ((cp = bozo_get_pref(prefs, "enable users")) != NULL && strcmp(cp, "true") == 0) { httpd->enable_users = 1; } + if ((cp = bozo_get_pref(prefs, "enable user cgibin")) != NULL && + strcmp(cp, "true") == 0) { + httpd->enable_cgi_users = 1; + } if ((cp = bozo_get_pref(prefs, "dirty environment")) != NULL && strcmp(cp, "true") == 0) { dirtyenv = 1; @@ -2243,11 +2264,12 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs httpd->dir_indexing = 1; } if ((cp = bozo_get_pref(prefs, "public_html")) != NULL) { - httpd->public_html = strdup(cp); + httpd->public_html = bozostrdup(httpd, NULL, cp); } httpd->server_software = - strdup(bozo_get_pref(prefs, "server software")); - httpd->index_html = strdup(bozo_get_pref(prefs, "index.html")); + bozostrdup(httpd, NULL, bozo_get_pref(prefs, "server software")); + httpd->index_html = + bozostrdup(httpd, NULL, bozo_get_pref(prefs, "index.html")); /* * initialise ssl and daemon mode if necessary. @@ -2255,39 +2277,33 @@ bozo_setup(bozohttpd_t *httpd, bozoprefs bozo_ssl_init(httpd); bozo_daemon_init(httpd); - if ((username = bozo_get_pref(prefs, "username")) == NULL) { - if ((pw = getpwuid(uid = 0)) == NULL) - bozo_err(httpd, 1, "getpwuid(0): %s", strerror(errno)); - httpd->username = strdup(pw->pw_name); - } else { - httpd->username = strdup(username); - if ((pw = getpwnam(httpd->username)) == NULL) - bozo_err(httpd, 1, "getpwnam(%s): %s", httpd->username, - strerror(errno)); + username = bozo_get_pref(prefs, "username"); + if (username != NULL) { + if ((pw = getpwnam(username)) == NULL) + bozoerr(httpd, 1, "getpwnam(%s): %s", username, + strerror(errno)); if (initgroups(pw->pw_name, pw->pw_gid) == -1) - bozo_err(httpd, 1, "initgroups: %s", strerror(errno)); + bozoerr(httpd, 1, "initgroups: %s", strerror(errno)); if (setgid(pw->pw_gid) == -1) - bozo_err(httpd, 1, "setgid(%u): %s", pw->pw_gid, - strerror(errno)); + bozoerr(httpd, 1, "setgid(%u): %s", pw->pw_gid, + strerror(errno)); uid = pw->pw_uid; } /* * handle chroot. */ if ((chrootdir = bozo_get_pref(prefs, "chroot dir")) != NULL) { - httpd->rootdir = strdup(chrootdir); + httpd->rootdir = bozostrdup(httpd, NULL, chrootdir); if (chdir(httpd->rootdir) == -1) - bozo_err(httpd, 1, "chdir(%s): %s", httpd->rootdir, + bozoerr(httpd, 1, "chdir(%s): %s", httpd->rootdir, strerror(errno)); if (chroot(httpd->rootdir) == -1) - bozo_err(httpd, 1, "chroot(%s): %s", httpd->rootdir, + bozoerr(httpd, 1, "chroot(%s): %s", httpd->rootdir, strerror(errno)); } - if (username != NULL) - if (setuid(uid) == -1) - bozo_err(httpd, 1, "setuid(%d): %s", uid, - strerror(errno)); + if (username != NULL && setuid(uid) == -1) + bozoerr(httpd, 1, "setuid(%d): %s", uid, strerror(errno)); /* * prevent info leakage between different compartments. Index: bozohttpd.h =================================================================== RCS file: /cvsroot/src/libexec/httpd/bozohttpd.h,v retrieving revision 1.20.2.1 diff -p -u -u -r1.20.2.1 bozohttpd.h --- bozohttpd.h 9 Jul 2014 09:42:39 -0000 1.20.2.1 +++ bozohttpd.h 10 Apr 2016 00:35:18 -0000 @@ -3,7 +3,7 @@ /* $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 +/* QNX provides a lot of NetBSD things in nbutil.h */ +#ifdef HAVE_NBUTIL_H +#include +#endif + /* lots of "const" but gets free()'ed etc at times, sigh */ /* headers */ @@ -68,7 +73,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 +90,9 @@ typedef struct bozo_consts_t { /* this structure encapsulates all the bozo flags and control vars */ typedef struct bozohttpd_t { char *rootdir; /* root directory */ - char *username; /* username to switch to */ int numeric; /* avoid gethostby*() */ char *virtbase; /* virtual directory base */ int unknown_slash; /* unknown vhosts go to normal slashdir */ - int untrustedref; /* make sure referrer = me unless url = / */ int logstderr; /* log to stderr (even if not tty) */ int background; /* drop into daemon mode */ int foreground; /* keep daemon mode in foreground */ @@ -105,6 +107,7 @@ typedef struct bozohttpd_t { const char *index_html; /* our home page */ const char *public_html; /* ~user/public_html page */ int enable_users; /* enable public_html */ + int enable_cgi_users; /* use the cgi handler */ int *sock; /* bound sockets */ int nsock; /* number of above */ struct pollfd *fds; /* current poll fd set */ @@ -147,6 +150,9 @@ typedef struct bozo_httpreq_t { char *hr_query; char *hr_host; /* HTTP/1.1 Host: or virtual hostname, possibly including a port number */ +#ifndef NO_USER_SUPPORT + char *hr_user; /* username if we hit userdir request */ +#endif /* !NO_USER_SUPPORT */ const char *hr_proto; const char *hr_content_type; const char *hr_content_length; @@ -177,8 +183,8 @@ typedef struct bozo_httpreq_t { /* structure to hold string based (name, value) pairs with preferences */ typedef struct bozoprefs_t { - unsigned size; /* size of the two arrays */ - unsigned c; /* # of entries in arrays */ + size_t size; /* size of the two arrays */ + size_t count; /* # of entries in arrays */ char **name; /* names of each entry */ char **value; /* values for the name entries */ } bozoprefs_t; @@ -211,42 +217,51 @@ void debug__(bozohttpd_t *, int, const c #define debug(x) #endif /* NO_DEBUG */ -void bozo_warn(bozohttpd_t *, const char *, ...) - BOZO_PRINTFLIKE(2, 3); -void bozo_err(bozohttpd_t *, int, const char *, ...) - BOZO_PRINTFLIKE(3, 4) - BOZO_DEAD; int bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *); int bozo_check_special_files(bozo_httpreq_t *, const char *); char *bozo_http_date(char *, size_t); -void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, const char *); -char *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url); +void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, + const char *); +char *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute); char *bozo_escape_html(bozohttpd_t *httpd, const char *url); -char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *, int, void *, size_t)); +/* these are similar to libc functions, no underscore here */ +void bozowarn(bozohttpd_t *, const char *, ...) + BOZO_PRINTFLIKE(2, 3); +void bozoerr(bozohttpd_t *, int, const char *, ...) + BOZO_PRINTFLIKE(3, 4) + BOZO_DEAD; +void bozoasprintf(bozohttpd_t *, char **, const char *, ...) + BOZO_PRINTFLIKE(3, 4); +char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *, + int, void *, size_t)); char *bozostrnsep(char **, const char *, ssize_t *); - void *bozomalloc(bozohttpd_t *, size_t); void *bozorealloc(bozohttpd_t *, void *, size_t); -char *bozostrdup(bozohttpd_t *, const char *); +char *bozostrdup(bozohttpd_t *, bozo_httpreq_t *, const char *); + +#define bozo_noop do { /* nothing */ } while (/*CONSTCOND*/0) /* ssl-bozo.c */ #ifdef NO_SSL_SUPPORT -#define bozo_ssl_set_opts(w, x, y) do { /* nothing */ } while (0) -#define bozo_ssl_init(x) do { /* nothing */ } while (0) -#define bozo_ssl_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 +270,13 @@ void bozo_auth_check_401(bozo_httpreq_t void bozo_auth_cgi_setenv(bozo_httpreq_t *, char ***); int bozo_auth_cgi_count(bozo_httpreq_t *); #else +#define bozo_auth_init(x) 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 +303,9 @@ int bozo_process_lua(bozo_httpreq_t *); /* daemon-bozo.c */ #ifdef NO_DAEMON_MODE -#define bozo_daemon_init(x) do { /* nothing */ } while (0) +#define bozo_daemon_init(x) bozo_noop #define bozo_daemon_fork(x) 0 -#define bozo_daemon_closefds(x) do { /* nothing */ } while (0) +#define bozo_daemon_closefds(x) bozo_noop #else void bozo_daemon_init(bozohttpd_t *); int bozo_daemon_fork(bozohttpd_t *); @@ -299,9 +315,11 @@ void bozo_daemon_closefds(bozohttpd_t *) /* tilde-luzah-bozo.c */ #ifdef NO_USER_SUPPORT -#define bozo_user_transform(a, c) 0 +#define bozo_user_transform(x) 0 +#define bozo_user_free(x) 0 #else -int bozo_user_transform(bozo_httpreq_t *, int *); +int bozo_user_transform(bozo_httpreq_t *); +#define bozo_user_free(x) free(x) #endif /* NO_USER_SUPPORT */ @@ -319,7 +337,8 @@ const char *bozo_content_encoding(bozo_h bozo_content_map_t *bozo_match_content_map(bozohttpd_t *, const char *, int); bozo_content_map_t *bozo_get_content_map(bozohttpd_t *, const char *); #ifndef NO_DYNAMIC_CONTENT -void bozo_add_content_map_mime(bozohttpd_t *, const char *, const char *, const char *, const char *); +void bozo_add_content_map_mime(bozohttpd_t *, const char *, const char *, + const char *, const char *); #endif /* I/O */ @@ -330,7 +349,7 @@ int bozo_flush(bozohttpd_t *, FILE *); /* misc */ int bozo_init_httpd(bozohttpd_t *); -int bozo_init_prefs(bozoprefs_t *); +int bozo_init_prefs(bozohttpd_t *, bozoprefs_t *); int bozo_set_defaults(bozohttpd_t *, bozoprefs_t *); int bozo_setup(bozohttpd_t *, bozoprefs_t *, const char *, const char *); bozo_httpreq_t *bozo_read_request(bozohttpd_t *); @@ -338,7 +357,7 @@ void bozo_process_request(bozo_httpreq_t void bozo_clean_request(bozo_httpreq_t *); /* variables */ -int bozo_set_pref(bozoprefs_t *, const char *, const char *); +int bozo_set_pref(bozohttpd_t *, bozoprefs_t *, const char *, const char *); char *bozo_get_pref(bozoprefs_t *, const char *); #endif /* BOZOHTTOPD_H_ */ Index: cgi-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/cgi-bozo.c,v retrieving revision 1.20.2.1 diff -p -u -u -r1.20.2.1 cgi-bozo.c --- cgi-bozo.c 9 Jul 2014 09:42:39 -0000 1.20.2.1 +++ cgi-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -3,7 +3,7 @@ /* $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)); } @@ -214,7 +215,7 @@ append_index_html(bozohttpd_t *httpd, ch void bozo_cgi_setbin(bozohttpd_t *httpd, const char *path) { - httpd->cgibin = strdup(path); + httpd->cgibin = bozostrdup(httpd, NULL, path); debug((httpd, DEBUG_OBESE, "cgibin (cgi-bin directory) is %s", httpd->cgibin)); } @@ -259,26 +260,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; @@ -310,13 +315,13 @@ bozo_process_cgi(bozo_httpreq_t *request ix = 0; if (cgihandler) { command = file + 1; - path = bozostrdup(httpd, cgihandler); + path = bozostrdup(httpd, request, cgihandler); argv[ix++] = path; /* argv[] = [ path, command, query, NULL ] */ } 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, @@ -413,21 +418,18 @@ bozo_process_cgi(bozo_httpreq_t *request bozo_setenv(httpd, "REMOTE_ADDR", request->hr_remoteaddr, curenvp++); /* - * XXX Apache does this when invoking content handlers, and PHP - * XXX 5.3 requires it as a "security" measure. + * Apache does this when invoking content handlers, and PHP + * 5.3 requires it as a "security" measure. */ if (cgihandler) bozo_setenv(httpd, "REDIRECT_STATUS", "200", curenvp++); bozo_auth_cgi_setenv(request, &curenvp); - free(file); - free(url); - debug((httpd, DEBUG_FAT, "bozo_process_cgi: going exec %s, %s %s %s", path, argv[0], strornull(argv[1]), strornull(argv[2]))); if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1) - bozo_err(httpd, 1, "child socketpair failed: %s", + bozoerr(httpd, 1, "child socketpair failed: %s", strerror(errno)); /* @@ -438,7 +440,7 @@ bozo_process_cgi(bozo_httpreq_t *request */ switch (fork()) { case -1: /* eep, failure */ - bozo_err(httpd, 1, "child fork failed: %s", strerror(errno)); + bozoerr(httpd, 1, "child fork failed: %s", strerror(errno)); /*NOTREACHED*/ case 0: close(sv[0]); @@ -450,19 +452,23 @@ bozo_process_cgi(bozo_httpreq_t *request bozo_daemon_closefds(httpd); if (-1 == execve(path, argv, envp)) - bozo_err(httpd, 1, "child exec failed: %s: %s", + bozoerr(httpd, 1, "child exec failed: %s: %s", path, strerror(errno)); /* NOT REACHED */ - bozo_err(httpd, 1, "child execve returned?!"); + bozoerr(httpd, 1, "child execve returned?!"); } + free(query); + free(file); + free(url); + close(sv[1]); /* parent: read from stdin (bozo_read()) write to sv[0] */ /* child: read from sv[0] (bozo_write()) write to stdout */ pid = fork(); if (pid == -1) - bozo_err(httpd, 1, "io child fork failed: %s", strerror(errno)); + bozoerr(httpd, 1, "io child fork failed: %s", strerror(errno)); else if (pid == 0) { /* child reader/writer */ close(STDIN_FILENO); @@ -486,7 +492,7 @@ bozo_process_cgi(bozo_httpreq_t *request rbytes -= wbytes; bp += wbytes; } else - bozo_err(httpd, 1, "write failed: %s", + bozoerr(httpd, 1, "write failed: %s", strerror(errno)); } } @@ -503,7 +509,8 @@ bozo_process_cgi(bozo_httpreq_t *request #ifndef NO_DYNAMIC_CONTENT /* cgi maps are simple ".postfix /path/to/prog" */ void -bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg, const char *cgihandler) +bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg, + const char *cgihandler) { bozo_content_map_t *map; @@ -514,7 +521,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: content-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/content-bozo.c,v retrieving revision 1.7.2.1 diff -p -u -u -r1.7.2.1 content-bozo.c --- content-bozo.c 9 Jul 2014 09:42:39 -0000 1.7.2.1 +++ content-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -3,7 +3,7 @@ /* $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: daemon-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/daemon-bozo.c,v retrieving revision 1.15.2.1 diff -p -u -u -r1.15.2.1 daemon-bozo.c --- daemon-bozo.c 9 Jul 2014 09:42:39 -0000 1.15.2.1 +++ daemon-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -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: dir-index-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/dir-index-bozo.c,v retrieving revision 1.13.2.2 diff -p -u -u -r1.13.2.2 dir-index-bozo.c --- dir-index-bozo.c 9 Jul 2014 09:42:39 -0000 1.13.2.2 +++ dir-index-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -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, "Index of %s\r\n", - request->hr_file); + printname); bozo_printf(httpd, "

Index of %s

\r\n", - request->hr_file); + printname); bozo_printf(httpd, "
\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, "
");
 
-	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: lua-bozo.c
===================================================================
RCS file: /cvsroot/src/libexec/httpd/lua-bozo.c,v
retrieving revision 1.9.6.2
diff -p -u -u -r1.9.6.2 lua-bozo.c
--- lua-bozo.c	9 Jul 2014 09:42:39 -0000	1.9.6.2
+++ lua-bozo.c	10 Apr 2016 00:35:18 -0000
@@ -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: main.c
===================================================================
RCS file: /cvsroot/src/libexec/httpd/main.c,v
retrieving revision 1.5.2.1
diff -p -u -u -r1.5.2.1 main.c
--- main.c	9 Jul 2014 09:42:39 -0000	1.5.2.1
+++ main.c	10 Apr 2016 00:35:18 -0000
@@ -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: printenv.lua
===================================================================
RCS file: /cvsroot/src/libexec/httpd/printenv.lua,v
retrieving revision 1.2.6.2
diff -p -u -u -r1.2.6.2 printenv.lua
--- printenv.lua	9 Jul 2014 09:42:39 -0000	1.2.6.2
+++ printenv.lua	10 Apr 2016 00:35:18 -0000
@@ -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([[
 		
 			
 				Bozotic Lua Environment
@@ -29,54 +35,58 @@ function printenv(env, headers, query)
 				

Bozotic Lua Environment

]]) - print('module version: ' .. httpd._VERSION .. '
') + httpd.print('module version: ' .. httpd._VERSION .. '
') - print('

Server Environment

') + httpd.print('

Server Environment

') -- print the list of "environment" variables for k, v in pairs(env) do - print(k .. '=' .. v .. '
') + httpd.print(k .. '=' .. v .. '
') end - print('

Request Headers

') + httpd.print('

Request Headers

') for k, v in pairs(headers) do - print(k .. '=' .. v .. '
') + httpd.print(k .. '=' .. v .. '
') end if query ~= nil then - print('

Query Variables

') + httpd.print('

Query Variables

') for k, v in pairs(query) do - print(k .. '=' .. v .. '
') + httpd.print(k .. '=' .. v .. '
') end end - print('

Form Test

') + httpd.print('

Form Test

') - print([[ -
+ httpd.print([[ +
]]) -- output a footer - print([[ + httpd.print([[ ]]) 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('

Form Variables

') + httpd.print('

Form Variables

') if env.CONTENT_TYPE ~= nil then - print('Content-type: ' .. env.CONTENT_TYPE .. '
') + httpd.print('Content-type: ' .. env.CONTENT_TYPE .. '
') end for k, v in pairs(query) do - print(k .. '=' .. v .. '
') + httpd.print(k .. '=' .. v .. '
') end else - print('No values') + httpd.print('No values') end end Index: ssl-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/ssl-bozo.c,v retrieving revision 1.13.2.1 diff -p -u -u -r1.13.2.1 ssl-bozo.c --- ssl-bozo.c 9 Jul 2014 09:42:39 -0000 1.13.2.1 +++ ssl-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -30,7 +30,7 @@ * */ -/* this code implements SSL for bozohttpd */ +/* this code implements SSL and backend IO for bozohttpd */ #include #include @@ -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; + unsigned long sslcode = ERR_get_error(); - 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 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: tilde-luzah-bozo.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/tilde-luzah-bozo.c,v retrieving revision 1.9.2.1 diff -p -u -u -r1.9.2.1 tilde-luzah-bozo.c --- tilde-luzah-bozo.c 9 Jul 2014 09:42:39 -0000 1.9.2.1 +++ tilde-luzah-bozo.c 10 Apr 2016 00:35:18 -0000 @@ -36,6 +36,7 @@ #include +#include #include #include #include @@ -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: lua/bozo.lua =================================================================== RCS file: /cvsroot/src/libexec/httpd/lua/bozo.lua,v retrieving revision 1.1.1.1 diff -p -u -u -r1.1.1.1 bozo.lua --- lua/bozo.lua 10 May 2010 03:30:04 -0000 1.1.1.1 +++ lua/bozo.lua 10 Apr 2016 00:35:18 -0000 @@ -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: lua/glue.c =================================================================== RCS file: /cvsroot/src/libexec/httpd/lua/glue.c,v retrieving revision 1.1.1.1 diff -p -u -u -r1.1.1.1 glue.c --- lua/glue.c 10 May 2010 03:30:04 -0000 1.1.1.1 +++ lua/glue.c 10 Apr 2016 00:35:18 -0000 @@ -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: testsuite/Makefile =================================================================== RCS file: /cvsroot/src/libexec/httpd/testsuite/Makefile,v retrieving revision 1.4 diff -p -u -u -r1.4 Makefile --- testsuite/Makefile 23 May 2009 02:26:03 -0000 1.4 +++ testsuite/Makefile 10 Apr 2016 00:35:18 -0000 @@ -6,6 +6,7 @@ BIGFILETESTS= partial4000 partial8000 BOZOHTTPD?= ../bozohttpd BOZOHTTPD?= ../debug/bozohttpd-debug WGET?= wget +DATA?= $(.CURDIR)/data all: @@ -19,14 +20,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 Index: testsuite/t10.out =================================================================== RCS file: /cvsroot/src/libexec/httpd/testsuite/t10.out,v retrieving revision 1.1.1.1 diff -p -u -u -r1.1.1.1 t10.out --- testsuite/t10.out 18 Apr 2009 07:09:27 -0000 1.1.1.1 +++ testsuite/t10.out 10 Apr 2016 00:35:18 -0000 @@ -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 -500 Internal Error -

500 Internal Error

-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file +404 Not Found +

404 Not Found

+/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file Index: testsuite/test-bigfile =================================================================== RCS file: /cvsroot/src/libexec/httpd/testsuite/test-bigfile,v retrieving revision 1.1.1.1 diff -p -u -u -r1.1.1.1 test-bigfile --- testsuite/test-bigfile 23 May 2009 02:21:19 -0000 1.1.1.1 +++ testsuite/test-bigfile 10 Apr 2016 00:35:18 -0000 @@ -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