1 /* $OpenBSD: httpd.c,v 1.74 2024/04/08 12:45:18 tobhe Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/socket.h> 22 #include <sys/stat.h> 23 #include <sys/resource.h> 24 25 #include <netinet/in.h> 26 #include <arpa/inet.h> 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <stdarg.h> 31 #include <string.h> 32 #include <signal.h> 33 #include <getopt.h> 34 #include <netdb.h> 35 #include <fnmatch.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <event.h> 39 #include <syslog.h> 40 #include <unistd.h> 41 #include <ctype.h> 42 #include <pwd.h> 43 44 #include "httpd.h" 45 46 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 47 48 __dead void usage(void); 49 50 int parent_configure(struct httpd *); 51 void parent_configure_done(struct httpd *); 52 void parent_reload(struct httpd *, unsigned int, const char *); 53 void parent_reopen(struct httpd *); 54 void parent_sig_handler(int, short, void *); 55 void parent_shutdown(struct httpd *); 56 int parent_dispatch_server(int, struct privsep_proc *, 57 struct imsg *); 58 int parent_dispatch_logger(int, struct privsep_proc *, 59 struct imsg *); 60 void parent_tls_ticket_rekey_start(struct server *); 61 void parent_tls_ticket_rekey(int, short, void *); 62 63 struct httpd *httpd_env; 64 65 static struct privsep_proc procs[] = { 66 { "server", PROC_SERVER, parent_dispatch_server, server }, 67 { "logger", PROC_LOGGER, parent_dispatch_logger, logger } 68 }; 69 70 enum privsep_procid privsep_process; 71 72 void 73 parent_sig_handler(int sig, short event, void *arg) 74 { 75 struct privsep *ps = arg; 76 77 switch (sig) { 78 case SIGTERM: 79 case SIGINT: 80 parent_shutdown(ps->ps_env); 81 break; 82 case SIGHUP: 83 log_info("%s: reload requested with SIGHUP", __func__); 84 85 /* 86 * This is safe because libevent uses async signal handlers 87 * that run in the event loop and not in signal context. 88 */ 89 parent_reload(ps->ps_env, CONFIG_RELOAD, NULL); 90 break; 91 case SIGPIPE: 92 /* ignore */ 93 break; 94 case SIGUSR1: 95 log_info("%s: reopen requested with SIGUSR1", __func__); 96 97 parent_reopen(ps->ps_env); 98 break; 99 default: 100 fatalx("unexpected signal"); 101 } 102 } 103 104 __dead void 105 usage(void) 106 { 107 extern char *__progname; 108 109 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n", 110 __progname); 111 exit(1); 112 } 113 114 int 115 main(int argc, char *argv[]) 116 { 117 int c; 118 unsigned int proc; 119 int debug = 0, verbose = 0; 120 uint32_t opts = 0; 121 struct httpd *env; 122 struct privsep *ps; 123 const char *conffile = CONF_FILE; 124 enum privsep_procid proc_id = PROC_PARENT; 125 int proc_instance = 0; 126 const char *errp, *title = NULL; 127 int argc0 = argc; 128 129 while ((c = getopt(argc, argv, "dD:nf:I:P:v")) != -1) { 130 switch (c) { 131 case 'd': 132 debug = 2; 133 break; 134 case 'D': 135 if (cmdline_symset(optarg) < 0) 136 log_warnx("could not parse macro definition %s", 137 optarg); 138 break; 139 case 'n': 140 debug = 2; 141 opts |= HTTPD_OPT_NOACTION; 142 break; 143 case 'f': 144 conffile = optarg; 145 break; 146 case 'v': 147 verbose++; 148 opts |= HTTPD_OPT_VERBOSE; 149 break; 150 case 'P': 151 title = optarg; 152 proc_id = proc_getid(procs, nitems(procs), title); 153 if (proc_id == PROC_MAX) 154 fatalx("invalid process name"); 155 break; 156 case 'I': 157 proc_instance = strtonum(optarg, 0, 158 PROC_MAX_INSTANCES, &errp); 159 if (errp) 160 fatalx("invalid process instance"); 161 break; 162 default: 163 usage(); 164 } 165 } 166 167 /* log to stderr until daemonized */ 168 log_init(debug ? debug : 1, LOG_DAEMON); 169 170 argc -= optind; 171 if (argc > 0) 172 usage(); 173 174 if ((env = calloc(1, sizeof(*env))) == NULL || 175 (ps = calloc(1, sizeof(*ps))) == NULL) 176 exit(1); 177 178 httpd_env = env; 179 env->sc_ps = ps; 180 ps->ps_env = env; 181 TAILQ_INIT(&ps->ps_rcsocks); 182 env->sc_conffile = conffile; 183 env->sc_opts = opts; 184 185 if (parse_config(env->sc_conffile, env) == -1) 186 exit(1); 187 188 if (geteuid()) 189 errx(1, "need root privileges"); 190 191 if ((ps->ps_pw = getpwnam(HTTPD_USER)) == NULL) 192 errx(1, "unknown user %s", HTTPD_USER); 193 194 /* Configure the control socket */ 195 ps->ps_csock.cs_name = NULL; 196 197 log_init(debug, LOG_DAEMON); 198 log_setverbose(verbose); 199 200 if (env->sc_opts & HTTPD_OPT_NOACTION) 201 ps->ps_noaction = 1; 202 203 ps->ps_instances[PROC_SERVER] = env->sc_prefork_server; 204 ps->ps_instance = proc_instance; 205 if (title != NULL) 206 ps->ps_title[proc_id] = title; 207 208 if (env->sc_chroot == NULL) 209 env->sc_chroot = ps->ps_pw->pw_dir; 210 for (proc = 0; proc < nitems(procs); proc++) 211 procs[proc].p_chroot = env->sc_chroot; 212 213 if (env->sc_logdir == NULL) { 214 if (asprintf(&env->sc_logdir, "%s%s", env->sc_chroot, 215 HTTPD_LOGROOT) == -1) 216 errx(1, "malloc failed"); 217 } 218 219 /* only the parent returns */ 220 proc_init(ps, procs, nitems(procs), debug, argc0, argv, proc_id); 221 222 log_procinit("parent"); 223 224 if (ps->ps_noaction == 0) 225 log_info("startup"); 226 227 if (pledge("stdio rpath wpath cpath inet dns sendfd", NULL) == -1) 228 fatal("pledge"); 229 230 event_init(); 231 232 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 233 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 234 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 235 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 236 signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps); 237 238 signal_add(&ps->ps_evsigint, NULL); 239 signal_add(&ps->ps_evsigterm, NULL); 240 signal_add(&ps->ps_evsighup, NULL); 241 signal_add(&ps->ps_evsigpipe, NULL); 242 signal_add(&ps->ps_evsigusr1, NULL); 243 244 proc_connect(ps); 245 246 if (load_config(env->sc_conffile, env) == -1) { 247 proc_kill(env->sc_ps); 248 exit(1); 249 } 250 251 if (env->sc_opts & HTTPD_OPT_NOACTION) { 252 fprintf(stderr, "configuration OK\n"); 253 proc_kill(env->sc_ps); 254 exit(0); 255 } 256 257 /* initialize the TLS session id to a random key for all procs */ 258 arc4random_buf(env->sc_tls_sid, sizeof(env->sc_tls_sid)); 259 260 if (parent_configure(env) == -1) 261 fatalx("configuration failed"); 262 263 event_dispatch(); 264 265 parent_shutdown(env); 266 /* NOTREACHED */ 267 268 return (0); 269 } 270 271 int 272 parent_configure(struct httpd *env) 273 { 274 int id; 275 struct ctl_flags cf; 276 int ret = -1; 277 struct server *srv; 278 struct media_type *media; 279 struct auth *auth; 280 281 RB_FOREACH(media, mediatypes, env->sc_mediatypes) { 282 if (config_setmedia(env, media) == -1) 283 fatal("send media"); 284 } 285 286 TAILQ_FOREACH(auth, env->sc_auth, auth_entry) { 287 if (config_setauth(env, auth) == -1) 288 fatal("send auth"); 289 } 290 291 /* First send the servers... */ 292 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { 293 if (srv->srv_conf.flags & SRVFLAG_LOCATION) 294 continue; 295 /* start the rekey of the tls ticket keys */ 296 if (srv->srv_conf.flags & SRVFLAG_TLS && 297 srv->srv_conf.tls_ticket_lifetime) 298 parent_tls_ticket_rekey_start(srv); 299 if (config_setserver(env, srv) == -1) 300 fatal("send server"); 301 } 302 /* ...and now send the locations */ 303 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { 304 if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) 305 continue; 306 if (config_setserver(env, srv) == -1) 307 fatal("send location"); 308 } 309 310 /* The servers need to reload their config. */ 311 env->sc_reload = env->sc_prefork_server + 1; 312 313 for (id = 0; id < PROC_MAX; id++) { 314 if (id == privsep_process) 315 continue; 316 cf.cf_opts = env->sc_opts; 317 cf.cf_flags = env->sc_flags; 318 memcpy(cf.cf_tls_sid, env->sc_tls_sid, sizeof(cf.cf_tls_sid)); 319 320 proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf)); 321 } 322 323 ret = 0; 324 325 config_purge(env, CONFIG_ALL & ~CONFIG_SERVERS); 326 return (ret); 327 } 328 329 void 330 parent_reload(struct httpd *env, unsigned int reset, const char *filename) 331 { 332 if (env->sc_reload) { 333 log_debug("%s: already in progress: %d pending", 334 __func__, env->sc_reload); 335 return; 336 } 337 338 /* Switch back to the default config file */ 339 if (filename == NULL || *filename == '\0') 340 filename = env->sc_conffile; 341 342 log_debug("%s: level %d config file %s", __func__, reset, filename); 343 344 config_purge(env, CONFIG_ALL); 345 346 if (reset == CONFIG_RELOAD) { 347 if (load_config(filename, env) == -1) { 348 log_debug("%s: failed to load config file %s", 349 __func__, filename); 350 } 351 352 config_setreset(env, CONFIG_ALL); 353 354 if (parent_configure(env) == -1) { 355 log_debug("%s: failed to commit config from %s", 356 __func__, filename); 357 } 358 } else 359 config_setreset(env, reset); 360 } 361 362 void 363 parent_reopen(struct httpd *env) 364 { 365 proc_compose(env->sc_ps, PROC_LOGGER, IMSG_CTL_REOPEN, NULL, 0); 366 } 367 368 void 369 parent_configure_done(struct httpd *env) 370 { 371 int id; 372 373 if (env->sc_reload == 0) { 374 log_warnx("%s: configuration already finished", __func__); 375 return; 376 } 377 378 env->sc_reload--; 379 if (env->sc_reload == 0) { 380 for (id = 0; id < PROC_MAX; id++) { 381 if (id == privsep_process) 382 continue; 383 384 proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL, 0); 385 } 386 } 387 } 388 389 void 390 parent_shutdown(struct httpd *env) 391 { 392 config_purge(env, CONFIG_ALL); 393 394 proc_kill(env->sc_ps); 395 control_cleanup(&env->sc_ps->ps_csock); 396 if (env->sc_ps->ps_csock.cs_name != NULL) 397 (void)unlink(env->sc_ps->ps_csock.cs_name); 398 399 free(env->sc_ps); 400 free(env); 401 402 log_info("parent terminating, pid %d", getpid()); 403 404 exit(0); 405 } 406 407 int 408 parent_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg) 409 { 410 struct privsep *ps = p->p_ps; 411 struct httpd *env = ps->ps_env; 412 413 switch (imsg->hdr.type) { 414 case IMSG_CFG_DONE: 415 parent_configure_done(env); 416 break; 417 default: 418 return (-1); 419 } 420 421 return (0); 422 } 423 424 int 425 parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg) 426 { 427 struct privsep *ps = p->p_ps; 428 struct httpd *env = ps->ps_env; 429 unsigned int v; 430 char *str = NULL; 431 432 switch (imsg->hdr.type) { 433 case IMSG_CTL_RESET: 434 IMSG_SIZE_CHECK(imsg, &v); 435 memcpy(&v, imsg->data, sizeof(v)); 436 parent_reload(env, v, NULL); 437 break; 438 case IMSG_CTL_RELOAD: 439 if (IMSG_DATA_SIZE(imsg) > 0) 440 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 441 parent_reload(env, CONFIG_RELOAD, str); 442 free(str); 443 break; 444 case IMSG_CTL_SHUTDOWN: 445 parent_shutdown(env); 446 break; 447 case IMSG_CTL_REOPEN: 448 parent_reopen(env); 449 break; 450 case IMSG_CFG_DONE: 451 parent_configure_done(env); 452 break; 453 case IMSG_LOG_OPEN: 454 if (logger_open_priv(imsg) == -1) 455 fatalx("failed to open log file"); 456 break; 457 default: 458 return (-1); 459 } 460 461 return (0); 462 } 463 464 void 465 parent_tls_ticket_rekey_start(struct server *srv) 466 { 467 struct timeval tv; 468 469 server_generate_ticket_key(&srv->srv_conf); 470 471 evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv); 472 timerclear(&tv); 473 tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4; 474 evtimer_add(&srv->srv_evt, &tv); 475 } 476 477 void 478 parent_tls_ticket_rekey(int fd, short events, void *arg) 479 { 480 struct server *srv = arg; 481 struct timeval tv; 482 483 server_generate_ticket_key(&srv->srv_conf); 484 proc_compose_imsg(httpd_env->sc_ps, PROC_SERVER, -1, 485 IMSG_TLSTICKET_REKEY, -1, -1, &srv->srv_conf.tls_ticket_key, 486 sizeof(srv->srv_conf.tls_ticket_key)); 487 explicit_bzero(&srv->srv_conf.tls_ticket_key, 488 sizeof(srv->srv_conf.tls_ticket_key)); 489 490 evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv); 491 timerclear(&tv); 492 tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4; 493 evtimer_add(&srv->srv_evt, &tv); 494 } 495 496 /* 497 * Utility functions 498 */ 499 500 void 501 event_again(struct event *ev, int fd, short event, 502 void (*fn)(int, short, void *), 503 struct timeval *start, struct timeval *end, void *arg) 504 { 505 struct timeval tv_next, tv_now, tv; 506 507 getmonotime(&tv_now); 508 memcpy(&tv_next, end, sizeof(tv_next)); 509 timersub(&tv_now, start, &tv_now); 510 timersub(&tv_next, &tv_now, &tv_next); 511 512 memset(&tv, 0, sizeof(tv)); 513 if (timercmp(&tv_next, &tv, >)) 514 memcpy(&tv, &tv_next, sizeof(tv)); 515 516 event_del(ev); 517 event_set(ev, fd, event, fn, arg); 518 event_add(ev, &tv); 519 } 520 521 int 522 expand_string(char *label, size_t len, const char *srch, const char *repl) 523 { 524 char *tmp; 525 char *p, *q; 526 527 if ((tmp = calloc(1, len)) == NULL) { 528 log_debug("%s: calloc", __func__); 529 return (-1); 530 } 531 p = q = label; 532 while ((q = strstr(p, srch)) != NULL) { 533 *q = '\0'; 534 if ((strlcat(tmp, p, len) >= len) || 535 (strlcat(tmp, repl, len) >= len)) { 536 log_debug("%s: string too long", __func__); 537 free(tmp); 538 return (-1); 539 } 540 q += strlen(srch); 541 p = q; 542 } 543 if (strlcat(tmp, p, len) >= len) { 544 log_debug("%s: string too long", __func__); 545 free(tmp); 546 return (-1); 547 } 548 (void)strlcpy(label, tmp, len); /* always fits */ 549 free(tmp); 550 551 return (0); 552 } 553 554 const char * 555 url_decode(char *url) 556 { 557 char *p, *q; 558 char hex[3]; 559 unsigned long x; 560 561 hex[2] = '\0'; 562 p = q = url; 563 564 while (*p != '\0') { 565 switch (*p) { 566 case '%': 567 /* Encoding character is followed by two hex chars */ 568 if (!(isxdigit((unsigned char)p[1]) && 569 isxdigit((unsigned char)p[2]))) 570 return (NULL); 571 572 hex[0] = p[1]; 573 hex[1] = p[2]; 574 575 /* 576 * We don't have to validate "hex" because it is 577 * guaranteed to include two hex chars followed by nul. 578 */ 579 x = strtoul(hex, NULL, 16); 580 *q = (char)x; 581 p += 2; 582 break; 583 default: 584 *q = *p; 585 break; 586 } 587 p++; 588 q++; 589 } 590 *q = '\0'; 591 592 return (url); 593 } 594 595 const char * 596 canonicalize_path(const char *input, char *path, size_t len) 597 { 598 const char *i; 599 char *p, *start, *end; 600 601 /* assuming input starts with '/' and is nul-terminated */ 602 i = input; 603 p = path; 604 605 if (*input != '/' || len < 3) 606 return (NULL); 607 608 start = p; 609 end = p + (len - 1); 610 611 while (*i != '\0') { 612 /* Detect truncation */ 613 if (p >= end) 614 return (NULL); 615 616 /* 1. check for special path elements */ 617 if (i[0] == '/') { 618 if (i[1] == '/') { 619 /* a) skip repeating '//' slashes */ 620 while (i[1] == '/') 621 i++; 622 continue; 623 } else if (i[1] == '.' && i[2] == '.' && 624 (i[3] == '/' || i[3] == '\0')) { 625 /* b) revert '..' to previous directory */ 626 i += 3; 627 while (p > start && *p != '/') 628 p--; 629 *p = '\0'; 630 continue; 631 } else if (i[1] == '.' && 632 (i[2] == '/' || i[2] == '\0')) { 633 /* c) skip unnecessary '.' current dir */ 634 i += 2; 635 continue; 636 } 637 } 638 639 /* 2. copy any other characters */ 640 *p++ = *i; 641 i++; 642 } 643 if (p == start) 644 *p++ = '/'; 645 *p++ = '\0'; 646 647 return (path); 648 } 649 650 size_t 651 path_info(char *path) 652 { 653 char *p, *start, *end, ch; 654 struct stat st; 655 int ret; 656 657 start = path; 658 end = start + strlen(path); 659 660 for (p = end; p > start; p--) { 661 /* Scan every path component from the end and at each '/' */ 662 if (p < end && *p != '/') 663 continue; 664 665 /* Temporarily cut the path component out */ 666 ch = *p; 667 *p = '\0'; 668 ret = stat(path, &st); 669 *p = ch; 670 671 /* Break if the initial path component was found */ 672 if (ret == 0) 673 break; 674 } 675 676 return (p - start); 677 } 678 679 char * 680 url_encode(const char *src) 681 { 682 static char hex[] = "0123456789ABCDEF"; 683 char *dp, *dst; 684 unsigned char c; 685 686 /* We need 3 times the memory if every letter is encoded. */ 687 if ((dst = calloc(3, strlen(src) + 1)) == NULL) 688 return (NULL); 689 690 for (dp = dst; *src != 0; src++) { 691 c = (unsigned char) *src; 692 if (c == ' ' || c == '#' || c == '%' || c == '?' || c == '"' || 693 c == '&' || c == '<' || c <= 0x1f || c >= 0x7f) { 694 *dp++ = '%'; 695 *dp++ = hex[c >> 4]; 696 *dp++ = hex[c & 0x0f]; 697 } else 698 *dp++ = *src; 699 } 700 return (dst); 701 } 702 703 char* 704 escape_html(const char* src) 705 { 706 char *dp, *dst; 707 708 /* We need 5 times the memory if every letter is "&" */ 709 if ((dst = calloc(5, strlen(src) + 1)) == NULL) 710 return NULL; 711 712 for (dp = dst; *src != 0; src++) { 713 if (*src == '<') { 714 *dp++ = '&'; 715 *dp++ = 'l'; 716 *dp++ = 't'; 717 *dp++ = ';'; 718 } else if (*src == '>') { 719 *dp++ = '&'; 720 *dp++ = 'g'; 721 *dp++ = 't'; 722 *dp++ = ';'; 723 } else if (*src == '&') { 724 *dp++ = '&'; 725 *dp++ = 'a'; 726 *dp++ = 'm'; 727 *dp++ = 'p'; 728 *dp++ = ';'; 729 } else 730 *dp++ = *src; 731 } 732 return (dst); 733 } 734 735 void 736 socket_rlimit(int maxfd) 737 { 738 struct rlimit rl; 739 740 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 741 fatal("%s: failed to get resource limit", __func__); 742 log_debug("%s: max open files %llu", __func__, rl.rlim_max); 743 744 /* 745 * Allow the maximum number of open file descriptors for this 746 * login class (which should be the class "daemon" by default). 747 */ 748 if (maxfd == -1) 749 rl.rlim_cur = rl.rlim_max; 750 else 751 rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd); 752 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 753 fatal("%s: failed to set resource limit", __func__); 754 } 755 756 char * 757 evbuffer_getline(struct evbuffer *evb) 758 { 759 uint8_t *ptr = EVBUFFER_DATA(evb); 760 size_t len = EVBUFFER_LENGTH(evb); 761 char *str; 762 size_t i; 763 764 /* Safe version of evbuffer_readline() */ 765 if ((str = get_string(ptr, len)) == NULL) 766 return (NULL); 767 768 for (i = 0; str[i] != '\0'; i++) { 769 if (str[i] == '\r' || str[i] == '\n') 770 break; 771 } 772 773 if (i == len) { 774 free(str); 775 return (NULL); 776 } 777 778 str[i] = '\0'; 779 780 if ((i + 1) < len) { 781 if (ptr[i] == '\r' && ptr[i + 1] == '\n') 782 i++; 783 } 784 785 evbuffer_drain(evb, ++i); 786 787 return (str); 788 } 789 790 char * 791 get_string(uint8_t *ptr, size_t len) 792 { 793 size_t i; 794 795 for (i = 0; i < len; i++) 796 if (!(isprint((unsigned char)ptr[i]) || 797 isspace((unsigned char)ptr[i]))) 798 break; 799 800 return strndup(ptr, i); 801 } 802 803 void * 804 get_data(uint8_t *ptr, size_t len) 805 { 806 uint8_t *data; 807 808 if ((data = malloc(len)) == NULL) 809 return (NULL); 810 memcpy(data, ptr, len); 811 812 return (data); 813 } 814 815 int 816 sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen) 817 { 818 struct sockaddr_in *a4, *b4; 819 struct sockaddr_in6 *a6, *b6; 820 uint32_t av[4], bv[4], mv[4]; 821 822 if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC) 823 return (0); 824 else if (a->sa_family > b->sa_family) 825 return (1); 826 else if (a->sa_family < b->sa_family) 827 return (-1); 828 829 if (prefixlen == -1) 830 memset(&mv, 0xff, sizeof(mv)); 831 832 switch (a->sa_family) { 833 case AF_INET: 834 a4 = (struct sockaddr_in *)a; 835 b4 = (struct sockaddr_in *)b; 836 837 av[0] = a4->sin_addr.s_addr; 838 bv[0] = b4->sin_addr.s_addr; 839 if (prefixlen != -1) 840 mv[0] = prefixlen2mask(prefixlen); 841 842 if ((av[0] & mv[0]) > (bv[0] & mv[0])) 843 return (1); 844 if ((av[0] & mv[0]) < (bv[0] & mv[0])) 845 return (-1); 846 break; 847 case AF_INET6: 848 a6 = (struct sockaddr_in6 *)a; 849 b6 = (struct sockaddr_in6 *)b; 850 851 memcpy(&av, &a6->sin6_addr.s6_addr, 16); 852 memcpy(&bv, &b6->sin6_addr.s6_addr, 16); 853 if (prefixlen != -1) 854 prefixlen2mask6(prefixlen, mv); 855 856 if ((av[3] & mv[3]) > (bv[3] & mv[3])) 857 return (1); 858 if ((av[3] & mv[3]) < (bv[3] & mv[3])) 859 return (-1); 860 if ((av[2] & mv[2]) > (bv[2] & mv[2])) 861 return (1); 862 if ((av[2] & mv[2]) < (bv[2] & mv[2])) 863 return (-1); 864 if ((av[1] & mv[1]) > (bv[1] & mv[1])) 865 return (1); 866 if ((av[1] & mv[1]) < (bv[1] & mv[1])) 867 return (-1); 868 if ((av[0] & mv[0]) > (bv[0] & mv[0])) 869 return (1); 870 if ((av[0] & mv[0]) < (bv[0] & mv[0])) 871 return (-1); 872 break; 873 } 874 875 return (0); 876 } 877 878 uint32_t 879 prefixlen2mask(uint8_t prefixlen) 880 { 881 if (prefixlen == 0) 882 return (0); 883 884 if (prefixlen > 32) 885 prefixlen = 32; 886 887 return (htonl(0xffffffff << (32 - prefixlen))); 888 } 889 890 struct in6_addr * 891 prefixlen2mask6(uint8_t prefixlen, uint32_t *mask) 892 { 893 static struct in6_addr s6; 894 int i; 895 896 if (prefixlen > 128) 897 prefixlen = 128; 898 899 memset(&s6, 0, sizeof(s6)); 900 for (i = 0; i < prefixlen / 8; i++) 901 s6.s6_addr[i] = 0xff; 902 i = prefixlen % 8; 903 if (i) 904 s6.s6_addr[prefixlen / 8] = 0xff00 >> i; 905 906 memcpy(mask, &s6, sizeof(s6)); 907 908 return (&s6); 909 } 910 911 int 912 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen, 913 int reserve, volatile int *counter) 914 { 915 int ret; 916 if (getdtablecount() + reserve + 917 *counter >= getdtablesize()) { 918 errno = EMFILE; 919 return (-1); 920 } 921 922 if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) { 923 (*counter)++; 924 DPRINTF("%s: inflight incremented, now %d",__func__, *counter); 925 } 926 return (ret); 927 } 928 929 struct kv * 930 kv_add(struct kvtree *keys, char *key, char *value) 931 { 932 struct kv *kv, *oldkv; 933 934 if (key == NULL) 935 return (NULL); 936 if ((kv = calloc(1, sizeof(*kv))) == NULL) 937 return (NULL); 938 if ((kv->kv_key = strdup(key)) == NULL) { 939 free(kv); 940 return (NULL); 941 } 942 if (value != NULL && 943 (kv->kv_value = strdup(value)) == NULL) { 944 free(kv->kv_key); 945 free(kv); 946 return (NULL); 947 } 948 TAILQ_INIT(&kv->kv_children); 949 950 if ((oldkv = RB_INSERT(kvtree, keys, kv)) != NULL) { 951 TAILQ_INSERT_TAIL(&oldkv->kv_children, kv, kv_entry); 952 kv->kv_parent = oldkv; 953 } 954 955 return (kv); 956 } 957 958 int 959 kv_set(struct kv *kv, char *fmt, ...) 960 { 961 va_list ap; 962 char *value = NULL; 963 struct kv *ckv; 964 int ret; 965 966 va_start(ap, fmt); 967 ret = vasprintf(&value, fmt, ap); 968 va_end(ap); 969 if (ret == -1) 970 return (-1); 971 972 /* Remove all children */ 973 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) { 974 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry); 975 kv_free(ckv); 976 free(ckv); 977 } 978 979 /* Set the new value */ 980 free(kv->kv_value); 981 kv->kv_value = value; 982 983 return (0); 984 } 985 986 int 987 kv_setkey(struct kv *kv, char *fmt, ...) 988 { 989 va_list ap; 990 char *key = NULL; 991 int ret; 992 993 va_start(ap, fmt); 994 ret = vasprintf(&key, fmt, ap); 995 va_end(ap); 996 if (ret == -1) 997 return (-1); 998 999 free(kv->kv_key); 1000 kv->kv_key = key; 1001 1002 return (0); 1003 } 1004 1005 void 1006 kv_delete(struct kvtree *keys, struct kv *kv) 1007 { 1008 struct kv *ckv; 1009 1010 RB_REMOVE(kvtree, keys, kv); 1011 1012 /* Remove all children */ 1013 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) { 1014 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry); 1015 kv_free(ckv); 1016 free(ckv); 1017 } 1018 1019 kv_free(kv); 1020 free(kv); 1021 } 1022 1023 struct kv * 1024 kv_extend(struct kvtree *keys, struct kv *kv, char *value) 1025 { 1026 char *newvalue; 1027 1028 if (kv == NULL) { 1029 return (NULL); 1030 } else if (kv->kv_value != NULL) { 1031 if (asprintf(&newvalue, "%s%s", kv->kv_value, value) == -1) 1032 return (NULL); 1033 1034 free(kv->kv_value); 1035 kv->kv_value = newvalue; 1036 } else if ((kv->kv_value = strdup(value)) == NULL) 1037 return (NULL); 1038 1039 return (kv); 1040 } 1041 1042 void 1043 kv_purge(struct kvtree *keys) 1044 { 1045 struct kv *kv; 1046 1047 while ((kv = RB_MIN(kvtree, keys)) != NULL) 1048 kv_delete(keys, kv); 1049 } 1050 1051 void 1052 kv_free(struct kv *kv) 1053 { 1054 free(kv->kv_key); 1055 kv->kv_key = NULL; 1056 free(kv->kv_value); 1057 kv->kv_value = NULL; 1058 memset(kv, 0, sizeof(*kv)); 1059 } 1060 1061 struct kv * 1062 kv_find(struct kvtree *keys, struct kv *kv) 1063 { 1064 return (RB_FIND(kvtree, keys, kv)); 1065 } 1066 1067 int 1068 kv_cmp(struct kv *a, struct kv *b) 1069 { 1070 return (strcasecmp(a->kv_key, b->kv_key)); 1071 } 1072 1073 RB_GENERATE(kvtree, kv, kv_node, kv_cmp); 1074 1075 struct media_type * 1076 media_add(struct mediatypes *types, struct media_type *media) 1077 { 1078 struct media_type *entry; 1079 1080 if ((entry = RB_FIND(mediatypes, types, media)) != NULL) { 1081 log_debug("%s: entry overwritten for \"%s\"", __func__, 1082 media->media_name); 1083 media_delete(types, entry); 1084 } 1085 1086 if ((entry = malloc(sizeof(*media))) == NULL) 1087 return (NULL); 1088 1089 memcpy(entry, media, sizeof(*entry)); 1090 if (media->media_encoding != NULL && 1091 (entry->media_encoding = strdup(media->media_encoding)) == NULL) { 1092 free(entry); 1093 return (NULL); 1094 } 1095 RB_INSERT(mediatypes, types, entry); 1096 1097 return (entry); 1098 } 1099 1100 void 1101 media_delete(struct mediatypes *types, struct media_type *media) 1102 { 1103 RB_REMOVE(mediatypes, types, media); 1104 1105 free(media->media_encoding); 1106 free(media); 1107 } 1108 1109 void 1110 media_purge(struct mediatypes *types) 1111 { 1112 struct media_type *media; 1113 1114 while ((media = RB_MIN(mediatypes, types)) != NULL) 1115 media_delete(types, media); 1116 } 1117 1118 struct media_type * 1119 media_find(struct mediatypes *types, const char *file) 1120 { 1121 struct media_type *match, media; 1122 char *p; 1123 1124 /* Last component of the file name */ 1125 p = strchr(file, '\0'); 1126 while (p > file && p[-1] != '.' && p[-1] != '/') 1127 p--; 1128 if (*p == '\0') 1129 return (NULL); 1130 1131 if (strlcpy(media.media_name, p, 1132 sizeof(media.media_name)) >= 1133 sizeof(media.media_name)) { 1134 return (NULL); 1135 } 1136 1137 /* Find media type by extension name */ 1138 match = RB_FIND(mediatypes, types, &media); 1139 1140 return (match); 1141 } 1142 1143 struct media_type * 1144 media_find_config(struct httpd *env, struct server_config *srv_conf, 1145 const char *file) 1146 { 1147 struct media_type *match; 1148 1149 if ((match = media_find(env->sc_mediatypes, file)) != NULL) 1150 return (match); 1151 else if (srv_conf->flags & SRVFLAG_DEFAULT_TYPE) 1152 return (&srv_conf->default_type); 1153 1154 /* fallback to the global default type */ 1155 return (&env->sc_default_type); 1156 } 1157 1158 int 1159 media_cmp(struct media_type *a, struct media_type *b) 1160 { 1161 return (strcasecmp(a->media_name, b->media_name)); 1162 } 1163 1164 RB_GENERATE(mediatypes, media_type, media_entry, media_cmp); 1165 1166 struct auth * 1167 auth_add(struct serverauth *serverauth, struct auth *auth) 1168 { 1169 struct auth *entry; 1170 1171 TAILQ_FOREACH(entry, serverauth, auth_entry) { 1172 if (strcmp(entry->auth_htpasswd, auth->auth_htpasswd) == 0) 1173 return (entry); 1174 } 1175 1176 if ((entry = calloc(1, sizeof(*entry))) == NULL) 1177 return (NULL); 1178 1179 memcpy(entry, auth, sizeof(*entry)); 1180 1181 TAILQ_INSERT_TAIL(serverauth, entry, auth_entry); 1182 1183 return (entry); 1184 } 1185 1186 struct auth * 1187 auth_byid(struct serverauth *serverauth, uint32_t id) 1188 { 1189 struct auth *auth; 1190 1191 TAILQ_FOREACH(auth, serverauth, auth_entry) { 1192 if (auth->auth_id == id) 1193 return (auth); 1194 } 1195 1196 return (NULL); 1197 } 1198 1199 void 1200 auth_free(struct serverauth *serverauth, struct auth *auth) 1201 { 1202 TAILQ_REMOVE(serverauth, auth, auth_entry); 1203 } 1204 1205 1206 const char * 1207 print_host(struct sockaddr_storage *ss, char *buf, size_t len) 1208 { 1209 if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 1210 buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 1211 buf[0] = '\0'; 1212 return (NULL); 1213 } 1214 return (buf); 1215 } 1216 1217 const char * 1218 printb_flags(const uint32_t v, const char *bits) 1219 { 1220 static char buf[2][BUFSIZ]; 1221 static int idx = 0; 1222 int i, any = 0; 1223 char c, *p, *r; 1224 1225 p = r = buf[++idx % 2]; 1226 memset(p, 0, BUFSIZ); 1227 1228 if (bits) { 1229 bits++; 1230 while ((i = *bits++)) { 1231 if (v & (1 << (i - 1))) { 1232 if (any) { 1233 *p++ = ','; 1234 *p++ = ' '; 1235 } 1236 any = 1; 1237 for (; (c = *bits) > 32; bits++) { 1238 if (c == '_') 1239 *p++ = ' '; 1240 else 1241 *p++ = 1242 tolower((unsigned char)c); 1243 } 1244 } else 1245 for (; *bits > 32; bits++) 1246 ; 1247 } 1248 } 1249 1250 return (r); 1251 } 1252 1253 void 1254 getmonotime(struct timeval *tv) 1255 { 1256 struct timespec ts; 1257 1258 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 1259 fatal("clock_gettime"); 1260 1261 TIMESPEC_TO_TIMEVAL(tv, &ts); 1262 } 1263