1 /* $OpenBSD: httpd.c,v 1.71 2021/01/27 07:21:52 deraadt 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 if (!debug && daemon(1, 0) == -1) 224 err(1, "failed to daemonize"); 225 226 if (ps->ps_noaction == 0) 227 log_info("startup"); 228 229 if (pledge("stdio rpath wpath cpath inet dns sendfd", NULL) == -1) 230 fatal("pledge"); 231 232 event_init(); 233 234 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 235 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 236 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 237 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 238 signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps); 239 240 signal_add(&ps->ps_evsigint, NULL); 241 signal_add(&ps->ps_evsigterm, NULL); 242 signal_add(&ps->ps_evsighup, NULL); 243 signal_add(&ps->ps_evsigpipe, NULL); 244 signal_add(&ps->ps_evsigusr1, NULL); 245 246 proc_connect(ps); 247 248 if (load_config(env->sc_conffile, env) == -1) { 249 proc_kill(env->sc_ps); 250 exit(1); 251 } 252 253 if (env->sc_opts & HTTPD_OPT_NOACTION) { 254 fprintf(stderr, "configuration OK\n"); 255 proc_kill(env->sc_ps); 256 exit(0); 257 } 258 259 /* initialize the TLS session id to a random key for all procs */ 260 arc4random_buf(env->sc_tls_sid, sizeof(env->sc_tls_sid)); 261 262 if (parent_configure(env) == -1) 263 fatalx("configuration failed"); 264 265 event_dispatch(); 266 267 parent_shutdown(env); 268 /* NOTREACHED */ 269 270 return (0); 271 } 272 273 int 274 parent_configure(struct httpd *env) 275 { 276 int id; 277 struct ctl_flags cf; 278 int ret = -1; 279 struct server *srv; 280 struct media_type *media; 281 struct auth *auth; 282 283 RB_FOREACH(media, mediatypes, env->sc_mediatypes) { 284 if (config_setmedia(env, media) == -1) 285 fatal("send media"); 286 } 287 288 TAILQ_FOREACH(auth, env->sc_auth, auth_entry) { 289 if (config_setauth(env, auth) == -1) 290 fatal("send auth"); 291 } 292 293 /* First send the servers... */ 294 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { 295 if (srv->srv_conf.flags & SRVFLAG_LOCATION) 296 continue; 297 /* start the rekey of the tls ticket keys */ 298 if (srv->srv_conf.flags & SRVFLAG_TLS && 299 srv->srv_conf.tls_ticket_lifetime) 300 parent_tls_ticket_rekey_start(srv); 301 if (config_setserver(env, srv) == -1) 302 fatal("send server"); 303 } 304 /* ...and now send the locations */ 305 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { 306 if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) 307 continue; 308 if (config_setserver(env, srv) == -1) 309 fatal("send location"); 310 } 311 312 /* The servers need to reload their config. */ 313 env->sc_reload = env->sc_prefork_server + 1; 314 315 for (id = 0; id < PROC_MAX; id++) { 316 if (id == privsep_process) 317 continue; 318 cf.cf_opts = env->sc_opts; 319 cf.cf_flags = env->sc_flags; 320 memcpy(cf.cf_tls_sid, env->sc_tls_sid, sizeof(cf.cf_tls_sid)); 321 322 proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf)); 323 } 324 325 ret = 0; 326 327 config_purge(env, CONFIG_ALL & ~CONFIG_SERVERS); 328 return (ret); 329 } 330 331 void 332 parent_reload(struct httpd *env, unsigned int reset, const char *filename) 333 { 334 if (env->sc_reload) { 335 log_debug("%s: already in progress: %d pending", 336 __func__, env->sc_reload); 337 return; 338 } 339 340 /* Switch back to the default config file */ 341 if (filename == NULL || *filename == '\0') 342 filename = env->sc_conffile; 343 344 log_debug("%s: level %d config file %s", __func__, reset, filename); 345 346 config_purge(env, CONFIG_ALL); 347 348 if (reset == CONFIG_RELOAD) { 349 if (load_config(filename, env) == -1) { 350 log_debug("%s: failed to load config file %s", 351 __func__, filename); 352 } 353 354 config_setreset(env, CONFIG_ALL); 355 356 if (parent_configure(env) == -1) { 357 log_debug("%s: failed to commit config from %s", 358 __func__, filename); 359 } 360 } else 361 config_setreset(env, reset); 362 } 363 364 void 365 parent_reopen(struct httpd *env) 366 { 367 proc_compose(env->sc_ps, PROC_LOGGER, IMSG_CTL_REOPEN, NULL, 0); 368 } 369 370 void 371 parent_configure_done(struct httpd *env) 372 { 373 int id; 374 375 if (env->sc_reload == 0) { 376 log_warnx("%s: configuration already finished", __func__); 377 return; 378 } 379 380 env->sc_reload--; 381 if (env->sc_reload == 0) { 382 for (id = 0; id < PROC_MAX; id++) { 383 if (id == privsep_process) 384 continue; 385 386 proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL, 0); 387 } 388 } 389 } 390 391 void 392 parent_shutdown(struct httpd *env) 393 { 394 config_purge(env, CONFIG_ALL); 395 396 proc_kill(env->sc_ps); 397 control_cleanup(&env->sc_ps->ps_csock); 398 if (env->sc_ps->ps_csock.cs_name != NULL) 399 (void)unlink(env->sc_ps->ps_csock.cs_name); 400 401 free(env->sc_ps); 402 free(env); 403 404 log_info("parent terminating, pid %d", getpid()); 405 406 exit(0); 407 } 408 409 int 410 parent_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg) 411 { 412 struct privsep *ps = p->p_ps; 413 struct httpd *env = ps->ps_env; 414 415 switch (imsg->hdr.type) { 416 case IMSG_CFG_DONE: 417 parent_configure_done(env); 418 break; 419 default: 420 return (-1); 421 } 422 423 return (0); 424 } 425 426 int 427 parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg) 428 { 429 struct privsep *ps = p->p_ps; 430 struct httpd *env = ps->ps_env; 431 unsigned int v; 432 char *str = NULL; 433 434 switch (imsg->hdr.type) { 435 case IMSG_CTL_RESET: 436 IMSG_SIZE_CHECK(imsg, &v); 437 memcpy(&v, imsg->data, sizeof(v)); 438 parent_reload(env, v, NULL); 439 break; 440 case IMSG_CTL_RELOAD: 441 if (IMSG_DATA_SIZE(imsg) > 0) 442 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 443 parent_reload(env, CONFIG_RELOAD, str); 444 free(str); 445 break; 446 case IMSG_CTL_SHUTDOWN: 447 parent_shutdown(env); 448 break; 449 case IMSG_CTL_REOPEN: 450 parent_reopen(env); 451 break; 452 case IMSG_CFG_DONE: 453 parent_configure_done(env); 454 break; 455 case IMSG_LOG_OPEN: 456 if (logger_open_priv(imsg) == -1) 457 fatalx("failed to open log file"); 458 break; 459 default: 460 return (-1); 461 } 462 463 return (0); 464 } 465 466 void 467 parent_tls_ticket_rekey_start(struct server *srv) 468 { 469 struct timeval tv; 470 471 server_generate_ticket_key(&srv->srv_conf); 472 473 evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv); 474 timerclear(&tv); 475 tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4; 476 evtimer_add(&srv->srv_evt, &tv); 477 } 478 479 void 480 parent_tls_ticket_rekey(int fd, short events, void *arg) 481 { 482 struct server *srv = arg; 483 struct timeval tv; 484 485 server_generate_ticket_key(&srv->srv_conf); 486 proc_compose_imsg(httpd_env->sc_ps, PROC_SERVER, -1, 487 IMSG_TLSTICKET_REKEY, -1, -1, &srv->srv_conf.tls_ticket_key, 488 sizeof(srv->srv_conf.tls_ticket_key)); 489 explicit_bzero(&srv->srv_conf.tls_ticket_key, 490 sizeof(srv->srv_conf.tls_ticket_key)); 491 492 evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv); 493 timerclear(&tv); 494 tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4; 495 evtimer_add(&srv->srv_evt, &tv); 496 } 497 498 /* 499 * Utility functions 500 */ 501 502 void 503 event_again(struct event *ev, int fd, short event, 504 void (*fn)(int, short, void *), 505 struct timeval *start, struct timeval *end, void *arg) 506 { 507 struct timeval tv_next, tv_now, tv; 508 509 getmonotime(&tv_now); 510 memcpy(&tv_next, end, sizeof(tv_next)); 511 timersub(&tv_now, start, &tv_now); 512 timersub(&tv_next, &tv_now, &tv_next); 513 514 memset(&tv, 0, sizeof(tv)); 515 if (timercmp(&tv_next, &tv, >)) 516 memcpy(&tv, &tv_next, sizeof(tv)); 517 518 event_del(ev); 519 event_set(ev, fd, event, fn, arg); 520 event_add(ev, &tv); 521 } 522 523 int 524 expand_string(char *label, size_t len, const char *srch, const char *repl) 525 { 526 char *tmp; 527 char *p, *q; 528 529 if ((tmp = calloc(1, len)) == NULL) { 530 log_debug("%s: calloc", __func__); 531 return (-1); 532 } 533 p = q = label; 534 while ((q = strstr(p, srch)) != NULL) { 535 *q = '\0'; 536 if ((strlcat(tmp, p, len) >= len) || 537 (strlcat(tmp, repl, len) >= len)) { 538 log_debug("%s: string too long", __func__); 539 free(tmp); 540 return (-1); 541 } 542 q += strlen(srch); 543 p = q; 544 } 545 if (strlcat(tmp, p, len) >= len) { 546 log_debug("%s: string too long", __func__); 547 free(tmp); 548 return (-1); 549 } 550 (void)strlcpy(label, tmp, len); /* always fits */ 551 free(tmp); 552 553 return (0); 554 } 555 556 const char * 557 url_decode(char *url) 558 { 559 char *p, *q; 560 char hex[3]; 561 unsigned long x; 562 563 hex[2] = '\0'; 564 p = q = url; 565 566 while (*p != '\0') { 567 switch (*p) { 568 case '%': 569 /* Encoding character is followed by two hex chars */ 570 if (!(isxdigit((unsigned char)p[1]) && 571 isxdigit((unsigned char)p[2]))) 572 return (NULL); 573 574 hex[0] = p[1]; 575 hex[1] = p[2]; 576 577 /* 578 * We don't have to validate "hex" because it is 579 * guaranteed to include two hex chars followed by nul. 580 */ 581 x = strtoul(hex, NULL, 16); 582 *q = (char)x; 583 p += 2; 584 break; 585 default: 586 *q = *p; 587 break; 588 } 589 p++; 590 q++; 591 } 592 *q = '\0'; 593 594 return (url); 595 } 596 597 const char * 598 canonicalize_path(const char *input, char *path, size_t len) 599 { 600 const char *i; 601 char *p, *start, *end; 602 603 /* assuming input starts with '/' and is nul-terminated */ 604 i = input; 605 p = path; 606 607 if (*input != '/' || len < 3) 608 return (NULL); 609 610 start = p; 611 end = p + (len - 1); 612 613 while (*i != '\0') { 614 /* Detect truncation */ 615 if (p >= end) 616 return (NULL); 617 618 /* 1. check for special path elements */ 619 if (i[0] == '/') { 620 if (i[1] == '/') { 621 /* a) skip repeating '//' slashes */ 622 while (i[1] == '/') 623 i++; 624 continue; 625 } else if (i[1] == '.' && i[2] == '.' && 626 (i[3] == '/' || i[3] == '\0')) { 627 /* b) revert '..' to previous directory */ 628 i += 3; 629 while (p > start && *p != '/') 630 p--; 631 *p = '\0'; 632 continue; 633 } else if (i[1] == '.' && 634 (i[2] == '/' || i[2] == '\0')) { 635 /* c) skip unnecessary '.' current dir */ 636 i += 2; 637 continue; 638 } 639 } 640 641 /* 2. copy any other characters */ 642 *p++ = *i; 643 i++; 644 } 645 if (p == start) 646 *p++ = '/'; 647 *p++ = '\0'; 648 649 return (path); 650 } 651 652 size_t 653 path_info(char *path) 654 { 655 char *p, *start, *end, ch; 656 struct stat st; 657 int ret; 658 659 start = path; 660 end = start + strlen(path); 661 662 for (p = end; p > start; p--) { 663 /* Scan every path component from the end and at each '/' */ 664 if (p < end && *p != '/') 665 continue; 666 667 /* Temporarily cut the path component out */ 668 ch = *p; 669 *p = '\0'; 670 ret = stat(path, &st); 671 *p = ch; 672 673 /* Break if the initial path component was found */ 674 if (ret == 0) 675 break; 676 } 677 678 return (p - start); 679 } 680 681 char * 682 url_encode(const char *src) 683 { 684 static char hex[] = "0123456789ABCDEF"; 685 char *dp, *dst; 686 unsigned char c; 687 688 /* We need 3 times the memory if every letter is encoded. */ 689 if ((dst = calloc(3, strlen(src) + 1)) == NULL) 690 return (NULL); 691 692 for (dp = dst; *src != 0; src++) { 693 c = (unsigned char) *src; 694 if (c == ' ' || c == '#' || c == '%' || c == '?' || c == '"' || 695 c == '&' || c == '<' || c <= 0x1f || c >= 0x7f) { 696 *dp++ = '%'; 697 *dp++ = hex[c >> 4]; 698 *dp++ = hex[c & 0x0f]; 699 } else 700 *dp++ = *src; 701 } 702 return (dst); 703 } 704 705 char* 706 escape_html(const char* src) 707 { 708 char *dp, *dst; 709 710 /* We need 5 times the memory if every letter is "&" */ 711 if ((dst = calloc(5, strlen(src) + 1)) == NULL) 712 return NULL; 713 714 for (dp = dst; *src != 0; src++) { 715 if (*src == '<') { 716 *dp++ = '&'; 717 *dp++ = 'l'; 718 *dp++ = 't'; 719 *dp++ = ';'; 720 } else if (*src == '>') { 721 *dp++ = '&'; 722 *dp++ = 'g'; 723 *dp++ = 't'; 724 *dp++ = ';'; 725 } else if (*src == '&') { 726 *dp++ = '&'; 727 *dp++ = 'a'; 728 *dp++ = 'm'; 729 *dp++ = 'p'; 730 *dp++ = ';'; 731 } else 732 *dp++ = *src; 733 } 734 return (dst); 735 } 736 737 void 738 socket_rlimit(int maxfd) 739 { 740 struct rlimit rl; 741 742 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 743 fatal("%s: failed to get resource limit", __func__); 744 log_debug("%s: max open files %llu", __func__, rl.rlim_max); 745 746 /* 747 * Allow the maximum number of open file descriptors for this 748 * login class (which should be the class "daemon" by default). 749 */ 750 if (maxfd == -1) 751 rl.rlim_cur = rl.rlim_max; 752 else 753 rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd); 754 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 755 fatal("%s: failed to set resource limit", __func__); 756 } 757 758 char * 759 evbuffer_getline(struct evbuffer *evb) 760 { 761 uint8_t *ptr = EVBUFFER_DATA(evb); 762 size_t len = EVBUFFER_LENGTH(evb); 763 char *str; 764 size_t i; 765 766 /* Safe version of evbuffer_readline() */ 767 if ((str = get_string(ptr, len)) == NULL) 768 return (NULL); 769 770 for (i = 0; str[i] != '\0'; i++) { 771 if (str[i] == '\r' || str[i] == '\n') 772 break; 773 } 774 775 if (i == len) { 776 free(str); 777 return (NULL); 778 } 779 780 str[i] = '\0'; 781 782 if ((i + 1) < len) { 783 if (ptr[i] == '\r' && ptr[i + 1] == '\n') 784 i++; 785 } 786 787 evbuffer_drain(evb, ++i); 788 789 return (str); 790 } 791 792 char * 793 get_string(uint8_t *ptr, size_t len) 794 { 795 size_t i; 796 797 for (i = 0; i < len; i++) 798 if (!(isprint((unsigned char)ptr[i]) || 799 isspace((unsigned char)ptr[i]))) 800 break; 801 802 return strndup(ptr, i); 803 } 804 805 void * 806 get_data(uint8_t *ptr, size_t len) 807 { 808 uint8_t *data; 809 810 if ((data = malloc(len)) == NULL) 811 return (NULL); 812 memcpy(data, ptr, len); 813 814 return (data); 815 } 816 817 int 818 sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen) 819 { 820 struct sockaddr_in *a4, *b4; 821 struct sockaddr_in6 *a6, *b6; 822 uint32_t av[4], bv[4], mv[4]; 823 824 if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC) 825 return (0); 826 else if (a->sa_family > b->sa_family) 827 return (1); 828 else if (a->sa_family < b->sa_family) 829 return (-1); 830 831 if (prefixlen == -1) 832 memset(&mv, 0xff, sizeof(mv)); 833 834 switch (a->sa_family) { 835 case AF_INET: 836 a4 = (struct sockaddr_in *)a; 837 b4 = (struct sockaddr_in *)b; 838 839 av[0] = a4->sin_addr.s_addr; 840 bv[0] = b4->sin_addr.s_addr; 841 if (prefixlen != -1) 842 mv[0] = prefixlen2mask(prefixlen); 843 844 if ((av[0] & mv[0]) > (bv[0] & mv[0])) 845 return (1); 846 if ((av[0] & mv[0]) < (bv[0] & mv[0])) 847 return (-1); 848 break; 849 case AF_INET6: 850 a6 = (struct sockaddr_in6 *)a; 851 b6 = (struct sockaddr_in6 *)b; 852 853 memcpy(&av, &a6->sin6_addr.s6_addr, 16); 854 memcpy(&bv, &b6->sin6_addr.s6_addr, 16); 855 if (prefixlen != -1) 856 prefixlen2mask6(prefixlen, mv); 857 858 if ((av[3] & mv[3]) > (bv[3] & mv[3])) 859 return (1); 860 if ((av[3] & mv[3]) < (bv[3] & mv[3])) 861 return (-1); 862 if ((av[2] & mv[2]) > (bv[2] & mv[2])) 863 return (1); 864 if ((av[2] & mv[2]) < (bv[2] & mv[2])) 865 return (-1); 866 if ((av[1] & mv[1]) > (bv[1] & mv[1])) 867 return (1); 868 if ((av[1] & mv[1]) < (bv[1] & mv[1])) 869 return (-1); 870 if ((av[0] & mv[0]) > (bv[0] & mv[0])) 871 return (1); 872 if ((av[0] & mv[0]) < (bv[0] & mv[0])) 873 return (-1); 874 break; 875 } 876 877 return (0); 878 } 879 880 uint32_t 881 prefixlen2mask(uint8_t prefixlen) 882 { 883 if (prefixlen == 0) 884 return (0); 885 886 if (prefixlen > 32) 887 prefixlen = 32; 888 889 return (htonl(0xffffffff << (32 - prefixlen))); 890 } 891 892 struct in6_addr * 893 prefixlen2mask6(uint8_t prefixlen, uint32_t *mask) 894 { 895 static struct in6_addr s6; 896 int i; 897 898 if (prefixlen > 128) 899 prefixlen = 128; 900 901 memset(&s6, 0, sizeof(s6)); 902 for (i = 0; i < prefixlen / 8; i++) 903 s6.s6_addr[i] = 0xff; 904 i = prefixlen % 8; 905 if (i) 906 s6.s6_addr[prefixlen / 8] = 0xff00 >> i; 907 908 memcpy(mask, &s6, sizeof(s6)); 909 910 return (&s6); 911 } 912 913 int 914 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen, 915 int reserve, volatile int *counter) 916 { 917 int ret; 918 if (getdtablecount() + reserve + 919 *counter >= getdtablesize()) { 920 errno = EMFILE; 921 return (-1); 922 } 923 924 if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) { 925 (*counter)++; 926 DPRINTF("%s: inflight incremented, now %d",__func__, *counter); 927 } 928 return (ret); 929 } 930 931 struct kv * 932 kv_add(struct kvtree *keys, char *key, char *value) 933 { 934 struct kv *kv, *oldkv; 935 936 if (key == NULL) 937 return (NULL); 938 if ((kv = calloc(1, sizeof(*kv))) == NULL) 939 return (NULL); 940 if ((kv->kv_key = strdup(key)) == NULL) { 941 free(kv); 942 return (NULL); 943 } 944 if (value != NULL && 945 (kv->kv_value = strdup(value)) == NULL) { 946 free(kv->kv_key); 947 free(kv); 948 return (NULL); 949 } 950 TAILQ_INIT(&kv->kv_children); 951 952 if ((oldkv = RB_INSERT(kvtree, keys, kv)) != NULL) { 953 TAILQ_INSERT_TAIL(&oldkv->kv_children, kv, kv_entry); 954 kv->kv_parent = oldkv; 955 } 956 957 return (kv); 958 } 959 960 int 961 kv_set(struct kv *kv, char *fmt, ...) 962 { 963 va_list ap; 964 char *value = NULL; 965 struct kv *ckv; 966 int ret; 967 968 va_start(ap, fmt); 969 ret = vasprintf(&value, fmt, ap); 970 va_end(ap); 971 if (ret == -1) 972 return (-1); 973 974 /* Remove all children */ 975 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) { 976 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry); 977 kv_free(ckv); 978 free(ckv); 979 } 980 981 /* Set the new value */ 982 free(kv->kv_value); 983 kv->kv_value = value; 984 985 return (0); 986 } 987 988 int 989 kv_setkey(struct kv *kv, char *fmt, ...) 990 { 991 va_list ap; 992 char *key = NULL; 993 int ret; 994 995 va_start(ap, fmt); 996 ret = vasprintf(&key, fmt, ap); 997 va_end(ap); 998 if (ret == -1) 999 return (-1); 1000 1001 free(kv->kv_key); 1002 kv->kv_key = key; 1003 1004 return (0); 1005 } 1006 1007 void 1008 kv_delete(struct kvtree *keys, struct kv *kv) 1009 { 1010 struct kv *ckv; 1011 1012 RB_REMOVE(kvtree, keys, kv); 1013 1014 /* Remove all children */ 1015 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) { 1016 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry); 1017 kv_free(ckv); 1018 free(ckv); 1019 } 1020 1021 kv_free(kv); 1022 free(kv); 1023 } 1024 1025 struct kv * 1026 kv_extend(struct kvtree *keys, struct kv *kv, char *value) 1027 { 1028 char *newvalue; 1029 1030 if (kv == NULL) { 1031 return (NULL); 1032 } else if (kv->kv_value != NULL) { 1033 if (asprintf(&newvalue, "%s%s", kv->kv_value, value) == -1) 1034 return (NULL); 1035 1036 free(kv->kv_value); 1037 kv->kv_value = newvalue; 1038 } else if ((kv->kv_value = strdup(value)) == NULL) 1039 return (NULL); 1040 1041 return (kv); 1042 } 1043 1044 void 1045 kv_purge(struct kvtree *keys) 1046 { 1047 struct kv *kv; 1048 1049 while ((kv = RB_MIN(kvtree, keys)) != NULL) 1050 kv_delete(keys, kv); 1051 } 1052 1053 void 1054 kv_free(struct kv *kv) 1055 { 1056 free(kv->kv_key); 1057 kv->kv_key = NULL; 1058 free(kv->kv_value); 1059 kv->kv_value = NULL; 1060 memset(kv, 0, sizeof(*kv)); 1061 } 1062 1063 struct kv * 1064 kv_find(struct kvtree *keys, struct kv *kv) 1065 { 1066 struct kv *match; 1067 const char *key; 1068 1069 if (kv->kv_flags & KV_FLAG_GLOBBING) { 1070 /* Test header key using shell globbing rules */ 1071 key = kv->kv_key == NULL ? "" : kv->kv_key; 1072 RB_FOREACH(match, kvtree, keys) { 1073 if (fnmatch(key, match->kv_key, FNM_CASEFOLD) == 0) 1074 break; 1075 } 1076 } else { 1077 /* Fast tree-based lookup only works without globbing */ 1078 match = RB_FIND(kvtree, keys, kv); 1079 } 1080 1081 return (match); 1082 } 1083 1084 int 1085 kv_cmp(struct kv *a, struct kv *b) 1086 { 1087 return (strcasecmp(a->kv_key, b->kv_key)); 1088 } 1089 1090 RB_GENERATE(kvtree, kv, kv_node, kv_cmp); 1091 1092 struct media_type * 1093 media_add(struct mediatypes *types, struct media_type *media) 1094 { 1095 struct media_type *entry; 1096 1097 if ((entry = RB_FIND(mediatypes, types, media)) != NULL) { 1098 log_debug("%s: duplicated entry for \"%s\"", __func__, 1099 media->media_name); 1100 return (NULL); 1101 } 1102 1103 if ((entry = malloc(sizeof(*media))) == NULL) 1104 return (NULL); 1105 1106 memcpy(entry, media, sizeof(*entry)); 1107 if (media->media_encoding != NULL && 1108 (entry->media_encoding = strdup(media->media_encoding)) == NULL) { 1109 free(entry); 1110 return (NULL); 1111 } 1112 RB_INSERT(mediatypes, types, entry); 1113 1114 return (entry); 1115 } 1116 1117 void 1118 media_delete(struct mediatypes *types, struct media_type *media) 1119 { 1120 RB_REMOVE(mediatypes, types, media); 1121 1122 free(media->media_encoding); 1123 free(media); 1124 } 1125 1126 void 1127 media_purge(struct mediatypes *types) 1128 { 1129 struct media_type *media; 1130 1131 while ((media = RB_MIN(mediatypes, types)) != NULL) 1132 media_delete(types, media); 1133 } 1134 1135 struct media_type * 1136 media_find(struct mediatypes *types, const char *file) 1137 { 1138 struct media_type *match, media; 1139 char *p; 1140 1141 /* Last component of the file name */ 1142 p = strchr(file, '\0'); 1143 while (p > file && p[-1] != '.' && p[-1] != '/') 1144 p--; 1145 if (*p == '\0') 1146 return (NULL); 1147 1148 if (strlcpy(media.media_name, p, 1149 sizeof(media.media_name)) >= 1150 sizeof(media.media_name)) { 1151 return (NULL); 1152 } 1153 1154 /* Find media type by extension name */ 1155 match = RB_FIND(mediatypes, types, &media); 1156 1157 return (match); 1158 } 1159 1160 struct media_type * 1161 media_find_config(struct httpd *env, struct server_config *srv_conf, 1162 const char *file) 1163 { 1164 struct media_type *match; 1165 1166 if ((match = media_find(env->sc_mediatypes, file)) != NULL) 1167 return (match); 1168 else if (srv_conf->flags & SRVFLAG_DEFAULT_TYPE) 1169 return (&srv_conf->default_type); 1170 1171 /* fallback to the global default type */ 1172 return (&env->sc_default_type); 1173 } 1174 1175 int 1176 media_cmp(struct media_type *a, struct media_type *b) 1177 { 1178 return (strcasecmp(a->media_name, b->media_name)); 1179 } 1180 1181 RB_GENERATE(mediatypes, media_type, media_entry, media_cmp); 1182 1183 struct auth * 1184 auth_add(struct serverauth *serverauth, struct auth *auth) 1185 { 1186 struct auth *entry; 1187 1188 TAILQ_FOREACH(entry, serverauth, auth_entry) { 1189 if (strcmp(entry->auth_htpasswd, auth->auth_htpasswd) == 0) 1190 return (entry); 1191 } 1192 1193 if ((entry = calloc(1, sizeof(*entry))) == NULL) 1194 return (NULL); 1195 1196 memcpy(entry, auth, sizeof(*entry)); 1197 1198 TAILQ_INSERT_TAIL(serverauth, entry, auth_entry); 1199 1200 return (entry); 1201 } 1202 1203 struct auth * 1204 auth_byid(struct serverauth *serverauth, uint32_t id) 1205 { 1206 struct auth *auth; 1207 1208 TAILQ_FOREACH(auth, serverauth, auth_entry) { 1209 if (auth->auth_id == id) 1210 return (auth); 1211 } 1212 1213 return (NULL); 1214 } 1215 1216 void 1217 auth_free(struct serverauth *serverauth, struct auth *auth) 1218 { 1219 TAILQ_REMOVE(serverauth, auth, auth_entry); 1220 } 1221 1222 1223 const char * 1224 print_host(struct sockaddr_storage *ss, char *buf, size_t len) 1225 { 1226 if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 1227 buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 1228 buf[0] = '\0'; 1229 return (NULL); 1230 } 1231 return (buf); 1232 } 1233 1234 const char * 1235 printb_flags(const uint32_t v, const char *bits) 1236 { 1237 static char buf[2][BUFSIZ]; 1238 static int idx = 0; 1239 int i, any = 0; 1240 char c, *p, *r; 1241 1242 p = r = buf[++idx % 2]; 1243 memset(p, 0, BUFSIZ); 1244 1245 if (bits) { 1246 bits++; 1247 while ((i = *bits++)) { 1248 if (v & (1 << (i - 1))) { 1249 if (any) { 1250 *p++ = ','; 1251 *p++ = ' '; 1252 } 1253 any = 1; 1254 for (; (c = *bits) > 32; bits++) { 1255 if (c == '_') 1256 *p++ = ' '; 1257 else 1258 *p++ = 1259 tolower((unsigned char)c); 1260 } 1261 } else 1262 for (; *bits > 32; bits++) 1263 ; 1264 } 1265 } 1266 1267 return (r); 1268 } 1269 1270 void 1271 getmonotime(struct timeval *tv) 1272 { 1273 struct timespec ts; 1274 1275 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 1276 fatal("clock_gettime"); 1277 1278 TIMESPEC_TO_TIMEVAL(tv, &ts); 1279 } 1280