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