1 /* $NetBSD: main.c,v 1.27 2021/02/27 12:36:46 mrg Exp $ */ 2 3 /* $eterna: main.c,v 1.6 2011/11/18 09:21:15 mrg Exp $ */ 4 /* from: eterna: bozohttpd.c,v 1.159 2009/05/23 02:14:30 mrg Exp */ 5 6 /* 7 * Copyright (c) 1997-2021 Matthew R. Green 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer and 17 * dedication in the documentation and/or other materials provided 18 * with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34 /* this program is dedicated to the Great God of Processed Cheese */ 35 36 /* 37 * main.c: C front end to bozohttpd 38 */ 39 40 #include <sys/types.h> 41 #include <sys/param.h> 42 43 #include <errno.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <syslog.h> 47 #include <time.h> 48 #include <unistd.h> 49 50 #include "bozohttpd.h" 51 52 /* variables and functions */ 53 #ifndef LOG_FTP 54 #define LOG_FTP LOG_DAEMON 55 #endif 56 57 /* print a usage message, and then exit */ 58 BOZO_DEAD static void 59 usage(bozohttpd_t *httpd, char *progname) 60 { 61 bozowarn(httpd, "usage: %s [options] slashdir [virtualhostname]", 62 progname); 63 bozowarn(httpd, "options:"); 64 65 if (have_daemon_mode) 66 bozowarn(httpd, " -b\t\t\tbackground in daemon mode"); 67 if (have_cgibin && 68 have_dynamic_content) 69 bozowarn(httpd, " -C suffix handler\tadd this CGI handler " 70 "for paths ending with `suffix'"); 71 if (have_cgibin) 72 bozowarn(httpd, " -c cgibin\t\tenable cgi-bin support in " 73 "this directory"); 74 if (have_debug) 75 bozowarn(httpd, " -d\t\t\tenable debug support"); 76 if (have_user && 77 have_cgibin) 78 bozowarn(httpd, " -E\t\t\tenable CGI support for user dirs"); 79 if (have_core) 80 bozowarn(httpd, " -e\t\t\tdon't clean the environment " 81 "(-t and -U only)"); 82 if (have_daemon_mode) 83 bozowarn(httpd, " -f\t\t\tforeground in daemon mode"); 84 if (have_core) 85 bozowarn(httpd, " -G\t\t\tprint version number and exit"); 86 if (have_dirindex) 87 bozowarn(httpd, " -H\t\t\thide files starting with a period " 88 "(.) in index mode"); 89 if (have_core) 90 bozowarn(httpd, " -I port\t\tbind or use on this port"); 91 if (have_daemon_mode) 92 bozowarn(httpd, " -i address\t\tbind on this address " 93 "(daemon mode only)"); 94 if (have_lua) 95 bozowarn(httpd, " -L prefix script\tadd this Lua script for " 96 "paths starting with `prefix'"); 97 if (have_dynamic_content) 98 bozowarn(httpd, " -M suffix t c c11\tadd this mime entry"); 99 if (have_core) 100 bozowarn(httpd, " -n\t\t\tdon't resolve host names"); 101 if (have_daemon_mode) 102 bozowarn(httpd, " -P pidfile\t\tpid file path"); 103 if (have_user) 104 bozowarn(httpd, " -p dir\t\t\"public_html\" directory name"); 105 106 if (have_core) { 107 bozowarn(httpd, " -S version\t\tset server version string"); 108 bozowarn(httpd, " -s\t\t\talways log to stderr"); 109 bozowarn(httpd, " -T type timeout\t" 110 "set <ssl|initial|header|request> timeout"); 111 bozowarn(httpd, " -t dir\t\tchroot to `dir'"); 112 bozowarn(httpd, " -U user\t\tchange user to `user'"); 113 } 114 if (have_user) 115 bozowarn(httpd, " -u\t\t\tenable ~user/public_html support"); 116 117 if (have_core) { 118 bozowarn(httpd, " -V\t\t\tUnknown virtual hosts go to " 119 "`slashdir'"); 120 bozowarn(httpd, " -v virtualroot\tenable virtual host " 121 "support in this directory"); 122 } 123 124 if (have_dirindex) 125 bozowarn(httpd, " -X\t\t\tdirectory index support"); 126 if (have_core) 127 bozowarn(httpd, " -x index\t\tdefault \"index.html\" " 128 "file name"); 129 130 if (have_ssl) { 131 bozowarn(httpd, " -Z cert privkey\tspecify path to server " 132 "certificate and private key file\n" 133 "\t\t\tin pem format and enable bozohttpd in " 134 "SSL mode"); 135 bozowarn(httpd, " -z ciphers\t\tspecify SSL ciphers"); 136 } 137 138 bozoerr(httpd, 1, "%s failed to start", progname); 139 } 140 141 int 142 main(int argc, char **argv) 143 { 144 bozo_httpreq_t *request; 145 bozohttpd_t httpd; 146 bozoprefs_t prefs; 147 char *progname; 148 const char *val; 149 int c; 150 151 (void) memset(&httpd, 0x0, sizeof(httpd)); 152 (void) memset(&prefs, 0x0, sizeof(prefs)); 153 154 if ((progname = strrchr(argv[0], '/')) == NULL) 155 progname = argv[0]; 156 else 157 progname++; 158 159 openlog(progname, LOG_PID|LOG_NDELAY, LOG_FTP); 160 161 bozo_set_defaults(&httpd, &prefs); 162 163 /* 164 * -r option was removed, do not reuse it for a while 165 */ 166 167 while ((c = getopt(argc, argv, 168 "C:EGHI:L:M:P:R:S:T:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) { 169 switch (c) { 170 171 case 'b': 172 if (!have_daemon_mode) 173 no_daemon_mode: 174 bozoerr(&httpd, 1, "Daemon mode not enabled"); 175 176 /* 177 * test suite support - undocumented 178 * background == 2 (aka, -b -b) means to 179 * only process 1 per kid 180 */ 181 val = bozo_get_pref(&prefs, "background") == NULL ? 182 "1" : "2"; 183 bozo_set_pref(&httpd, &prefs, "background", val); 184 break; 185 186 case 'C': 187 if (!have_dynamic_content || 188 !have_cgibin) 189 bozoerr(&httpd, 1, 190 "dynamic CGI handler support not enabled"); 191 192 /* make sure there's two arguments */ 193 if (argc - optind < 1) 194 usage(&httpd, progname); 195 bozo_add_content_map_cgi(&httpd, optarg, 196 argv[optind++]); 197 break; 198 199 case 'c': 200 if (!have_cgibin) 201 bozoerr(&httpd, 1, "CGI not enabled"); 202 203 bozo_cgi_setbin(&httpd, optarg); 204 break; 205 206 case 'd': 207 if (!have_debug) 208 bozowarn(&httpd, "Debugging not enabled"); 209 httpd.debug++; 210 break; 211 212 case 'E': 213 if (!have_user || 214 !have_cgibin) 215 bozoerr(&httpd, 1, "CGI not enabled"); 216 217 bozo_set_pref(&httpd, &prefs, "enable user cgibin", 218 "true"); 219 break; 220 221 case 'e': 222 bozo_set_pref(&httpd, &prefs, "dirty environment", 223 "true"); 224 break; 225 226 case 'f': 227 if (!have_daemon_mode) 228 goto no_daemon_mode; 229 230 bozo_set_pref(&httpd, &prefs, "foreground", "true"); 231 break; 232 233 case 'G': 234 { 235 char version[128]; 236 237 bozo_get_version(version, sizeof(version)); 238 printf("bozohttpd version %s\n", version); 239 } 240 return 0; 241 242 case 'H': 243 if (!have_dirindex) 244 no_dirindex_support: 245 bozoerr(&httpd, 1, 246 "directory indexing not enabled"); 247 248 bozo_set_pref(&httpd, &prefs, "hide dots", "true"); 249 break; 250 251 case 'I': 252 bozo_set_pref(&httpd, &prefs, "port number", optarg); 253 break; 254 255 case 'i': 256 if (!have_daemon_mode) 257 goto no_daemon_mode; 258 259 bozo_set_pref(&httpd, &prefs, "bind address", optarg); 260 break; 261 262 case 'L': 263 if (!have_lua) 264 bozoerr(&httpd, 1, "Lua support not enabled"); 265 266 /* make sure there's two argument */ 267 if (argc - optind < 1) 268 usage(&httpd, progname); 269 bozo_add_lua_map(&httpd, optarg, argv[optind]); 270 optind++; 271 break; 272 273 case 'M': 274 if (!have_dynamic_content) 275 bozoerr(&httpd, 1, 276 "dynamic mime content support not enabled"); 277 278 /* make sure there're four arguments */ 279 if (argc - optind < 3) 280 usage(&httpd, progname); 281 bozo_add_content_map_mime(&httpd, optarg, argv[optind], 282 argv[optind+1], argv[optind+2]); 283 optind += 3; 284 break; 285 286 case 'n': 287 bozo_set_pref(&httpd, &prefs, "numeric", "true"); 288 break; 289 290 case 'P': 291 if (!have_daemon_mode) 292 goto no_daemon_mode; 293 294 bozo_set_pref(&httpd, &prefs, "pid file", optarg); 295 break; 296 297 case 'p': 298 if (!have_user) 299 no_user_support: 300 bozoerr(&httpd, 1, "User support not enabled"); 301 302 bozo_set_pref(&httpd, &prefs, "public_html", optarg); 303 break; 304 305 case 'R': 306 bozo_set_pref(&httpd, &prefs, "directory index readme", 307 optarg); 308 break; 309 310 case 'S': 311 bozo_set_pref(&httpd, &prefs, "server software", 312 optarg); 313 break; 314 315 case 's': 316 bozo_set_pref(&httpd, &prefs, "log to stderr", "true"); 317 break; 318 319 case 'T': 320 /* make sure there're two arguments */ 321 if (argc - optind < 1) 322 usage(&httpd, progname); 323 if (bozo_set_timeout(&httpd, &prefs, 324 optarg, argv[optind])) { 325 bozoerr(&httpd, 1, 326 "invalid type '%s'", optarg); 327 /* NOTREACHED */ 328 } 329 optind++; 330 break; 331 332 case 't': 333 bozo_set_pref(&httpd, &prefs, "chroot dir", optarg); 334 break; 335 336 case 'U': 337 bozo_set_pref(&httpd, &prefs, "username", optarg); 338 break; 339 340 case 'u': 341 if (!have_user) 342 goto no_user_support; 343 344 bozo_set_pref(&httpd, &prefs, "enable users", "true"); 345 break; 346 347 case 'V': 348 bozo_set_pref(&httpd, &prefs, "unknown slash", "true"); 349 break; 350 351 case 'v': 352 bozo_set_pref(&httpd, &prefs, "virtual base", optarg); 353 break; 354 355 case 'X': 356 if (!have_dirindex) 357 goto no_dirindex_support; 358 359 bozo_set_pref(&httpd, &prefs, "directory indexing", 360 "true"); 361 break; 362 363 case 'x': 364 bozo_set_pref(&httpd, &prefs, "index.html", optarg); 365 break; 366 367 case 'Z': 368 if (!have_ssl) 369 no_ssl: 370 bozoerr(&httpd, 1, "ssl support not enabled"); 371 372 /* make sure there's two arguments */ 373 if (argc - optind < 1) 374 usage(&httpd, progname); 375 bozo_ssl_set_opts(&httpd, optarg, argv[optind++]); 376 break; 377 378 case 'z': 379 if (!have_ssl) 380 goto no_ssl; 381 382 bozo_ssl_set_ciphers(&httpd, optarg); 383 break; 384 385 default: 386 usage(&httpd, progname); 387 /* NOTREACHED */ 388 } 389 } 390 391 argc -= optind; 392 argv += optind; 393 394 if (argc == 0 || argc > 2) { 395 usage(&httpd, progname); 396 } 397 398 /* virtual host, and root of tree to serve */ 399 bozo_setup(&httpd, &prefs, argv[1], argv[0]); 400 401 /* 402 * read and process the HTTP request. 403 */ 404 do { 405 if ((request = bozo_read_request(&httpd)) != NULL) { 406 bozo_process_request(request); 407 bozo_clean_request(request); 408 } 409 } while (httpd.background); 410 411 bozo_cleanup(&httpd, &prefs); 412 413 return (0); 414 } 415