jcs's openbsd hax
openbsd
at jcs 2588 lines 59 kB view raw
1/* $OpenBSD: parse.y,v 1.130 2025/11/28 16:10:00 rsadowski Exp $ */ 2 3/* 4 * Copyright (c) 2020 Matthias Pressfreund <mpfr@fn.de> 5 * Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org> 6 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 7 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 8 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 9 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org> 10 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 11 * Copyright (c) 2001 Markus Friedl. All rights reserved. 12 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 13 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 14 * 15 * Permission to use, copy, modify, and distribute this software for any 16 * purpose with or without fee is hereby granted, provided that the above 17 * copyright notice and this permission notice appear in all copies. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 20 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 22 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 24 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 25 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 */ 27 28%{ 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <sys/un.h> 32#include <sys/stat.h> 33#include <sys/queue.h> 34#include <sys/tree.h> 35#include <sys/ioctl.h> 36#include <sys/sockio.h> 37#include <sys/time.h> 38 39#include <net/if.h> 40#include <netinet/in.h> 41#include <arpa/inet.h> 42 43#include <ctype.h> 44#include <unistd.h> 45#include <err.h> 46#include <errno.h> 47#include <limits.h> 48#include <stdint.h> 49#include <stdarg.h> 50#include <stdio.h> 51#include <netdb.h> 52#include <string.h> 53#include <ifaddrs.h> 54#include <syslog.h> 55 56#include "httpd.h" 57#include "http.h" 58 59TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 60static struct file { 61 TAILQ_ENTRY(file) entry; 62 FILE *stream; 63 char *name; 64 size_t ungetpos; 65 size_t ungetsize; 66 u_char *ungetbuf; 67 int eof_reached; 68 int lineno; 69 int errors; 70} *file, *topfile; 71struct file *pushfile(const char *, int); 72int popfile(void); 73int check_file_secrecy(int, const char *); 74int yyparse(void); 75int yylex(void); 76int yyerror(const char *, ...) 77 __attribute__((__format__ (printf, 1, 2))) 78 __attribute__((__nonnull__ (1))); 79int kw_cmp(const void *, const void *); 80int lookup(char *); 81int igetc(void); 82int lgetc(int); 83void lungetc(int); 84int findeol(void); 85 86TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 87struct sym { 88 TAILQ_ENTRY(sym) entry; 89 int used; 90 int persist; 91 char *nam; 92 char *val; 93}; 94int symset(const char *, const char *, int); 95char *symget(const char *); 96 97struct httpd *conf = NULL; 98static int errors = 0; 99static int loadcfg = 0; 100uint32_t last_server_id = 0; 101uint32_t last_auth_id = 0; 102 103static struct server *srv = NULL, *parentsrv = NULL; 104static struct server_config *srv_conf = NULL; 105struct serverlist servers; 106struct media_type media; 107 108struct address *host_v4(const char *); 109struct address *host_v6(const char *); 110int host_dns(const char *, struct addresslist *, 111 int, struct portrange *, const char *, int); 112int host_if(const char *, struct addresslist *, 113 int, struct portrange *, const char *, int); 114int host(const char *, struct addresslist *, 115 int, struct portrange *, const char *, int); 116struct server *server_inherit(struct server *, struct server_config *, 117 struct server_config *); 118int listen_on(const char *, int, struct portrange *); 119int getservice(char *); 120int is_if_in_group(const char *, const char *); 121int get_fastcgi_dest(struct server_config *, const char *, char *); 122void remove_locations(struct server_config *); 123 124typedef struct { 125 union { 126 int64_t number; 127 char *string; 128 struct timeval tv; 129 struct portrange port; 130 struct auth auth; 131 } v; 132 int lineno; 133} YYSTYPE; 134 135%} 136 137%token ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON 138%token COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY LIFETIME 139%token LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT PREFORK 140%token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TICKET 141%token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST 142%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE 143%token CA CLIENT CRL OPTIONAL PARAM FORWARDED FOUND NOT 144%token ERRDOCS GZIPSTATIC BANNER 145%token <v.string> STRING 146%token <v.number> NUMBER 147%type <v.port> port 148%type <v.string> fcgiport 149%type <v.number> opttls optmatch optfound 150%type <v.tv> timeout 151%type <v.string> numberstring optstring 152%type <v.auth> authopts 153 154%% 155 156grammar : /* empty */ 157 | grammar include '\n' 158 | grammar '\n' 159 | grammar varset '\n' 160 | grammar main '\n' 161 | grammar server '\n' 162 | grammar types '\n' 163 | grammar error '\n' { file->errors++; } 164 ; 165 166include : INCLUDE STRING { 167 struct file *nfile; 168 169 if ((nfile = pushfile($2, 0)) == NULL) { 170 yyerror("failed to include file %s", $2); 171 free($2); 172 YYERROR; 173 } 174 free($2); 175 176 file = nfile; 177 lungetc('\n'); 178 } 179 ; 180 181varset : STRING '=' STRING { 182 char *s = $1; 183 while (*s++) { 184 if (isspace((unsigned char)*s)) { 185 yyerror("macro name cannot contain " 186 "whitespace"); 187 free($1); 188 free($3); 189 YYERROR; 190 } 191 } 192 if (symset($1, $3, 0) == -1) 193 fatal("cannot store variable"); 194 free($1); 195 free($3); 196 } 197 ; 198 199opttls : /*empty*/ { $$ = 0; } 200 | TLS { $$ = 1; } 201 ; 202 203main : PREFORK NUMBER { 204 if (loadcfg) 205 break; 206 if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) { 207 yyerror("invalid number of preforked " 208 "servers: %lld", $2); 209 YYERROR; 210 } 211 conf->sc_prefork_server = $2; 212 } 213 | CHROOT STRING { 214 conf->sc_chroot = $2; 215 } 216 | ERRDOCS STRING { 217 if ($2 != NULL && strlcpy(conf->sc_errdocroot, $2, 218 sizeof(conf->sc_errdocroot)) >= 219 sizeof(conf->sc_errdocroot)) { 220 yyerror("errdoc root path too long"); 221 free($2); 222 YYERROR; 223 } 224 free($2); 225 conf->sc_custom_errdocs = 1; 226 } 227 | LOGDIR STRING { 228 conf->sc_logdir = $2; 229 } 230 | NO BANNER { 231 conf->sc_flags |= SRVFLAG_NO_BANNER; 232 } 233 | DEFAULT TYPE mediastring { 234 memcpy(&conf->sc_default_type, &media, 235 sizeof(struct media_type)); 236 } 237 ; 238 239server : SERVER optmatch STRING { 240 struct server *s; 241 struct sockaddr_un *sun; 242 243 if (!loadcfg) { 244 free($3); 245 YYACCEPT; 246 } 247 248 if ((s = calloc(1, sizeof (*s))) == NULL) 249 fatal("out of memory"); 250 251 if (strlcpy(s->srv_conf.name, $3, 252 sizeof(s->srv_conf.name)) >= 253 sizeof(s->srv_conf.name)) { 254 yyerror("server name truncated"); 255 free($3); 256 free(s); 257 YYERROR; 258 } 259 free($3); 260 261 strlcpy(s->srv_conf.root, HTTPD_DOCROOT, 262 sizeof(s->srv_conf.root)); 263 strlcpy(s->srv_conf.index, HTTPD_INDEX, 264 sizeof(s->srv_conf.index)); 265 strlcpy(s->srv_conf.accesslog, HTTPD_ACCESS_LOG, 266 sizeof(s->srv_conf.accesslog)); 267 strlcpy(s->srv_conf.errorlog, HTTPD_ERROR_LOG, 268 sizeof(s->srv_conf.errorlog)); 269 s->srv_conf.id = ++last_server_id; 270 s->srv_conf.parent_id = s->srv_conf.id; 271 s->srv_s = -1; 272 s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT; 273 s->srv_conf.requesttimeout.tv_sec = 274 SERVER_REQUESTTIMEOUT; 275 s->srv_conf.maxrequests = SERVER_MAXREQUESTS; 276 s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY; 277 s->srv_conf.flags = SRVFLAG_LOG; 278 if ($2) 279 s->srv_conf.flags |= SRVFLAG_SERVER_MATCH; 280 s->srv_conf.logformat = LOG_FORMAT_COMMON; 281 s->srv_conf.tls_protocols = TLS_PROTOCOLS_DEFAULT; 282 if ((s->srv_conf.tls_cert_file = 283 strdup(HTTPD_TLS_CERT)) == NULL) 284 fatal("out of memory"); 285 if ((s->srv_conf.tls_key_file = 286 strdup(HTTPD_TLS_KEY)) == NULL) 287 fatal("out of memory"); 288 strlcpy(s->srv_conf.tls_ciphers, 289 HTTPD_TLS_CIPHERS, 290 sizeof(s->srv_conf.tls_ciphers)); 291 strlcpy(s->srv_conf.tls_dhe_params, 292 HTTPD_TLS_DHE_PARAMS, 293 sizeof(s->srv_conf.tls_dhe_params)); 294 strlcpy(s->srv_conf.tls_ecdhe_curves, 295 HTTPD_TLS_ECDHE_CURVES, 296 sizeof(s->srv_conf.tls_ecdhe_curves)); 297 298 sun = (struct sockaddr_un *)&s->srv_conf.fastcgi_ss; 299 sun->sun_family = AF_UNIX; 300 (void)strlcpy(sun->sun_path, HTTPD_FCGI_SOCKET, 301 sizeof(sun->sun_path)); 302 sun->sun_len = sizeof(struct sockaddr_un); 303 304 s->srv_conf.hsts_max_age = SERVER_HSTS_DEFAULT_AGE; 305 306 if (conf->sc_flags & SRVFLAG_NO_BANNER) 307 s->srv_conf.flags |= SRVFLAG_NO_BANNER; 308 309 (void)strlcpy(s->srv_conf.errdocroot, 310 conf->sc_errdocroot, 311 sizeof(s->srv_conf.errdocroot)); 312 if (conf->sc_custom_errdocs) 313 s->srv_conf.flags |= SRVFLAG_ERRDOCS; 314 315 if (last_server_id == INT_MAX) { 316 yyerror("too many servers defined"); 317 free(s); 318 YYERROR; 319 } 320 srv = s; 321 srv_conf = &srv->srv_conf; 322 323 SPLAY_INIT(&srv->srv_clients); 324 TAILQ_INIT(&srv->srv_hosts); 325 TAILQ_INIT(&srv_conf->fcgiparams); 326 327 TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry); 328 } '{' optnl serveropts_l '}' { 329 struct server *s, *sn; 330 struct server_config *a, *b; 331 332 srv_conf = &srv->srv_conf; 333 334 /* Check if the new server already exists. */ 335 if (server_match(srv, 1) != NULL) { 336 yyerror("server \"%s\" defined twice", 337 srv->srv_conf.name); 338 serverconfig_free(srv_conf); 339 free(srv); 340 YYABORT; 341 } 342 343 if (srv->srv_conf.ss.ss_family == AF_UNSPEC) { 344 yyerror("listen address not specified"); 345 serverconfig_free(srv_conf); 346 free(srv); 347 YYERROR; 348 } 349 350 if ((s = server_match(srv, 0)) != NULL) { 351 if ((s->srv_conf.flags & SRVFLAG_TLS) != 352 (srv->srv_conf.flags & SRVFLAG_TLS)) { 353 yyerror("server \"%s\": tls and " 354 "non-tls on same address/port", 355 srv->srv_conf.name); 356 serverconfig_free(srv_conf); 357 free(srv); 358 YYERROR; 359 } 360 if (srv->srv_conf.flags & SRVFLAG_TLS && 361 server_tls_cmp(s, srv) != 0) { 362 yyerror("server \"%s\": tls " 363 "configuration mismatch on same " 364 "address/port", 365 srv->srv_conf.name); 366 serverconfig_free(srv_conf); 367 free(srv); 368 YYERROR; 369 } 370 } 371 372 if ((srv->srv_conf.flags & SRVFLAG_TLS) && 373 srv->srv_conf.tls_protocols == 0) { 374 yyerror("server \"%s\": no tls protocols", 375 srv->srv_conf.name); 376 serverconfig_free(srv_conf); 377 free(srv); 378 YYERROR; 379 } 380 381 if (server_tls_load_keypair(srv) == -1) { 382 /* Soft fail as there may be no certificate. */ 383 log_warnx("%s:%d: server \"%s\": failed to " 384 "load public/private keys", file->name, 385 yylval.lineno, srv->srv_conf.name); 386 387 remove_locations(srv_conf); 388 serverconfig_free(srv_conf); 389 srv_conf = NULL; 390 free(srv); 391 srv = NULL; 392 break; 393 } 394 395 if (server_tls_load_ca(srv) == -1) { 396 yyerror("server \"%s\": failed to load " 397 "ca cert(s)", srv->srv_conf.name); 398 serverconfig_free(srv_conf); 399 free(srv); 400 YYERROR; 401 } 402 403 if (server_tls_load_crl(srv) == -1) { 404 yyerror("server \"%s\": failed to load crl(s)", 405 srv->srv_conf.name); 406 serverconfig_free(srv_conf); 407 free(srv); 408 YYERROR; 409 } 410 411 if (server_tls_load_ocsp(srv) == -1) { 412 yyerror("server \"%s\": failed to load " 413 "ocsp staple", srv->srv_conf.name); 414 serverconfig_free(srv_conf); 415 free(srv); 416 YYERROR; 417 } 418 419 DPRINTF("adding server \"%s[%u]\"", 420 srv->srv_conf.name, srv->srv_conf.id); 421 422 TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry); 423 424 /* 425 * Add aliases and additional listen addresses as 426 * individual servers. 427 */ 428 TAILQ_FOREACH(a, &srv->srv_hosts, entry) { 429 /* listen address */ 430 if (a->ss.ss_family == AF_UNSPEC) 431 continue; 432 TAILQ_FOREACH(b, &srv->srv_hosts, entry) { 433 /* alias name */ 434 if (*b->name == '\0' || 435 (b == &srv->srv_conf && b == a)) 436 continue; 437 438 if ((sn = server_inherit(srv, 439 b, a)) == NULL) { 440 serverconfig_free(srv_conf); 441 free(srv); 442 YYABORT; 443 } 444 445 DPRINTF("adding server \"%s[%u]\"", 446 sn->srv_conf.name, sn->srv_conf.id); 447 448 TAILQ_INSERT_TAIL(conf->sc_servers, 449 sn, srv_entry); 450 } 451 } 452 453 /* Remove temporary aliases */ 454 TAILQ_FOREACH_SAFE(a, &srv->srv_hosts, entry, b) { 455 TAILQ_REMOVE(&srv->srv_hosts, a, entry); 456 if (a == &srv->srv_conf) 457 continue; 458 serverconfig_free(a); 459 free(a); 460 } 461 462 srv = NULL; 463 srv_conf = NULL; 464 } 465 ; 466 467serveropts_l : serveropts_l serveroptsl nl 468 | serveroptsl optnl 469 ; 470 471serveroptsl : LISTEN ON STRING opttls port { 472 if (listen_on($3, $4, &$5) == -1) { 473 free($3); 474 YYERROR; 475 } 476 free($3); 477 } 478 | ALIAS optmatch STRING { 479 struct server_config *alias; 480 481 if (parentsrv != NULL) { 482 yyerror("alias inside location"); 483 free($3); 484 YYERROR; 485 } 486 487 if ((alias = calloc(1, sizeof(*alias))) == NULL) 488 fatal("out of memory"); 489 490 if (strlcpy(alias->name, $3, sizeof(alias->name)) >= 491 sizeof(alias->name)) { 492 yyerror("server alias truncated"); 493 free($3); 494 free(alias); 495 YYERROR; 496 } 497 free($3); 498 499 if ($2) 500 alias->flags |= SRVFLAG_SERVER_MATCH; 501 502 TAILQ_INSERT_TAIL(&srv->srv_hosts, alias, entry); 503 } 504 | ERRDOCS STRING { 505 if (parentsrv != NULL) { 506 yyerror("errdocs inside location"); 507 YYERROR; 508 } 509 if ($2 != NULL && strlcpy(srv->srv_conf.errdocroot, $2, 510 sizeof(srv->srv_conf.errdocroot)) >= 511 sizeof(srv->srv_conf.errdocroot)) { 512 yyerror("errdoc root path too long"); 513 free($2); 514 YYERROR; 515 } 516 free($2); 517 srv->srv_conf.flags |= SRVFLAG_ERRDOCS; 518 } 519 | NO ERRDOCS { 520 if (parentsrv != NULL) { 521 yyerror("errdocs inside location"); 522 YYERROR; 523 } 524 srv->srv_conf.flags &= ~SRVFLAG_ERRDOCS; 525 } 526 | tcpip { 527 if (parentsrv != NULL) { 528 yyerror("tcp flags inside location"); 529 YYERROR; 530 } 531 } 532 | connection { 533 if (parentsrv != NULL) { 534 yyerror("connection options inside location"); 535 YYERROR; 536 } 537 } 538 | tls { 539 struct server_config *sc; 540 int tls_flag = 0; 541 542 if (parentsrv != NULL) { 543 yyerror("tls configuration inside location"); 544 YYERROR; 545 } 546 547 /* Ensure that at least one server has TLS enabled. */ 548 TAILQ_FOREACH(sc, &srv->srv_hosts, entry) { 549 tls_flag |= (sc->flags & SRVFLAG_TLS); 550 } 551 if (tls_flag == 0) { 552 yyerror("tls options without tls listener"); 553 YYERROR; 554 } 555 } 556 | request 557 | root 558 | directory 559 | banner 560 | logformat 561 | fastcgi 562 | authenticate 563 | gzip_static 564 | filter 565 | LOCATION optfound optmatch STRING { 566 struct server *s; 567 struct sockaddr_un *sun; 568 569 if (srv->srv_conf.ss.ss_family == AF_UNSPEC) { 570 yyerror("listen address not specified"); 571 free($4); 572 YYERROR; 573 } 574 575 if (parentsrv != NULL) { 576 yyerror("location %s inside location", $4); 577 free($4); 578 YYERROR; 579 } 580 581 if (!loadcfg) { 582 free($4); 583 YYACCEPT; 584 } 585 586 if ((s = calloc(1, sizeof (*s))) == NULL) 587 fatal("out of memory"); 588 589 if (strlcpy(s->srv_conf.location, $4, 590 sizeof(s->srv_conf.location)) >= 591 sizeof(s->srv_conf.location)) { 592 yyerror("server location truncated"); 593 free($4); 594 free(s); 595 YYERROR; 596 } 597 free($4); 598 599 if (strlcpy(s->srv_conf.name, srv->srv_conf.name, 600 sizeof(s->srv_conf.name)) >= 601 sizeof(s->srv_conf.name)) { 602 yyerror("server name truncated"); 603 free(s); 604 YYERROR; 605 } 606 607 sun = (struct sockaddr_un *)&s->srv_conf.fastcgi_ss; 608 sun->sun_family = AF_UNIX; 609 (void)strlcpy(sun->sun_path, HTTPD_FCGI_SOCKET, 610 sizeof(sun->sun_path)); 611 sun->sun_len = sizeof(struct sockaddr_un); 612 613 s->srv_conf.id = ++last_server_id; 614 /* A location entry uses the parent id */ 615 s->srv_conf.parent_id = srv->srv_conf.id; 616 s->srv_conf.flags = SRVFLAG_LOCATION; 617 if ($2 == 1) { 618 s->srv_conf.flags &= 619 ~SRVFLAG_LOCATION_NOT_FOUND; 620 s->srv_conf.flags |= 621 SRVFLAG_LOCATION_FOUND; 622 } else if ($2 == -1) { 623 s->srv_conf.flags &= 624 ~SRVFLAG_LOCATION_FOUND; 625 s->srv_conf.flags |= 626 SRVFLAG_LOCATION_NOT_FOUND; 627 } 628 if ($3) 629 s->srv_conf.flags |= SRVFLAG_LOCATION_MATCH; 630 s->srv_s = -1; 631 memcpy(&s->srv_conf.ss, &srv->srv_conf.ss, 632 sizeof(s->srv_conf.ss)); 633 s->srv_conf.port = srv->srv_conf.port; 634 s->srv_conf.prefixlen = srv->srv_conf.prefixlen; 635 s->srv_conf.tls_flags = srv->srv_conf.tls_flags; 636 637 if (last_server_id == INT_MAX) { 638 yyerror("too many servers/locations defined"); 639 free(s); 640 YYERROR; 641 } 642 parentsrv = srv; 643 srv = s; 644 srv_conf = &srv->srv_conf; 645 SPLAY_INIT(&srv->srv_clients); 646 } '{' optnl serveropts_l '}' { 647 struct server *s = NULL; 648 uint32_t f; 649 650 f = SRVFLAG_LOCATION_FOUND | 651 SRVFLAG_LOCATION_NOT_FOUND; 652 653 TAILQ_FOREACH(s, conf->sc_servers, srv_entry) { 654 /* Compare locations of same parent server */ 655 if ((s->srv_conf.flags & SRVFLAG_LOCATION) && 656 s->srv_conf.parent_id == 657 srv_conf->parent_id && 658 (s->srv_conf.flags & f) == 659 (srv_conf->flags & f) && 660 strcmp(s->srv_conf.location, 661 srv_conf->location) == 0) 662 break; 663 } 664 if (s != NULL) { 665 yyerror("location \"%s\" defined twice", 666 srv->srv_conf.location); 667 serverconfig_free(srv_conf); 668 free(srv); 669 YYABORT; 670 } 671 672 DPRINTF("adding location \"%s\" for \"%s[%u]\"", 673 srv->srv_conf.location, 674 srv->srv_conf.name, srv->srv_conf.id); 675 676 TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry); 677 678 srv = parentsrv; 679 srv_conf = &parentsrv->srv_conf; 680 parentsrv = NULL; 681 } 682 | DEFAULT TYPE mediastring { 683 srv_conf->flags |= SRVFLAG_DEFAULT_TYPE; 684 memcpy(&srv_conf->default_type, &media, 685 sizeof(struct media_type)); 686 } 687 | include 688 | hsts { 689 if (parentsrv != NULL) { 690 yyerror("hsts inside location"); 691 YYERROR; 692 } 693 srv->srv_conf.flags |= SRVFLAG_SERVER_HSTS; 694 } 695 ; 696 697banner : BANNER { 698 if (parentsrv != NULL) { 699 yyerror("banner inside location"); 700 YYERROR; 701 } 702 srv->srv_conf.flags &= ~SRVFLAG_NO_BANNER; 703 } 704 | NO BANNER { 705 if (parentsrv != NULL) { 706 yyerror("no banner inside location"); 707 YYERROR; 708 } 709 srv->srv_conf.flags |= SRVFLAG_NO_BANNER; 710 } 711 ; 712 713optfound : /* empty */ { $$ = 0; } 714 | FOUND { $$ = 1; } 715 | NOT FOUND { $$ = -1; } 716 ; 717 718hsts : HSTS '{' optnl hstsflags_l '}' 719 | HSTS hstsflags 720 | HSTS 721 ; 722 723hstsflags_l : hstsflags optcommanl hstsflags_l 724 | hstsflags optnl 725 ; 726 727hstsflags : MAXAGE NUMBER { 728 if ($2 < 0 || $2 > INT_MAX) { 729 yyerror("invalid number of seconds: %lld", $2); 730 YYERROR; 731 } 732 srv_conf->hsts_max_age = $2; 733 } 734 | SUBDOMAINS { 735 srv->srv_conf.hsts_flags |= HSTSFLAG_SUBDOMAINS; 736 } 737 | PRELOAD { 738 srv->srv_conf.hsts_flags |= HSTSFLAG_PRELOAD; 739 } 740 ; 741 742fastcgi : NO FCGI { 743 srv_conf->flags &= ~SRVFLAG_FCGI; 744 srv_conf->flags |= SRVFLAG_NO_FCGI; 745 } 746 | FCGI { 747 srv_conf->flags &= ~SRVFLAG_NO_FCGI; 748 srv_conf->flags |= SRVFLAG_FCGI; 749 } 750 | FCGI { 751 srv_conf->flags &= ~SRVFLAG_NO_FCGI; 752 srv_conf->flags |= SRVFLAG_FCGI; 753 } '{' optnl fcgiflags_l '}' 754 | FCGI { 755 srv_conf->flags &= ~SRVFLAG_NO_FCGI; 756 srv_conf->flags |= SRVFLAG_FCGI; 757 } fcgiflags 758 ; 759 760fcgiflags_l : fcgiflags optcommanl fcgiflags_l 761 | fcgiflags optnl 762 ; 763 764fcgiflags : SOCKET STRING { 765 struct sockaddr_un *sun; 766 sun = (struct sockaddr_un *)&srv_conf->fastcgi_ss; 767 memset(sun, 0, sizeof(*sun)); 768 sun->sun_family = AF_UNIX; 769 if (strlcpy(sun->sun_path, $2, sizeof(sun->sun_path)) 770 >= sizeof(sun->sun_path)) { 771 yyerror("socket path too long"); 772 free($2); 773 YYERROR; 774 } 775 srv_conf->fastcgi_ss.ss_len = 776 sizeof(struct sockaddr_un); 777 free($2); 778 } 779 | SOCKET TCP STRING { 780 if (get_fastcgi_dest(srv_conf, $3, FCGI_DEFAULT_PORT) 781 == -1) { 782 free($3); 783 YYERROR; 784 } 785 free($3); 786 } 787 | SOCKET TCP STRING fcgiport { 788 if (get_fastcgi_dest(srv_conf, $3, $4) == -1) { 789 free($3); 790 free($4); 791 YYERROR; 792 } 793 free($3); 794 free($4); 795 } 796 | PARAM STRING STRING { 797 struct fastcgi_param *param; 798 799 if ((param = calloc(1, sizeof(*param))) == NULL) 800 fatal("out of memory"); 801 802 if (strlcpy(param->name, $2, sizeof(param->name)) >= 803 sizeof(param->name)) { 804 yyerror("fastcgi_param name truncated"); 805 free($2); 806 free($3); 807 free(param); 808 YYERROR; 809 } 810 if (strlcpy(param->value, $3, sizeof(param->value)) >= 811 sizeof(param->value)) { 812 yyerror("fastcgi_param value truncated"); 813 free($2); 814 free($3); 815 free(param); 816 YYERROR; 817 } 818 free($2); 819 free($3); 820 821 DPRINTF("[%s,%s,%d]: adding param \"%s\" value \"%s\"", 822 srv_conf->location, srv_conf->name, srv_conf->id, 823 param->name, param->value); 824 TAILQ_INSERT_HEAD(&srv_conf->fcgiparams, param, entry); 825 } 826 | STRIP NUMBER { 827 if ($2 < 0 || $2 > INT_MAX) { 828 yyerror("invalid fastcgi strip number"); 829 YYERROR; 830 } 831 srv_conf->fcgistrip = $2; 832 } 833 ; 834 835connection : CONNECTION '{' optnl conflags_l '}' 836 | CONNECTION conflags 837 ; 838 839conflags_l : conflags optcommanl conflags_l 840 | conflags optnl 841 ; 842 843conflags : TIMEOUT timeout { 844 memcpy(&srv_conf->timeout, &$2, 845 sizeof(struct timeval)); 846 } 847 | REQUEST TIMEOUT timeout { 848 memcpy(&srv_conf->requesttimeout, &$3, 849 sizeof(struct timeval)); 850 } 851 | MAXIMUM REQUESTS NUMBER { 852 srv_conf->maxrequests = $3; 853 } 854 | MAXIMUM REQUEST BODY NUMBER { 855 srv_conf->maxrequestbody = $4; 856 } 857 ; 858 859tls : TLS '{' optnl tlsopts_l '}' 860 | TLS tlsopts 861 ; 862 863tlsopts_l : tlsopts optcommanl tlsopts_l 864 | tlsopts optnl 865 ; 866 867tlsopts : CERTIFICATE STRING { 868 free(srv_conf->tls_cert_file); 869 if ((srv_conf->tls_cert_file = strdup($2)) == NULL) 870 fatal("out of memory"); 871 free($2); 872 } 873 | KEY STRING { 874 free(srv_conf->tls_key_file); 875 if ((srv_conf->tls_key_file = strdup($2)) == NULL) 876 fatal("out of memory"); 877 free($2); 878 } 879 | OCSP STRING { 880 free(srv_conf->tls_ocsp_staple_file); 881 if ((srv_conf->tls_ocsp_staple_file = strdup($2)) 882 == NULL) 883 fatal("out of memory"); 884 free($2); 885 } 886 | CIPHERS STRING { 887 if (strlcpy(srv_conf->tls_ciphers, $2, 888 sizeof(srv_conf->tls_ciphers)) >= 889 sizeof(srv_conf->tls_ciphers)) { 890 yyerror("ciphers too long"); 891 free($2); 892 YYERROR; 893 } 894 free($2); 895 } 896 | CLIENT CA STRING tlsclientopt { 897 srv_conf->tls_flags |= TLSFLAG_CA; 898 free(srv_conf->tls_ca_file); 899 if ((srv_conf->tls_ca_file = strdup($3)) == NULL) 900 fatal("out of memory"); 901 free($3); 902 } 903 | DHE STRING { 904 if (strlcpy(srv_conf->tls_dhe_params, $2, 905 sizeof(srv_conf->tls_dhe_params)) >= 906 sizeof(srv_conf->tls_dhe_params)) { 907 yyerror("dhe too long"); 908 free($2); 909 YYERROR; 910 } 911 free($2); 912 } 913 | ECDHE STRING { 914 if (strlcpy(srv_conf->tls_ecdhe_curves, $2, 915 sizeof(srv_conf->tls_ecdhe_curves)) >= 916 sizeof(srv_conf->tls_ecdhe_curves)) { 917 yyerror("ecdhe too long"); 918 free($2); 919 YYERROR; 920 } 921 free($2); 922 } 923 | PROTOCOLS STRING { 924 if (tls_config_parse_protocols( 925 &srv_conf->tls_protocols, $2) != 0) { 926 yyerror("invalid tls protocols"); 927 free($2); 928 YYERROR; 929 } 930 free($2); 931 } 932 | TICKET LIFETIME DEFAULT { 933 srv_conf->tls_ticket_lifetime = SERVER_DEF_TLS_LIFETIME; 934 } 935 | TICKET LIFETIME NUMBER { 936 if ($3 != 0 && $3 < SERVER_MIN_TLS_LIFETIME) { 937 yyerror("ticket lifetime too small"); 938 YYERROR; 939 } 940 if ($3 > SERVER_MAX_TLS_LIFETIME) { 941 yyerror("ticket lifetime too large"); 942 YYERROR; 943 } 944 srv_conf->tls_ticket_lifetime = $3; 945 } 946 | NO TICKET { 947 srv_conf->tls_ticket_lifetime = 0; 948 } 949 ; 950 951tlsclientopt : /* empty */ 952 | tlsclientopt CRL STRING { 953 srv_conf->tls_flags = TLSFLAG_CRL; 954 free(srv_conf->tls_crl_file); 955 if ((srv_conf->tls_crl_file = strdup($3)) == NULL) 956 fatal("out of memory"); 957 free($3); 958 } 959 | tlsclientopt OPTIONAL { 960 srv_conf->tls_flags |= TLSFLAG_OPTIONAL; 961 } 962 ; 963root : ROOT rootflags 964 | ROOT '{' optnl rootflags_l '}' 965 ; 966 967rootflags_l : rootflags optcommanl rootflags_l 968 | rootflags optnl 969 ; 970 971rootflags : STRING { 972 if (strlcpy(srv->srv_conf.root, $1, 973 sizeof(srv->srv_conf.root)) >= 974 sizeof(srv->srv_conf.root)) { 975 yyerror("document root too long"); 976 free($1); 977 YYERROR; 978 } 979 free($1); 980 srv->srv_conf.flags |= SRVFLAG_ROOT; 981 } 982 ; 983 984request : REQUEST requestflags 985 | REQUEST '{' optnl requestflags_l '}' 986 ; 987 988requestflags_l : requestflags optcommanl requestflags_l 989 | requestflags optnl 990 ; 991 992requestflags : REWRITE STRING { 993 if (strlcpy(srv->srv_conf.path, $2, 994 sizeof(srv->srv_conf.path)) >= 995 sizeof(srv->srv_conf.path)) { 996 yyerror("request path too long"); 997 free($2); 998 YYERROR; 999 } 1000 free($2); 1001 srv->srv_conf.flags |= SRVFLAG_PATH_REWRITE; 1002 srv->srv_conf.flags &= ~SRVFLAG_NO_PATH_REWRITE; 1003 } 1004 | NO REWRITE { 1005 srv->srv_conf.flags |= SRVFLAG_NO_PATH_REWRITE; 1006 srv->srv_conf.flags &= ~SRVFLAG_PATH_REWRITE; 1007 } 1008 | STRIP NUMBER { 1009 if ($2 < 0 || $2 > INT_MAX) { 1010 yyerror("invalid strip number"); 1011 YYERROR; 1012 } 1013 srv->srv_conf.strip = $2; 1014 } 1015 ; 1016 1017authenticate : NO AUTHENTICATE { 1018 srv->srv_conf.flags |= SRVFLAG_NO_AUTH; 1019 } 1020 | AUTHENTICATE authopts { 1021 struct auth *auth; 1022 1023 if ((auth = auth_add(conf->sc_auth, &$2)) == NULL) { 1024 yyerror("failed to add auth"); 1025 YYERROR; 1026 } 1027 1028 if (auth->auth_id == 0) { 1029 /* New htpasswd, get new Id */ 1030 auth->auth_id = ++last_auth_id; 1031 if (last_auth_id == INT_MAX) { 1032 yyerror("too many auth ids defined"); 1033 auth_free(conf->sc_auth, auth); 1034 YYERROR; 1035 } 1036 } 1037 1038 srv->srv_conf.auth_id = auth->auth_id; 1039 srv->srv_conf.flags |= SRVFLAG_AUTH; 1040 } 1041 ; 1042 1043authopts : STRING WITH STRING { 1044 if (strlcpy(srv->srv_conf.auth_realm, $1, 1045 sizeof(srv->srv_conf.auth_realm)) >= 1046 sizeof(srv->srv_conf.auth_realm)) { 1047 yyerror("basic auth realm name too long"); 1048 free($1); 1049 YYERROR; 1050 } 1051 free($1); 1052 if (strlcpy($$.auth_htpasswd, $3, 1053 sizeof($$.auth_htpasswd)) >= 1054 sizeof($$.auth_htpasswd)) { 1055 yyerror("password file name too long"); 1056 free($3); 1057 YYERROR; 1058 } 1059 free($3); 1060 1061 } 1062 | WITH STRING { 1063 if (strlcpy($$.auth_htpasswd, $2, 1064 sizeof($$.auth_htpasswd)) >= 1065 sizeof($$.auth_htpasswd)) { 1066 yyerror("password file name too long"); 1067 free($2); 1068 YYERROR; 1069 } 1070 free($2); 1071 }; 1072 1073directory : DIRECTORY dirflags 1074 | DIRECTORY '{' optnl dirflags_l '}' 1075 ; 1076 1077dirflags_l : dirflags optcommanl dirflags_l 1078 | dirflags optnl 1079 ; 1080 1081dirflags : INDEX STRING { 1082 if (strlcpy(srv_conf->index, $2, 1083 sizeof(srv_conf->index)) >= 1084 sizeof(srv_conf->index)) { 1085 yyerror("index file too long"); 1086 free($2); 1087 YYERROR; 1088 } 1089 srv_conf->flags &= ~SRVFLAG_NO_INDEX; 1090 srv_conf->flags |= SRVFLAG_INDEX; 1091 free($2); 1092 } 1093 | NO INDEX { 1094 srv_conf->flags &= ~SRVFLAG_INDEX; 1095 srv_conf->flags |= SRVFLAG_NO_INDEX; 1096 } 1097 | AUTO INDEX { 1098 srv_conf->flags &= ~SRVFLAG_NO_AUTO_INDEX; 1099 srv_conf->flags |= SRVFLAG_AUTO_INDEX; 1100 } 1101 | NO AUTO INDEX { 1102 srv_conf->flags &= ~SRVFLAG_AUTO_INDEX; 1103 srv_conf->flags |= SRVFLAG_NO_AUTO_INDEX; 1104 } 1105 ; 1106 1107 1108logformat : LOG logflags 1109 | LOG '{' optnl logflags_l '}' 1110 | NO LOG { 1111 srv_conf->flags &= ~SRVFLAG_LOG; 1112 srv_conf->flags |= SRVFLAG_NO_LOG; 1113 } 1114 ; 1115 1116logflags_l : logflags optcommanl logflags_l 1117 | logflags optnl 1118 ; 1119 1120logflags : STYLE logstyle 1121 | SYSLOG { 1122 srv_conf->flags &= ~SRVFLAG_NO_SYSLOG; 1123 srv_conf->flags |= SRVFLAG_SYSLOG; 1124 } 1125 | NO SYSLOG { 1126 srv_conf->flags &= ~SRVFLAG_SYSLOG; 1127 srv_conf->flags |= SRVFLAG_NO_SYSLOG; 1128 } 1129 | ACCESS STRING { 1130 if (strlcpy(srv_conf->accesslog, $2, 1131 sizeof(srv_conf->accesslog)) >= 1132 sizeof(srv_conf->accesslog)) { 1133 yyerror("access log name too long"); 1134 free($2); 1135 YYERROR; 1136 } 1137 free($2); 1138 srv_conf->flags |= SRVFLAG_ACCESS_LOG; 1139 } 1140 | ERR STRING { 1141 if (strlcpy(srv_conf->errorlog, $2, 1142 sizeof(srv_conf->errorlog)) >= 1143 sizeof(srv_conf->errorlog)) { 1144 yyerror("error log name too long"); 1145 free($2); 1146 YYERROR; 1147 } 1148 free($2); 1149 srv_conf->flags |= SRVFLAG_ERROR_LOG; 1150 } 1151 ; 1152 1153logstyle : COMMON { 1154 srv_conf->flags &= ~SRVFLAG_NO_LOG; 1155 srv_conf->flags |= SRVFLAG_LOG; 1156 srv_conf->logformat = LOG_FORMAT_COMMON; 1157 } 1158 | COMBINED { 1159 srv_conf->flags &= ~SRVFLAG_NO_LOG; 1160 srv_conf->flags |= SRVFLAG_LOG; 1161 srv_conf->logformat = LOG_FORMAT_COMBINED; 1162 } 1163 | CONNECTION { 1164 srv_conf->flags &= ~SRVFLAG_NO_LOG; 1165 srv_conf->flags |= SRVFLAG_LOG; 1166 srv_conf->logformat = LOG_FORMAT_CONNECTION; 1167 } 1168 | FORWARDED { 1169 srv_conf->flags &= ~SRVFLAG_NO_LOG; 1170 srv_conf->flags |= SRVFLAG_LOG; 1171 srv_conf->logformat = LOG_FORMAT_FORWARDED; 1172 } 1173 ; 1174 1175filter : block RETURN NUMBER optstring { 1176 if ($3 <= 0 || server_httperror_byid($3) == NULL) { 1177 yyerror("invalid return code: %lld", $3); 1178 free($4); 1179 YYERROR; 1180 } 1181 srv_conf->return_code = $3; 1182 1183 if ($4 != NULL) { 1184 /* Only for 3xx redirection headers */ 1185 if ($3 < 300 || $3 > 399) { 1186 yyerror("invalid return code for " 1187 "location URI"); 1188 free($4); 1189 YYERROR; 1190 } 1191 srv_conf->return_uri = $4; 1192 srv_conf->return_uri_len = strlen($4) + 1; 1193 } 1194 } 1195 | block DROP { 1196 /* No return code, silently drop the connection */ 1197 srv_conf->return_code = 0; 1198 } 1199 | block { 1200 /* Forbidden */ 1201 srv_conf->return_code = 403; 1202 } 1203 | PASS { 1204 srv_conf->flags &= ~SRVFLAG_BLOCK; 1205 srv_conf->flags |= SRVFLAG_NO_BLOCK; 1206 } 1207 ; 1208 1209block : BLOCK { 1210 srv_conf->flags &= ~SRVFLAG_NO_BLOCK; 1211 srv_conf->flags |= SRVFLAG_BLOCK; 1212 } 1213 ; 1214 1215optmatch : /* empty */ { $$ = 0; } 1216 | MATCH { $$ = 1; } 1217 ; 1218 1219optstring : /* empty */ { $$ = NULL; } 1220 | STRING { $$ = $1; } 1221 ; 1222 1223fcgiport : NUMBER { 1224 if ($1 <= 0 || $1 > (int)USHRT_MAX) { 1225 yyerror("invalid port: %lld", $1); 1226 YYERROR; 1227 } 1228 if (asprintf(&$$, "%lld", $1) == -1) { 1229 yyerror("out of memory"); 1230 YYERROR; 1231 } 1232 } 1233 | STRING { 1234 if (getservice($1) <= 0) { 1235 yyerror("invalid port: %s", $1); 1236 free($1); 1237 YYERROR; 1238 } 1239 1240 $$ = $1; 1241 } 1242 ; 1243 1244gzip_static : NO GZIPSTATIC { 1245 srv->srv_conf.flags &= ~SRVFLAG_GZIP_STATIC; 1246 } 1247 | GZIPSTATIC { 1248 srv->srv_conf.flags |= SRVFLAG_GZIP_STATIC; 1249 } 1250 ; 1251 1252tcpip : TCP '{' optnl tcpflags_l '}' 1253 | TCP tcpflags 1254 ; 1255 1256tcpflags_l : tcpflags optcommanl tcpflags_l 1257 | tcpflags optnl 1258 ; 1259 1260tcpflags : SACK { srv_conf->tcpflags |= TCPFLAG_SACK; } 1261 | NO SACK { srv_conf->tcpflags |= TCPFLAG_NSACK; } 1262 | NODELAY { 1263 srv_conf->tcpflags |= TCPFLAG_NODELAY; 1264 } 1265 | NO NODELAY { 1266 srv_conf->tcpflags |= TCPFLAG_NNODELAY; 1267 } 1268 | BACKLOG NUMBER { 1269 if ($2 < 0 || $2 > SERVER_MAX_CLIENTS) { 1270 yyerror("invalid backlog: %lld", $2); 1271 YYERROR; 1272 } 1273 srv_conf->tcpbacklog = $2; 1274 } 1275 | SOCKET BUFFER NUMBER { 1276 srv_conf->tcpflags |= TCPFLAG_BUFSIZ; 1277 if ((srv_conf->tcpbufsiz = $3) < 0) { 1278 yyerror("invalid socket buffer size: %lld", $3); 1279 YYERROR; 1280 } 1281 } 1282 | IP STRING NUMBER { 1283 if ($3 < 0) { 1284 yyerror("invalid ttl: %lld", $3); 1285 free($2); 1286 YYERROR; 1287 } 1288 if (strcasecmp("ttl", $2) == 0) { 1289 srv_conf->tcpflags |= TCPFLAG_IPTTL; 1290 srv_conf->tcpipttl = $3; 1291 } else if (strcasecmp("minttl", $2) == 0) { 1292 srv_conf->tcpflags |= TCPFLAG_IPMINTTL; 1293 srv_conf->tcpipminttl = $3; 1294 } else { 1295 yyerror("invalid TCP/IP flag: %s", $2); 1296 free($2); 1297 YYERROR; 1298 } 1299 free($2); 1300 } 1301 ; 1302 1303types : TYPES '{' optnl mediaopts_l '}' 1304 ; 1305 1306mediaopts_l : mediaopts_l mediaoptsl nl 1307 | mediaoptsl nl 1308 ; 1309 1310mediaoptsl : mediastring medianames_l optsemicolon 1311 | include 1312 ; 1313 1314mediastring : STRING '/' STRING { 1315 if (strlcpy(media.media_type, $1, 1316 sizeof(media.media_type)) >= 1317 sizeof(media.media_type) || 1318 strlcpy(media.media_subtype, $3, 1319 sizeof(media.media_subtype)) >= 1320 sizeof(media.media_subtype)) { 1321 yyerror("media type too long"); 1322 free($1); 1323 free($3); 1324 YYERROR; 1325 } 1326 free($1); 1327 free($3); 1328 } 1329 ; 1330 1331medianames_l : medianames_l medianamesl 1332 | medianamesl 1333 ; 1334 1335medianamesl : numberstring { 1336 if (strlcpy(media.media_name, $1, 1337 sizeof(media.media_name)) >= 1338 sizeof(media.media_name)) { 1339 yyerror("media name too long"); 1340 free($1); 1341 YYERROR; 1342 } 1343 free($1); 1344 1345 if (!loadcfg) 1346 break; 1347 1348 if (media_add(conf->sc_mediatypes, &media) == NULL) { 1349 yyerror("failed to add media type"); 1350 YYERROR; 1351 } 1352 } 1353 ; 1354 1355port : PORT NUMBER { 1356 if ($2 <= 0 || $2 > (int)USHRT_MAX) { 1357 yyerror("invalid port: %lld", $2); 1358 YYERROR; 1359 } 1360 $$.val[0] = htons($2); 1361 $$.op = 1; 1362 } 1363 | PORT STRING { 1364 int val; 1365 1366 if ((val = getservice($2)) == -1) { 1367 yyerror("invalid port: %s", $2); 1368 free($2); 1369 YYERROR; 1370 } 1371 free($2); 1372 1373 $$.val[0] = val; 1374 $$.op = 1; 1375 } 1376 ; 1377 1378timeout : NUMBER 1379 { 1380 if ($1 < 0) { 1381 yyerror("invalid timeout: %lld", $1); 1382 YYERROR; 1383 } 1384 $$.tv_sec = $1; 1385 $$.tv_usec = 0; 1386 } 1387 ; 1388 1389numberstring : NUMBER { 1390 char *s; 1391 if (asprintf(&s, "%lld", $1) == -1) { 1392 yyerror("asprintf: number"); 1393 YYERROR; 1394 } 1395 $$ = s; 1396 } 1397 | STRING 1398 ; 1399 1400optsemicolon : ';' 1401 | 1402 ; 1403 1404optnl : '\n' optnl 1405 | 1406 ; 1407 1408optcommanl : ',' optnl 1409 | nl 1410 ; 1411 1412nl : '\n' optnl 1413 ; 1414 1415%% 1416 1417struct keywords { 1418 const char *k_name; 1419 int k_val; 1420}; 1421 1422int 1423yyerror(const char *fmt, ...) 1424{ 1425 va_list ap; 1426 char *msg; 1427 1428 file->errors++; 1429 va_start(ap, fmt); 1430 if (vasprintf(&msg, fmt, ap) == -1) 1431 fatalx("yyerror vasprintf"); 1432 va_end(ap); 1433 logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg); 1434 free(msg); 1435 return (0); 1436} 1437 1438int 1439kw_cmp(const void *k, const void *e) 1440{ 1441 return (strcmp(k, ((const struct keywords *)e)->k_name)); 1442} 1443 1444int 1445lookup(char *s) 1446{ 1447 /* this has to be sorted always */ 1448 static const struct keywords keywords[] = { 1449 { "access", ACCESS }, 1450 { "alias", ALIAS }, 1451 { "authenticate", AUTHENTICATE}, 1452 { "auto", AUTO }, 1453 { "backlog", BACKLOG }, 1454 { "banner", BANNER }, 1455 { "block", BLOCK }, 1456 { "body", BODY }, 1457 { "buffer", BUFFER }, 1458 { "ca", CA }, 1459 { "certificate", CERTIFICATE }, 1460 { "chroot", CHROOT }, 1461 { "ciphers", CIPHERS }, 1462 { "client", CLIENT }, 1463 { "combined", COMBINED }, 1464 { "common", COMMON }, 1465 { "connection", CONNECTION }, 1466 { "crl", CRL }, 1467 { "default", DEFAULT }, 1468 { "dhe", DHE }, 1469 { "directory", DIRECTORY }, 1470 { "drop", DROP }, 1471 { "ecdhe", ECDHE }, 1472 { "errdocs", ERRDOCS }, 1473 { "error", ERR }, 1474 { "fastcgi", FCGI }, 1475 { "forwarded", FORWARDED }, 1476 { "found", FOUND }, 1477 { "gzip-static", GZIPSTATIC }, 1478 { "hsts", HSTS }, 1479 { "include", INCLUDE }, 1480 { "index", INDEX }, 1481 { "ip", IP }, 1482 { "key", KEY }, 1483 { "lifetime", LIFETIME }, 1484 { "listen", LISTEN }, 1485 { "location", LOCATION }, 1486 { "log", LOG }, 1487 { "logdir", LOGDIR }, 1488 { "match", MATCH }, 1489 { "max", MAXIMUM }, 1490 { "max-age", MAXAGE }, 1491 { "no", NO }, 1492 { "nodelay", NODELAY }, 1493 { "not", NOT }, 1494 { "ocsp", OCSP }, 1495 { "on", ON }, 1496 { "optional", OPTIONAL }, 1497 { "param", PARAM }, 1498 { "pass", PASS }, 1499 { "port", PORT }, 1500 { "prefork", PREFORK }, 1501 { "preload", PRELOAD }, 1502 { "protocols", PROTOCOLS }, 1503 { "request", REQUEST }, 1504 { "requests", REQUESTS }, 1505 { "return", RETURN }, 1506 { "rewrite", REWRITE }, 1507 { "root", ROOT }, 1508 { "sack", SACK }, 1509 { "server", SERVER }, 1510 { "socket", SOCKET }, 1511 { "strip", STRIP }, 1512 { "style", STYLE }, 1513 { "subdomains", SUBDOMAINS }, 1514 { "syslog", SYSLOG }, 1515 { "tcp", TCP }, 1516 { "ticket", TICKET }, 1517 { "timeout", TIMEOUT }, 1518 { "tls", TLS }, 1519 { "type", TYPE }, 1520 { "types", TYPES }, 1521 { "with", WITH } 1522 }; 1523 const struct keywords *p; 1524 1525 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 1526 sizeof(keywords[0]), kw_cmp); 1527 1528 if (p) 1529 return (p->k_val); 1530 else 1531 return (STRING); 1532} 1533 1534#define START_EXPAND 1 1535#define DONE_EXPAND 2 1536 1537static int expanding; 1538 1539int 1540igetc(void) 1541{ 1542 int c; 1543 1544 while (1) { 1545 if (file->ungetpos > 0) 1546 c = file->ungetbuf[--file->ungetpos]; 1547 else 1548 c = getc(file->stream); 1549 1550 if (c == START_EXPAND) 1551 expanding = 1; 1552 else if (c == DONE_EXPAND) 1553 expanding = 0; 1554 else 1555 break; 1556 } 1557 return (c); 1558} 1559 1560int 1561lgetc(int quotec) 1562{ 1563 int c, next; 1564 1565 if (quotec) { 1566 if ((c = igetc()) == EOF) { 1567 yyerror("reached end of file while parsing " 1568 "quoted string"); 1569 if (file == topfile || popfile() == EOF) 1570 return (EOF); 1571 return (quotec); 1572 } 1573 return (c); 1574 } 1575 1576 while ((c = igetc()) == '\\') { 1577 next = igetc(); 1578 if (next != '\n') { 1579 c = next; 1580 break; 1581 } 1582 yylval.lineno = file->lineno; 1583 file->lineno++; 1584 } 1585 1586 if (c == EOF) { 1587 /* 1588 * Fake EOL when hit EOF for the first time. This gets line 1589 * count right if last line in included file is syntactically 1590 * invalid and has no newline. 1591 */ 1592 if (file->eof_reached == 0) { 1593 file->eof_reached = 1; 1594 return ('\n'); 1595 } 1596 while (c == EOF) { 1597 if (file == topfile || popfile() == EOF) 1598 return (EOF); 1599 c = igetc(); 1600 } 1601 } 1602 return (c); 1603} 1604 1605void 1606lungetc(int c) 1607{ 1608 if (c == EOF) 1609 return; 1610 1611 if (file->ungetpos >= file->ungetsize) { 1612 void *p = reallocarray(file->ungetbuf, file->ungetsize, 2); 1613 if (p == NULL) 1614 err(1, "%s", __func__); 1615 file->ungetbuf = p; 1616 file->ungetsize *= 2; 1617 } 1618 file->ungetbuf[file->ungetpos++] = c; 1619} 1620 1621int 1622findeol(void) 1623{ 1624 int c; 1625 1626 /* skip to either EOF or the first real EOL */ 1627 while (1) { 1628 c = lgetc(0); 1629 if (c == '\n') { 1630 file->lineno++; 1631 break; 1632 } 1633 if (c == EOF) 1634 break; 1635 } 1636 return (ERROR); 1637} 1638 1639int 1640yylex(void) 1641{ 1642 char buf[8096]; 1643 char *p, *val; 1644 int quotec, next, c; 1645 int token; 1646 1647top: 1648 p = buf; 1649 while ((c = lgetc(0)) == ' ' || c == '\t') 1650 ; /* nothing */ 1651 1652 yylval.lineno = file->lineno; 1653 if (c == '#') 1654 while ((c = lgetc(0)) != '\n' && c != EOF) 1655 ; /* nothing */ 1656 if (c == '$' && !expanding) { 1657 while (1) { 1658 if ((c = lgetc(0)) == EOF) 1659 return (0); 1660 1661 if (p + 1 >= buf + sizeof(buf) - 1) { 1662 yyerror("string too long"); 1663 return (findeol()); 1664 } 1665 if (isalnum(c) || c == '_') { 1666 *p++ = c; 1667 continue; 1668 } 1669 *p = '\0'; 1670 lungetc(c); 1671 break; 1672 } 1673 val = symget(buf); 1674 if (val == NULL) { 1675 yyerror("macro '%s' not defined", buf); 1676 return (findeol()); 1677 } 1678 p = val + strlen(val) - 1; 1679 lungetc(DONE_EXPAND); 1680 while (p >= val) { 1681 lungetc((unsigned char)*p); 1682 p--; 1683 } 1684 lungetc(START_EXPAND); 1685 goto top; 1686 } 1687 1688 switch (c) { 1689 case '\'': 1690 case '"': 1691 quotec = c; 1692 while (1) { 1693 if ((c = lgetc(quotec)) == EOF) 1694 return (0); 1695 if (c == '\n') { 1696 file->lineno++; 1697 continue; 1698 } else if (c == '\\') { 1699 if ((next = lgetc(quotec)) == EOF) 1700 return (0); 1701 if (next == quotec || next == ' ' || 1702 next == '\t') 1703 c = next; 1704 else if (next == '\n') { 1705 file->lineno++; 1706 continue; 1707 } else 1708 lungetc(next); 1709 } else if (c == quotec) { 1710 *p = '\0'; 1711 break; 1712 } else if (c == '\0') { 1713 yyerror("syntax error"); 1714 return (findeol()); 1715 } 1716 if (p + 1 >= buf + sizeof(buf) - 1) { 1717 yyerror("string too long"); 1718 return (findeol()); 1719 } 1720 *p++ = c; 1721 } 1722 yylval.v.string = strdup(buf); 1723 if (yylval.v.string == NULL) 1724 err(1, "%s", __func__); 1725 return (STRING); 1726 } 1727 1728#define allowed_to_end_number(x) \ 1729 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 1730 1731 if (c == '-' || isdigit(c)) { 1732 do { 1733 *p++ = c; 1734 if ((size_t)(p-buf) >= sizeof(buf)) { 1735 yyerror("string too long"); 1736 return (findeol()); 1737 } 1738 } while ((c = lgetc(0)) != EOF && isdigit(c)); 1739 lungetc(c); 1740 if (p == buf + 1 && buf[0] == '-') 1741 goto nodigits; 1742 if (c == EOF || allowed_to_end_number(c)) { 1743 const char *errstr = NULL; 1744 1745 *p = '\0'; 1746 yylval.v.number = strtonum(buf, LLONG_MIN, 1747 LLONG_MAX, &errstr); 1748 if (errstr) { 1749 yyerror("\"%s\" invalid number: %s", 1750 buf, errstr); 1751 return (findeol()); 1752 } 1753 return (NUMBER); 1754 } else { 1755nodigits: 1756 while (p > buf + 1) 1757 lungetc((unsigned char)*--p); 1758 c = (unsigned char)*--p; 1759 if (c == '-') 1760 return (c); 1761 } 1762 } 1763 1764#define allowed_in_string(x) \ 1765 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1766 x != '{' && x != '}' && x != '<' && x != '>' && \ 1767 x != '!' && x != '=' && x != '#' && \ 1768 x != ',' && x != ';' && x != '/')) 1769 1770 if (isalnum(c) || c == ':' || c == '_' || c == '*') { 1771 do { 1772 *p++ = c; 1773 if ((size_t)(p-buf) >= sizeof(buf)) { 1774 yyerror("string too long"); 1775 return (findeol()); 1776 } 1777 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 1778 lungetc(c); 1779 *p = '\0'; 1780 if ((token = lookup(buf)) == STRING) 1781 if ((yylval.v.string = strdup(buf)) == NULL) 1782 err(1, "%s", __func__); 1783 return (token); 1784 } 1785 if (c == '\n') { 1786 yylval.lineno = file->lineno; 1787 file->lineno++; 1788 } 1789 if (c == EOF) 1790 return (0); 1791 return (c); 1792} 1793 1794int 1795check_file_secrecy(int fd, const char *fname) 1796{ 1797 struct stat st; 1798 1799 if (fstat(fd, &st)) { 1800 log_warn("cannot stat %s", fname); 1801 return (-1); 1802 } 1803 if (st.st_uid != 0 && st.st_uid != getuid()) { 1804 log_warnx("%s: owner not root or current user", fname); 1805 return (-1); 1806 } 1807 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 1808 log_warnx("%s: group writable or world read/writable", fname); 1809 return (-1); 1810 } 1811 return (0); 1812} 1813 1814struct file * 1815pushfile(const char *name, int secret) 1816{ 1817 struct file *nfile; 1818 1819 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 1820 log_warn("%s", __func__); 1821 return (NULL); 1822 } 1823 if ((nfile->name = strdup(name)) == NULL) { 1824 log_warn("%s", __func__); 1825 free(nfile); 1826 return (NULL); 1827 } 1828 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 1829 log_warn("%s: %s", __func__, nfile->name); 1830 free(nfile->name); 1831 free(nfile); 1832 return (NULL); 1833 } else if (secret && 1834 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 1835 fclose(nfile->stream); 1836 free(nfile->name); 1837 free(nfile); 1838 return (NULL); 1839 } 1840 nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0; 1841 nfile->ungetsize = 16; 1842 nfile->ungetbuf = malloc(nfile->ungetsize); 1843 if (nfile->ungetbuf == NULL) { 1844 log_warn("%s", __func__); 1845 fclose(nfile->stream); 1846 free(nfile->name); 1847 free(nfile); 1848 return (NULL); 1849 } 1850 TAILQ_INSERT_TAIL(&files, nfile, entry); 1851 return (nfile); 1852} 1853 1854int 1855popfile(void) 1856{ 1857 struct file *prev; 1858 1859 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 1860 prev->errors += file->errors; 1861 1862 TAILQ_REMOVE(&files, file, entry); 1863 fclose(file->stream); 1864 free(file->name); 1865 free(file->ungetbuf); 1866 free(file); 1867 file = prev; 1868 return (file ? 0 : EOF); 1869} 1870 1871int 1872parse_config(const char *filename, struct httpd *x_conf) 1873{ 1874 struct sym *sym, *next; 1875 struct media_type dflt = HTTPD_DEFAULT_TYPE; 1876 1877 conf = x_conf; 1878 if (config_init(conf) == -1) { 1879 log_warn("%s: cannot initialize configuration", __func__); 1880 return (-1); 1881 } 1882 1883 /* Set default media type */ 1884 memcpy(&conf->sc_default_type, &dflt, sizeof(struct media_type)); 1885 1886 errors = 0; 1887 1888 if ((file = pushfile(filename, 0)) == NULL) 1889 return (-1); 1890 1891 topfile = file; 1892 setservent(1); 1893 1894 yyparse(); 1895 errors = file->errors; 1896 while (popfile() != EOF) 1897 ; 1898 1899 endservent(); 1900 endprotoent(); 1901 1902 /* Free macros */ 1903 TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) { 1904 if (!sym->persist) { 1905 free(sym->nam); 1906 free(sym->val); 1907 TAILQ_REMOVE(&symhead, sym, entry); 1908 free(sym); 1909 } 1910 } 1911 1912 return (errors ? -1 : 0); 1913} 1914 1915int 1916load_config(const char *filename, struct httpd *x_conf) 1917{ 1918 struct sym *sym, *next; 1919 struct http_mediatype mediatypes[] = MEDIA_TYPES; 1920 struct media_type m; 1921 int i; 1922 1923 memset(&m, 0, sizeof(m)); 1924 conf = x_conf; 1925 conf->sc_flags = 0; 1926 1927 loadcfg = 1; 1928 errors = 0; 1929 last_server_id = 0; 1930 last_auth_id = 0; 1931 1932 srv = NULL; 1933 1934 if ((file = pushfile(filename, 0)) == NULL) 1935 return (-1); 1936 1937 topfile = file; 1938 setservent(1); 1939 1940 yyparse(); 1941 errors = file->errors; 1942 popfile(); 1943 1944 endservent(); 1945 endprotoent(); 1946 1947 /* Free macros and check which have not been used. */ 1948 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 1949 next = TAILQ_NEXT(sym, entry); 1950 if ((conf->sc_opts & HTTPD_OPT_VERBOSE) && !sym->used) 1951 fprintf(stderr, "warning: macro '%s' not " 1952 "used\n", sym->nam); 1953 if (!sym->persist) { 1954 free(sym->nam); 1955 free(sym->val); 1956 TAILQ_REMOVE(&symhead, sym, entry); 1957 free(sym); 1958 } 1959 } 1960 1961 if (TAILQ_EMPTY(conf->sc_servers)) { 1962 log_warnx("no actions, nothing to do"); 1963 errors++; 1964 } 1965 1966 if (RB_EMPTY(conf->sc_mediatypes)) { 1967 /* Add default media types */ 1968 for (i = 0; mediatypes[i].media_name != NULL; i++) { 1969 (void)strlcpy(m.media_name, mediatypes[i].media_name, 1970 sizeof(m.media_name)); 1971 (void)strlcpy(m.media_type, mediatypes[i].media_type, 1972 sizeof(m.media_type)); 1973 (void)strlcpy(m.media_subtype, 1974 mediatypes[i].media_subtype, 1975 sizeof(m.media_subtype)); 1976 m.media_encoding = NULL; 1977 1978 if (media_add(conf->sc_mediatypes, &m) == NULL) { 1979 log_warnx("failed to add default media \"%s\"", 1980 m.media_name); 1981 errors++; 1982 } 1983 } 1984 } 1985 1986 return (errors ? -1 : 0); 1987} 1988 1989int 1990symset(const char *nam, const char *val, int persist) 1991{ 1992 struct sym *sym; 1993 1994 TAILQ_FOREACH(sym, &symhead, entry) { 1995 if (strcmp(nam, sym->nam) == 0) 1996 break; 1997 } 1998 1999 if (sym != NULL) { 2000 if (sym->persist == 1) 2001 return (0); 2002 else { 2003 free(sym->nam); 2004 free(sym->val); 2005 TAILQ_REMOVE(&symhead, sym, entry); 2006 free(sym); 2007 } 2008 } 2009 if ((sym = calloc(1, sizeof(*sym))) == NULL) 2010 return (-1); 2011 2012 sym->nam = strdup(nam); 2013 if (sym->nam == NULL) { 2014 free(sym); 2015 return (-1); 2016 } 2017 sym->val = strdup(val); 2018 if (sym->val == NULL) { 2019 free(sym->nam); 2020 free(sym); 2021 return (-1); 2022 } 2023 sym->used = 0; 2024 sym->persist = persist; 2025 TAILQ_INSERT_TAIL(&symhead, sym, entry); 2026 return (0); 2027} 2028 2029int 2030cmdline_symset(char *s) 2031{ 2032 char *sym, *val; 2033 int ret; 2034 2035 if ((val = strrchr(s, '=')) == NULL) 2036 return (-1); 2037 sym = strndup(s, val - s); 2038 if (sym == NULL) 2039 errx(1, "%s: strndup", __func__); 2040 ret = symset(sym, val + 1, 1); 2041 free(sym); 2042 2043 return (ret); 2044} 2045 2046char * 2047symget(const char *nam) 2048{ 2049 struct sym *sym; 2050 2051 TAILQ_FOREACH(sym, &symhead, entry) { 2052 if (strcmp(nam, sym->nam) == 0) { 2053 sym->used = 1; 2054 return (sym->val); 2055 } 2056 } 2057 return (NULL); 2058} 2059 2060struct address * 2061host_v4(const char *s) 2062{ 2063 struct in_addr ina; 2064 struct sockaddr_in *sain; 2065 struct address *h; 2066 2067 memset(&ina, 0, sizeof(ina)); 2068 if (inet_pton(AF_INET, s, &ina) != 1) 2069 return (NULL); 2070 2071 if ((h = calloc(1, sizeof(*h))) == NULL) 2072 fatal(__func__); 2073 sain = (struct sockaddr_in *)&h->ss; 2074 sain->sin_len = sizeof(struct sockaddr_in); 2075 sain->sin_family = AF_INET; 2076 sain->sin_addr.s_addr = ina.s_addr; 2077 if (sain->sin_addr.s_addr == INADDR_ANY) 2078 h->prefixlen = 0; /* 0.0.0.0 address */ 2079 else 2080 h->prefixlen = -1; /* host address */ 2081 return (h); 2082} 2083 2084struct address * 2085host_v6(const char *s) 2086{ 2087 struct addrinfo hints, *res; 2088 struct sockaddr_in6 *sa_in6; 2089 struct address *h = NULL; 2090 2091 memset(&hints, 0, sizeof(hints)); 2092 hints.ai_family = AF_INET6; 2093 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 2094 hints.ai_flags = AI_NUMERICHOST; 2095 if (getaddrinfo(s, "0", &hints, &res) == 0) { 2096 if ((h = calloc(1, sizeof(*h))) == NULL) 2097 fatal(__func__); 2098 sa_in6 = (struct sockaddr_in6 *)&h->ss; 2099 sa_in6->sin6_len = sizeof(struct sockaddr_in6); 2100 sa_in6->sin6_family = AF_INET6; 2101 memcpy(&sa_in6->sin6_addr, 2102 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 2103 sizeof(sa_in6->sin6_addr)); 2104 sa_in6->sin6_scope_id = 2105 ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 2106 if (memcmp(&sa_in6->sin6_addr, &in6addr_any, 2107 sizeof(sa_in6->sin6_addr)) == 0) 2108 h->prefixlen = 0; /* any address */ 2109 else 2110 h->prefixlen = -1; /* host address */ 2111 freeaddrinfo(res); 2112 } 2113 2114 return (h); 2115} 2116 2117int 2118host_dns(const char *s, struct addresslist *al, int max, 2119 struct portrange *port, const char *ifname, int ipproto) 2120{ 2121 struct addrinfo hints, *res0, *res; 2122 int error, cnt = 0; 2123 struct sockaddr_in *sain; 2124 struct sockaddr_in6 *sin6; 2125 struct address *h; 2126 2127 if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0) 2128 return (cnt); 2129 2130 memset(&hints, 0, sizeof(hints)); 2131 hints.ai_family = PF_UNSPEC; 2132 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 2133 hints.ai_flags = AI_ADDRCONFIG; 2134 error = getaddrinfo(s, NULL, &hints, &res0); 2135 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 2136 return (0); 2137 if (error) { 2138 log_warnx("%s: could not parse \"%s\": %s", __func__, s, 2139 gai_strerror(error)); 2140 return (-1); 2141 } 2142 2143 for (res = res0; res && cnt < max; res = res->ai_next) { 2144 if (res->ai_family != AF_INET && 2145 res->ai_family != AF_INET6) 2146 continue; 2147 if ((h = calloc(1, sizeof(*h))) == NULL) 2148 fatal(__func__); 2149 2150 if (port != NULL) 2151 memcpy(&h->port, port, sizeof(h->port)); 2152 if (ifname != NULL) { 2153 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 2154 sizeof(h->ifname)) 2155 log_warnx("%s: interface name truncated", 2156 __func__); 2157 freeaddrinfo(res0); 2158 free(h); 2159 return (-1); 2160 } 2161 if (ipproto != -1) 2162 h->ipproto = ipproto; 2163 h->ss.ss_family = res->ai_family; 2164 h->prefixlen = -1; /* host address */ 2165 2166 if (res->ai_family == AF_INET) { 2167 sain = (struct sockaddr_in *)&h->ss; 2168 sain->sin_len = sizeof(struct sockaddr_in); 2169 sain->sin_addr.s_addr = ((struct sockaddr_in *) 2170 res->ai_addr)->sin_addr.s_addr; 2171 } else { 2172 sin6 = (struct sockaddr_in6 *)&h->ss; 2173 sin6->sin6_len = sizeof(struct sockaddr_in6); 2174 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 2175 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 2176 } 2177 2178 TAILQ_INSERT_HEAD(al, h, entry); 2179 cnt++; 2180 } 2181 if (cnt == max && res) { 2182 log_warnx("%s: %s resolves to more than %d hosts", __func__, 2183 s, max); 2184 } 2185 freeaddrinfo(res0); 2186 return (cnt); 2187} 2188 2189int 2190host_if(const char *s, struct addresslist *al, int max, 2191 struct portrange *port, const char *ifname, int ipproto) 2192{ 2193 struct ifaddrs *ifap, *p; 2194 struct sockaddr_in *sain; 2195 struct sockaddr_in6 *sin6; 2196 struct address *h; 2197 int cnt = 0, af; 2198 2199 if (getifaddrs(&ifap) == -1) 2200 fatal("getifaddrs"); 2201 2202 /* First search for IPv4 addresses */ 2203 af = AF_INET; 2204 2205 nextaf: 2206 for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) { 2207 if (p->ifa_addr == NULL || 2208 p->ifa_addr->sa_family != af || 2209 (strcmp(s, p->ifa_name) != 0 && 2210 !is_if_in_group(p->ifa_name, s))) 2211 continue; 2212 if ((h = calloc(1, sizeof(*h))) == NULL) 2213 fatal("calloc"); 2214 2215 if (port != NULL) 2216 memcpy(&h->port, port, sizeof(h->port)); 2217 if (ifname != NULL) { 2218 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 2219 sizeof(h->ifname)) 2220 log_warnx("%s: interface name truncated", 2221 __func__); 2222 freeifaddrs(ifap); 2223 free(h); 2224 return (-1); 2225 } 2226 if (ipproto != -1) 2227 h->ipproto = ipproto; 2228 h->ss.ss_family = af; 2229 h->prefixlen = -1; /* host address */ 2230 2231 if (af == AF_INET) { 2232 sain = (struct sockaddr_in *)&h->ss; 2233 sain->sin_len = sizeof(struct sockaddr_in); 2234 sain->sin_addr.s_addr = ((struct sockaddr_in *) 2235 p->ifa_addr)->sin_addr.s_addr; 2236 } else { 2237 sin6 = (struct sockaddr_in6 *)&h->ss; 2238 sin6->sin6_len = sizeof(struct sockaddr_in6); 2239 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 2240 p->ifa_addr)->sin6_addr, sizeof(struct in6_addr)); 2241 sin6->sin6_scope_id = ((struct sockaddr_in6 *) 2242 p->ifa_addr)->sin6_scope_id; 2243 } 2244 2245 TAILQ_INSERT_HEAD(al, h, entry); 2246 cnt++; 2247 } 2248 if (af == AF_INET) { 2249 /* Next search for IPv6 addresses */ 2250 af = AF_INET6; 2251 goto nextaf; 2252 } 2253 2254 if (cnt > max) { 2255 log_warnx("%s: %s resolves to more than %d hosts", __func__, 2256 s, max); 2257 } 2258 freeifaddrs(ifap); 2259 return (cnt); 2260} 2261 2262int 2263host(const char *s, struct addresslist *al, int max, 2264 struct portrange *port, const char *ifname, int ipproto) 2265{ 2266 struct address *h; 2267 2268 h = host_v4(s); 2269 2270 /* IPv6 address? */ 2271 if (h == NULL) 2272 h = host_v6(s); 2273 2274 if (h != NULL) { 2275 if (port != NULL) 2276 memcpy(&h->port, port, sizeof(h->port)); 2277 if (ifname != NULL) { 2278 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 2279 sizeof(h->ifname)) { 2280 log_warnx("%s: interface name truncated", 2281 __func__); 2282 free(h); 2283 return (-1); 2284 } 2285 } 2286 if (ipproto != -1) 2287 h->ipproto = ipproto; 2288 2289 TAILQ_INSERT_HEAD(al, h, entry); 2290 return (1); 2291 } 2292 2293 return (host_dns(s, al, max, port, ifname, ipproto)); 2294} 2295 2296struct server * 2297server_inherit(struct server *src, struct server_config *alias, 2298 struct server_config *addr) 2299{ 2300 struct server *dst, *s, *dstl; 2301 2302 if ((dst = calloc(1, sizeof(*dst))) == NULL) 2303 fatal("out of memory"); 2304 2305 /* Copy the source server and assign a new Id */ 2306 memcpy(&dst->srv_conf, &src->srv_conf, sizeof(dst->srv_conf)); 2307 if ((dst->srv_conf.tls_cert_file = 2308 strdup(src->srv_conf.tls_cert_file)) == NULL) 2309 fatal("out of memory"); 2310 if ((dst->srv_conf.tls_key_file = 2311 strdup(src->srv_conf.tls_key_file)) == NULL) 2312 fatal("out of memory"); 2313 if (src->srv_conf.tls_ocsp_staple_file != NULL) { 2314 if ((dst->srv_conf.tls_ocsp_staple_file = 2315 strdup(src->srv_conf.tls_ocsp_staple_file)) == NULL) 2316 fatal("out of memory"); 2317 } 2318 2319 if (src->srv_conf.return_uri != NULL && 2320 (dst->srv_conf.return_uri = 2321 strdup(src->srv_conf.return_uri)) == NULL) 2322 fatal("out of memory"); 2323 2324 dst->srv_conf.id = ++last_server_id; 2325 dst->srv_conf.parent_id = dst->srv_conf.id; 2326 dst->srv_s = -1; 2327 2328 if (last_server_id == INT_MAX) { 2329 yyerror("too many servers defined"); 2330 serverconfig_free(&dst->srv_conf); 2331 free(dst); 2332 return (NULL); 2333 } 2334 2335 /* Now set alias and listen address */ 2336 strlcpy(dst->srv_conf.name, alias->name, sizeof(dst->srv_conf.name)); 2337 memcpy(&dst->srv_conf.ss, &addr->ss, sizeof(dst->srv_conf.ss)); 2338 dst->srv_conf.port = addr->port; 2339 dst->srv_conf.prefixlen = addr->prefixlen; 2340 if (addr->flags & SRVFLAG_TLS) 2341 dst->srv_conf.flags |= SRVFLAG_TLS; 2342 else 2343 dst->srv_conf.flags &= ~SRVFLAG_TLS; 2344 2345 /* Don't inherit the "match" option, use it from the alias */ 2346 dst->srv_conf.flags &= ~SRVFLAG_SERVER_MATCH; 2347 dst->srv_conf.flags |= (alias->flags & SRVFLAG_SERVER_MATCH); 2348 2349 if (server_tls_load_keypair(dst) == -1) 2350 log_warnx("%s:%d: server \"%s\": failed to " 2351 "load public/private keys", file->name, 2352 yylval.lineno, dst->srv_conf.name); 2353 2354 if (server_tls_load_ca(dst) == -1) { 2355 yyerror("failed to load ca cert(s) for server %s", 2356 dst->srv_conf.name); 2357 serverconfig_free(&dst->srv_conf); 2358 return NULL; 2359 } 2360 2361 if (server_tls_load_crl(dst) == -1) { 2362 yyerror("failed to load crl(s) for server %s", 2363 dst->srv_conf.name); 2364 serverconfig_free(&dst->srv_conf); 2365 free(dst); 2366 return NULL; 2367 } 2368 2369 if (server_tls_load_ocsp(dst) == -1) { 2370 yyerror("failed to load ocsp staple " 2371 "for server %s", dst->srv_conf.name); 2372 serverconfig_free(&dst->srv_conf); 2373 free(dst); 2374 return (NULL); 2375 } 2376 2377 /* Check if the new server already exists */ 2378 if (server_match(dst, 1) != NULL) { 2379 yyerror("server \"%s\" defined twice", 2380 dst->srv_conf.name); 2381 serverconfig_free(&dst->srv_conf); 2382 free(dst); 2383 return (NULL); 2384 } 2385 2386 /* Copy all the locations of the source server */ 2387 TAILQ_FOREACH(s, conf->sc_servers, srv_entry) { 2388 if (!(s->srv_conf.flags & SRVFLAG_LOCATION && 2389 s->srv_conf.parent_id == src->srv_conf.parent_id)) 2390 continue; 2391 2392 if ((dstl = calloc(1, sizeof(*dstl))) == NULL) 2393 fatal("out of memory"); 2394 2395 memcpy(&dstl->srv_conf, &s->srv_conf, sizeof(dstl->srv_conf)); 2396 strlcpy(dstl->srv_conf.name, alias->name, 2397 sizeof(dstl->srv_conf.name)); 2398 2399 /* Copy the new Id and listen address */ 2400 dstl->srv_conf.id = ++last_server_id; 2401 dstl->srv_conf.parent_id = dst->srv_conf.id; 2402 memcpy(&dstl->srv_conf.ss, &addr->ss, 2403 sizeof(dstl->srv_conf.ss)); 2404 dstl->srv_conf.port = addr->port; 2405 dstl->srv_conf.prefixlen = addr->prefixlen; 2406 dstl->srv_s = -1; 2407 2408 DPRINTF("adding location \"%s\" for \"%s[%u]\"", 2409 dstl->srv_conf.location, 2410 dstl->srv_conf.name, dstl->srv_conf.id); 2411 2412 TAILQ_INSERT_TAIL(conf->sc_servers, dstl, srv_entry); 2413 } 2414 2415 return (dst); 2416} 2417 2418int 2419listen_on(const char *addr, int tls, struct portrange *port) 2420{ 2421 struct addresslist al; 2422 struct address *h; 2423 struct server_config *s_conf, *alias = NULL; 2424 2425 if (parentsrv != NULL) { 2426 yyerror("listen %s inside location", addr); 2427 return (-1); 2428 } 2429 2430 TAILQ_INIT(&al); 2431 if (strcmp("*", addr) == 0) { 2432 if (host("0.0.0.0", &al, 1, port, NULL, -1) <= 0) { 2433 yyerror("invalid listen ip: %s", 2434 "0.0.0.0"); 2435 return (-1); 2436 } 2437 if (host("::", &al, 1, port, NULL, -1) <= 0) { 2438 yyerror("invalid listen ip: %s", "::"); 2439 return (-1); 2440 } 2441 } else { 2442 if (host(addr, &al, HTTPD_MAX_ALIAS_IP, port, NULL, 2443 -1) <= 0) { 2444 yyerror("invalid listen ip: %s", addr); 2445 return (-1); 2446 } 2447 } 2448 2449 while ((h = TAILQ_FIRST(&al)) != NULL) { 2450 if (srv->srv_conf.ss.ss_family != AF_UNSPEC) { 2451 if ((alias = calloc(1, 2452 sizeof(*alias))) == NULL) 2453 fatal("out of memory"); 2454 /* Add as an IP-based alias. */ 2455 s_conf = alias; 2456 } else 2457 s_conf = &srv->srv_conf; 2458 memcpy(&s_conf->ss, &h->ss, sizeof(s_conf->ss)); 2459 s_conf->prefixlen = h->prefixlen; 2460 /* Set the default port to 80 or 443 */ 2461 if (!h->port.op) 2462 s_conf->port = htons(tls ? 2463 HTTPS_PORT : HTTP_PORT); 2464 else 2465 s_conf->port = h->port.val[0]; 2466 2467 if (tls) 2468 s_conf->flags |= SRVFLAG_TLS; 2469 2470 if (alias != NULL) { 2471 /* 2472 * IP-based; use name match flags from 2473 * parent 2474 */ 2475 alias->flags &= ~SRVFLAG_SERVER_MATCH; 2476 alias->flags |= srv->srv_conf.flags & 2477 SRVFLAG_SERVER_MATCH; 2478 TAILQ_INSERT_TAIL(&srv->srv_hosts, 2479 alias, entry); 2480 } 2481 TAILQ_REMOVE(&al, h, entry); 2482 free(h); 2483 } 2484 2485 return (0); 2486} 2487 2488int 2489getservice(char *n) 2490{ 2491 struct servent *s; 2492 const char *errstr; 2493 long long llval; 2494 2495 llval = strtonum(n, 0, UINT16_MAX, &errstr); 2496 if (errstr) { 2497 s = getservbyname(n, "tcp"); 2498 if (s == NULL) 2499 s = getservbyname(n, "udp"); 2500 if (s == NULL) 2501 return (-1); 2502 return (s->s_port); 2503 } 2504 2505 return (htons((unsigned short)llval)); 2506} 2507 2508int 2509is_if_in_group(const char *ifname, const char *groupname) 2510{ 2511 unsigned int len; 2512 struct ifgroupreq ifgr; 2513 struct ifg_req *ifg; 2514 int s; 2515 int ret = 0; 2516 2517 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 2518 err(1, "socket"); 2519 2520 memset(&ifgr, 0, sizeof(ifgr)); 2521 if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ) 2522 err(1, "IFNAMSIZ"); 2523 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 2524 if (errno == EINVAL || errno == ENOTTY) 2525 goto end; 2526 err(1, "SIOCGIFGROUP"); 2527 } 2528 2529 len = ifgr.ifgr_len; 2530 ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req), 2531 sizeof(struct ifg_req)); 2532 if (ifgr.ifgr_groups == NULL) 2533 err(1, "getifgroups"); 2534 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 2535 err(1, "SIOCGIFGROUP"); 2536 2537 ifg = ifgr.ifgr_groups; 2538 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 2539 len -= sizeof(struct ifg_req); 2540 if (strcmp(ifg->ifgrq_group, groupname) == 0) { 2541 ret = 1; 2542 break; 2543 } 2544 } 2545 free(ifgr.ifgr_groups); 2546 2547end: 2548 close(s); 2549 return (ret); 2550} 2551 2552int 2553get_fastcgi_dest(struct server_config *xsrv_conf, const char *node, char *port) 2554{ 2555 struct addrinfo hints, *res; 2556 int s; 2557 2558 memset(&hints, 0, sizeof(hints)); 2559 hints.ai_family = AF_UNSPEC; 2560 hints.ai_socktype = SOCK_STREAM; 2561 2562 if ((s = getaddrinfo(node, port, &hints, &res)) != 0) { 2563 yyerror("getaddrinfo: %s\n", gai_strerror(s)); 2564 return -1; 2565 } 2566 2567 memset(&(xsrv_conf)->fastcgi_ss, 0, sizeof(xsrv_conf->fastcgi_ss)); 2568 memcpy(&(xsrv_conf)->fastcgi_ss, res->ai_addr, res->ai_addrlen); 2569 2570 freeaddrinfo(res); 2571 2572 return (0); 2573} 2574 2575void 2576remove_locations(struct server_config *xsrv_conf) 2577{ 2578 struct server *s, *next; 2579 2580 TAILQ_FOREACH_SAFE(s, conf->sc_servers, srv_entry, next) { 2581 if (!(s->srv_conf.flags & SRVFLAG_LOCATION && 2582 s->srv_conf.parent_id == xsrv_conf->parent_id)) 2583 continue; 2584 TAILQ_REMOVE(conf->sc_servers, s, srv_entry); 2585 serverconfig_free(&s->srv_conf); 2586 free(s); 2587 } 2588}