1 /* $NetBSD: main.c,v 1.23 2020/07/06 23:31:36 jmcneill 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-2018 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 and go into daemon mode"); 67 if (have_cgibin && 68 have_dynamic_content) 69 bozowarn(httpd, " -C arg prog\t\tadd this CGI handler"); 70 if (have_cgibin) 71 bozowarn(httpd, " -c cgibin\t\tenable cgi-bin support in " 72 "this directory"); 73 if (have_debug) 74 bozowarn(httpd, " -d\t\t\tenable debug support"); 75 if (have_cgibin) 76 bozowarn(httpd, " -E\t\t\tenable CGI support for user dirs"); 77 if (have_user && 78 have_cgibin) 79 bozowarn(httpd, " -e\t\t\tdon't clean the environment " 80 "(-t and -U only)"); 81 if (have_daemon_mode) 82 bozowarn(httpd, " -f\t\t\tforeground in daemon mode"); 83 if (have_all) 84 bozowarn(httpd, " -G print version number and exit"); 85 if (have_dirindex) 86 bozowarn(httpd, " -H\t\t\thide files starting with a period " 87 "(.) in index mode"); 88 if (have_all) 89 bozowarn(httpd, " -I port\t\tbind or use on this port"); 90 if (have_daemon_mode) 91 bozowarn(httpd, " -i address\t\tbind on this address " 92 "(daemon mode only)"); 93 if (have_lua) 94 bozowarn(httpd, " -L arg script\tadd this Lua script"); 95 if (have_dynamic_content) 96 bozowarn(httpd, " -M arg t c c11\tadd this mime extenstion"); 97 if (have_daemon_mode) 98 bozowarn(httpd, " -P pidfile\t\tpid file path"); 99 if (have_user) 100 bozowarn(httpd, " -p dir\t\t\"public_html\" directory name"); 101 102 if (have_all) { 103 bozowarn(httpd, " -S version\t\tset server version string"); 104 bozowarn(httpd, " -s\t\t\talways log to stderr"); 105 bozowarn(httpd, " -T type timeout\tset `type' timeout"); 106 bozowarn(httpd, " -t dir\t\tchroot to `dir'"); 107 bozowarn(httpd, " -U username\t\tchange user to `user'"); 108 } 109 if (have_user) 110 bozowarn(httpd, " -u\t\t\tenable ~user/public_html support"); 111 112 if (have_all) { 113 bozowarn(httpd, " -V\t\t\tUnknown virtual hosts go to " 114 "`slashdir'"); 115 bozowarn(httpd, " -v virtualroot\tenable virtual host " 116 "support in this directory"); 117 } 118 119 if (have_dirindex) 120 bozowarn(httpd, " -X\t\t\tdirectory index support"); 121 if (have_all) 122 bozowarn(httpd, " -x index\t\tdefault \"index.html\" " 123 "file name"); 124 125 if (have_ssl) { 126 bozowarn(httpd, " -Z cert privkey\tspecify path to server " 127 "certificate and private key file\n" 128 "\t\t\tin pem format and enable bozohttpd in " 129 "SSL mode"); 130 bozowarn(httpd, " -z ciphers\t\tspecify SSL ciphers"); 131 } 132 133 bozoerr(httpd, 1, "%s failed to start", progname); 134 } 135 136 int 137 main(int argc, char **argv) 138 { 139 bozo_httpreq_t *request; 140 bozohttpd_t httpd; 141 bozoprefs_t prefs; 142 char *progname; 143 const char *val; 144 int c; 145 146 (void) memset(&httpd, 0x0, sizeof(httpd)); 147 (void) memset(&prefs, 0x0, sizeof(prefs)); 148 149 if ((progname = strrchr(argv[0], '/')) == NULL) 150 progname = argv[0]; 151 else 152 progname++; 153 154 openlog(progname, LOG_PID|LOG_NDELAY, LOG_FTP); 155 156 bozo_set_defaults(&httpd, &prefs); 157 158 /* 159 * -r option was removed, do not reuse it for a while 160 */ 161 162 while ((c = getopt(argc, argv, 163 "C:EGHI:L:M:P:R:S:T:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) { 164 switch (c) { 165 166 case 'b': 167 if (!have_daemon_mode) 168 no_daemon_mode: 169 bozoerr(&httpd, 1, "Daemon mode not enabled"); 170 171 /* 172 * test suite support - undocumented 173 * background == 2 (aka, -b -b) means to 174 * only process 1 per kid 175 */ 176 val = bozo_get_pref(&prefs, "background") == NULL ? 177 "1" : "2"; 178 bozo_set_pref(&httpd, &prefs, "background", val); 179 break; 180 181 case 'c': 182 if (!have_cgibin) 183 bozoerr(&httpd, 1, "CGI not enabled"); 184 185 bozo_cgi_setbin(&httpd, optarg); 186 break; 187 188 case 'C': 189 if (!have_dynamic_content && !have_cgibin) 190 bozoerr(&httpd, 1, 191 "dynamic CGI handler support not enabled"); 192 193 /* make sure there's two arguments */ 194 if (argc - optind < 1) 195 usage(&httpd, progname); 196 bozo_add_content_map_cgi(&httpd, optarg, 197 argv[optind++]); 198 break; 199 200 case 'd': 201 if (!have_debug) 202 bozowarn(&httpd, "Debugging not enabled"); 203 httpd.debug++; 204 break; 205 206 case 'E': 207 if (have_user && 208 have_cgibin) 209 bozoerr(&httpd, 1, "CGI not enabled"); 210 211 bozo_set_pref(&httpd, &prefs, "enable user cgibin", 212 "true"); 213 break; 214 215 case 'e': 216 if (!have_daemon_mode) 217 goto no_daemon_mode; 218 219 bozo_set_pref(&httpd, &prefs, "dirty environment", 220 "true"); 221 break; 222 223 case 'f': 224 if (!have_daemon_mode) 225 goto no_daemon_mode; 226 227 bozo_set_pref(&httpd, &prefs, "foreground", "true"); 228 break; 229 230 case 'G': 231 { 232 char version[128]; 233 234 bozo_get_version(version, sizeof(version)); 235 printf("bozohttpd version %s\n", version); 236 } 237 return 0; 238 239 case 'H': 240 if (!have_dirindex) 241 no_dirindex_support: 242 bozoerr(&httpd, 1, 243 "directory indexing not enabled"); 244 245 bozo_set_pref(&httpd, &prefs, "hide dots", "true"); 246 break; 247 248 case 'I': 249 bozo_set_pref(&httpd, &prefs, "port number", optarg); 250 break; 251 252 case 'i': 253 if (!have_daemon_mode) 254 goto no_daemon_mode; 255 256 bozo_set_pref(&httpd, &prefs, "bind address", optarg); 257 break; 258 259 case 'L': 260 if (!have_lua) 261 bozoerr(&httpd, 1, "Lua support not enabled"); 262 263 /* make sure there's two argument */ 264 if (argc - optind < 1) 265 usage(&httpd, progname); 266 bozo_add_lua_map(&httpd, optarg, argv[optind]); 267 optind++; 268 break; 269 270 case 'M': 271 if (!have_dynamic_content) 272 bozoerr(&httpd, 1, 273 "dynamic mime content support not enabled"); 274 275 /* make sure there're four arguments */ 276 if (argc - optind < 3) 277 usage(&httpd, progname); 278 bozo_add_content_map_mime(&httpd, optarg, argv[optind], 279 argv[optind+1], argv[optind+2]); 280 optind += 3; 281 break; 282 283 case 'n': 284 bozo_set_pref(&httpd, &prefs, "numeric", "true"); 285 break; 286 287 case 'P': 288 if (!have_daemon_mode) 289 goto no_daemon_mode; 290 291 bozo_set_pref(&httpd, &prefs, "pid file", optarg); 292 break; 293 294 case 'p': 295 if (!have_user) 296 no_user_support: 297 bozoerr(&httpd, 1, "User support not enabled"); 298 299 bozo_set_pref(&httpd, &prefs, "public_html", optarg); 300 break; 301 302 case 'R': 303 bozo_set_pref(&httpd, &prefs, "directory index readme", 304 optarg); 305 break; 306 307 case 'S': 308 bozo_set_pref(&httpd, &prefs, "server software", 309 optarg); 310 break; 311 312 case 's': 313 bozo_set_pref(&httpd, &prefs, "log to stderr", "true"); 314 break; 315 316 case 'T': 317 /* make sure there're two arguments */ 318 if (argc - optind < 1) 319 usage(&httpd, progname); 320 if (bozo_set_timeout(&httpd, &prefs, 321 optarg, argv[optind])) { 322 bozoerr(&httpd, 1, 323 "invalid type '%s'", optarg); 324 /* NOTREACHED */ 325 } 326 optind++; 327 break; 328 329 case 't': 330 bozo_set_pref(&httpd, &prefs, "chroot dir", optarg); 331 break; 332 333 case 'U': 334 bozo_set_pref(&httpd, &prefs, "username", optarg); 335 break; 336 337 case 'u': 338 if (!have_user) 339 goto no_user_support; 340 341 bozo_set_pref(&httpd, &prefs, "enable users", "true"); 342 break; 343 344 case 'V': 345 bozo_set_pref(&httpd, &prefs, "unknown slash", "true"); 346 break; 347 348 case 'v': 349 bozo_set_pref(&httpd, &prefs, "virtual base", optarg); 350 break; 351 352 case 'X': 353 if (!have_dirindex) 354 goto no_dirindex_support; 355 356 bozo_set_pref(&httpd, &prefs, "directory indexing", 357 "true"); 358 break; 359 360 case 'x': 361 bozo_set_pref(&httpd, &prefs, "index.html", optarg); 362 break; 363 364 case 'Z': 365 if (!have_ssl) 366 no_ssl: 367 bozoerr(&httpd, 1, "ssl support not enabled"); 368 369 /* make sure there's two arguments */ 370 if (argc - optind < 1) 371 usage(&httpd, progname); 372 bozo_ssl_set_opts(&httpd, optarg, argv[optind++]); 373 break; 374 375 case 'z': 376 if (!have_ssl) 377 goto no_ssl; 378 379 bozo_ssl_set_ciphers(&httpd, optarg); 380 break; 381 382 default: 383 usage(&httpd, progname); 384 /* NOTREACHED */ 385 } 386 } 387 388 argc -= optind; 389 argv += optind; 390 391 if (argc == 0 || argc > 2) { 392 usage(&httpd, progname); 393 } 394 395 /* virtual host, and root of tree to serve */ 396 bozo_setup(&httpd, &prefs, argv[1], argv[0]); 397 398 /* 399 * read and process the HTTP request. 400 */ 401 do { 402 if ((request = bozo_read_request(&httpd)) != NULL) { 403 bozo_process_request(request); 404 bozo_clean_request(request); 405 } 406 } while (httpd.background); 407 408 return (0); 409 } 410