1 /* $NetBSD: bozohttpd.h,v 1.63 2020/08/20 05:46:31 spz Exp $ */ 2 3 /* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */ 4 5 /* 6 * Copyright (c) 1997-2019 Matthew R. Green 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer and 16 * dedication in the documentation and/or other materials provided 17 * with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 #ifndef BOZOHTTOPD_H_ 33 #define BOZOHTTOPD_H_ 1 34 35 #include "netbsd_queue.h" 36 37 #include <stdbool.h> 38 #include <stdio.h> 39 #include <signal.h> 40 41 #include <sys/stat.h> 42 43 #ifndef NO_LUA_SUPPORT 44 #include <lua.h> 45 #endif 46 47 #ifndef NO_BLOCKLIST_SUPPORT 48 #include <blocklist.h> 49 void pfilter_notify(const int, const int); 50 #endif 51 52 /* QNX provides a lot of NetBSD things in nbutil.h */ 53 #ifdef HAVE_NBUTIL_H 54 #include <nbutil.h> 55 #endif 56 57 /* lots of "const" but gets free()'ed etc at times, sigh */ 58 59 /* headers */ 60 typedef struct bozoheaders { 61 /*const*/ char *h_header; 62 /*const*/ char *h_value; /* this gets free()'ed etc at times */ 63 SIMPLEQ_ENTRY(bozoheaders) h_next; 64 } bozoheaders_t; 65 SIMPLEQ_HEAD(qheaders, bozoheaders); 66 67 #ifndef NO_LUA_SUPPORT 68 typedef struct lua_handler { 69 const char *name; 70 int ref; 71 SIMPLEQ_ENTRY(lua_handler) h_next; 72 } lua_handler_t; 73 74 typedef struct lua_state_map { 75 const char *script; 76 const char *prefix; 77 lua_State *L; 78 SIMPLEQ_HEAD(, lua_handler) handlers; 79 SIMPLEQ_ENTRY(lua_state_map) s_next; 80 } lua_state_map_t; 81 #endif 82 83 typedef struct bozo_content_map_t { 84 const char *name; /* postfix of file */ 85 const char *type; /* matching content-type */ 86 const char *encoding; /* matching content-encoding */ 87 const char *encoding11; /* matching content-encoding (HTTP/1.1) */ 88 const char *cgihandler; /* optional CGI handler */ 89 } bozo_content_map_t; 90 91 /* this struct holds the bozo constants */ 92 typedef struct bozo_consts_t { 93 const char *http_09; /* "HTTP/0.9" */ 94 const char *http_10; /* "HTTP/1.0" */ 95 const char *http_11; /* "HTTP/1.1" */ 96 const char *text_plain; /* "text/plain" */ 97 } bozo_consts_t; 98 99 /* this structure encapsulates all the bozo flags and control vars */ 100 typedef struct bozohttpd_t { 101 char *rootdir; /* root directory */ 102 int numeric; /* avoid gethostby*() */ 103 char *virtbase; /* virtual directory base */ 104 int unknown_slash; /* unknown vhosts go to normal slashdir */ 105 int logstderr; /* log to stderr (even if not tty) */ 106 int background; /* drop into daemon mode */ 107 int foreground; /* keep daemon mode in foreground */ 108 char *pidfile; /* path to the pid file, if any */ 109 size_t page_size; /* page size */ 110 char *slashdir; /* www slash directory */ 111 char *bindport; /* bind port; default "http" */ 112 char *bindaddress; /* address for binding - INADDR_ANY */ 113 int debug; /* debugging level */ 114 char *virthostname; /* my name */ 115 const char *server_software;/* our brand :-) */ 116 const char *index_html; /* our home page */ 117 const char *public_html; /* ~user/public_html page */ 118 int enable_users; /* enable public_html */ 119 int enable_cgi_users; /* use the cgi handler */ 120 int *sock; /* bound sockets */ 121 int nsock; /* number of above */ 122 struct pollfd *fds; /* current poll fd set */ 123 int request_times; /* # times a request was processed */ 124 int dir_indexing; /* handle directories */ 125 const char *dir_readme; /* include README footer in indexes */ 126 int hide_dots; /* hide .* */ 127 int process_cgi; /* use the cgi handler */ 128 char *cgibin; /* cgi-bin directory */ 129 unsigned ssl_timeout; /* ssl timeout */ 130 unsigned initial_timeout;/* first line timeout */ 131 unsigned header_timeout; /* header lines timeout */ 132 unsigned request_timeout;/* total session timeout */ 133 #ifndef NO_LUA_SUPPORT 134 int process_lua; /* use the Lua handler */ 135 SIMPLEQ_HEAD(, lua_state_map) lua_states; 136 #endif 137 void *sslinfo; /* pointer to ssl struct */ 138 int dynamic_content_map_size;/* size of dyn cont map */ 139 bozo_content_map_t *dynamic_content_map;/* dynamic content map */ 140 size_t mmapsz; /* size of region to mmap */ 141 char *getln_buffer; /* space for getln buffer */ 142 ssize_t getln_buflen; /* length of allocated space */ 143 char *errorbuf; /* no dynamic allocation allowed */ 144 bozo_consts_t consts; /* various constants */ 145 } bozohttpd_t; 146 147 /* bozo_httpreq_t */ 148 typedef struct bozo_httpreq_t { 149 bozohttpd_t *hr_httpd; 150 int hr_method; 151 #define HTTP_GET 0x01 152 #define HTTP_POST 0x02 153 #define HTTP_HEAD 0x03 154 #define HTTP_OPTIONS 0x04 /* not supported */ 155 #define HTTP_PUT 0x05 /* not supported */ 156 #define HTTP_DELETE 0x06 /* not supported */ 157 #define HTTP_TRACE 0x07 /* not supported */ 158 #define HTTP_CONNECT 0x08 /* not supported */ 159 const char *hr_methodstr; 160 char *hr_virthostname; /* server name (if not identical 161 to hr_httpd->virthostname) */ 162 char *hr_file; 163 char *hr_oldfile; /* if we added an index_html */ 164 char *hr_query; 165 char *hr_host; /* HTTP/1.1 Host: or virtual hostname, 166 possibly including a port number */ 167 #ifndef NO_USER_SUPPORT 168 char *hr_user; /* username if we hit userdir request */ 169 #endif /* !NO_USER_SUPPORT */ 170 const char *hr_proto; 171 const char *hr_content_type; 172 const char *hr_content_length; 173 const char *hr_allow; 174 const char *hr_referrer; 175 const char *hr_range; 176 const char *hr_if_modified_since; 177 const char *hr_accept_encoding; 178 int hr_have_range; 179 off_t hr_first_byte_pos; 180 off_t hr_last_byte_pos; 181 /*const*/ char *hr_remotehost; 182 /*const*/ char *hr_remoteaddr; 183 /*const*/ char *hr_serverport; 184 #ifdef DO_HTPASSWD 185 /*const*/ char *hr_authrealm; 186 /*const*/ char *hr_authuser; 187 /*const*/ char *hr_authpass; 188 #endif 189 struct qheaders hr_headers; 190 struct qheaders hr_replheaders; 191 unsigned hr_nheaders; 192 size_t hr_header_bytes; 193 } bozo_httpreq_t; 194 195 /* helper to access the "active" host name from a httpd/request pair */ 196 #define BOZOHOST(HTTPD,REQUEST) ((REQUEST)->hr_virthostname ? \ 197 (REQUEST)->hr_virthostname : \ 198 (HTTPD)->virthostname) 199 200 /* structure to hold string based (name, value) pairs with preferences */ 201 typedef struct bozoprefs_t { 202 size_t size; /* size of the two arrays */ 203 size_t count; /* # of entries in arrays */ 204 char **name; /* names of each entry */ 205 char **value; /* values for the name entries */ 206 } bozoprefs_t; 207 208 /* sun2 has a tiny VA range */ 209 #ifdef __mc68010__ 210 #ifndef BOZO_WRSZ 211 #define BOZO_WRSZ (16 * 1024) 212 #endif 213 #ifndef BOZO_MMAPSZ 214 #define BOZO_MMAPSZ (BOZO_WRSZ * 4) 215 #endif 216 #endif 217 218 /* by default write in upto 64KiB chunks, and mmap in upto 64MiB chunks */ 219 #ifndef BOZO_WRSZ 220 #define BOZO_WRSZ (64 * 1024) 221 #endif 222 #ifndef BOZO_MMAPSZ 223 #define BOZO_MMAPSZ (BOZO_WRSZ * 1024) 224 #endif 225 226 /* only allow this many total headers bytes */ 227 #define BOZO_HEADERS_MAX_SIZE (16 * 1024) 228 229 /* debug flags */ 230 #define DEBUG_NORMAL 1 231 #define DEBUG_FAT 2 232 #define DEBUG_OBESE 3 233 #define DEBUG_EXPLODING 4 234 235 #define strornull(x) ((x) ? (x) : "<null>") 236 237 #if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__lint__) 238 #define BOZO_PRINTFLIKE(x,y) __attribute__((__format__(__printf__, x,y))) 239 #define BOZO_DEAD __attribute__((__noreturn__)) 240 #define BOZO_CHECKRET __attribute__((__warn_unused_result__)) 241 #else 242 #define BOZO_PRINTFLIKE(x,y) 243 #define BOZO_DEAD 244 #define BOZO_CHECKRET 245 #endif 246 247 #ifdef NO_DEBUG 248 #define debug(x) 249 #define have_debug (0) 250 #else 251 void debug__(bozohttpd_t *, int, const char *, ...) BOZO_PRINTFLIKE(3, 4); 252 #define debug(x) debug__ x 253 #define have_debug (1) 254 #endif /* NO_DEBUG */ 255 256 /* 257 * bozohttpd special files. avoid serving these out. 258 * 259 * When you add some .bz* file, make sure to also check it in 260 * bozo_check_special_files() 261 */ 262 263 #ifndef DIRECT_ACCESS_FILE 264 #define DIRECT_ACCESS_FILE ".bzdirect" 265 #endif 266 #ifndef REDIRECT_FILE 267 #define REDIRECT_FILE ".bzredirect" 268 #endif 269 #ifndef ABSREDIRECT_FILE 270 #define ABSREDIRECT_FILE ".bzabsredirect" 271 #endif 272 #ifndef REMAP_FILE 273 #define REMAP_FILE ".bzremap" 274 #endif 275 #ifndef AUTH_FILE 276 #define AUTH_FILE ".htpasswd" 277 #endif 278 279 /* be sure to always return this error up */ 280 int bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *); 281 282 int bozo_check_special_files(bozo_httpreq_t *, const char *, bool) BOZO_CHECKRET; 283 char *bozo_http_date(char *, size_t); 284 void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, 285 const char *); 286 char *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute); 287 char *bozo_escape_html(bozohttpd_t *httpd, const char *url); 288 int bozo_decode_url_percent(bozo_httpreq_t *, char *); 289 290 /* these are similar to libc functions, no underscore here */ 291 void bozowarn(bozohttpd_t *, const char *, ...) 292 BOZO_PRINTFLIKE(2, 3); 293 void bozoerr(bozohttpd_t *, int, const char *, ...) 294 BOZO_PRINTFLIKE(3, 4) 295 BOZO_DEAD; 296 void bozoasprintf(bozohttpd_t *, char **, const char *, ...) 297 BOZO_PRINTFLIKE(3, 4); 298 char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *, 299 int, void *, size_t)); 300 char *bozostrnsep(char **, const char *, ssize_t *); 301 void *bozomalloc(bozohttpd_t *, size_t); 302 void *bozorealloc(bozohttpd_t *, void *, size_t); 303 char *bozostrdup(bozohttpd_t *, bozo_httpreq_t *, const char *); 304 305 #define bozo_noop do { /* nothing */ } while (/*CONSTCOND*/0) 306 307 #define have_all (1) 308 309 /* ssl-bozo.c */ 310 #ifdef NO_SSL_SUPPORT 311 #define bozo_ssl_set_opts(w, x, y) bozo_noop 312 #define bozo_ssl_set_ciphers(w, x) bozo_noop 313 #define bozo_ssl_init(x) bozo_noop 314 #define bozo_ssl_accept(x) (0) 315 #define bozo_ssl_shutdown(x) bozo_noop 316 #define bozo_ssl_destroy(x) bozo_noop 317 #define have_ssl (0) 318 #else 319 void bozo_ssl_set_opts(bozohttpd_t *, const char *, const char *); 320 void bozo_ssl_set_ciphers(bozohttpd_t *, const char *); 321 void bozo_ssl_init(bozohttpd_t *); 322 int bozo_ssl_accept(bozohttpd_t *); 323 void bozo_ssl_shutdown(bozohttpd_t *); 324 void bozo_ssl_destroy(bozohttpd_t *); 325 #define have_ssl (1) 326 #endif 327 328 329 /* auth-bozo.c */ 330 #ifdef DO_HTPASSWD 331 void bozo_auth_init(bozo_httpreq_t *); 332 int bozo_auth_check(bozo_httpreq_t *, const char *); 333 void bozo_auth_cleanup(bozo_httpreq_t *); 334 int bozo_auth_check_headers(bozo_httpreq_t *, char *, char *, ssize_t); 335 void bozo_auth_check_401(bozo_httpreq_t *, int); 336 void bozo_auth_cgi_setenv(bozo_httpreq_t *, char ***); 337 int bozo_auth_cgi_count(bozo_httpreq_t *); 338 #else 339 #define bozo_auth_init(x) bozo_noop 340 #define bozo_auth_check(x, y) (0) 341 #define bozo_auth_cleanup(x) bozo_noop 342 #define bozo_auth_check_headers(y, z, a, b) (0) 343 #define bozo_auth_check_401(x, y) bozo_noop 344 #define bozo_auth_cgi_setenv(x, y) bozo_noop 345 #define bozo_auth_cgi_count(x) (0) 346 #endif /* DO_HTPASSWD */ 347 348 349 /* cgi-bozo.c */ 350 #ifdef NO_CGIBIN_SUPPORT 351 #define bozo_cgi_setbin(h,s) bozo_noop 352 #define bozo_process_cgi(h) (0) 353 #define have_cgibin (0) 354 #else 355 void bozo_cgi_setbin(bozohttpd_t *, const char *); 356 void bozo_setenv(bozohttpd_t *, const char *, const char *, char **); 357 int bozo_process_cgi(bozo_httpreq_t *); 358 #define have_cgibin (1) 359 #endif /* NO_CGIBIN_SUPPORT */ 360 361 362 /* lua-bozo.c */ 363 #ifdef NO_LUA_SUPPORT 364 #define bozo_process_lua(h) (0) 365 #define bozo_add_lua_map(h,s,t) bozo_noop 366 #define have_lua (0) 367 #else 368 void bozo_add_lua_map(bozohttpd_t *, const char *, const char *); 369 int bozo_process_lua(bozo_httpreq_t *); 370 #define have_lua (1) 371 #endif /* NO_LUA_SUPPORT */ 372 373 374 /* daemon-bozo.c */ 375 #ifdef NO_DAEMON_MODE 376 #define bozo_daemon_init(x) bozo_noop 377 #define bozo_daemon_fork(x) (0) 378 #define bozo_daemon_closefds(x) bozo_noop 379 #define have_daemon_mode (0) 380 #else 381 void bozo_daemon_init(bozohttpd_t *); 382 int bozo_daemon_fork(bozohttpd_t *); 383 void bozo_daemon_closefds(bozohttpd_t *); 384 #define have_daemon_mode (1) 385 #endif /* NO_DAEMON_MODE */ 386 387 388 /* tilde-luzah-bozo.c */ 389 #ifdef NO_USER_SUPPORT 390 #define bozo_user_transform(x) (0) 391 #define bozo_user_free(x) /* nothing */ 392 #define have_user (0) 393 #else 394 int bozo_user_transform(bozo_httpreq_t *); 395 #define bozo_user_free(x) free(x) 396 #define have_user (1) 397 #endif /* NO_USER_SUPPORT */ 398 399 400 /* dir-index-bozo.c */ 401 #ifdef NO_DIRINDEX_SUPPORT 402 #define bozo_dir_index(a, b, c) (0) 403 #define have_dirindex (0) 404 #else 405 int bozo_dir_index(bozo_httpreq_t *, const char *, int); 406 #define have_dirindex (1) 407 #endif /* NO_DIRINDEX_SUPPORT */ 408 409 410 /* content-bozo.c */ 411 const char *bozo_content_type(bozo_httpreq_t *, const char *); 412 const char *bozo_content_encoding(bozo_httpreq_t *, const char *); 413 bozo_content_map_t *bozo_match_content_map(bozohttpd_t *, const char *, int); 414 bozo_content_map_t *bozo_get_content_map(bozohttpd_t *, const char *); 415 #ifdef NO_DYNAMIC_CONTENT 416 #define bozo_add_content_map_mime(h,s,t,u,v) bozo_noop 417 #define have_dynamic_content (0) 418 #else 419 void bozo_add_content_map_mime(bozohttpd_t *, const char *, const char *, 420 const char *, const char *); 421 #define have_dynamic_content (1) 422 #endif 423 424 /* additional cgi-bozo.c */ 425 #if have_cgibin && have_dynamic_content 426 void bozo_add_content_map_cgi(bozohttpd_t *, const char *, const char *); 427 #else 428 #define bozo_add_content_map_cgi(h,s,t) 429 #endif 430 431 /* I/O */ 432 int bozo_printf(bozohttpd_t *, const char *, ...) BOZO_PRINTFLIKE(2, 3); 433 ssize_t bozo_read(bozohttpd_t *, int, void *, size_t); 434 ssize_t bozo_write(bozohttpd_t *, int, const void *, size_t); 435 int bozo_flush(bozohttpd_t *, FILE *); 436 437 /* misc */ 438 int bozo_init_httpd(bozohttpd_t *); 439 int bozo_init_prefs(bozohttpd_t *, bozoprefs_t *); 440 int bozo_set_defaults(bozohttpd_t *, bozoprefs_t *); 441 int bozo_setup(bozohttpd_t *, bozoprefs_t *, const char *, const char *); 442 bozo_httpreq_t *bozo_read_request(bozohttpd_t *); 443 void bozo_process_request(bozo_httpreq_t *); 444 void bozo_clean_request(bozo_httpreq_t *); 445 int bozo_set_timeout(bozohttpd_t *, bozoprefs_t *, const char *, const char *); 446 bozoheaders_t *addmerge_reqheader(bozo_httpreq_t *, const char *, 447 const char *, ssize_t); 448 bozoheaders_t *addmerge_replheader(bozo_httpreq_t *, const char *, 449 const char *, ssize_t); 450 451 /* variables */ 452 int bozo_set_pref(bozohttpd_t *, bozoprefs_t *, const char *, const char *); 453 char *bozo_get_pref(bozoprefs_t *, const char *); 454 455 int bozo_get_version(char */*buf*/, size_t /*size*/); 456 457 extern volatile sig_atomic_t bozo_timeout_hit; 458 459 #endif /* BOZOHTTOPD_H_ */ 460