1 /* $OpenBSD: parse.y,v 1.190 2016/09/12 07:33:00 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * Copyright (c) 2001 Markus Friedl. All rights reserved. 8 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 9 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 10 * 11 * Permission to use, copy, modify, and distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24 %{ 25 #include <sys/types.h> 26 #include <sys/queue.h> 27 #include <sys/tree.h> 28 #include <sys/socket.h> 29 #include <sys/stat.h> 30 #include <sys/ioctl.h> 31 32 #include <net/if.h> 33 #include <netinet/in.h> 34 #include <arpa/inet.h> 35 36 #include <ctype.h> 37 #include <err.h> 38 #include <errno.h> 39 #include <event.h> 40 #include <ifaddrs.h> 41 #include <imsg.h> 42 #include <inttypes.h> 43 #include <limits.h> 44 #include <netdb.h> 45 #include <paths.h> 46 #include <pwd.h> 47 #include <resolv.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <syslog.h> 52 #include <unistd.h> 53 #include <util.h> 54 55 #include <openssl/ssl.h> 56 57 #include "smtpd.h" 58 #include "ssl.h" 59 #include "log.h" 60 61 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 62 static struct file { 63 TAILQ_ENTRY(file) entry; 64 FILE *stream; 65 char *name; 66 int lineno; 67 int errors; 68 } *file, *topfile; 69 struct file *pushfile(const char *, int); 70 int popfile(void); 71 int check_file_secrecy(int, const char *); 72 int yyparse(void); 73 int yylex(void); 74 int kw_cmp(const void *, const void *); 75 int lookup(char *); 76 int lgetc(int); 77 int lungetc(int); 78 int findeol(void); 79 int yyerror(const char *, ...) 80 __attribute__((__format__ (printf, 1, 2))) 81 __attribute__((__nonnull__ (1))); 82 83 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 84 struct sym { 85 TAILQ_ENTRY(sym) entry; 86 int used; 87 int persist; 88 char *nam; 89 char *val; 90 }; 91 int symset(const char *, const char *, int); 92 char *symget(const char *); 93 94 struct smtpd *conf = NULL; 95 static int errors = 0; 96 97 struct filter_conf *filter = NULL; 98 struct table *table = NULL; 99 struct rule *rule = NULL; 100 struct mta_limits *limits; 101 static struct pki *pki; 102 static struct ca *sca; 103 104 enum listen_options { 105 LO_FAMILY = 0x000001, 106 LO_PORT = 0x000002, 107 LO_SSL = 0x000004, 108 LO_FILTER = 0x000008, 109 LO_PKI = 0x000010, 110 LO_AUTH = 0x000020, 111 LO_TAG = 0x000040, 112 LO_HOSTNAME = 0x000080, 113 LO_HOSTNAMES = 0x000100, 114 LO_MASKSOURCE = 0x000200, 115 LO_NODSN = 0x000400, 116 LO_SENDERS = 0x000800, 117 LO_RECEIVEDAUTH = 0x001000, 118 LO_MASQUERADE = 0x002000, 119 LO_CA = 0x010000 120 }; 121 122 static struct listen_opts { 123 char *ifx; 124 int family; 125 in_port_t port; 126 uint16_t ssl; 127 char *filtername; 128 char *pki; 129 char *ca; 130 uint16_t auth; 131 struct table *authtable; 132 char *tag; 133 char *hostname; 134 struct table *hostnametable; 135 struct table *sendertable; 136 uint16_t flags; 137 138 uint32_t options; 139 } listen_opts; 140 141 static void create_sock_listener(struct listen_opts *); 142 static void create_if_listener(struct listen_opts *); 143 static void config_listener(struct listener *, struct listen_opts *); 144 static int host_v4(struct listen_opts *); 145 static int host_v6(struct listen_opts *); 146 static int host_dns(struct listen_opts *); 147 static int interface(struct listen_opts *); 148 149 void set_local(const char *); 150 void set_localaddrs(struct table *); 151 int delaytonum(char *); 152 int is_if_in_group(const char *, const char *); 153 154 static struct filter_conf *create_filter_proc(char *, char *); 155 static struct filter_conf *create_filter_chain(char *); 156 static int add_filter_arg(struct filter_conf *, char *); 157 158 static int config_lo_filter(struct listen_opts *, char *); 159 static int config_lo_mask_source(struct listen_opts *); 160 161 typedef struct { 162 union { 163 int64_t number; 164 struct table *table; 165 char *string; 166 struct host *host; 167 struct mailaddr *maddr; 168 } v; 169 int lineno; 170 } YYSTYPE; 171 172 %} 173 174 %token AS QUEUE COMPRESSION ENCRYPTION MAXMESSAGESIZE MAXMTADEFERRED LISTEN ON ANY PORT EXPIRE 175 %token TABLE SECURE SMTPS CERTIFICATE DOMAIN BOUNCEWARN LIMIT INET4 INET6 NODSN SESSION 176 %token RELAY BACKUP VIA DELIVER TO LMTP MAILDIR MBOX RCPTTO HOSTNAME HOSTNAMES 177 %token ACCEPT REJECT INCLUDE ERROR MDA FROM FOR SOURCE MTA PKI SCHEDULER 178 %token ARROW AUTH TLS LOCAL VIRTUAL TAG TAGGED ALIAS FILTER KEY CA DHE 179 %token AUTH_OPTIONAL TLS_REQUIRE USERBASE SENDER SENDERS MASK_SOURCE VERIFY FORWARDONLY RECIPIENT 180 %token CIPHERS RECEIVEDAUTH MASQUERADE SOCKET SUBADDRESSING_DELIM AUTHENTICATED 181 %token <v.string> STRING 182 %token <v.number> NUMBER 183 %type <v.table> table 184 %type <v.number> size negation 185 %type <v.table> tables tablenew tableref alias virtual userbase 186 %type <v.string> tagged 187 %% 188 189 grammar : /* empty */ 190 | grammar '\n' 191 | grammar include '\n' 192 | grammar varset '\n' 193 | grammar main '\n' 194 | grammar table '\n' 195 | grammar rule '\n' 196 | grammar error '\n' { file->errors++; } 197 ; 198 199 include : INCLUDE STRING { 200 struct file *nfile; 201 202 if ((nfile = pushfile($2, 0)) == NULL) { 203 yyerror("failed to include file %s", $2); 204 free($2); 205 YYERROR; 206 } 207 free($2); 208 209 file = nfile; 210 lungetc('\n'); 211 } 212 ; 213 214 varset : STRING '=' STRING { 215 char *s = $1; 216 while (*s++) { 217 if (isspace((unsigned char)*s)) { 218 yyerror("macro name cannot contain " 219 "whitespace"); 220 YYERROR; 221 } 222 } 223 if (symset($1, $3, 0) == -1) 224 fatal("cannot store variable"); 225 free($1); 226 free($3); 227 } 228 ; 229 230 comma : ',' 231 | nl 232 | /* empty */ 233 ; 234 235 optnl : '\n' optnl 236 | 237 ; 238 239 nl : '\n' optnl 240 ; 241 242 size : NUMBER { 243 if ($1 < 0) { 244 yyerror("invalid size: %" PRId64, $1); 245 YYERROR; 246 } 247 $$ = $1; 248 } 249 | STRING { 250 long long result; 251 252 if (scan_scaled($1, &result) == -1 || result < 0) { 253 yyerror("invalid size: %s", $1); 254 free($1); 255 YYERROR; 256 } 257 free($1); 258 $$ = result; 259 } 260 ; 261 262 tagged : TAGGED negation STRING { 263 if (strlcpy(rule->r_tag, $3, sizeof rule->r_tag) 264 >= sizeof rule->r_tag) { 265 yyerror("tag name too long: %s", $3); 266 free($3); 267 YYERROR; 268 } 269 free($3); 270 rule->r_nottag = $2; 271 } 272 ; 273 274 authenticated : AUTHENTICATED { 275 rule->r_wantauth = 1; 276 } 277 ; 278 279 bouncedelay : STRING { 280 time_t d; 281 int i; 282 283 d = delaytonum($1); 284 if (d < 0) { 285 yyerror("invalid bounce delay: %s", $1); 286 free($1); 287 YYERROR; 288 } 289 free($1); 290 for (i = 0; i < MAX_BOUNCE_WARN; i++) { 291 if (conf->sc_bounce_warn[i] != 0) 292 continue; 293 conf->sc_bounce_warn[i] = d; 294 break; 295 } 296 } 297 298 bouncedelays : bouncedelays ',' bouncedelay 299 | bouncedelay 300 | /* EMPTY */ 301 ; 302 303 opt_limit_mda : STRING NUMBER { 304 if (!strcmp($1, "max-session")) { 305 conf->sc_mda_max_session = $2; 306 } 307 else if (!strcmp($1, "max-session-per-user")) { 308 conf->sc_mda_max_user_session = $2; 309 } 310 else if (!strcmp($1, "task-lowat")) { 311 conf->sc_mda_task_lowat = $2; 312 } 313 else if (!strcmp($1, "task-hiwat")) { 314 conf->sc_mda_task_hiwat = $2; 315 } 316 else if (!strcmp($1, "task-release")) { 317 conf->sc_mda_task_release = $2; 318 } 319 else { 320 yyerror("invalid scheduler limit keyword: %s", $1); 321 free($1); 322 YYERROR; 323 } 324 free($1); 325 } 326 ; 327 328 limits_session : opt_limit_session limits_session 329 | /* empty */ 330 ; 331 332 opt_limit_session : STRING NUMBER { 333 if (!strcmp($1, "max-rcpt")) { 334 conf->sc_session_max_rcpt = $2; 335 } 336 else if (!strcmp($1, "max-mails")) { 337 conf->sc_session_max_mails = $2; 338 } 339 else { 340 yyerror("invalid session limit keyword: %s", $1); 341 free($1); 342 YYERROR; 343 } 344 free($1); 345 } 346 ; 347 348 limits_mda : opt_limit_mda limits_mda 349 | /* empty */ 350 ; 351 352 opt_limit_mta : INET4 { 353 limits->family = AF_INET; 354 } 355 | INET6 { 356 limits->family = AF_INET6; 357 } 358 | STRING NUMBER { 359 if (!limit_mta_set(limits, $1, $2)) { 360 yyerror("invalid mta limit keyword: %s", $1); 361 free($1); 362 YYERROR; 363 } 364 free($1); 365 } 366 ; 367 368 limits_mta : opt_limit_mta limits_mta 369 | /* empty */ 370 ; 371 372 opt_limit_scheduler : STRING NUMBER { 373 if (!strcmp($1, "max-inflight")) { 374 conf->sc_scheduler_max_inflight = $2; 375 } 376 else if (!strcmp($1, "max-evp-batch-size")) { 377 conf->sc_scheduler_max_evp_batch_size = $2; 378 } 379 else if (!strcmp($1, "max-msg-batch-size")) { 380 conf->sc_scheduler_max_msg_batch_size = $2; 381 } 382 else if (!strcmp($1, "max-schedule")) { 383 conf->sc_scheduler_max_schedule = $2; 384 } 385 else { 386 yyerror("invalid scheduler limit keyword: %s", $1); 387 free($1); 388 YYERROR; 389 } 390 free($1); 391 } 392 ; 393 394 limits_scheduler: opt_limit_scheduler limits_scheduler 395 | /* empty */ 396 ; 397 398 opt_ca : CERTIFICATE STRING { 399 sca->ca_cert_file = $2; 400 } 401 ; 402 403 ca : opt_ca 404 ; 405 406 opt_pki : CERTIFICATE STRING { 407 pki->pki_cert_file = $2; 408 } 409 | KEY STRING { 410 pki->pki_key_file = $2; 411 } 412 | DHE STRING { 413 if (strcasecmp($2, "none") == 0) 414 pki->pki_dhe = 0; 415 else if (strcasecmp($2, "auto") == 0) 416 pki->pki_dhe = 1; 417 else if (strcasecmp($2, "legacy") == 0) 418 pki->pki_dhe = 2; 419 else { 420 yyerror("invalid DHE keyword: %s", $2); 421 free($2); 422 YYERROR; 423 } 424 free($2); 425 } 426 ; 427 428 pki : opt_pki pki 429 | /* empty */ 430 ; 431 432 opt_sock_listen : FILTER STRING { 433 if (config_lo_filter(&listen_opts, $2)) { 434 YYERROR; 435 } 436 } 437 | MASK_SOURCE { 438 if (config_lo_mask_source(&listen_opts)) { 439 YYERROR; 440 } 441 } 442 ; 443 444 opt_if_listen : INET4 { 445 if (listen_opts.options & LO_FAMILY) { 446 yyerror("address family already specified"); 447 YYERROR; 448 } 449 listen_opts.options |= LO_FAMILY; 450 listen_opts.family = AF_INET; 451 } 452 | INET6 { 453 if (listen_opts.options & LO_FAMILY) { 454 yyerror("address family already specified"); 455 YYERROR; 456 } 457 listen_opts.options |= LO_FAMILY; 458 listen_opts.family = AF_INET6; 459 } 460 | PORT STRING { 461 struct servent *servent; 462 463 if (listen_opts.options & LO_PORT) { 464 yyerror("port already specified"); 465 YYERROR; 466 } 467 listen_opts.options |= LO_PORT; 468 469 servent = getservbyname($2, "tcp"); 470 if (servent == NULL) { 471 yyerror("invalid port: %s", $2); 472 free($2); 473 YYERROR; 474 } 475 free($2); 476 listen_opts.port = ntohs(servent->s_port); 477 } 478 | PORT NUMBER { 479 if (listen_opts.options & LO_PORT) { 480 yyerror("port already specified"); 481 YYERROR; 482 } 483 listen_opts.options |= LO_PORT; 484 485 if ($2 <= 0 || $2 >= (int)USHRT_MAX) { 486 yyerror("invalid port: %" PRId64, $2); 487 YYERROR; 488 } 489 listen_opts.port = $2; 490 } 491 | FILTER STRING { 492 if (config_lo_filter(&listen_opts, $2)) { 493 YYERROR; 494 } 495 } 496 | SMTPS { 497 if (listen_opts.options & LO_SSL) { 498 yyerror("TLS mode already specified"); 499 YYERROR; 500 } 501 listen_opts.options |= LO_SSL; 502 listen_opts.ssl = F_SMTPS; 503 } 504 | SMTPS VERIFY { 505 if (listen_opts.options & LO_SSL) { 506 yyerror("TLS mode already specified"); 507 YYERROR; 508 } 509 listen_opts.options |= LO_SSL; 510 listen_opts.ssl = F_SMTPS|F_TLS_VERIFY; 511 } 512 | TLS { 513 if (listen_opts.options & LO_SSL) { 514 yyerror("TLS mode already specified"); 515 YYERROR; 516 } 517 listen_opts.options |= LO_SSL; 518 listen_opts.ssl = F_STARTTLS; 519 } 520 | SECURE { 521 if (listen_opts.options & LO_SSL) { 522 yyerror("TLS mode already specified"); 523 YYERROR; 524 } 525 listen_opts.options |= LO_SSL; 526 listen_opts.ssl = F_SSL; 527 } 528 | TLS_REQUIRE { 529 if (listen_opts.options & LO_SSL) { 530 yyerror("TLS mode already specified"); 531 YYERROR; 532 } 533 listen_opts.options |= LO_SSL; 534 listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE; 535 } 536 | TLS_REQUIRE VERIFY { 537 if (listen_opts.options & LO_SSL) { 538 yyerror("TLS mode already specified"); 539 YYERROR; 540 } 541 listen_opts.options |= LO_SSL; 542 listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY; 543 } 544 | PKI STRING { 545 if (listen_opts.options & LO_PKI) { 546 yyerror("pki already specified"); 547 YYERROR; 548 } 549 listen_opts.options |= LO_PKI; 550 listen_opts.pki = $2; 551 } 552 | CA STRING { 553 if (listen_opts.options & LO_CA) { 554 yyerror("ca already specified"); 555 YYERROR; 556 } 557 listen_opts.options |= LO_CA; 558 listen_opts.ca = $2; 559 } 560 | AUTH { 561 if (listen_opts.options & LO_AUTH) { 562 yyerror("auth already specified"); 563 YYERROR; 564 } 565 listen_opts.options |= LO_AUTH; 566 listen_opts.auth = F_AUTH|F_AUTH_REQUIRE; 567 } 568 | AUTH_OPTIONAL { 569 if (listen_opts.options & LO_AUTH) { 570 yyerror("auth already specified"); 571 YYERROR; 572 } 573 listen_opts.options |= LO_AUTH; 574 listen_opts.auth = F_AUTH; 575 } 576 | AUTH tables { 577 if (listen_opts.options & LO_AUTH) { 578 yyerror("auth already specified"); 579 YYERROR; 580 } 581 listen_opts.options |= LO_AUTH; 582 listen_opts.authtable = $2; 583 listen_opts.auth = F_AUTH|F_AUTH_REQUIRE; 584 } 585 | AUTH_OPTIONAL tables { 586 if (listen_opts.options & LO_AUTH) { 587 yyerror("auth already specified"); 588 YYERROR; 589 } 590 listen_opts.options |= LO_AUTH; 591 listen_opts.authtable = $2; 592 listen_opts.auth = F_AUTH; 593 } 594 | TAG STRING { 595 if (listen_opts.options & LO_TAG) { 596 yyerror("tag already specified"); 597 YYERROR; 598 } 599 listen_opts.options |= LO_TAG; 600 601 if (strlen($2) >= SMTPD_TAG_SIZE) { 602 yyerror("tag name too long"); 603 free($2); 604 YYERROR; 605 } 606 listen_opts.tag = $2; 607 } 608 | HOSTNAME STRING { 609 if (listen_opts.options & LO_HOSTNAME) { 610 yyerror("hostname already specified"); 611 YYERROR; 612 } 613 listen_opts.options |= LO_HOSTNAME; 614 615 listen_opts.hostname = $2; 616 } 617 | HOSTNAMES tables { 618 struct table *t = $2; 619 620 if (listen_opts.options & LO_HOSTNAMES) { 621 yyerror("hostnames already specified"); 622 YYERROR; 623 } 624 listen_opts.options |= LO_HOSTNAMES; 625 626 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) { 627 yyerror("invalid use of table \"%s\" as " 628 "HOSTNAMES parameter", t->t_name); 629 YYERROR; 630 } 631 listen_opts.hostnametable = t; 632 } 633 | MASK_SOURCE { 634 if (config_lo_mask_source(&listen_opts)) { 635 YYERROR; 636 } 637 } 638 | RECEIVEDAUTH { 639 if (listen_opts.options & LO_RECEIVEDAUTH) { 640 yyerror("received-auth already specified"); 641 YYERROR; 642 } 643 listen_opts.options |= LO_RECEIVEDAUTH; 644 listen_opts.flags |= F_RECEIVEDAUTH; 645 } 646 | NODSN { 647 if (listen_opts.options & LO_NODSN) { 648 yyerror("no-dsn already specified"); 649 YYERROR; 650 } 651 listen_opts.options |= LO_NODSN; 652 listen_opts.flags &= ~F_EXT_DSN; 653 } 654 | SENDERS tables { 655 struct table *t = $2; 656 657 if (listen_opts.options & LO_SENDERS) { 658 yyerror("senders already specified"); 659 YYERROR; 660 } 661 listen_opts.options |= LO_SENDERS; 662 663 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) { 664 yyerror("invalid use of table \"%s\" as " 665 "SENDERS parameter", t->t_name); 666 YYERROR; 667 } 668 listen_opts.sendertable = t; 669 } 670 | SENDERS tables MASQUERADE { 671 struct table *t = $2; 672 673 if (listen_opts.options & LO_SENDERS) { 674 yyerror("senders already specified"); 675 YYERROR; 676 } 677 listen_opts.options |= LO_SENDERS|LO_MASQUERADE; 678 679 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) { 680 yyerror("invalid use of table \"%s\" as " 681 "SENDERS parameter", t->t_name); 682 YYERROR; 683 } 684 listen_opts.sendertable = t; 685 } 686 ; 687 688 listener_type : socket_listener 689 | if_listener 690 ; 691 692 socket_listener : SOCKET sock_listen { 693 if (conf->sc_sock_listener) { 694 yyerror("socket listener already configured"); 695 YYERROR; 696 } 697 create_sock_listener(&listen_opts); 698 } 699 ; 700 701 if_listener : STRING if_listen { 702 listen_opts.ifx = $1; 703 create_if_listener(&listen_opts); 704 } 705 ; 706 707 sock_listen : opt_sock_listen sock_listen 708 | /* empty */ 709 ; 710 711 if_listen : opt_if_listen if_listen 712 | /* empty */ 713 ; 714 715 opt_relay_common: AS STRING { 716 struct mailaddr maddr, *maddrp; 717 718 if (!text_to_mailaddr(&maddr, $2)) { 719 yyerror("invalid parameter to AS: %s", $2); 720 free($2); 721 YYERROR; 722 } 723 free($2); 724 725 if (maddr.user[0] == '\0' && maddr.domain[0] == '\0') { 726 yyerror("invalid empty parameter to AS"); 727 YYERROR; 728 } 729 else if (maddr.domain[0] == '\0') { 730 if (strlcpy(maddr.domain, conf->sc_hostname, 731 sizeof (maddr.domain)) 732 >= sizeof (maddr.domain)) { 733 yyerror("hostname too long for AS parameter: %s", 734 conf->sc_hostname); 735 YYERROR; 736 } 737 } 738 rule->r_as = xmemdup(&maddr, sizeof (*maddrp), "parse relay_as: AS"); 739 } 740 | SOURCE tables { 741 struct table *t = $2; 742 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_SOURCE)) { 743 yyerror("invalid use of table \"%s\" as " 744 "SOURCE parameter", t->t_name); 745 YYERROR; 746 } 747 (void)strlcpy(rule->r_value.relayhost.sourcetable, t->t_name, 748 sizeof rule->r_value.relayhost.sourcetable); 749 } 750 | HOSTNAME STRING { 751 (void)strlcpy(rule->r_value.relayhost.heloname, $2, 752 sizeof rule->r_value.relayhost.heloname); 753 free($2); 754 } 755 | HOSTNAMES tables { 756 struct table *t = $2; 757 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) { 758 yyerror("invalid use of table \"%s\" as " 759 "HOSTNAMES parameter", t->t_name); 760 YYERROR; 761 } 762 (void)strlcpy(rule->r_value.relayhost.helotable, t->t_name, 763 sizeof rule->r_value.relayhost.helotable); 764 } 765 | PKI STRING { 766 if (!lowercase(rule->r_value.relayhost.pki_name, $2, 767 sizeof(rule->r_value.relayhost.pki_name))) { 768 yyerror("pki name too long: %s", $2); 769 free($2); 770 YYERROR; 771 } 772 if (dict_get(conf->sc_pki_dict, 773 rule->r_value.relayhost.pki_name) == NULL) { 774 log_warnx("pki name not found: %s", $2); 775 free($2); 776 YYERROR; 777 } 778 free($2); 779 } 780 | CA STRING { 781 if (!lowercase(rule->r_value.relayhost.ca_name, $2, 782 sizeof(rule->r_value.relayhost.ca_name))) { 783 yyerror("ca name too long: %s", $2); 784 free($2); 785 YYERROR; 786 } 787 if (dict_get(conf->sc_ca_dict, 788 rule->r_value.relayhost.ca_name) == NULL) { 789 log_warnx("ca name not found: %s", $2); 790 free($2); 791 YYERROR; 792 } 793 free($2); 794 } 795 ; 796 797 opt_relay : BACKUP STRING { 798 rule->r_value.relayhost.flags |= F_BACKUP; 799 if (strlcpy(rule->r_value.relayhost.hostname, $2, 800 sizeof (rule->r_value.relayhost.hostname)) 801 >= sizeof (rule->r_value.relayhost.hostname)) { 802 log_warnx("hostname too long: %s", $2); 803 free($2); 804 YYERROR; 805 } 806 free($2); 807 } 808 | BACKUP { 809 rule->r_value.relayhost.flags |= F_BACKUP; 810 (void)strlcpy(rule->r_value.relayhost.hostname, 811 conf->sc_hostname, 812 sizeof (rule->r_value.relayhost.hostname)); 813 } 814 | TLS { 815 rule->r_value.relayhost.flags |= F_STARTTLS; 816 } 817 | TLS VERIFY { 818 rule->r_value.relayhost.flags |= F_STARTTLS|F_TLS_VERIFY; 819 } 820 ; 821 822 relay : opt_relay_common relay 823 | opt_relay relay 824 | /* empty */ 825 ; 826 827 opt_relay_via : AUTH tables { 828 struct table *t = $2; 829 830 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_CREDENTIALS)) { 831 yyerror("invalid use of table \"%s\" as AUTH parameter", 832 t->t_name); 833 YYERROR; 834 } 835 (void)strlcpy(rule->r_value.relayhost.authtable, t->t_name, 836 sizeof(rule->r_value.relayhost.authtable)); 837 } 838 | VERIFY { 839 if (!(rule->r_value.relayhost.flags & F_SSL)) { 840 yyerror("cannot \"verify\" with insecure protocol"); 841 YYERROR; 842 } 843 rule->r_value.relayhost.flags |= F_TLS_VERIFY; 844 } 845 ; 846 847 relay_via : opt_relay_common relay_via 848 | opt_relay_via relay_via 849 | /* empty */ 850 ; 851 852 main : BOUNCEWARN { 853 memset(conf->sc_bounce_warn, 0, sizeof conf->sc_bounce_warn); 854 } bouncedelays 855 | SUBADDRESSING_DELIM STRING { 856 if (strlen($2) != 1) { 857 yyerror("subaddressing-delimiter must be one character"); 858 free($2); 859 YYERROR; 860 } 861 862 if (isspace((int)*$2) || !isprint((int)*$2) || *$2== '@') { 863 yyerror("subaddressing-delimiter uses invalid character"); 864 free($2); 865 YYERROR; 866 } 867 868 conf->sc_subaddressing_delim = $2; 869 } 870 | QUEUE COMPRESSION { 871 conf->sc_queue_flags |= QUEUE_COMPRESSION; 872 } 873 | QUEUE ENCRYPTION { 874 conf->sc_queue_flags |= QUEUE_ENCRYPTION; 875 } 876 | QUEUE ENCRYPTION KEY STRING { 877 if (strcasecmp($4, "stdin") == 0 || strcasecmp($4, "-") == 0) { 878 conf->sc_queue_key = "stdin"; 879 free($4); 880 } 881 else 882 conf->sc_queue_key = $4; 883 conf->sc_queue_flags |= QUEUE_ENCRYPTION; 884 } 885 | EXPIRE STRING { 886 conf->sc_qexpire = delaytonum($2); 887 if (conf->sc_qexpire == -1) { 888 yyerror("invalid expire delay: %s", $2); 889 free($2); 890 YYERROR; 891 } 892 free($2); 893 } 894 | MAXMESSAGESIZE size { 895 conf->sc_maxsize = $2; 896 } 897 | MAXMTADEFERRED NUMBER { 898 conf->sc_mta_max_deferred = $2; 899 } 900 | LIMIT SESSION limits_session 901 | LIMIT MDA limits_mda 902 | LIMIT MTA FOR DOMAIN STRING { 903 struct mta_limits *d; 904 905 limits = dict_get(conf->sc_limits_dict, $5); 906 if (limits == NULL) { 907 limits = xcalloc(1, sizeof(*limits), "mta_limits"); 908 dict_xset(conf->sc_limits_dict, $5, limits); 909 d = dict_xget(conf->sc_limits_dict, "default"); 910 memmove(limits, d, sizeof(*limits)); 911 } 912 free($5); 913 } limits_mta 914 | LIMIT MTA { 915 limits = dict_get(conf->sc_limits_dict, "default"); 916 } limits_mta 917 | LIMIT SCHEDULER limits_scheduler 918 | LISTEN { 919 memset(&listen_opts, 0, sizeof listen_opts); 920 listen_opts.family = AF_UNSPEC; 921 listen_opts.flags |= F_EXT_DSN; 922 } ON listener_type 923 | FILTER STRING STRING { 924 if (!strcmp($3, "chain")) { 925 free($3); 926 if ((filter = create_filter_chain($2)) == NULL) { 927 free($2); 928 YYERROR; 929 } 930 } 931 else { 932 if ((filter = create_filter_proc($2, $3)) == NULL) { 933 free($2); 934 free($3); 935 YYERROR; 936 } 937 } 938 } filter_args 939 | PKI STRING { 940 char buf[HOST_NAME_MAX+1]; 941 942 /* if not catchall, check that it is a valid domain */ 943 if (strcmp($2, "*") != 0) { 944 if (!res_hnok($2)) { 945 yyerror("not a valid domain name: %s", $2); 946 free($2); 947 YYERROR; 948 } 949 } 950 xlowercase(buf, $2, sizeof(buf)); 951 free($2); 952 pki = dict_get(conf->sc_pki_dict, buf); 953 if (pki == NULL) { 954 pki = xcalloc(1, sizeof *pki, "parse:pki"); 955 (void)strlcpy(pki->pki_name, buf, sizeof(pki->pki_name)); 956 dict_set(conf->sc_pki_dict, pki->pki_name, pki); 957 } 958 } pki 959 | CA STRING { 960 char buf[HOST_NAME_MAX+1]; 961 962 /* if not catchall, check that it is a valid domain */ 963 if (strcmp($2, "*") != 0) { 964 if (!res_hnok($2)) { 965 yyerror("not a valid domain name: %s", $2); 966 free($2); 967 YYERROR; 968 } 969 } 970 xlowercase(buf, $2, sizeof(buf)); 971 free($2); 972 sca = dict_get(conf->sc_ca_dict, buf); 973 if (sca == NULL) { 974 sca = xcalloc(1, sizeof *sca, "parse:ca"); 975 (void)strlcpy(sca->ca_name, buf, sizeof(sca->ca_name)); 976 dict_set(conf->sc_ca_dict, sca->ca_name, sca); 977 } 978 } ca 979 | CIPHERS STRING { 980 conf->sc_tls_ciphers = $2; 981 } 982 ; 983 984 filter_args : 985 | STRING { 986 if (!add_filter_arg(filter, $1)) { 987 free($1); 988 YYERROR; 989 } 990 } filter_args 991 ; 992 993 table : TABLE STRING STRING { 994 char *p, *backend, *config; 995 996 p = $3; 997 if (*p == '/') { 998 backend = "static"; 999 config = $3; 1000 } 1001 else { 1002 backend = $3; 1003 config = NULL; 1004 for (p = $3; *p && *p != ':'; p++) 1005 ; 1006 if (*p == ':') { 1007 *p = '\0'; 1008 backend = $3; 1009 config = p+1; 1010 } 1011 } 1012 if (config != NULL && *config != '/') { 1013 yyerror("invalid backend parameter for table: %s", 1014 $2); 1015 free($2); 1016 free($3); 1017 YYERROR; 1018 } 1019 table = table_create(backend, $2, NULL, config); 1020 if (!table_config(table)) { 1021 yyerror("invalid configuration file %s for table %s", 1022 config, table->t_name); 1023 free($2); 1024 free($3); 1025 YYERROR; 1026 } 1027 free($2); 1028 free($3); 1029 } 1030 | TABLE STRING { 1031 table = table_create("static", $2, NULL, NULL); 1032 free($2); 1033 } '{' tableval_list '}' { 1034 table = NULL; 1035 } 1036 ; 1037 1038 assign : '=' | ARROW; 1039 1040 keyval : STRING assign STRING { 1041 table->t_type = T_HASH; 1042 table_add(table, $1, $3); 1043 free($1); 1044 free($3); 1045 } 1046 ; 1047 1048 keyval_list : keyval 1049 | keyval comma keyval_list 1050 ; 1051 1052 stringel : STRING { 1053 table->t_type = T_LIST; 1054 table_add(table, $1, NULL); 1055 free($1); 1056 } 1057 ; 1058 1059 string_list : stringel 1060 | stringel comma string_list 1061 ; 1062 1063 tableval_list : string_list { } 1064 | keyval_list { } 1065 ; 1066 1067 tablenew : STRING { 1068 struct table *t; 1069 1070 t = table_create("static", NULL, NULL, NULL); 1071 t->t_type = T_LIST; 1072 table_add(t, $1, NULL); 1073 free($1); 1074 $$ = t; 1075 } 1076 | '{' { 1077 table = table_create("static", NULL, NULL, NULL); 1078 } tableval_list '}' { 1079 $$ = table; 1080 } 1081 ; 1082 1083 tableref : '<' STRING '>' { 1084 struct table *t; 1085 1086 if ((t = table_find($2, NULL)) == NULL) { 1087 yyerror("no such table: %s", $2); 1088 free($2); 1089 YYERROR; 1090 } 1091 free($2); 1092 $$ = t; 1093 } 1094 ; 1095 1096 tables : tablenew { $$ = $1; } 1097 | tableref { $$ = $1; } 1098 ; 1099 1100 alias : ALIAS tables { 1101 struct table *t = $2; 1102 1103 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) { 1104 yyerror("invalid use of table \"%s\" as ALIAS parameter", 1105 t->t_name); 1106 YYERROR; 1107 } 1108 1109 $$ = t; 1110 } 1111 ; 1112 1113 virtual : VIRTUAL tables { 1114 struct table *t = $2; 1115 1116 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) { 1117 yyerror("invalid use of table \"%s\" as VIRTUAL parameter", 1118 t->t_name); 1119 YYERROR; 1120 } 1121 $$ = t; 1122 } 1123 ; 1124 1125 usermapping : alias { 1126 if (rule->r_mapping) { 1127 yyerror("alias specified multiple times"); 1128 YYERROR; 1129 } 1130 rule->r_desttype = DEST_DOM; 1131 rule->r_mapping = $1; 1132 } 1133 | virtual { 1134 if (rule->r_mapping) { 1135 yyerror("virtual specified multiple times"); 1136 YYERROR; 1137 } 1138 rule->r_desttype = DEST_VDOM; 1139 rule->r_mapping = $1; 1140 } 1141 ; 1142 1143 userbase : USERBASE tables { 1144 struct table *t = $2; 1145 1146 if (rule->r_userbase) { 1147 yyerror("userbase specified multiple times"); 1148 YYERROR; 1149 } 1150 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_USERINFO)) { 1151 yyerror("invalid use of table \"%s\" as USERBASE parameter", 1152 t->t_name); 1153 YYERROR; 1154 } 1155 rule->r_userbase = t; 1156 } 1157 ; 1158 1159 deliver_as : AS STRING { 1160 if (strlcpy(rule->r_delivery_user, $2, 1161 sizeof(rule->r_delivery_user)) 1162 >= sizeof(rule->r_delivery_user)) 1163 fatal("username too long"); 1164 free($2); 1165 } 1166 | /* empty */ {} 1167 ; 1168 1169 deliver_action : DELIVER TO MAILDIR { 1170 rule->r_action = A_MAILDIR; 1171 if (strlcpy(rule->r_value.buffer, "~/Maildir", 1172 sizeof(rule->r_value.buffer)) >= 1173 sizeof(rule->r_value.buffer)) 1174 fatal("pathname too long"); 1175 } 1176 | DELIVER TO MAILDIR STRING { 1177 rule->r_action = A_MAILDIR; 1178 if (strlcpy(rule->r_value.buffer, $4, 1179 sizeof(rule->r_value.buffer)) >= 1180 sizeof(rule->r_value.buffer)) 1181 fatal("pathname too long"); 1182 free($4); 1183 } 1184 | DELIVER TO MBOX { 1185 rule->r_action = A_MBOX; 1186 if (strlcpy(rule->r_value.buffer, _PATH_MAILDIR "/%u", 1187 sizeof(rule->r_value.buffer)) 1188 >= sizeof(rule->r_value.buffer)) 1189 fatal("pathname too long"); 1190 } 1191 | DELIVER TO LMTP STRING deliver_as { 1192 rule->r_action = A_LMTP; 1193 if (strchr($4, ':') || $4[0] == '/') { 1194 if (strlcpy(rule->r_value.buffer, $4, 1195 sizeof(rule->r_value.buffer)) 1196 >= sizeof(rule->r_value.buffer)) 1197 fatal("lmtp destination too long"); 1198 } else 1199 fatal("invalid lmtp destination"); 1200 free($4); 1201 } 1202 | DELIVER TO LMTP STRING RCPTTO deliver_as { 1203 rule->r_action = A_LMTP; 1204 if (strchr($4, ':') || $4[0] == '/') { 1205 if (strlcpy(rule->r_value.buffer, $4, 1206 sizeof(rule->r_value.buffer)) 1207 >= sizeof(rule->r_value.buffer)) 1208 fatal("lmtp destination too long"); 1209 if (strlcat(rule->r_value.buffer, " rcpt-to", 1210 sizeof(rule->r_value.buffer)) 1211 >= sizeof(rule->r_value.buffer)) 1212 fatal("lmtp recipient too long"); 1213 } else 1214 fatal("invalid lmtp destination"); 1215 free($4); 1216 } 1217 | DELIVER TO MDA STRING deliver_as { 1218 rule->r_action = A_MDA; 1219 if (strlcpy(rule->r_value.buffer, $4, 1220 sizeof(rule->r_value.buffer)) 1221 >= sizeof(rule->r_value.buffer)) 1222 fatal("command too long"); 1223 free($4); 1224 } 1225 ; 1226 1227 relay_action : RELAY relay { 1228 rule->r_action = A_RELAY; 1229 } 1230 | RELAY VIA STRING { 1231 rule->r_action = A_RELAYVIA; 1232 if (!text_to_relayhost(&rule->r_value.relayhost, $3)) { 1233 yyerror("error: invalid url: %s", $3); 1234 free($3); 1235 YYERROR; 1236 } 1237 free($3); 1238 } relay_via { 1239 /* no worries, F_AUTH cant be set without SSL */ 1240 if (rule->r_value.relayhost.flags & F_AUTH) { 1241 if (rule->r_value.relayhost.authtable[0] == '\0') { 1242 yyerror("error: auth without auth table"); 1243 YYERROR; 1244 } 1245 } 1246 } 1247 ; 1248 1249 negation : '!' { $$ = 1; } 1250 | /* empty */ { $$ = 0; } 1251 ; 1252 1253 from : FROM negation SOURCE tables { 1254 struct table *t = $4; 1255 1256 if (rule->r_sources) { 1257 yyerror("from specified multiple times"); 1258 YYERROR; 1259 } 1260 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_NETADDR)) { 1261 yyerror("invalid use of table \"%s\" as FROM parameter", 1262 t->t_name); 1263 YYERROR; 1264 } 1265 rule->r_notsources = $2; 1266 rule->r_sources = t; 1267 } 1268 | FROM negation ANY { 1269 if (rule->r_sources) { 1270 yyerror("from specified multiple times"); 1271 YYERROR; 1272 } 1273 rule->r_sources = table_find("<anyhost>", NULL); 1274 rule->r_notsources = $2; 1275 } 1276 | FROM negation LOCAL { 1277 if (rule->r_sources) { 1278 yyerror("from specified multiple times"); 1279 YYERROR; 1280 } 1281 rule->r_sources = table_find("<localhost>", NULL); 1282 rule->r_notsources = $2; 1283 } 1284 ; 1285 1286 for : FOR negation DOMAIN tables { 1287 struct table *t = $4; 1288 1289 if (rule->r_destination) { 1290 yyerror("for specified multiple times"); 1291 YYERROR; 1292 } 1293 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) { 1294 yyerror("invalid use of table \"%s\" as DOMAIN parameter", 1295 t->t_name); 1296 YYERROR; 1297 } 1298 rule->r_notdestination = $2; 1299 rule->r_destination = t; 1300 } 1301 | FOR negation ANY { 1302 if (rule->r_destination) { 1303 yyerror("for specified multiple times"); 1304 YYERROR; 1305 } 1306 rule->r_notdestination = $2; 1307 rule->r_destination = table_find("<anydestination>", NULL); 1308 } 1309 | FOR negation LOCAL { 1310 if (rule->r_destination) { 1311 yyerror("for specified multiple times"); 1312 YYERROR; 1313 } 1314 rule->r_notdestination = $2; 1315 rule->r_destination = table_find("<localnames>", NULL); 1316 } 1317 ; 1318 1319 sender : SENDER negation tables { 1320 struct table *t = $3; 1321 1322 if (rule->r_senders) { 1323 yyerror("sender specified multiple times"); 1324 YYERROR; 1325 } 1326 1327 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 1328 yyerror("invalid use of table \"%s\" as SENDER parameter", 1329 t->t_name); 1330 YYERROR; 1331 } 1332 rule->r_notsenders = $2; 1333 rule->r_senders = t; 1334 } 1335 ; 1336 1337 recipient : RECIPIENT negation tables { 1338 struct table *t = $3; 1339 1340 if (rule->r_recipients) { 1341 yyerror("recipient specified multiple times"); 1342 YYERROR; 1343 } 1344 1345 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 1346 yyerror("invalid use of table \"%s\" as RECIPIENT parameter", 1347 t->t_name); 1348 YYERROR; 1349 } 1350 rule->r_notrecipients = $2; 1351 rule->r_recipients = t; 1352 } 1353 ; 1354 1355 forwardonly : FORWARDONLY { 1356 if (rule->r_forwardonly) { 1357 yyerror("forward-only specified multiple times"); 1358 YYERROR; 1359 } 1360 rule->r_forwardonly = 1; 1361 } 1362 ; 1363 1364 expire : EXPIRE STRING { 1365 if (rule->r_qexpire != -1) { 1366 yyerror("expire specified multiple times"); 1367 YYERROR; 1368 } 1369 rule->r_qexpire = delaytonum($2); 1370 if (rule->r_qexpire == -1) { 1371 yyerror("invalid expire delay: %s", $2); 1372 free($2); 1373 YYERROR; 1374 } 1375 free($2); 1376 } 1377 ; 1378 1379 opt_decision : sender 1380 | recipient 1381 | from 1382 | for 1383 | tagged 1384 | authenticated 1385 ; 1386 decision : opt_decision decision 1387 | 1388 ; 1389 1390 opt_lookup : userbase 1391 | usermapping 1392 ; 1393 lookup : opt_lookup lookup 1394 | 1395 ; 1396 1397 action : deliver_action 1398 | relay_action 1399 | 1400 ; 1401 1402 opt_accept : expire 1403 | forwardonly 1404 ; 1405 1406 accept_params : opt_accept accept_params 1407 | 1408 ; 1409 1410 rule : ACCEPT { 1411 rule = xcalloc(1, sizeof(*rule), "parse rule: ACCEPT"); 1412 rule->r_action = A_NONE; 1413 rule->r_decision = R_ACCEPT; 1414 rule->r_desttype = DEST_DOM; 1415 rule->r_qexpire = -1; 1416 } decision lookup action accept_params { 1417 if (!rule->r_sources) 1418 rule->r_sources = table_find("<localhost>", NULL); 1419 if (!rule->r_destination) 1420 rule->r_destination = table_find("<localnames>", NULL); 1421 if (!rule->r_userbase) 1422 rule->r_userbase = table_find("<getpwnam>", NULL); 1423 if (rule->r_qexpire == -1) 1424 rule->r_qexpire = conf->sc_qexpire; 1425 if (rule->r_action == A_RELAY || rule->r_action == A_RELAYVIA) { 1426 if (rule->r_userbase != table_find("<getpwnam>", NULL)) { 1427 yyerror("userbase may not be used with a relay rule"); 1428 YYERROR; 1429 } 1430 if (rule->r_mapping) { 1431 yyerror("aliases/virtual may not be used with a relay rule"); 1432 YYERROR; 1433 } 1434 } 1435 if (rule->r_forwardonly && rule->r_action != A_NONE) { 1436 yyerror("forward-only may not be used with a default action"); 1437 YYERROR; 1438 } 1439 TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry); 1440 rule = NULL; 1441 } 1442 | REJECT { 1443 rule = xcalloc(1, sizeof(*rule), "parse rule: REJECT"); 1444 rule->r_decision = R_REJECT; 1445 rule->r_desttype = DEST_DOM; 1446 } decision { 1447 if (!rule->r_sources) 1448 rule->r_sources = table_find("<localhost>", NULL); 1449 if (!rule->r_destination) 1450 rule->r_destination = table_find("<localnames>", NULL); 1451 TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry); 1452 rule = NULL; 1453 } 1454 ; 1455 %% 1456 1457 struct keywords { 1458 const char *k_name; 1459 int k_val; 1460 }; 1461 1462 int 1463 yyerror(const char *fmt, ...) 1464 { 1465 va_list ap; 1466 char *msg; 1467 1468 file->errors++; 1469 va_start(ap, fmt); 1470 if (vasprintf(&msg, fmt, ap) == -1) 1471 fatalx("yyerror vasprintf"); 1472 va_end(ap); 1473 logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg); 1474 free(msg); 1475 return (0); 1476 } 1477 1478 int 1479 kw_cmp(const void *k, const void *e) 1480 { 1481 return (strcmp(k, ((const struct keywords *)e)->k_name)); 1482 } 1483 1484 int 1485 lookup(char *s) 1486 { 1487 /* this has to be sorted always */ 1488 static const struct keywords keywords[] = { 1489 { "accept", ACCEPT }, 1490 { "alias", ALIAS }, 1491 { "any", ANY }, 1492 { "as", AS }, 1493 { "auth", AUTH }, 1494 { "auth-optional", AUTH_OPTIONAL }, 1495 { "authenticated", AUTHENTICATED }, 1496 { "backup", BACKUP }, 1497 { "bounce-warn", BOUNCEWARN }, 1498 { "ca", CA }, 1499 { "certificate", CERTIFICATE }, 1500 { "ciphers", CIPHERS }, 1501 { "compression", COMPRESSION }, 1502 { "deliver", DELIVER }, 1503 { "dhe", DHE }, 1504 { "domain", DOMAIN }, 1505 { "encryption", ENCRYPTION }, 1506 { "expire", EXPIRE }, 1507 { "filter", FILTER }, 1508 { "for", FOR }, 1509 { "forward-only", FORWARDONLY }, 1510 { "from", FROM }, 1511 { "hostname", HOSTNAME }, 1512 { "hostnames", HOSTNAMES }, 1513 { "include", INCLUDE }, 1514 { "inet4", INET4 }, 1515 { "inet6", INET6 }, 1516 { "key", KEY }, 1517 { "limit", LIMIT }, 1518 { "listen", LISTEN }, 1519 { "lmtp", LMTP }, 1520 { "local", LOCAL }, 1521 { "maildir", MAILDIR }, 1522 { "mask-source", MASK_SOURCE }, 1523 { "masquerade", MASQUERADE }, 1524 { "max-message-size", MAXMESSAGESIZE }, 1525 { "max-mta-deferred", MAXMTADEFERRED }, 1526 { "mbox", MBOX }, 1527 { "mda", MDA }, 1528 { "mta", MTA }, 1529 { "no-dsn", NODSN }, 1530 { "on", ON }, 1531 { "pki", PKI }, 1532 { "port", PORT }, 1533 { "queue", QUEUE }, 1534 { "rcpt-to", RCPTTO }, 1535 { "received-auth", RECEIVEDAUTH }, 1536 { "recipient", RECIPIENT }, 1537 { "reject", REJECT }, 1538 { "relay", RELAY }, 1539 { "scheduler", SCHEDULER }, 1540 { "secure", SECURE }, 1541 { "sender", SENDER }, 1542 { "senders", SENDERS }, 1543 { "session", SESSION }, 1544 { "smtps", SMTPS }, 1545 { "socket", SOCKET }, 1546 { "source", SOURCE }, 1547 { "subaddressing-delimiter", SUBADDRESSING_DELIM }, 1548 { "table", TABLE }, 1549 { "tag", TAG }, 1550 { "tagged", TAGGED }, 1551 { "tls", TLS }, 1552 { "tls-require", TLS_REQUIRE }, 1553 { "to", TO }, 1554 { "userbase", USERBASE }, 1555 { "verify", VERIFY }, 1556 { "via", VIA }, 1557 { "virtual", VIRTUAL }, 1558 }; 1559 const struct keywords *p; 1560 1561 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 1562 sizeof(keywords[0]), kw_cmp); 1563 1564 if (p) 1565 return (p->k_val); 1566 else 1567 return (STRING); 1568 } 1569 1570 #define MAXPUSHBACK 128 1571 1572 unsigned char *parsebuf; 1573 int parseindex; 1574 unsigned char pushback_buffer[MAXPUSHBACK]; 1575 int pushback_index = 0; 1576 1577 int 1578 lgetc(int quotec) 1579 { 1580 int c, next; 1581 1582 if (parsebuf) { 1583 /* Read character from the parsebuffer instead of input. */ 1584 if (parseindex >= 0) { 1585 c = parsebuf[parseindex++]; 1586 if (c != '\0') 1587 return (c); 1588 parsebuf = NULL; 1589 } else 1590 parseindex++; 1591 } 1592 1593 if (pushback_index) 1594 return (pushback_buffer[--pushback_index]); 1595 1596 if (quotec) { 1597 if ((c = getc(file->stream)) == EOF) { 1598 yyerror("reached end of file while parsing " 1599 "quoted string"); 1600 if (file == topfile || popfile() == EOF) 1601 return (EOF); 1602 return (quotec); 1603 } 1604 return (c); 1605 } 1606 1607 while ((c = getc(file->stream)) == '\\') { 1608 next = getc(file->stream); 1609 if (next != '\n') { 1610 c = next; 1611 break; 1612 } 1613 yylval.lineno = file->lineno; 1614 file->lineno++; 1615 } 1616 1617 while (c == EOF) { 1618 if (file == topfile || popfile() == EOF) 1619 return (EOF); 1620 c = getc(file->stream); 1621 } 1622 return (c); 1623 } 1624 1625 int 1626 lungetc(int c) 1627 { 1628 if (c == EOF) 1629 return (EOF); 1630 if (parsebuf) { 1631 parseindex--; 1632 if (parseindex >= 0) 1633 return (c); 1634 } 1635 if (pushback_index < MAXPUSHBACK-1) 1636 return (pushback_buffer[pushback_index++] = c); 1637 else 1638 return (EOF); 1639 } 1640 1641 int 1642 findeol(void) 1643 { 1644 int c; 1645 1646 parsebuf = NULL; 1647 pushback_index = 0; 1648 1649 /* skip to either EOF or the first real EOL */ 1650 while (1) { 1651 c = lgetc(0); 1652 if (c == '\n') { 1653 file->lineno++; 1654 break; 1655 } 1656 if (c == EOF) 1657 break; 1658 } 1659 return (ERROR); 1660 } 1661 1662 int 1663 yylex(void) 1664 { 1665 unsigned char buf[8096]; 1666 unsigned char *p, *val; 1667 int quotec, next, c; 1668 int token; 1669 1670 top: 1671 p = buf; 1672 while ((c = lgetc(0)) == ' ' || c == '\t') 1673 ; /* nothing */ 1674 1675 yylval.lineno = file->lineno; 1676 if (c == '#') 1677 while ((c = lgetc(0)) != '\n' && c != EOF) 1678 ; /* nothing */ 1679 if (c == '$' && parsebuf == NULL) { 1680 while (1) { 1681 if ((c = lgetc(0)) == EOF) 1682 return (0); 1683 1684 if (p + 1 >= buf + sizeof(buf) - 1) { 1685 yyerror("string too long"); 1686 return (findeol()); 1687 } 1688 if (isalnum(c) || c == '_') { 1689 *p++ = c; 1690 continue; 1691 } 1692 *p = '\0'; 1693 lungetc(c); 1694 break; 1695 } 1696 val = symget(buf); 1697 if (val == NULL) { 1698 yyerror("macro '%s' not defined", buf); 1699 return (findeol()); 1700 } 1701 parsebuf = val; 1702 parseindex = 0; 1703 goto top; 1704 } 1705 1706 switch (c) { 1707 case '\'': 1708 case '"': 1709 quotec = c; 1710 while (1) { 1711 if ((c = lgetc(quotec)) == EOF) 1712 return (0); 1713 if (c == '\n') { 1714 file->lineno++; 1715 continue; 1716 } else if (c == '\\') { 1717 if ((next = lgetc(quotec)) == EOF) 1718 return (0); 1719 if (next == quotec || c == ' ' || c == '\t') 1720 c = next; 1721 else if (next == '\n') { 1722 file->lineno++; 1723 continue; 1724 } else 1725 lungetc(next); 1726 } else if (c == quotec) { 1727 *p = '\0'; 1728 break; 1729 } else if (c == '\0') { 1730 yyerror("syntax error"); 1731 return (findeol()); 1732 } 1733 if (p + 1 >= buf + sizeof(buf) - 1) { 1734 yyerror("string too long"); 1735 return (findeol()); 1736 } 1737 *p++ = c; 1738 } 1739 yylval.v.string = strdup(buf); 1740 if (yylval.v.string == NULL) 1741 err(1, "yylex: strdup"); 1742 return (STRING); 1743 } 1744 1745 #define allowed_to_end_number(x) \ 1746 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 1747 1748 if (c == '-' || isdigit(c)) { 1749 do { 1750 *p++ = c; 1751 if ((unsigned)(p-buf) >= sizeof(buf)) { 1752 yyerror("string too long"); 1753 return (findeol()); 1754 } 1755 } while ((c = lgetc(0)) != EOF && isdigit(c)); 1756 lungetc(c); 1757 if (p == buf + 1 && buf[0] == '-') 1758 goto nodigits; 1759 if (c == EOF || allowed_to_end_number(c)) { 1760 const char *errstr = NULL; 1761 1762 *p = '\0'; 1763 yylval.v.number = strtonum(buf, LLONG_MIN, 1764 LLONG_MAX, &errstr); 1765 if (errstr) { 1766 yyerror("\"%s\" invalid number: %s", 1767 buf, errstr); 1768 return (findeol()); 1769 } 1770 return (NUMBER); 1771 } else { 1772 nodigits: 1773 while (p > buf + 1) 1774 lungetc(*--p); 1775 c = *--p; 1776 if (c == '-') 1777 return (c); 1778 } 1779 } 1780 1781 if (c == '=') { 1782 if ((c = lgetc(0)) != EOF && c == '>') 1783 return (ARROW); 1784 lungetc(c); 1785 c = '='; 1786 } 1787 1788 #define allowed_in_string(x) \ 1789 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1790 x != '{' && x != '}' && x != '<' && x != '>' && \ 1791 x != '!' && x != '=' && x != '#' && \ 1792 x != ',')) 1793 1794 if (isalnum(c) || c == ':' || c == '_') { 1795 do { 1796 *p++ = c; 1797 if ((unsigned)(p-buf) >= sizeof(buf)) { 1798 yyerror("string too long"); 1799 return (findeol()); 1800 } 1801 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 1802 lungetc(c); 1803 *p = '\0'; 1804 if ((token = lookup(buf)) == STRING) 1805 if ((yylval.v.string = strdup(buf)) == NULL) 1806 err(1, "yylex: strdup"); 1807 return (token); 1808 } 1809 if (c == '\n') { 1810 yylval.lineno = file->lineno; 1811 file->lineno++; 1812 } 1813 if (c == EOF) 1814 return (0); 1815 return (c); 1816 } 1817 1818 int 1819 check_file_secrecy(int fd, const char *fname) 1820 { 1821 struct stat st; 1822 1823 if (fstat(fd, &st)) { 1824 log_warn("warn: cannot stat %s", fname); 1825 return (-1); 1826 } 1827 if (st.st_uid != 0 && st.st_uid != getuid()) { 1828 log_warnx("warn: %s: owner not root or current user", fname); 1829 return (-1); 1830 } 1831 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 1832 log_warnx("warn: %s: group/world readable/writeable", fname); 1833 return (-1); 1834 } 1835 return (0); 1836 } 1837 1838 struct file * 1839 pushfile(const char *name, int secret) 1840 { 1841 struct file *nfile; 1842 1843 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 1844 log_warn("warn: malloc"); 1845 return (NULL); 1846 } 1847 if ((nfile->name = strdup(name)) == NULL) { 1848 log_warn("warn: malloc"); 1849 free(nfile); 1850 return (NULL); 1851 } 1852 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 1853 log_warn("warn: %s", nfile->name); 1854 free(nfile->name); 1855 free(nfile); 1856 return (NULL); 1857 } else if (secret && 1858 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 1859 fclose(nfile->stream); 1860 free(nfile->name); 1861 free(nfile); 1862 return (NULL); 1863 } 1864 nfile->lineno = 1; 1865 TAILQ_INSERT_TAIL(&files, nfile, entry); 1866 return (nfile); 1867 } 1868 1869 int 1870 popfile(void) 1871 { 1872 struct file *prev; 1873 1874 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 1875 prev->errors += file->errors; 1876 1877 TAILQ_REMOVE(&files, file, entry); 1878 fclose(file->stream); 1879 free(file->name); 1880 free(file); 1881 file = prev; 1882 return (file ? 0 : EOF); 1883 } 1884 1885 int 1886 parse_config(struct smtpd *x_conf, const char *filename, int opts) 1887 { 1888 struct sym *sym, *next; 1889 struct table *t; 1890 char hostname[HOST_NAME_MAX+1]; 1891 char hostname_copy[HOST_NAME_MAX+1]; 1892 1893 if (getmailname(hostname, sizeof hostname) == -1) 1894 return (-1); 1895 1896 conf = x_conf; 1897 memset(conf, 0, sizeof(*conf)); 1898 1899 (void)strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname)); 1900 1901 conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE; 1902 conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER; 1903 1904 conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict)); 1905 conf->sc_rules = calloc(1, sizeof(*conf->sc_rules)); 1906 conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners)); 1907 conf->sc_ca_dict = calloc(1, sizeof(*conf->sc_ca_dict)); 1908 conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict)); 1909 conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict)); 1910 conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict)); 1911 1912 /* Report mails delayed for more than 4 hours */ 1913 conf->sc_bounce_warn[0] = 3600 * 4; 1914 1915 if (conf->sc_tables_dict == NULL || 1916 conf->sc_rules == NULL || 1917 conf->sc_listeners == NULL || 1918 conf->sc_ca_dict == NULL || 1919 conf->sc_pki_dict == NULL || 1920 conf->sc_ssl_dict == NULL || 1921 conf->sc_limits_dict == NULL) { 1922 log_warn("warn: cannot allocate memory"); 1923 free(conf->sc_tables_dict); 1924 free(conf->sc_rules); 1925 free(conf->sc_listeners); 1926 free(conf->sc_ca_dict); 1927 free(conf->sc_pki_dict); 1928 free(conf->sc_ssl_dict); 1929 free(conf->sc_limits_dict); 1930 return (-1); 1931 } 1932 1933 errors = 0; 1934 1935 table = NULL; 1936 rule = NULL; 1937 1938 dict_init(&conf->sc_filters); 1939 1940 dict_init(conf->sc_ca_dict); 1941 dict_init(conf->sc_pki_dict); 1942 dict_init(conf->sc_ssl_dict); 1943 dict_init(conf->sc_tables_dict); 1944 1945 dict_init(conf->sc_limits_dict); 1946 limits = xcalloc(1, sizeof(*limits), "mta_limits"); 1947 limit_mta_set_defaults(limits); 1948 dict_xset(conf->sc_limits_dict, "default", limits); 1949 1950 TAILQ_INIT(conf->sc_listeners); 1951 TAILQ_INIT(conf->sc_rules); 1952 1953 conf->sc_qexpire = SMTPD_QUEUE_EXPIRY; 1954 conf->sc_opts = opts; 1955 1956 conf->sc_mta_max_deferred = 100; 1957 conf->sc_scheduler_max_inflight = 5000; 1958 conf->sc_scheduler_max_schedule = 10; 1959 conf->sc_scheduler_max_evp_batch_size = 256; 1960 conf->sc_scheduler_max_msg_batch_size = 1024; 1961 1962 conf->sc_session_max_rcpt = 1000; 1963 conf->sc_session_max_mails = 100; 1964 1965 conf->sc_mda_max_session = 50; 1966 conf->sc_mda_max_user_session = 7; 1967 conf->sc_mda_task_hiwat = 50; 1968 conf->sc_mda_task_lowat = 30; 1969 conf->sc_mda_task_release = 10; 1970 1971 if ((file = pushfile(filename, 0)) == NULL) { 1972 purge_config(PURGE_EVERYTHING); 1973 return (-1); 1974 } 1975 topfile = file; 1976 1977 /* 1978 * declare special "localhost", "anyhost" and "localnames" tables 1979 */ 1980 set_local(hostname); 1981 1982 t = table_create("static", "<anydestination>", NULL, NULL); 1983 t->t_type = T_LIST; 1984 table_add(t, "*", NULL); 1985 1986 /* can't truncate here */ 1987 (void)strlcpy(hostname_copy, hostname, sizeof hostname_copy); 1988 1989 hostname_copy[strcspn(hostname_copy, ".")] = '\0'; 1990 if (strcmp(hostname, hostname_copy) != 0) 1991 table_add(t, hostname_copy, NULL); 1992 1993 table_create("getpwnam", "<getpwnam>", NULL, NULL); 1994 1995 /* 1996 * parse configuration 1997 */ 1998 setservent(1); 1999 yyparse(); 2000 errors = file->errors; 2001 popfile(); 2002 endservent(); 2003 2004 /* If the socket listener was not configured, create a default one. */ 2005 if (!conf->sc_sock_listener) { 2006 memset(&listen_opts, 0, sizeof listen_opts); 2007 create_sock_listener(&listen_opts); 2008 } 2009 2010 /* Free macros and check which have not been used. */ 2011 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 2012 next = TAILQ_NEXT(sym, entry); 2013 if ((conf->sc_opts & SMTPD_OPT_VERBOSE) && !sym->used) 2014 fprintf(stderr, "warning: macro '%s' not " 2015 "used\n", sym->nam); 2016 if (!sym->persist) { 2017 free(sym->nam); 2018 free(sym->val); 2019 TAILQ_REMOVE(&symhead, sym, entry); 2020 free(sym); 2021 } 2022 } 2023 2024 if (TAILQ_EMPTY(conf->sc_rules)) { 2025 log_warnx("warn: no rules, nothing to do"); 2026 errors++; 2027 } 2028 2029 if (errors) { 2030 purge_config(PURGE_EVERYTHING); 2031 return (-1); 2032 } 2033 2034 return (0); 2035 } 2036 2037 int 2038 symset(const char *nam, const char *val, int persist) 2039 { 2040 struct sym *sym; 2041 2042 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 2043 sym = TAILQ_NEXT(sym, entry)) 2044 ; /* nothing */ 2045 2046 if (sym != NULL) { 2047 if (sym->persist == 1) 2048 return (0); 2049 else { 2050 free(sym->nam); 2051 free(sym->val); 2052 TAILQ_REMOVE(&symhead, sym, entry); 2053 free(sym); 2054 } 2055 } 2056 if ((sym = calloc(1, sizeof(*sym))) == NULL) 2057 return (-1); 2058 2059 sym->nam = strdup(nam); 2060 if (sym->nam == NULL) { 2061 free(sym); 2062 return (-1); 2063 } 2064 sym->val = strdup(val); 2065 if (sym->val == NULL) { 2066 free(sym->nam); 2067 free(sym); 2068 return (-1); 2069 } 2070 sym->used = 0; 2071 sym->persist = persist; 2072 TAILQ_INSERT_TAIL(&symhead, sym, entry); 2073 return (0); 2074 } 2075 2076 int 2077 cmdline_symset(char *s) 2078 { 2079 char *sym, *val; 2080 int ret; 2081 size_t len; 2082 2083 if ((val = strrchr(s, '=')) == NULL) 2084 return (-1); 2085 2086 len = strlen(s) - strlen(val) + 1; 2087 if ((sym = malloc(len)) == NULL) 2088 errx(1, "cmdline_symset: malloc"); 2089 2090 (void)strlcpy(sym, s, len); 2091 2092 ret = symset(sym, val + 1, 1); 2093 free(sym); 2094 2095 return (ret); 2096 } 2097 2098 char * 2099 symget(const char *nam) 2100 { 2101 struct sym *sym; 2102 2103 TAILQ_FOREACH(sym, &symhead, entry) 2104 if (strcmp(nam, sym->nam) == 0) { 2105 sym->used = 1; 2106 return (sym->val); 2107 } 2108 return (NULL); 2109 } 2110 2111 static void 2112 create_sock_listener(struct listen_opts *lo) 2113 { 2114 struct listener *l = xcalloc(1, sizeof(*l), "create_sock_listener"); 2115 lo->tag = "local"; 2116 lo->hostname = conf->sc_hostname; 2117 l->ss.ss_family = AF_LOCAL; 2118 l->ss.ss_len = sizeof(struct sockaddr *); 2119 l->local = 1; 2120 conf->sc_sock_listener = l; 2121 config_listener(l, lo); 2122 } 2123 2124 static void 2125 create_if_listener(struct listen_opts *lo) 2126 { 2127 uint16_t flags; 2128 2129 if (lo->port != 0 && lo->ssl == F_SSL) 2130 errx(1, "invalid listen option: tls/smtps on same port"); 2131 2132 if (lo->auth != 0 && !lo->ssl) 2133 errx(1, "invalid listen option: auth requires tls/smtps"); 2134 2135 if (lo->pki && !lo->ssl) 2136 errx(1, "invalid listen option: pki requires tls/smtps"); 2137 2138 flags = lo->flags; 2139 2140 if (lo->port) { 2141 lo->flags = lo->ssl|lo->auth|flags; 2142 lo->port = htons(lo->port); 2143 } 2144 else { 2145 if (lo->ssl & F_SMTPS) { 2146 lo->port = htons(465); 2147 lo->flags = F_SMTPS|lo->auth|flags; 2148 } 2149 2150 if (!lo->ssl || (lo->ssl & F_STARTTLS)) { 2151 lo->port = htons(25); 2152 lo->flags = lo->auth|flags; 2153 if (lo->ssl & F_STARTTLS) 2154 lo->flags |= F_STARTTLS; 2155 } 2156 } 2157 2158 if (interface(lo)) 2159 return; 2160 if (host_v4(lo)) 2161 return; 2162 if (host_v6(lo)) 2163 return; 2164 if (host_dns(lo)) 2165 return; 2166 2167 errx(1, "invalid virtual ip or interface: %s", lo->ifx); 2168 } 2169 2170 static void 2171 config_listener(struct listener *h, struct listen_opts *lo) 2172 { 2173 h->fd = -1; 2174 h->port = lo->port; 2175 h->flags = lo->flags; 2176 2177 if (lo->hostname == NULL) 2178 lo->hostname = conf->sc_hostname; 2179 2180 if (lo->filtername) { 2181 if (dict_get(&conf->sc_filters, lo->filtername) == NULL) { 2182 log_warnx("undefined filter: %s", lo->filtername); 2183 fatalx(NULL); 2184 } 2185 (void)strlcpy(h->filter, lo->filtername, sizeof(h->filter)); 2186 } 2187 2188 h->pki_name[0] = '\0'; 2189 2190 if (lo->authtable != NULL) 2191 (void)strlcpy(h->authtable, lo->authtable->t_name, sizeof(h->authtable)); 2192 if (lo->pki != NULL) { 2193 if (!lowercase(h->pki_name, lo->pki, sizeof(h->pki_name))) { 2194 log_warnx("pki name too long: %s", lo->pki); 2195 fatalx(NULL); 2196 } 2197 if (dict_get(conf->sc_pki_dict, h->pki_name) == NULL) { 2198 log_warnx("pki name not found: %s", lo->pki); 2199 fatalx(NULL); 2200 } 2201 } 2202 2203 if (lo->ca != NULL) { 2204 if (!lowercase(h->ca_name, lo->ca, sizeof(h->ca_name))) { 2205 log_warnx("ca name too long: %s", lo->ca); 2206 fatalx(NULL); 2207 } 2208 if (dict_get(conf->sc_ca_dict, h->ca_name) == NULL) { 2209 log_warnx("ca name not found: %s", lo->ca); 2210 fatalx(NULL); 2211 } 2212 } 2213 if (lo->tag != NULL) 2214 (void)strlcpy(h->tag, lo->tag, sizeof(h->tag)); 2215 2216 (void)strlcpy(h->hostname, lo->hostname, sizeof(h->hostname)); 2217 if (lo->hostnametable) 2218 (void)strlcpy(h->hostnametable, lo->hostnametable->t_name, sizeof(h->hostnametable)); 2219 if (lo->sendertable) { 2220 (void)strlcpy(h->sendertable, lo->sendertable->t_name, sizeof(h->sendertable)); 2221 if (lo->options & LO_MASQUERADE) 2222 h->flags |= F_MASQUERADE; 2223 } 2224 2225 if (lo->ssl & F_TLS_VERIFY) 2226 h->flags |= F_TLS_VERIFY; 2227 2228 if (h != conf->sc_sock_listener) 2229 TAILQ_INSERT_TAIL(conf->sc_listeners, h, entry); 2230 } 2231 2232 static int 2233 host_v4(struct listen_opts *lo) 2234 { 2235 struct in_addr ina; 2236 struct sockaddr_in *sain; 2237 struct listener *h; 2238 2239 if (lo->family != AF_UNSPEC && lo->family != AF_INET) 2240 return (0); 2241 2242 memset(&ina, 0, sizeof(ina)); 2243 if (inet_pton(AF_INET, lo->ifx, &ina) != 1) 2244 return (0); 2245 2246 h = xcalloc(1, sizeof(*h), "host_v4"); 2247 sain = (struct sockaddr_in *)&h->ss; 2248 sain->sin_len = sizeof(struct sockaddr_in); 2249 sain->sin_family = AF_INET; 2250 sain->sin_addr.s_addr = ina.s_addr; 2251 sain->sin_port = lo->port; 2252 2253 if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) 2254 h->local = 1; 2255 config_listener(h, lo); 2256 2257 return (1); 2258 } 2259 2260 static int 2261 host_v6(struct listen_opts *lo) 2262 { 2263 struct in6_addr ina6; 2264 struct sockaddr_in6 *sin6; 2265 struct listener *h; 2266 2267 if (lo->family != AF_UNSPEC && lo->family != AF_INET6) 2268 return (0); 2269 2270 memset(&ina6, 0, sizeof(ina6)); 2271 if (inet_pton(AF_INET6, lo->ifx, &ina6) != 1) 2272 return (0); 2273 2274 h = xcalloc(1, sizeof(*h), "host_v6"); 2275 sin6 = (struct sockaddr_in6 *)&h->ss; 2276 sin6->sin6_len = sizeof(struct sockaddr_in6); 2277 sin6->sin6_family = AF_INET6; 2278 sin6->sin6_port = lo->port; 2279 memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6)); 2280 2281 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 2282 h->local = 1; 2283 config_listener(h, lo); 2284 2285 return (1); 2286 } 2287 2288 static int 2289 host_dns(struct listen_opts *lo) 2290 { 2291 struct addrinfo hints, *res0, *res; 2292 int error, cnt = 0; 2293 struct sockaddr_in *sain; 2294 struct sockaddr_in6 *sin6; 2295 struct listener *h; 2296 2297 memset(&hints, 0, sizeof(hints)); 2298 hints.ai_family = lo->family; 2299 hints.ai_socktype = SOCK_STREAM; 2300 hints.ai_flags = AI_ADDRCONFIG; 2301 error = getaddrinfo(lo->ifx, NULL, &hints, &res0); 2302 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 2303 return (0); 2304 if (error) { 2305 log_warnx("warn: host_dns: could not parse \"%s\": %s", lo->ifx, 2306 gai_strerror(error)); 2307 return (-1); 2308 } 2309 2310 for (res = res0; res; res = res->ai_next) { 2311 if (res->ai_family != AF_INET && 2312 res->ai_family != AF_INET6) 2313 continue; 2314 h = xcalloc(1, sizeof(*h), "host_dns"); 2315 2316 h->ss.ss_family = res->ai_family; 2317 if (res->ai_family == AF_INET) { 2318 sain = (struct sockaddr_in *)&h->ss; 2319 sain->sin_len = sizeof(struct sockaddr_in); 2320 sain->sin_addr.s_addr = ((struct sockaddr_in *) 2321 res->ai_addr)->sin_addr.s_addr; 2322 sain->sin_port = lo->port; 2323 if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) 2324 h->local = 1; 2325 } else { 2326 sin6 = (struct sockaddr_in6 *)&h->ss; 2327 sin6->sin6_len = sizeof(struct sockaddr_in6); 2328 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 2329 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 2330 sin6->sin6_port = lo->port; 2331 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 2332 h->local = 1; 2333 } 2334 2335 config_listener(h, lo); 2336 2337 cnt++; 2338 } 2339 2340 freeaddrinfo(res0); 2341 return (cnt); 2342 } 2343 2344 static int 2345 interface(struct listen_opts *lo) 2346 { 2347 struct ifaddrs *ifap, *p; 2348 struct sockaddr_in *sain; 2349 struct sockaddr_in6 *sin6; 2350 struct listener *h; 2351 int ret = 0; 2352 2353 if (getifaddrs(&ifap) == -1) 2354 fatal("getifaddrs"); 2355 2356 for (p = ifap; p != NULL; p = p->ifa_next) { 2357 if (p->ifa_addr == NULL) 2358 continue; 2359 if (strcmp(p->ifa_name, lo->ifx) != 0 && 2360 !is_if_in_group(p->ifa_name, lo->ifx)) 2361 continue; 2362 if (lo->family != AF_UNSPEC && lo->family != p->ifa_addr->sa_family) 2363 continue; 2364 2365 h = xcalloc(1, sizeof(*h), "interface"); 2366 2367 switch (p->ifa_addr->sa_family) { 2368 case AF_INET: 2369 sain = (struct sockaddr_in *)&h->ss; 2370 *sain = *(struct sockaddr_in *)p->ifa_addr; 2371 sain->sin_len = sizeof(struct sockaddr_in); 2372 sain->sin_port = lo->port; 2373 if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) 2374 h->local = 1; 2375 break; 2376 2377 case AF_INET6: 2378 sin6 = (struct sockaddr_in6 *)&h->ss; 2379 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 2380 sin6->sin6_len = sizeof(struct sockaddr_in6); 2381 sin6->sin6_port = lo->port; 2382 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 2383 h->local = 1; 2384 break; 2385 2386 default: 2387 free(h); 2388 continue; 2389 } 2390 2391 config_listener(h, lo); 2392 ret = 1; 2393 } 2394 2395 freeifaddrs(ifap); 2396 2397 return ret; 2398 } 2399 2400 void 2401 set_local(const char *hostname) 2402 { 2403 struct table *t; 2404 2405 t = table_create("static", "<localnames>", NULL, NULL); 2406 t->t_type = T_LIST; 2407 table_add(t, "localhost", NULL); 2408 table_add(t, hostname, NULL); 2409 2410 set_localaddrs(t); 2411 } 2412 2413 void 2414 set_localaddrs(struct table *localnames) 2415 { 2416 struct ifaddrs *ifap, *p; 2417 struct sockaddr_storage ss; 2418 struct sockaddr_in *sain; 2419 struct sockaddr_in6 *sin6; 2420 struct table *t; 2421 char buf[NI_MAXHOST + 5]; 2422 2423 t = table_create("static", "<anyhost>", NULL, NULL); 2424 table_add(t, "local", NULL); 2425 table_add(t, "0.0.0.0/0", NULL); 2426 table_add(t, "::/0", NULL); 2427 2428 if (getifaddrs(&ifap) == -1) 2429 fatal("getifaddrs"); 2430 2431 t = table_create("static", "<localhost>", NULL, NULL); 2432 table_add(t, "local", NULL); 2433 2434 for (p = ifap; p != NULL; p = p->ifa_next) { 2435 if (p->ifa_addr == NULL) 2436 continue; 2437 switch (p->ifa_addr->sa_family) { 2438 case AF_INET: 2439 sain = (struct sockaddr_in *)&ss; 2440 *sain = *(struct sockaddr_in *)p->ifa_addr; 2441 sain->sin_len = sizeof(struct sockaddr_in); 2442 table_add(t, ss_to_text(&ss), NULL); 2443 table_add(localnames, ss_to_text(&ss), NULL); 2444 (void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss)); 2445 table_add(localnames, buf, NULL); 2446 break; 2447 2448 case AF_INET6: 2449 sin6 = (struct sockaddr_in6 *)&ss; 2450 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 2451 sin6->sin6_len = sizeof(struct sockaddr_in6); 2452 table_add(t, ss_to_text(&ss), NULL); 2453 table_add(localnames, ss_to_text(&ss), NULL); 2454 (void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss)); 2455 table_add(localnames, buf, NULL); 2456 (void)snprintf(buf, sizeof buf, "[ipv6:%s]", ss_to_text(&ss)); 2457 table_add(localnames, buf, NULL); 2458 break; 2459 } 2460 } 2461 2462 freeifaddrs(ifap); 2463 } 2464 2465 int 2466 delaytonum(char *str) 2467 { 2468 unsigned int factor; 2469 size_t len; 2470 const char *errstr = NULL; 2471 int delay; 2472 2473 /* we need at least 1 digit and 1 unit */ 2474 len = strlen(str); 2475 if (len < 2) 2476 goto bad; 2477 2478 switch(str[len - 1]) { 2479 2480 case 's': 2481 factor = 1; 2482 break; 2483 2484 case 'm': 2485 factor = 60; 2486 break; 2487 2488 case 'h': 2489 factor = 60 * 60; 2490 break; 2491 2492 case 'd': 2493 factor = 24 * 60 * 60; 2494 break; 2495 2496 default: 2497 goto bad; 2498 } 2499 2500 str[len - 1] = '\0'; 2501 delay = strtonum(str, 1, INT_MAX / factor, &errstr); 2502 if (errstr) 2503 goto bad; 2504 2505 return (delay * factor); 2506 2507 bad: 2508 return (-1); 2509 } 2510 2511 int 2512 is_if_in_group(const char *ifname, const char *groupname) 2513 { 2514 unsigned int len; 2515 struct ifgroupreq ifgr; 2516 struct ifg_req *ifg; 2517 int s; 2518 int ret = 0; 2519 2520 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 2521 err(1, "socket"); 2522 2523 memset(&ifgr, 0, sizeof(ifgr)); 2524 if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ) 2525 errx(1, "interface name too large"); 2526 2527 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 2528 if (errno == EINVAL || errno == ENOTTY) 2529 goto end; 2530 err(1, "SIOCGIFGROUP"); 2531 } 2532 2533 len = ifgr.ifgr_len; 2534 ifgr.ifgr_groups = xcalloc(len/sizeof(struct ifg_req), 2535 sizeof(struct ifg_req), "is_if_in_group"); 2536 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 2537 err(1, "SIOCGIFGROUP"); 2538 2539 ifg = ifgr.ifgr_groups; 2540 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 2541 len -= sizeof(struct ifg_req); 2542 if (strcmp(ifg->ifgrq_group, groupname) == 0) { 2543 ret = 1; 2544 break; 2545 } 2546 } 2547 free(ifgr.ifgr_groups); 2548 2549 end: 2550 close(s); 2551 return ret; 2552 } 2553 2554 static struct filter_conf * 2555 create_filter_proc(char *name, char *prog) 2556 { 2557 struct filter_conf *f; 2558 char *path; 2559 2560 if (dict_get(&conf->sc_filters, name)) { 2561 yyerror("filter \"%s\" already defined", name); 2562 return (NULL); 2563 } 2564 2565 if (asprintf(&path, "%s/filter-%s", PATH_LIBEXEC, prog) == -1) { 2566 yyerror("filter \"%s\" asprintf failed", name); 2567 return (0); 2568 } 2569 2570 f = xcalloc(1, sizeof(*f), "create_filter"); 2571 f->path = path; 2572 f->name = name; 2573 f->argv[f->argc++] = name; 2574 2575 dict_xset(&conf->sc_filters, name, f); 2576 2577 return (f); 2578 } 2579 2580 static struct filter_conf * 2581 create_filter_chain(char *name) 2582 { 2583 struct filter_conf *f; 2584 2585 if (dict_get(&conf->sc_filters, name)) { 2586 yyerror("filter \"%s\" already defined", name); 2587 return (NULL); 2588 } 2589 2590 f = xcalloc(1, sizeof(*f), "create_filter_chain"); 2591 f->chain = 1; 2592 f->name = name; 2593 2594 dict_xset(&conf->sc_filters, name, f); 2595 2596 return (f); 2597 } 2598 2599 static int 2600 add_filter_arg(struct filter_conf *f, char *arg) 2601 { 2602 int i; 2603 2604 if (f->argc == MAX_FILTER_ARGS) { 2605 yyerror("filter \"%s\" is full", f->name); 2606 return (0); 2607 } 2608 2609 if (f->chain) { 2610 if (dict_get(&conf->sc_filters, arg) == NULL) { 2611 yyerror("undefined filter \"%s\"", arg); 2612 return (0); 2613 } 2614 if (dict_get(&conf->sc_filters, arg) == f) { 2615 yyerror("filter chain cannot contain itself"); 2616 return (0); 2617 } 2618 for (i = 0; i < f->argc; ++i) 2619 if (strcasecmp(f->argv[i], arg) == 0) { 2620 yyerror("filter chain cannot contain twice the same filter instance"); 2621 return (0); 2622 } 2623 } 2624 2625 f->argv[f->argc++] = arg; 2626 2627 return (1); 2628 } 2629 2630 static int 2631 config_lo_filter(struct listen_opts *lo, char *filter_name) { 2632 if (lo->options & LO_FILTER) { 2633 yyerror("filter already specified"); 2634 return -1; 2635 } 2636 lo->options |= LO_FILTER; 2637 lo->filtername = filter_name; 2638 2639 return 0; 2640 } 2641 2642 static int 2643 config_lo_mask_source(struct listen_opts *lo) { 2644 if (lo->options & LO_MASKSOURCE) { 2645 yyerror("mask-source already specified"); 2646 return -1; 2647 } 2648 lo->options |= LO_MASKSOURCE; 2649 lo->flags |= F_MASK_SOURCE; 2650 2651 return 0; 2652 } 2653 2654