1 /* $OpenBSD: parse.y,v 1.297 2024/02/02 20:54:27 millert 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/stat.h> 26 #include <sys/ioctl.h> 27 28 #include <net/if.h> 29 #include <netinet/in.h> 30 31 #include <arpa/inet.h> 32 #include <ctype.h> 33 #include <errno.h> 34 #include <ifaddrs.h> 35 #include <inttypes.h> 36 #include <resolv.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <syslog.h> 40 #include <unistd.h> 41 #include <util.h> 42 43 #include "smtpd.h" 44 #include "ssl.h" 45 #include "log.h" 46 47 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 48 static struct file { 49 TAILQ_ENTRY(file) entry; 50 FILE *stream; 51 char *name; 52 size_t ungetpos; 53 size_t ungetsize; 54 u_char *ungetbuf; 55 int eof_reached; 56 int lineno; 57 int errors; 58 } *file, *topfile; 59 struct file *pushfile(const char *, int); 60 int popfile(void); 61 int check_file_secrecy(int, const char *); 62 int yyparse(void); 63 int yylex(void); 64 int kw_cmp(const void *, const void *); 65 int lookup(char *); 66 int igetc(void); 67 int lgetc(int); 68 void lungetc(int); 69 int findeol(void); 70 int yyerror(const char *, ...) 71 __attribute__((__format__ (printf, 1, 2))) 72 __attribute__((__nonnull__ (1))); 73 74 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 75 struct sym { 76 TAILQ_ENTRY(sym) entry; 77 int used; 78 int persist; 79 char *nam; 80 char *val; 81 }; 82 int symset(const char *, const char *, int); 83 char *symget(const char *); 84 85 struct smtpd *conf = NULL; 86 static int errors = 0; 87 88 struct table *table = NULL; 89 struct mta_limits *limits; 90 static struct pki *pki; 91 static struct ca *sca; 92 93 struct dispatcher *dsp; 94 struct rule *rule; 95 struct filter_proc *processor; 96 struct filter_config *filter_config; 97 static uint32_t last_dynchain_id = 1; 98 99 enum listen_options { 100 LO_FAMILY = 0x000001, 101 LO_PORT = 0x000002, 102 LO_SSL = 0x000004, 103 LO_FILTER = 0x000008, 104 LO_PKI = 0x000010, 105 LO_AUTH = 0x000020, 106 LO_TAG = 0x000040, 107 LO_HOSTNAME = 0x000080, 108 LO_HOSTNAMES = 0x000100, 109 LO_MASKSOURCE = 0x000200, 110 LO_NODSN = 0x000400, 111 LO_SENDERS = 0x000800, 112 LO_RECEIVEDAUTH = 0x001000, 113 LO_MASQUERADE = 0x002000, 114 LO_CA = 0x004000, 115 LO_PROXY = 0x008000, 116 }; 117 118 #define PKI_MAX 32 119 static struct listen_opts { 120 char *ifx; 121 int family; 122 in_port_t port; 123 uint16_t ssl; 124 char *filtername; 125 char *pki[PKI_MAX]; 126 int pkicount; 127 char *tls_ciphers; 128 char *tls_protocols; 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 int delaytonum(char *); 150 int is_if_in_group(const char *, const char *); 151 152 static int config_lo_mask_source(struct listen_opts *); 153 154 typedef struct { 155 union { 156 int64_t number; 157 struct table *table; 158 char *string; 159 struct host *host; 160 struct mailaddr *maddr; 161 } v; 162 int lineno; 163 } YYSTYPE; 164 165 %} 166 167 %token ACTION ADMD ALIAS ANY ARROW AUTH AUTH_OPTIONAL 168 %token BACKUP BOUNCE BYPASS 169 %token CA CERT CHAIN CHROOT CIPHERS COMMIT COMPRESSION CONNECT 170 %token DATA DATA_LINE DHE DISCONNECT DOMAIN 171 %token EHLO ENABLE ENCRYPTION ERROR EXPAND_ONLY 172 %token FCRDNS FILTER FOR FORWARD_ONLY FROM 173 %token GROUP 174 %token HELO HELO_SRC HOST HOSTNAME HOSTNAMES 175 %token INCLUDE INET4 INET6 176 %token JUNK 177 %token KEY 178 %token LIMIT LISTEN LMTP LOCAL 179 %token MAIL_FROM MAILDIR MASK_SRC MASQUERADE MATCH MAX_MESSAGE_SIZE MAX_DEFERRED MBOX MDA MTA MX 180 %token NO_DSN NO_VERIFY NOOP 181 %token ON 182 %token PHASE PKI PORT PROC PROC_EXEC PROTOCOLS PROXY_V2 183 %token QUEUE QUIT 184 %token RCPT_TO RDNS RECIPIENT RECEIVEDAUTH REGEX RELAY REJECT REPORT REWRITE RSET 185 %token SCHEDULER SENDER SENDERS SMTP SMTP_IN SMTP_OUT SMTPS SOCKET SRC SRS SUB_ADDR_DELIM 186 %token TABLE TAG TAGGED TLS TLS_REQUIRE TTL 187 %token USER USERBASE 188 %token VERIFY VIRTUAL 189 %token WARN_INTERVAL WRAPPER 190 191 %token <v.string> STRING 192 %token <v.number> NUMBER 193 %type <v.table> table 194 %type <v.number> size negation 195 %type <v.table> tables tablenew tableref 196 %% 197 198 grammar : /* empty */ 199 | grammar '\n' 200 | grammar include '\n' 201 | grammar varset '\n' 202 | grammar bounce '\n' 203 | grammar admd '\n' 204 | grammar ca '\n' 205 | grammar mda '\n' 206 | grammar mta '\n' 207 | grammar pki '\n' 208 | grammar proc '\n' 209 | grammar queue '\n' 210 | grammar scheduler '\n' 211 | grammar smtp '\n' 212 | grammar srs '\n' 213 | grammar listen '\n' 214 | grammar table '\n' 215 | grammar dispatcher '\n' 216 | grammar match '\n' 217 | grammar filter '\n' 218 | grammar error '\n' { file->errors++; } 219 ; 220 221 include : INCLUDE STRING { 222 struct file *nfile; 223 224 if ((nfile = pushfile($2, 0)) == NULL) { 225 yyerror("failed to include file %s", $2); 226 free($2); 227 YYERROR; 228 } 229 free($2); 230 231 file = nfile; 232 lungetc('\n'); 233 } 234 ; 235 236 varset : STRING '=' STRING { 237 char *s = $1; 238 while (*s++) { 239 if (isspace((unsigned char)*s)) { 240 yyerror("macro name cannot contain " 241 "whitespace"); 242 free($1); 243 free($3); 244 YYERROR; 245 } 246 } 247 if (symset($1, $3, 0) == -1) 248 fatal("cannot store variable"); 249 free($1); 250 free($3); 251 } 252 ; 253 254 comma : ',' optnl 255 | nl 256 | /* empty */ 257 ; 258 259 optnl : '\n' optnl 260 | 261 ; 262 263 nl : '\n' optnl 264 ; 265 266 negation : '!' { $$ = 1; } 267 | /* empty */ { $$ = 0; } 268 ; 269 270 assign : '=' | ARROW; 271 272 273 keyval : STRING assign STRING { 274 table_add(table, $1, $3); 275 free($1); 276 free($3); 277 } 278 ; 279 280 keyval_list : keyval optnl 281 | keyval comma keyval_list 282 ; 283 284 stringel : STRING { 285 table_add(table, $1, NULL); 286 free($1); 287 } 288 ; 289 290 string_list : stringel optnl 291 | stringel comma string_list 292 ; 293 294 tableval_list : string_list { } 295 | keyval_list { } 296 ; 297 298 bounce: 299 BOUNCE WARN_INTERVAL { 300 memset(conf->sc_bounce_warn, 0, sizeof conf->sc_bounce_warn); 301 } bouncedelays 302 ; 303 304 305 admd: 306 ADMD STRING { 307 size_t i; 308 309 for (i = 0; $2[i] != '\0'; i++) { 310 if (!isprint($2[i])) { 311 yyerror("not a valid admd"); 312 free($2); 313 YYERROR; 314 } 315 } 316 conf->sc_admd = $2; 317 }; 318 319 320 ca: 321 CA STRING { 322 char buf[HOST_NAME_MAX+1]; 323 324 /* if not catchall, check that it is a valid domain */ 325 if (strcmp($2, "*") != 0) { 326 if (!res_hnok($2)) { 327 yyerror("not a valid domain name: %s", $2); 328 free($2); 329 YYERROR; 330 } 331 } 332 xlowercase(buf, $2, sizeof(buf)); 333 free($2); 334 sca = dict_get(conf->sc_ca_dict, buf); 335 if (sca == NULL) { 336 sca = xcalloc(1, sizeof *sca); 337 (void)strlcpy(sca->ca_name, buf, sizeof(sca->ca_name)); 338 dict_set(conf->sc_ca_dict, sca->ca_name, sca); 339 } 340 } ca_params 341 ; 342 343 344 ca_params_opt: 345 CERT STRING { 346 sca->ca_cert_file = $2; 347 } 348 ; 349 350 ca_params: 351 ca_params_opt 352 ; 353 354 355 mda: 356 MDA LIMIT limits_mda 357 | MDA WRAPPER STRING STRING { 358 if (dict_get(conf->sc_mda_wrappers, $3)) { 359 yyerror("mda wrapper already declared with that name: %s", $3); 360 YYERROR; 361 } 362 dict_set(conf->sc_mda_wrappers, $3, $4); 363 } 364 ; 365 366 367 mta: 368 MTA MAX_DEFERRED NUMBER { 369 conf->sc_mta_max_deferred = $3; 370 } 371 | MTA LIMIT FOR DOMAIN STRING { 372 struct mta_limits *d; 373 374 limits = dict_get(conf->sc_limits_dict, $5); 375 if (limits == NULL) { 376 limits = xcalloc(1, sizeof(*limits)); 377 dict_xset(conf->sc_limits_dict, $5, limits); 378 d = dict_xget(conf->sc_limits_dict, "default"); 379 memmove(limits, d, sizeof(*limits)); 380 } 381 free($5); 382 } limits_mta 383 | MTA LIMIT { 384 limits = dict_get(conf->sc_limits_dict, "default"); 385 } limits_mta 386 ; 387 388 389 pki: 390 PKI STRING { 391 char buf[HOST_NAME_MAX+1]; 392 393 /* if not catchall, check that it is a valid domain */ 394 if (strcmp($2, "*") != 0) { 395 if (!res_hnok($2)) { 396 yyerror("not a valid domain name: %s", $2); 397 free($2); 398 YYERROR; 399 } 400 } 401 xlowercase(buf, $2, sizeof(buf)); 402 free($2); 403 pki = dict_get(conf->sc_pki_dict, buf); 404 if (pki == NULL) { 405 pki = xcalloc(1, sizeof *pki); 406 (void)strlcpy(pki->pki_name, buf, sizeof(pki->pki_name)); 407 dict_set(conf->sc_pki_dict, pki->pki_name, pki); 408 } 409 } pki_params 410 ; 411 412 pki_params_opt: 413 CERT STRING { 414 pki->pki_cert_file = $2; 415 } 416 | KEY STRING { 417 pki->pki_key_file = $2; 418 } 419 | DHE STRING { 420 if (strcasecmp($2, "none") == 0) 421 pki->pki_dhe = 0; 422 else if (strcasecmp($2, "auto") == 0) 423 pki->pki_dhe = 1; 424 else if (strcasecmp($2, "legacy") == 0) 425 pki->pki_dhe = 2; 426 else { 427 yyerror("invalid DHE keyword: %s", $2); 428 free($2); 429 YYERROR; 430 } 431 free($2); 432 } 433 ; 434 435 436 pki_params: 437 pki_params_opt pki_params 438 | /* empty */ 439 ; 440 441 442 proc: 443 PROC STRING STRING { 444 if (dict_get(conf->sc_filter_processes_dict, $2)) { 445 yyerror("processor already exists with that name: %s", $2); 446 free($2); 447 free($3); 448 YYERROR; 449 } 450 processor = xcalloc(1, sizeof *processor); 451 processor->command = $3; 452 } proc_params { 453 dict_set(conf->sc_filter_processes_dict, $2, processor); 454 processor = NULL; 455 } 456 ; 457 458 459 proc_params_opt: 460 USER STRING { 461 if (processor->user) { 462 yyerror("user already specified for this processor"); 463 free($2); 464 YYERROR; 465 } 466 processor->user = $2; 467 } 468 | GROUP STRING { 469 if (processor->group) { 470 yyerror("group already specified for this processor"); 471 free($2); 472 YYERROR; 473 } 474 processor->group = $2; 475 } 476 | CHROOT STRING { 477 if (processor->chroot) { 478 yyerror("chroot already specified for this processor"); 479 free($2); 480 YYERROR; 481 } 482 processor->chroot = $2; 483 } 484 ; 485 486 proc_params: 487 proc_params_opt proc_params 488 | /* empty */ 489 ; 490 491 492 queue: 493 QUEUE COMPRESSION { 494 conf->sc_queue_flags |= QUEUE_COMPRESSION; 495 } 496 | QUEUE ENCRYPTION { 497 conf->sc_queue_flags |= QUEUE_ENCRYPTION; 498 } 499 | QUEUE ENCRYPTION STRING { 500 if (strcasecmp($3, "stdin") == 0 || strcasecmp($3, "-") == 0) { 501 conf->sc_queue_key = "stdin"; 502 free($3); 503 } 504 else 505 conf->sc_queue_key = $3; 506 conf->sc_queue_flags |= QUEUE_ENCRYPTION; 507 } 508 | QUEUE TTL STRING { 509 conf->sc_ttl = delaytonum($3); 510 if (conf->sc_ttl == -1) { 511 yyerror("invalid ttl delay: %s", $3); 512 free($3); 513 YYERROR; 514 } 515 free($3); 516 } 517 ; 518 519 520 scheduler: 521 SCHEDULER LIMIT limits_scheduler 522 ; 523 524 525 smtp: 526 SMTP LIMIT limits_smtp 527 | SMTP CIPHERS STRING { 528 conf->sc_tls_ciphers = $3; 529 } 530 | SMTP MAX_MESSAGE_SIZE size { 531 conf->sc_maxsize = $3; 532 } 533 | SMTP SUB_ADDR_DELIM STRING { 534 if (strlen($3) != 1) { 535 yyerror("subaddressing-delimiter must be one character"); 536 free($3); 537 YYERROR; 538 } 539 if (isspace((unsigned char)*$3) || !isprint((unsigned char)*$3) || *$3 == '@') { 540 yyerror("sub-addr-delim uses invalid character"); 541 free($3); 542 YYERROR; 543 } 544 conf->sc_subaddressing_delim = $3; 545 } 546 ; 547 548 srs: 549 SRS KEY STRING { 550 conf->sc_srs_key = $3; 551 } 552 | SRS KEY BACKUP STRING { 553 conf->sc_srs_key_backup = $4; 554 } 555 | SRS TTL STRING { 556 conf->sc_srs_ttl = delaytonum($3); 557 if (conf->sc_srs_ttl == -1) { 558 yyerror("ttl delay \"%s\" is invalid", $3); 559 free($3); 560 YYERROR; 561 } 562 563 conf->sc_srs_ttl /= 86400; 564 if (conf->sc_srs_ttl == 0) { 565 yyerror("ttl delay \"%s\" is too short", $3); 566 free($3); 567 YYERROR; 568 } 569 free($3); 570 } 571 ; 572 573 574 dispatcher_local_option: 575 USER STRING { 576 if (dsp->u.local.is_mbox) { 577 yyerror("user may not be specified for this dispatcher"); 578 YYERROR; 579 } 580 581 if (dsp->u.local.forward_only) { 582 yyerror("user may not be specified for forward-only"); 583 YYERROR; 584 } 585 586 if (dsp->u.local.expand_only) { 587 yyerror("user may not be specified for expand-only"); 588 YYERROR; 589 } 590 591 if (dsp->u.local.user) { 592 yyerror("user already specified for this dispatcher"); 593 YYERROR; 594 } 595 596 dsp->u.local.user = $2; 597 } 598 | ALIAS tables { 599 struct table *t = $2; 600 601 if (dsp->u.local.table_alias) { 602 yyerror("alias mapping already specified for this dispatcher"); 603 YYERROR; 604 } 605 606 if (dsp->u.local.table_virtual) { 607 yyerror("virtual mapping already specified for this dispatcher"); 608 YYERROR; 609 } 610 611 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) { 612 yyerror("table \"%s\" may not be used for alias lookups", 613 t->t_name); 614 YYERROR; 615 } 616 617 dsp->u.local.table_alias = strdup(t->t_name); 618 } 619 | VIRTUAL tables { 620 struct table *t = $2; 621 622 if (dsp->u.local.table_virtual) { 623 yyerror("virtual mapping already specified for this dispatcher"); 624 YYERROR; 625 } 626 627 if (dsp->u.local.table_alias) { 628 yyerror("alias mapping already specified for this dispatcher"); 629 YYERROR; 630 } 631 632 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) { 633 yyerror("table \"%s\" may not be used for virtual lookups", 634 t->t_name); 635 YYERROR; 636 } 637 638 dsp->u.local.table_virtual = strdup(t->t_name); 639 } 640 | USERBASE tables { 641 struct table *t = $2; 642 643 if (dsp->u.local.table_userbase) { 644 yyerror("userbase mapping already specified for this dispatcher"); 645 YYERROR; 646 } 647 648 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_USERINFO)) { 649 yyerror("table \"%s\" may not be used for userbase lookups", 650 t->t_name); 651 YYERROR; 652 } 653 654 dsp->u.local.table_userbase = strdup(t->t_name); 655 } 656 | WRAPPER STRING { 657 if (! dict_get(conf->sc_mda_wrappers, $2)) { 658 yyerror("no mda wrapper with that name: %s", $2); 659 YYERROR; 660 } 661 dsp->u.local.mda_wrapper = $2; 662 } 663 ; 664 665 dispatcher_local_options: 666 dispatcher_local_option dispatcher_local_options 667 | /* empty */ 668 ; 669 670 dispatcher_local: 671 MBOX { 672 dsp->u.local.is_mbox = 1; 673 asprintf(&dsp->u.local.command, "/usr/libexec/mail.local -f %%{mbox.from} -- %%{user.username}"); 674 } dispatcher_local_options 675 | MAILDIR { 676 asprintf(&dsp->u.local.command, "/usr/libexec/mail.maildir"); 677 } dispatcher_local_options 678 | MAILDIR JUNK { 679 asprintf(&dsp->u.local.command, "/usr/libexec/mail.maildir -j"); 680 } dispatcher_local_options 681 | MAILDIR STRING { 682 if (strncmp($2, "~/", 2) == 0) 683 asprintf(&dsp->u.local.command, 684 "/usr/libexec/mail.maildir \"%%{user.directory}/%s\"", $2+2); 685 else 686 asprintf(&dsp->u.local.command, 687 "/usr/libexec/mail.maildir \"%s\"", $2); 688 } dispatcher_local_options 689 | MAILDIR STRING JUNK { 690 if (strncmp($2, "~/", 2) == 0) 691 asprintf(&dsp->u.local.command, 692 "/usr/libexec/mail.maildir -j \"%%{user.directory}/%s\"", $2+2); 693 else 694 asprintf(&dsp->u.local.command, 695 "/usr/libexec/mail.maildir -j \"%s\"", $2); 696 } dispatcher_local_options 697 | LMTP STRING { 698 asprintf(&dsp->u.local.command, 699 "/usr/libexec/mail.lmtp -d %s -u", $2); 700 } dispatcher_local_options 701 | LMTP STRING RCPT_TO { 702 asprintf(&dsp->u.local.command, 703 "/usr/libexec/mail.lmtp -d %s -r", $2); 704 } dispatcher_local_options 705 | MDA STRING { 706 asprintf(&dsp->u.local.command, 707 "/usr/libexec/mail.mda \"%s\"", $2); 708 } dispatcher_local_options 709 | FORWARD_ONLY { 710 dsp->u.local.forward_only = 1; 711 } dispatcher_local_options 712 | EXPAND_ONLY { 713 dsp->u.local.expand_only = 1; 714 } dispatcher_local_options 715 716 ; 717 718 dispatcher_remote_option: 719 HELO STRING { 720 if (dsp->u.remote.helo) { 721 yyerror("helo already specified for this dispatcher"); 722 YYERROR; 723 } 724 725 dsp->u.remote.helo = $2; 726 } 727 | HELO_SRC tables { 728 struct table *t = $2; 729 730 if (dsp->u.remote.helo_source) { 731 yyerror("helo-source mapping already specified for this dispatcher"); 732 YYERROR; 733 } 734 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) { 735 yyerror("table \"%s\" may not be used for helo-source lookups", 736 t->t_name); 737 YYERROR; 738 } 739 740 dsp->u.remote.helo_source = strdup(t->t_name); 741 } 742 | PKI STRING { 743 if (dsp->u.remote.pki) { 744 yyerror("pki already specified for this dispatcher"); 745 YYERROR; 746 } 747 748 dsp->u.remote.pki = $2; 749 } 750 | CA STRING { 751 if (dsp->u.remote.ca) { 752 yyerror("ca already specified for this dispatcher"); 753 YYERROR; 754 } 755 756 dsp->u.remote.ca = $2; 757 } 758 | CIPHERS STRING { 759 if (dsp->u.remote.tls_ciphers) { 760 yyerror("ciphers already specified for this dispatcher"); 761 YYERROR; 762 } 763 764 dsp->u.remote.tls_ciphers = $2; 765 } 766 | PROTOCOLS STRING { 767 if (dsp->u.remote.tls_protocols) { 768 yyerror("protocols already specified for this dispatcher"); 769 YYERROR; 770 } 771 772 dsp->u.remote.tls_protocols = $2; 773 } 774 | SRC tables { 775 struct table *t = $2; 776 777 if (dsp->u.remote.source) { 778 yyerror("source mapping already specified for this dispatcher"); 779 YYERROR; 780 } 781 782 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_SOURCE)) { 783 yyerror("table \"%s\" may not be used for source lookups", 784 t->t_name); 785 YYERROR; 786 } 787 788 dsp->u.remote.source = strdup(t->t_name); 789 } 790 | MAIL_FROM STRING { 791 if (dsp->u.remote.mail_from) { 792 yyerror("mail-from already specified for this dispatcher"); 793 YYERROR; 794 } 795 796 dsp->u.remote.mail_from = $2; 797 } 798 | BACKUP MX STRING { 799 if (dsp->u.remote.backup) { 800 yyerror("backup already specified for this dispatcher"); 801 YYERROR; 802 } 803 if (dsp->u.remote.smarthost) { 804 yyerror("backup and host are mutually exclusive"); 805 YYERROR; 806 } 807 808 dsp->u.remote.backup = 1; 809 dsp->u.remote.backupmx = $3; 810 } 811 | BACKUP { 812 if (dsp->u.remote.backup) { 813 yyerror("backup already specified for this dispatcher"); 814 YYERROR; 815 } 816 if (dsp->u.remote.smarthost) { 817 yyerror("backup and host are mutually exclusive"); 818 YYERROR; 819 } 820 821 dsp->u.remote.backup = 1; 822 } 823 | HOST tables { 824 struct table *t = $2; 825 826 if (dsp->u.remote.smarthost) { 827 yyerror("host mapping already specified for this dispatcher"); 828 YYERROR; 829 } 830 if (dsp->u.remote.backup) { 831 yyerror("backup and host are mutually exclusive"); 832 YYERROR; 833 } 834 835 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_RELAYHOST)) { 836 yyerror("table \"%s\" may not be used for host lookups", 837 t->t_name); 838 YYERROR; 839 } 840 841 dsp->u.remote.smarthost = strdup(t->t_name); 842 } 843 | DOMAIN tables { 844 struct table *t = $2; 845 846 if (dsp->u.remote.smarthost) { 847 yyerror("host mapping already specified for this dispatcher"); 848 YYERROR; 849 } 850 if (dsp->u.remote.backup) { 851 yyerror("backup and domain are mutually exclusive"); 852 YYERROR; 853 } 854 855 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_RELAYHOST)) { 856 yyerror("table \"%s\" may not be used for host lookups", 857 t->t_name); 858 YYERROR; 859 } 860 861 dsp->u.remote.smarthost = strdup(t->t_name); 862 dsp->u.remote.smarthost_domain = 1; 863 } 864 | TLS { 865 if (dsp->u.remote.tls_required == 1) { 866 yyerror("tls already specified for this dispatcher"); 867 YYERROR; 868 } 869 870 dsp->u.remote.tls_required = 1; 871 dsp->u.remote.tls_verify = 1; 872 } 873 | TLS NO_VERIFY { 874 if (dsp->u.remote.tls_required == 1) { 875 yyerror("tls already specified for this dispatcher"); 876 YYERROR; 877 } 878 879 dsp->u.remote.tls_required = 1; 880 } 881 | AUTH tables { 882 struct table *t = $2; 883 884 if (dsp->u.remote.smarthost == NULL) { 885 yyerror("auth may not be specified without host on a dispatcher"); 886 YYERROR; 887 } 888 889 if (dsp->u.remote.auth) { 890 yyerror("auth mapping already specified for this dispatcher"); 891 YYERROR; 892 } 893 894 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_CREDENTIALS)) { 895 yyerror("table \"%s\" may not be used for auth lookups", 896 t->t_name); 897 YYERROR; 898 } 899 900 dsp->u.remote.auth = strdup(t->t_name); 901 } 902 | FILTER STRING { 903 struct filter_config *fc; 904 905 if (dsp->u.remote.filtername) { 906 yyerror("filter already specified for this dispatcher"); 907 YYERROR; 908 } 909 910 if ((fc = dict_get(conf->sc_filters_dict, $2)) == NULL) { 911 yyerror("no filter exist with that name: %s", $2); 912 free($2); 913 YYERROR; 914 } 915 fc->filter_subsystem |= FILTER_SUBSYSTEM_SMTP_OUT; 916 dsp->u.remote.filtername = $2; 917 } 918 | FILTER { 919 char buffer[128]; 920 char *filtername; 921 922 if (dsp->u.remote.filtername) { 923 yyerror("filter already specified for this dispatcher"); 924 YYERROR; 925 } 926 927 do { 928 (void)snprintf(buffer, sizeof buffer, "<dynchain:%08x>", last_dynchain_id++); 929 } while (dict_check(conf->sc_filters_dict, buffer)); 930 931 filtername = xstrdup(buffer); 932 filter_config = xcalloc(1, sizeof *filter_config); 933 filter_config->filter_type = FILTER_TYPE_CHAIN; 934 filter_config->filter_subsystem |= FILTER_SUBSYSTEM_SMTP_OUT; 935 dict_init(&filter_config->chain_procs); 936 dsp->u.remote.filtername = filtername; 937 } '{' optnl filter_list '}' { 938 dict_set(conf->sc_filters_dict, dsp->u.remote.filtername, filter_config); 939 filter_config = NULL; 940 } 941 | SRS { 942 if (conf->sc_srs_key == NULL) { 943 yyerror("an srs key is required for srs to be specified in an action"); 944 YYERROR; 945 } 946 if (dsp->u.remote.srs == 1) { 947 yyerror("srs already specified for this dispatcher"); 948 YYERROR; 949 } 950 951 dsp->u.remote.srs = 1; 952 } 953 ; 954 955 dispatcher_remote_options: 956 dispatcher_remote_option dispatcher_remote_options 957 | /* empty */ 958 ; 959 960 dispatcher_remote : 961 RELAY dispatcher_remote_options 962 ; 963 964 dispatcher_type: 965 dispatcher_local { 966 dsp->type = DISPATCHER_LOCAL; 967 } 968 | dispatcher_remote { 969 dsp->type = DISPATCHER_REMOTE; 970 } 971 ; 972 973 dispatcher_option: 974 TTL STRING { 975 if (dsp->ttl) { 976 yyerror("ttl already specified for this dispatcher"); 977 YYERROR; 978 } 979 980 dsp->ttl = delaytonum($2); 981 if (dsp->ttl == -1) { 982 yyerror("ttl delay \"%s\" is invalid", $2); 983 free($2); 984 YYERROR; 985 } 986 free($2); 987 } 988 ; 989 990 dispatcher_options: 991 dispatcher_option dispatcher_options 992 | /* empty */ 993 ; 994 995 dispatcher: 996 ACTION STRING { 997 if (dict_get(conf->sc_dispatchers, $2)) { 998 yyerror("dispatcher already declared with that name: %s", $2); 999 YYERROR; 1000 } 1001 dsp = xcalloc(1, sizeof *dsp); 1002 } dispatcher_type dispatcher_options { 1003 if (dsp->type == DISPATCHER_LOCAL) 1004 if (dsp->u.local.table_userbase == NULL) 1005 dsp->u.local.table_userbase = "<getpwnam>"; 1006 dict_set(conf->sc_dispatchers, $2, dsp); 1007 dsp = NULL; 1008 } 1009 ; 1010 1011 match_option: 1012 negation TAG tables { 1013 struct table *t = $3; 1014 1015 if (rule->flag_tag) { 1016 yyerror("tag already specified for this rule"); 1017 YYERROR; 1018 } 1019 1020 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_STRING)) { 1021 yyerror("table \"%s\" may not be used for tag lookups", 1022 t->t_name); 1023 YYERROR; 1024 } 1025 1026 rule->flag_tag = $1 ? -1 : 1; 1027 rule->table_tag = strdup(t->t_name); 1028 } 1029 | 1030 negation TAG REGEX tables { 1031 struct table *t = $4; 1032 1033 if (rule->flag_tag) { 1034 yyerror("tag already specified for this rule"); 1035 YYERROR; 1036 } 1037 1038 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1039 yyerror("table \"%s\" may not be used for tag lookups", 1040 t->t_name); 1041 YYERROR; 1042 } 1043 1044 rule->flag_tag = $1 ? -1 : 1; 1045 rule->flag_tag_regex = 1; 1046 rule->table_tag = strdup(t->t_name); 1047 } 1048 1049 | negation HELO tables { 1050 struct table *t = $3; 1051 1052 if (rule->flag_smtp_helo) { 1053 yyerror("helo already specified for this rule"); 1054 YYERROR; 1055 } 1056 1057 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) { 1058 yyerror("table \"%s\" may not be used for helo lookups", 1059 t->t_name); 1060 YYERROR; 1061 } 1062 1063 rule->flag_smtp_helo = $1 ? -1 : 1; 1064 rule->table_smtp_helo = strdup(t->t_name); 1065 } 1066 | negation HELO REGEX tables { 1067 struct table *t = $4; 1068 1069 if (rule->flag_smtp_helo) { 1070 yyerror("helo already specified for this rule"); 1071 YYERROR; 1072 } 1073 1074 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1075 yyerror("table \"%s\" may not be used for helo lookups", 1076 t->t_name); 1077 YYERROR; 1078 } 1079 1080 rule->flag_smtp_helo = $1 ? -1 : 1; 1081 rule->flag_smtp_helo_regex = 1; 1082 rule->table_smtp_helo = strdup(t->t_name); 1083 } 1084 | negation TLS { 1085 if (rule->flag_smtp_starttls) { 1086 yyerror("tls already specified for this rule"); 1087 YYERROR; 1088 } 1089 rule->flag_smtp_starttls = $1 ? -1 : 1; 1090 } 1091 | negation AUTH { 1092 if (rule->flag_smtp_auth) { 1093 yyerror("auth already specified for this rule"); 1094 YYERROR; 1095 } 1096 rule->flag_smtp_auth = $1 ? -1 : 1; 1097 } 1098 | negation AUTH tables { 1099 struct table *t = $3; 1100 1101 if (rule->flag_smtp_auth) { 1102 yyerror("auth already specified for this rule"); 1103 YYERROR; 1104 } 1105 1106 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_STRING|K_CREDENTIALS)) { 1107 yyerror("table \"%s\" may not be used for auth lookups", 1108 t->t_name); 1109 YYERROR; 1110 } 1111 1112 rule->flag_smtp_auth = $1 ? -1 : 1; 1113 rule->table_smtp_auth = strdup(t->t_name); 1114 } 1115 | negation AUTH REGEX tables { 1116 struct table *t = $4; 1117 1118 if (rule->flag_smtp_auth) { 1119 yyerror("auth already specified for this rule"); 1120 YYERROR; 1121 } 1122 1123 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1124 yyerror("table \"%s\" may not be used for auth lookups", 1125 t->t_name); 1126 YYERROR; 1127 } 1128 1129 rule->flag_smtp_auth = $1 ? -1 : 1; 1130 rule->flag_smtp_auth_regex = 1; 1131 rule->table_smtp_auth = strdup(t->t_name); 1132 } 1133 | negation MAIL_FROM tables { 1134 struct table *t = $3; 1135 1136 if (rule->flag_smtp_mail_from) { 1137 yyerror("mail-from already specified for this rule"); 1138 YYERROR; 1139 } 1140 1141 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 1142 yyerror("table \"%s\" may not be used for mail-from lookups", 1143 t->t_name); 1144 YYERROR; 1145 } 1146 1147 rule->flag_smtp_mail_from = $1 ? -1 : 1; 1148 rule->table_smtp_mail_from = strdup(t->t_name); 1149 } 1150 | negation MAIL_FROM REGEX tables { 1151 struct table *t = $4; 1152 1153 if (rule->flag_smtp_mail_from) { 1154 yyerror("mail-from already specified for this rule"); 1155 YYERROR; 1156 } 1157 1158 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1159 yyerror("table \"%s\" may not be used for mail-from lookups", 1160 t->t_name); 1161 YYERROR; 1162 } 1163 1164 rule->flag_smtp_mail_from = $1 ? -1 : 1; 1165 rule->flag_smtp_mail_from_regex = 1; 1166 rule->table_smtp_mail_from = strdup(t->t_name); 1167 } 1168 | negation RCPT_TO tables { 1169 struct table *t = $3; 1170 1171 if (rule->flag_smtp_rcpt_to) { 1172 yyerror("rcpt-to already specified for this rule"); 1173 YYERROR; 1174 } 1175 1176 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 1177 yyerror("table \"%s\" may not be used for rcpt-to lookups", 1178 t->t_name); 1179 YYERROR; 1180 } 1181 1182 rule->flag_smtp_rcpt_to = $1 ? -1 : 1; 1183 rule->table_smtp_rcpt_to = strdup(t->t_name); 1184 } 1185 | negation RCPT_TO REGEX tables { 1186 struct table *t = $4; 1187 1188 if (rule->flag_smtp_rcpt_to) { 1189 yyerror("rcpt-to already specified for this rule"); 1190 YYERROR; 1191 } 1192 1193 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1194 yyerror("table \"%s\" may not be used for rcpt-to lookups", 1195 t->t_name); 1196 YYERROR; 1197 } 1198 1199 rule->flag_smtp_rcpt_to = $1 ? -1 : 1; 1200 rule->flag_smtp_rcpt_to_regex = 1; 1201 rule->table_smtp_rcpt_to = strdup(t->t_name); 1202 } 1203 1204 | negation FROM SOCKET { 1205 if (rule->flag_from) { 1206 yyerror("from already specified for this rule"); 1207 YYERROR; 1208 } 1209 rule->flag_from = $1 ? -1 : 1; 1210 rule->flag_from_socket = 1; 1211 } 1212 | negation FROM LOCAL { 1213 struct table *t = table_find(conf, "<localhost>"); 1214 1215 if (rule->flag_from) { 1216 yyerror("from already specified for this rule"); 1217 YYERROR; 1218 } 1219 rule->flag_from = $1 ? -1 : 1; 1220 rule->table_from = strdup(t->t_name); 1221 } 1222 | negation FROM ANY { 1223 struct table *t = table_find(conf, "<anyhost>"); 1224 1225 if (rule->flag_from) { 1226 yyerror("from already specified for this rule"); 1227 YYERROR; 1228 } 1229 rule->flag_from = $1 ? -1 : 1; 1230 rule->table_from = strdup(t->t_name); 1231 } 1232 | negation FROM SRC tables { 1233 struct table *t = $4; 1234 1235 if (rule->flag_from) { 1236 yyerror("from already specified for this rule"); 1237 YYERROR; 1238 } 1239 1240 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_NETADDR)) { 1241 yyerror("table \"%s\" may not be used for from lookups", 1242 t->t_name); 1243 YYERROR; 1244 } 1245 1246 rule->flag_from = $1 ? -1 : 1; 1247 rule->table_from = strdup(t->t_name); 1248 } 1249 | negation FROM SRC REGEX tables { 1250 struct table *t = $5; 1251 1252 if (rule->flag_from) { 1253 yyerror("from already specified for this rule"); 1254 YYERROR; 1255 } 1256 1257 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1258 yyerror("table \"%s\" may not be used for from lookups", 1259 t->t_name); 1260 YYERROR; 1261 } 1262 1263 rule->flag_from = $1 ? -1 : 1; 1264 rule->flag_from_regex = 1; 1265 rule->table_from = strdup(t->t_name); 1266 } 1267 | negation FROM RDNS { 1268 if (rule->flag_from) { 1269 yyerror("from already specified for this rule"); 1270 YYERROR; 1271 } 1272 rule->flag_from = $1 ? -1 : 1; 1273 rule->flag_from_rdns = 1; 1274 } 1275 | negation FROM RDNS tables { 1276 struct table *t = $4; 1277 1278 if (rule->flag_from) { 1279 yyerror("from already specified for this rule"); 1280 YYERROR; 1281 } 1282 1283 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) { 1284 yyerror("table \"%s\" may not be used for rdns lookups", 1285 t->t_name); 1286 YYERROR; 1287 } 1288 1289 rule->flag_from = $1 ? -1 : 1; 1290 rule->flag_from_rdns = 1; 1291 rule->table_from = strdup(t->t_name); 1292 } 1293 | negation FROM RDNS REGEX tables { 1294 struct table *t = $5; 1295 1296 if (rule->flag_from) { 1297 yyerror("from already specified for this rule"); 1298 YYERROR; 1299 } 1300 1301 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) { 1302 yyerror("table \"%s\" may not be used for rdns lookups", 1303 t->t_name); 1304 YYERROR; 1305 } 1306 1307 rule->flag_from = $1 ? -1 : 1; 1308 rule->flag_from_regex = 1; 1309 rule->flag_from_rdns = 1; 1310 rule->table_from = strdup(t->t_name); 1311 } 1312 1313 | negation FROM AUTH { 1314 struct table *anyhost = table_find(conf, "<anyhost>"); 1315 1316 if (rule->flag_from) { 1317 yyerror("from already specified for this rule"); 1318 YYERROR; 1319 } 1320 1321 rule->flag_from = 1; 1322 rule->table_from = strdup(anyhost->t_name); 1323 rule->flag_smtp_auth = $1 ? -1 : 1; 1324 } 1325 | negation FROM AUTH tables { 1326 struct table *anyhost = table_find(conf, "<anyhost>"); 1327 struct table *t = $4; 1328 1329 if (rule->flag_from) { 1330 yyerror("from already specified for this rule"); 1331 YYERROR; 1332 } 1333 1334 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_STRING|K_CREDENTIALS)) { 1335 yyerror("table \"%s\" may not be used for from lookups", 1336 t->t_name); 1337 YYERROR; 1338 } 1339 1340 rule->flag_from = 1; 1341 rule->table_from = strdup(anyhost->t_name); 1342 rule->flag_smtp_auth = $1 ? -1 : 1; 1343 rule->table_smtp_auth = strdup(t->t_name); 1344 } 1345 | negation FROM AUTH REGEX tables { 1346 struct table *anyhost = table_find(conf, "<anyhost>"); 1347 struct table *t = $5; 1348 1349 if (rule->flag_from) { 1350 yyerror("from already specified for this rule"); 1351 YYERROR; 1352 } 1353 1354 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1355 yyerror("table \"%s\" may not be used for from lookups", 1356 t->t_name); 1357 YYERROR; 1358 } 1359 1360 rule->flag_from = 1; 1361 rule->table_from = strdup(anyhost->t_name); 1362 rule->flag_smtp_auth = $1 ? -1 : 1; 1363 rule->flag_smtp_auth_regex = 1; 1364 rule->table_smtp_auth = strdup(t->t_name); 1365 } 1366 1367 | negation FROM MAIL_FROM tables { 1368 struct table *anyhost = table_find(conf, "<anyhost>"); 1369 struct table *t = $4; 1370 1371 if (rule->flag_from) { 1372 yyerror("from already specified for this rule"); 1373 YYERROR; 1374 } 1375 1376 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 1377 yyerror("table \"%s\" may not be used for from lookups", 1378 t->t_name); 1379 YYERROR; 1380 } 1381 1382 rule->flag_from = 1; 1383 rule->table_from = strdup(anyhost->t_name); 1384 rule->flag_smtp_mail_from = $1 ? -1 : 1; 1385 rule->table_smtp_mail_from = strdup(t->t_name); 1386 } 1387 | negation FROM MAIL_FROM REGEX tables { 1388 struct table *anyhost = table_find(conf, "<anyhost>"); 1389 struct table *t = $5; 1390 1391 if (rule->flag_from) { 1392 yyerror("from already specified for this rule"); 1393 YYERROR; 1394 } 1395 1396 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1397 yyerror("table \"%s\" may not be used for from lookups", 1398 t->t_name); 1399 YYERROR; 1400 } 1401 1402 rule->flag_from = 1; 1403 rule->table_from = strdup(anyhost->t_name); 1404 rule->flag_smtp_mail_from = $1 ? -1 : 1; 1405 rule->flag_smtp_mail_from_regex = 1; 1406 rule->table_smtp_mail_from = strdup(t->t_name); 1407 } 1408 1409 | negation FOR LOCAL { 1410 struct table *t = table_find(conf, "<localnames>"); 1411 1412 if (rule->flag_for) { 1413 yyerror("for already specified for this rule"); 1414 YYERROR; 1415 } 1416 rule->flag_for = $1 ? -1 : 1; 1417 rule->table_for = strdup(t->t_name); 1418 } 1419 | negation FOR ANY { 1420 struct table *t = table_find(conf, "<anydestination>"); 1421 1422 if (rule->flag_for) { 1423 yyerror("for already specified for this rule"); 1424 YYERROR; 1425 } 1426 rule->flag_for = $1 ? -1 : 1; 1427 rule->table_for = strdup(t->t_name); 1428 } 1429 | negation FOR DOMAIN tables { 1430 struct table *t = $4; 1431 1432 if (rule->flag_for) { 1433 yyerror("for already specified for this rule"); 1434 YYERROR; 1435 } 1436 1437 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) { 1438 yyerror("table \"%s\" may not be used for 'for' lookups", 1439 t->t_name); 1440 YYERROR; 1441 } 1442 1443 rule->flag_for = $1 ? -1 : 1; 1444 rule->table_for = strdup(t->t_name); 1445 } 1446 | negation FOR DOMAIN REGEX tables { 1447 struct table *t = $5; 1448 1449 if (rule->flag_for) { 1450 yyerror("for already specified for this rule"); 1451 YYERROR; 1452 } 1453 1454 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1455 yyerror("table \"%s\" may not be used for 'for' lookups", 1456 t->t_name); 1457 YYERROR; 1458 } 1459 1460 rule->flag_for = $1 ? -1 : 1; 1461 rule->flag_for_regex = 1; 1462 rule->table_for = strdup(t->t_name); 1463 } 1464 | negation FOR RCPT_TO tables { 1465 struct table *anyhost = table_find(conf, "<anydestination>"); 1466 struct table *t = $4; 1467 1468 if (rule->flag_for) { 1469 yyerror("for already specified for this rule"); 1470 YYERROR; 1471 } 1472 1473 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 1474 yyerror("table \"%s\" may not be used for for lookups", 1475 t->t_name); 1476 YYERROR; 1477 } 1478 1479 rule->flag_for = 1; 1480 rule->table_for = strdup(anyhost->t_name); 1481 rule->flag_smtp_rcpt_to = $1 ? -1 : 1; 1482 rule->table_smtp_rcpt_to = strdup(t->t_name); 1483 } 1484 | negation FOR RCPT_TO REGEX tables { 1485 struct table *anyhost = table_find(conf, "<anydestination>"); 1486 struct table *t = $5; 1487 1488 if (rule->flag_for) { 1489 yyerror("for already specified for this rule"); 1490 YYERROR; 1491 } 1492 1493 if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) { 1494 yyerror("table \"%s\" may not be used for for lookups", 1495 t->t_name); 1496 YYERROR; 1497 } 1498 1499 rule->flag_for = 1; 1500 rule->table_for = strdup(anyhost->t_name); 1501 rule->flag_smtp_rcpt_to = $1 ? -1 : 1; 1502 rule->flag_smtp_rcpt_to_regex = 1; 1503 rule->table_smtp_rcpt_to = strdup(t->t_name); 1504 } 1505 ; 1506 1507 match_options: 1508 match_option match_options 1509 | /* empty */ 1510 ; 1511 1512 match_dispatcher: 1513 STRING { 1514 if (dict_get(conf->sc_dispatchers, $1) == NULL) { 1515 yyerror("no such dispatcher: %s", $1); 1516 YYERROR; 1517 } 1518 rule->dispatcher = $1; 1519 } 1520 ; 1521 1522 action: 1523 REJECT { 1524 rule->reject = 1; 1525 } 1526 | ACTION match_dispatcher 1527 ; 1528 1529 match: 1530 MATCH { 1531 rule = xcalloc(1, sizeof *rule); 1532 } match_options action { 1533 if (!rule->flag_from) { 1534 rule->table_from = strdup("<localhost>"); 1535 rule->flag_from = 1; 1536 } 1537 if (!rule->flag_for) { 1538 rule->table_for = strdup("<localnames>"); 1539 rule->flag_for = 1; 1540 } 1541 TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry); 1542 rule = NULL; 1543 } 1544 ; 1545 1546 filter_action_builtin: 1547 filter_action_builtin_nojunk 1548 | JUNK { 1549 filter_config->junk = 1; 1550 } 1551 | BYPASS { 1552 filter_config->bypass = 1; 1553 } 1554 ; 1555 1556 filter_action_builtin_nojunk: 1557 REJECT STRING { 1558 filter_config->reject = $2; 1559 } 1560 | DISCONNECT STRING { 1561 filter_config->disconnect = $2; 1562 } 1563 | REWRITE STRING { 1564 filter_config->rewrite = $2; 1565 } 1566 | REPORT STRING { 1567 filter_config->report = $2; 1568 } 1569 ; 1570 1571 filter_phase_check_fcrdns: 1572 negation FCRDNS { 1573 filter_config->not_fcrdns = $1 ? -1 : 1; 1574 filter_config->fcrdns = 1; 1575 } 1576 ; 1577 1578 filter_phase_check_rdns: 1579 negation RDNS { 1580 filter_config->not_rdns = $1 ? -1 : 1; 1581 filter_config->rdns = 1; 1582 } 1583 ; 1584 1585 filter_phase_check_rdns_table: 1586 negation RDNS tables { 1587 filter_config->not_rdns_table = $1 ? -1 : 1; 1588 filter_config->rdns_table = $3; 1589 } 1590 ; 1591 filter_phase_check_rdns_regex: 1592 negation RDNS REGEX tables { 1593 filter_config->not_rdns_regex = $1 ? -1 : 1; 1594 filter_config->rdns_regex = $4; 1595 } 1596 ; 1597 1598 filter_phase_check_src_table: 1599 negation SRC tables { 1600 filter_config->not_src_table = $1 ? -1 : 1; 1601 filter_config->src_table = $3; 1602 } 1603 ; 1604 filter_phase_check_src_regex: 1605 negation SRC REGEX tables { 1606 filter_config->not_src_regex = $1 ? -1 : 1; 1607 filter_config->src_regex = $4; 1608 } 1609 ; 1610 1611 filter_phase_check_helo_table: 1612 negation HELO tables { 1613 filter_config->not_helo_table = $1 ? -1 : 1; 1614 filter_config->helo_table = $3; 1615 } 1616 ; 1617 filter_phase_check_helo_regex: 1618 negation HELO REGEX tables { 1619 filter_config->not_helo_regex = $1 ? -1 : 1; 1620 filter_config->helo_regex = $4; 1621 } 1622 ; 1623 1624 filter_phase_check_auth: 1625 negation AUTH { 1626 filter_config->not_auth = $1 ? -1 : 1; 1627 filter_config->auth = 1; 1628 } 1629 ; 1630 filter_phase_check_auth_table: 1631 negation AUTH tables { 1632 filter_config->not_auth_table = $1 ? -1 : 1; 1633 filter_config->auth_table = $3; 1634 } 1635 ; 1636 filter_phase_check_auth_regex: 1637 negation AUTH REGEX tables { 1638 filter_config->not_auth_regex = $1 ? -1 : 1; 1639 filter_config->auth_regex = $4; 1640 } 1641 ; 1642 1643 filter_phase_check_mail_from_table: 1644 negation MAIL_FROM tables { 1645 filter_config->not_mail_from_table = $1 ? -1 : 1; 1646 filter_config->mail_from_table = $3; 1647 } 1648 ; 1649 filter_phase_check_mail_from_regex: 1650 negation MAIL_FROM REGEX tables { 1651 filter_config->not_mail_from_regex = $1 ? -1 : 1; 1652 filter_config->mail_from_regex = $4; 1653 } 1654 ; 1655 1656 filter_phase_check_rcpt_to_table: 1657 negation RCPT_TO tables { 1658 filter_config->not_rcpt_to_table = $1 ? -1 : 1; 1659 filter_config->rcpt_to_table = $3; 1660 } 1661 ; 1662 filter_phase_check_rcpt_to_regex: 1663 negation RCPT_TO REGEX tables { 1664 filter_config->not_rcpt_to_regex = $1 ? -1 : 1; 1665 filter_config->rcpt_to_regex = $4; 1666 } 1667 ; 1668 1669 filter_phase_global_options: 1670 filter_phase_check_fcrdns | 1671 filter_phase_check_rdns | 1672 filter_phase_check_rdns_regex | 1673 filter_phase_check_rdns_table | 1674 filter_phase_check_src_regex | 1675 filter_phase_check_src_table; 1676 1677 filter_phase_connect_options: 1678 filter_phase_global_options; 1679 1680 filter_phase_helo_options: 1681 filter_phase_check_helo_table | 1682 filter_phase_check_helo_regex | 1683 filter_phase_global_options; 1684 1685 filter_phase_auth_options: 1686 filter_phase_check_helo_table | 1687 filter_phase_check_helo_regex | 1688 filter_phase_check_auth | 1689 filter_phase_check_auth_table | 1690 filter_phase_check_auth_regex | 1691 filter_phase_global_options; 1692 1693 filter_phase_mail_from_options: 1694 filter_phase_check_helo_table | 1695 filter_phase_check_helo_regex | 1696 filter_phase_check_auth | 1697 filter_phase_check_auth_table | 1698 filter_phase_check_auth_regex | 1699 filter_phase_check_mail_from_table | 1700 filter_phase_check_mail_from_regex | 1701 filter_phase_global_options; 1702 1703 filter_phase_rcpt_to_options: 1704 filter_phase_check_helo_table | 1705 filter_phase_check_helo_regex | 1706 filter_phase_check_auth | 1707 filter_phase_check_auth_table | 1708 filter_phase_check_auth_regex | 1709 filter_phase_check_mail_from_table | 1710 filter_phase_check_mail_from_regex | 1711 filter_phase_check_rcpt_to_table | 1712 filter_phase_check_rcpt_to_regex | 1713 filter_phase_global_options; 1714 1715 filter_phase_data_options: 1716 filter_phase_check_helo_table | 1717 filter_phase_check_helo_regex | 1718 filter_phase_check_auth | 1719 filter_phase_check_auth_table | 1720 filter_phase_check_auth_regex | 1721 filter_phase_check_mail_from_table | 1722 filter_phase_check_mail_from_regex | 1723 filter_phase_global_options; 1724 1725 /* 1726 filter_phase_quit_options: 1727 filter_phase_check_helo_table | 1728 filter_phase_check_helo_regex | 1729 filter_phase_global_options; 1730 1731 filter_phase_rset_options: 1732 filter_phase_check_helo_table | 1733 filter_phase_check_helo_regex | 1734 filter_phase_global_options; 1735 1736 filter_phase_noop_options: 1737 filter_phase_check_helo_table | 1738 filter_phase_check_helo_regex | 1739 filter_phase_global_options; 1740 */ 1741 1742 filter_phase_commit_options: 1743 filter_phase_check_helo_table | 1744 filter_phase_check_helo_regex | 1745 filter_phase_check_auth | 1746 filter_phase_check_auth_table | 1747 filter_phase_check_auth_regex | 1748 filter_phase_check_mail_from_table | 1749 filter_phase_check_mail_from_regex | 1750 filter_phase_global_options; 1751 1752 1753 filter_phase_connect: 1754 CONNECT { 1755 filter_config->phase = FILTER_CONNECT; 1756 } MATCH filter_phase_connect_options filter_action_builtin 1757 ; 1758 1759 1760 filter_phase_helo: 1761 HELO { 1762 filter_config->phase = FILTER_HELO; 1763 } MATCH filter_phase_helo_options filter_action_builtin 1764 ; 1765 1766 filter_phase_ehlo: 1767 EHLO { 1768 filter_config->phase = FILTER_EHLO; 1769 } MATCH filter_phase_helo_options filter_action_builtin 1770 ; 1771 1772 filter_phase_auth: 1773 AUTH { 1774 } MATCH filter_phase_auth_options filter_action_builtin 1775 ; 1776 1777 filter_phase_mail_from: 1778 MAIL_FROM { 1779 filter_config->phase = FILTER_MAIL_FROM; 1780 } MATCH filter_phase_mail_from_options filter_action_builtin 1781 ; 1782 1783 filter_phase_rcpt_to: 1784 RCPT_TO { 1785 filter_config->phase = FILTER_RCPT_TO; 1786 } MATCH filter_phase_rcpt_to_options filter_action_builtin 1787 ; 1788 1789 filter_phase_data: 1790 DATA { 1791 filter_config->phase = FILTER_DATA; 1792 } MATCH filter_phase_data_options filter_action_builtin 1793 ; 1794 1795 /* 1796 filter_phase_data_line: 1797 DATA_LINE { 1798 filter_config->phase = FILTER_DATA_LINE; 1799 } MATCH filter_action_builtin 1800 ; 1801 1802 filter_phase_quit: 1803 QUIT { 1804 filter_config->phase = FILTER_QUIT; 1805 } filter_phase_quit_options filter_action_builtin 1806 ; 1807 1808 filter_phase_rset: 1809 RSET { 1810 filter_config->phase = FILTER_RSET; 1811 } MATCH filter_phase_rset_options filter_action_builtin 1812 ; 1813 1814 filter_phase_noop: 1815 NOOP { 1816 filter_config->phase = FILTER_NOOP; 1817 } MATCH filter_phase_noop_options filter_action_builtin 1818 ; 1819 */ 1820 1821 filter_phase_commit: 1822 COMMIT { 1823 filter_config->phase = FILTER_COMMIT; 1824 } MATCH filter_phase_commit_options filter_action_builtin_nojunk 1825 ; 1826 1827 1828 1829 filter_phase: 1830 filter_phase_connect 1831 | filter_phase_helo 1832 | filter_phase_ehlo 1833 | filter_phase_auth 1834 | filter_phase_mail_from 1835 | filter_phase_rcpt_to 1836 | filter_phase_data 1837 /*| filter_phase_data_line*/ 1838 /*| filter_phase_quit*/ 1839 /*| filter_phase_noop*/ 1840 /*| filter_phase_rset*/ 1841 | filter_phase_commit 1842 ; 1843 1844 1845 filterel: 1846 STRING { 1847 struct filter_config *fr; 1848 size_t i; 1849 1850 if ((fr = dict_get(conf->sc_filters_dict, $1)) == NULL) { 1851 yyerror("no filter exist with that name: %s", $1); 1852 free($1); 1853 YYERROR; 1854 } 1855 if (fr->filter_type == FILTER_TYPE_CHAIN) { 1856 yyerror("no filter chain allowed within a filter chain: %s", $1); 1857 free($1); 1858 YYERROR; 1859 } 1860 1861 for (i = 0; i < filter_config->chain_size; i++) { 1862 if (strcmp(filter_config->chain[i], $1) == 0) { 1863 yyerror("no filter allowed twice within a filter chain: %s", $1); 1864 free($1); 1865 YYERROR; 1866 } 1867 } 1868 1869 if (fr->proc) { 1870 if (dict_get(&filter_config->chain_procs, fr->proc)) { 1871 yyerror("no proc allowed twice within a filter chain: %s", fr->proc); 1872 free($1); 1873 YYERROR; 1874 } 1875 dict_set(&filter_config->chain_procs, fr->proc, NULL); 1876 } 1877 1878 fr->filter_subsystem |= filter_config->filter_subsystem; 1879 filter_config->chain_size += 1; 1880 filter_config->chain = reallocarray(filter_config->chain, filter_config->chain_size, sizeof(char *)); 1881 if (filter_config->chain == NULL) 1882 fatal("reallocarray"); 1883 filter_config->chain[filter_config->chain_size - 1] = $1; 1884 } 1885 ; 1886 1887 filter_list: 1888 filterel optnl 1889 | filterel comma filter_list 1890 ; 1891 1892 filter: 1893 FILTER STRING PROC STRING { 1894 1895 if (dict_get(conf->sc_filters_dict, $2)) { 1896 yyerror("filter already exists with that name: %s", $2); 1897 free($2); 1898 free($4); 1899 YYERROR; 1900 } 1901 if (dict_get(conf->sc_filter_processes_dict, $4) == NULL) { 1902 yyerror("no processor exist with that name: %s", $4); 1903 free($4); 1904 YYERROR; 1905 } 1906 1907 filter_config = xcalloc(1, sizeof *filter_config); 1908 filter_config->filter_type = FILTER_TYPE_PROC; 1909 filter_config->name = $2; 1910 filter_config->proc = $4; 1911 dict_set(conf->sc_filters_dict, $2, filter_config); 1912 filter_config = NULL; 1913 } 1914 | 1915 FILTER STRING PROC_EXEC STRING { 1916 if (dict_get(conf->sc_filters_dict, $2)) { 1917 yyerror("filter already exists with that name: %s", $2); 1918 free($2); 1919 free($4); 1920 YYERROR; 1921 } 1922 1923 processor = xcalloc(1, sizeof *processor); 1924 processor->command = $4; 1925 1926 filter_config = xcalloc(1, sizeof *filter_config); 1927 filter_config->filter_type = FILTER_TYPE_PROC; 1928 filter_config->name = $2; 1929 filter_config->proc = xstrdup($2); 1930 dict_set(conf->sc_filters_dict, $2, filter_config); 1931 } proc_params { 1932 dict_set(conf->sc_filter_processes_dict, filter_config->proc, processor); 1933 processor = NULL; 1934 filter_config = NULL; 1935 } 1936 | 1937 FILTER STRING PHASE { 1938 if (dict_get(conf->sc_filters_dict, $2)) { 1939 yyerror("filter already exists with that name: %s", $2); 1940 free($2); 1941 YYERROR; 1942 } 1943 filter_config = xcalloc(1, sizeof *filter_config); 1944 filter_config->name = $2; 1945 filter_config->filter_type = FILTER_TYPE_BUILTIN; 1946 dict_set(conf->sc_filters_dict, $2, filter_config); 1947 } filter_phase { 1948 filter_config = NULL; 1949 } 1950 | 1951 FILTER STRING CHAIN { 1952 if (dict_get(conf->sc_filters_dict, $2)) { 1953 yyerror("filter already exists with that name: %s", $2); 1954 free($2); 1955 YYERROR; 1956 } 1957 filter_config = xcalloc(1, sizeof *filter_config); 1958 filter_config->filter_type = FILTER_TYPE_CHAIN; 1959 dict_init(&filter_config->chain_procs); 1960 } '{' optnl filter_list '}' { 1961 dict_set(conf->sc_filters_dict, $2, filter_config); 1962 filter_config = NULL; 1963 } 1964 ; 1965 1966 size : NUMBER { 1967 if ($1 < 0) { 1968 yyerror("invalid size: %" PRId64, $1); 1969 YYERROR; 1970 } 1971 $$ = $1; 1972 } 1973 | STRING { 1974 long long result; 1975 1976 if (scan_scaled($1, &result) == -1 || result < 0) { 1977 yyerror("invalid size: %s", $1); 1978 free($1); 1979 YYERROR; 1980 } 1981 free($1); 1982 $$ = result; 1983 } 1984 ; 1985 1986 bouncedelay : STRING { 1987 time_t d; 1988 int i; 1989 1990 d = delaytonum($1); 1991 if (d < 0) { 1992 yyerror("invalid bounce delay: %s", $1); 1993 free($1); 1994 YYERROR; 1995 } 1996 free($1); 1997 for (i = 0; i < MAX_BOUNCE_WARN; i++) { 1998 if (conf->sc_bounce_warn[i] != 0) 1999 continue; 2000 conf->sc_bounce_warn[i] = d; 2001 break; 2002 } 2003 } 2004 ; 2005 2006 bouncedelays : bouncedelays ',' bouncedelay 2007 | bouncedelay 2008 ; 2009 2010 opt_limit_mda : STRING NUMBER { 2011 if (!strcmp($1, "max-session")) { 2012 conf->sc_mda_max_session = $2; 2013 } 2014 else if (!strcmp($1, "max-session-per-user")) { 2015 conf->sc_mda_max_user_session = $2; 2016 } 2017 else if (!strcmp($1, "task-lowat")) { 2018 conf->sc_mda_task_lowat = $2; 2019 } 2020 else if (!strcmp($1, "task-hiwat")) { 2021 conf->sc_mda_task_hiwat = $2; 2022 } 2023 else if (!strcmp($1, "task-release")) { 2024 conf->sc_mda_task_release = $2; 2025 } 2026 else { 2027 yyerror("invalid scheduler limit keyword: %s", $1); 2028 free($1); 2029 YYERROR; 2030 } 2031 free($1); 2032 } 2033 ; 2034 2035 limits_smtp : opt_limit_smtp limits_smtp 2036 | /* empty */ 2037 ; 2038 2039 opt_limit_smtp : STRING NUMBER { 2040 if (!strcmp($1, "max-rcpt")) { 2041 conf->sc_session_max_rcpt = $2; 2042 } 2043 else if (!strcmp($1, "max-mails")) { 2044 conf->sc_session_max_mails = $2; 2045 } 2046 else { 2047 yyerror("invalid session limit keyword: %s", $1); 2048 free($1); 2049 YYERROR; 2050 } 2051 free($1); 2052 } 2053 ; 2054 2055 limits_mda : opt_limit_mda limits_mda 2056 | /* empty */ 2057 ; 2058 2059 opt_limit_mta : INET4 { 2060 limits->family = AF_INET; 2061 } 2062 | INET6 { 2063 limits->family = AF_INET6; 2064 } 2065 | STRING NUMBER { 2066 if (!limit_mta_set(limits, $1, $2)) { 2067 yyerror("invalid mta limit keyword: %s", $1); 2068 free($1); 2069 YYERROR; 2070 } 2071 free($1); 2072 } 2073 ; 2074 2075 limits_mta : opt_limit_mta limits_mta 2076 | /* empty */ 2077 ; 2078 2079 opt_limit_scheduler : STRING NUMBER { 2080 if (!strcmp($1, "max-inflight")) { 2081 conf->sc_scheduler_max_inflight = $2; 2082 } 2083 else if (!strcmp($1, "max-evp-batch-size")) { 2084 conf->sc_scheduler_max_evp_batch_size = $2; 2085 } 2086 else if (!strcmp($1, "max-msg-batch-size")) { 2087 conf->sc_scheduler_max_msg_batch_size = $2; 2088 } 2089 else if (!strcmp($1, "max-schedule")) { 2090 conf->sc_scheduler_max_schedule = $2; 2091 } 2092 else { 2093 yyerror("invalid scheduler limit keyword: %s", $1); 2094 free($1); 2095 YYERROR; 2096 } 2097 free($1); 2098 } 2099 ; 2100 2101 limits_scheduler: opt_limit_scheduler limits_scheduler 2102 | /* empty */ 2103 ; 2104 2105 2106 opt_sock_listen : FILTER STRING { 2107 struct filter_config *fc; 2108 2109 if (listen_opts.options & LO_FILTER) { 2110 yyerror("filter already specified"); 2111 free($2); 2112 YYERROR; 2113 } 2114 if ((fc = dict_get(conf->sc_filters_dict, $2)) == NULL) { 2115 yyerror("no filter exist with that name: %s", $2); 2116 free($2); 2117 YYERROR; 2118 } 2119 fc->filter_subsystem |= FILTER_SUBSYSTEM_SMTP_IN; 2120 listen_opts.options |= LO_FILTER; 2121 listen_opts.filtername = $2; 2122 } 2123 | FILTER { 2124 char buffer[128]; 2125 2126 if (listen_opts.options & LO_FILTER) { 2127 yyerror("filter already specified"); 2128 YYERROR; 2129 } 2130 2131 do { 2132 (void)snprintf(buffer, sizeof buffer, "<dynchain:%08x>", last_dynchain_id++); 2133 } while (dict_check(conf->sc_filters_dict, buffer)); 2134 2135 listen_opts.options |= LO_FILTER; 2136 listen_opts.filtername = xstrdup(buffer); 2137 filter_config = xcalloc(1, sizeof *filter_config); 2138 filter_config->filter_type = FILTER_TYPE_CHAIN; 2139 filter_config->filter_subsystem |= FILTER_SUBSYSTEM_SMTP_IN; 2140 dict_init(&filter_config->chain_procs); 2141 } '{' optnl filter_list '}' { 2142 dict_set(conf->sc_filters_dict, listen_opts.filtername, filter_config); 2143 filter_config = NULL; 2144 } 2145 | MASK_SRC { 2146 if (config_lo_mask_source(&listen_opts)) { 2147 YYERROR; 2148 } 2149 } 2150 | NO_DSN { 2151 if (listen_opts.options & LO_NODSN) { 2152 yyerror("no-dsn already specified"); 2153 YYERROR; 2154 } 2155 listen_opts.options |= LO_NODSN; 2156 listen_opts.flags &= ~F_EXT_DSN; 2157 } 2158 | TAG STRING { 2159 if (listen_opts.options & LO_TAG) { 2160 yyerror("tag already specified"); 2161 YYERROR; 2162 } 2163 listen_opts.options |= LO_TAG; 2164 2165 if (strlen($2) >= SMTPD_TAG_SIZE) { 2166 yyerror("tag name too long"); 2167 free($2); 2168 YYERROR; 2169 } 2170 listen_opts.tag = $2; 2171 } 2172 ; 2173 2174 opt_if_listen : INET4 { 2175 if (listen_opts.options & LO_FAMILY) { 2176 yyerror("address family already specified"); 2177 YYERROR; 2178 } 2179 listen_opts.options |= LO_FAMILY; 2180 listen_opts.family = AF_INET; 2181 } 2182 | INET6 { 2183 if (listen_opts.options & LO_FAMILY) { 2184 yyerror("address family already specified"); 2185 YYERROR; 2186 } 2187 listen_opts.options |= LO_FAMILY; 2188 listen_opts.family = AF_INET6; 2189 } 2190 | PORT STRING { 2191 struct servent *servent; 2192 2193 if (listen_opts.options & LO_PORT) { 2194 yyerror("port already specified"); 2195 YYERROR; 2196 } 2197 listen_opts.options |= LO_PORT; 2198 2199 servent = getservbyname($2, "tcp"); 2200 if (servent == NULL) { 2201 yyerror("invalid port: %s", $2); 2202 free($2); 2203 YYERROR; 2204 } 2205 free($2); 2206 listen_opts.port = ntohs(servent->s_port); 2207 } 2208 | PORT SMTP { 2209 struct servent *servent; 2210 2211 if (listen_opts.options & LO_PORT) { 2212 yyerror("port already specified"); 2213 YYERROR; 2214 } 2215 listen_opts.options |= LO_PORT; 2216 2217 servent = getservbyname("smtp", "tcp"); 2218 if (servent == NULL) { 2219 yyerror("invalid port: smtp"); 2220 YYERROR; 2221 } 2222 listen_opts.port = ntohs(servent->s_port); 2223 } 2224 | PORT SMTPS { 2225 struct servent *servent; 2226 2227 if (listen_opts.options & LO_PORT) { 2228 yyerror("port already specified"); 2229 YYERROR; 2230 } 2231 listen_opts.options |= LO_PORT; 2232 2233 servent = getservbyname("smtps", "tcp"); 2234 if (servent == NULL) { 2235 yyerror("invalid port: smtps"); 2236 YYERROR; 2237 } 2238 listen_opts.port = ntohs(servent->s_port); 2239 } 2240 | PORT NUMBER { 2241 if (listen_opts.options & LO_PORT) { 2242 yyerror("port already specified"); 2243 YYERROR; 2244 } 2245 listen_opts.options |= LO_PORT; 2246 2247 if ($2 <= 0 || $2 > (int)USHRT_MAX) { 2248 yyerror("invalid port: %" PRId64, $2); 2249 YYERROR; 2250 } 2251 listen_opts.port = $2; 2252 } 2253 | FILTER STRING { 2254 struct filter_config *fc; 2255 2256 if (listen_opts.options & LO_FILTER) { 2257 yyerror("filter already specified"); 2258 YYERROR; 2259 } 2260 if ((fc = dict_get(conf->sc_filters_dict, $2)) == NULL) { 2261 yyerror("no filter exist with that name: %s", $2); 2262 free($2); 2263 YYERROR; 2264 } 2265 fc->filter_subsystem |= FILTER_SUBSYSTEM_SMTP_IN; 2266 listen_opts.options |= LO_FILTER; 2267 listen_opts.filtername = $2; 2268 } 2269 | FILTER { 2270 char buffer[128]; 2271 2272 if (listen_opts.options & LO_FILTER) { 2273 yyerror("filter already specified"); 2274 YYERROR; 2275 } 2276 2277 do { 2278 (void)snprintf(buffer, sizeof buffer, "<dynchain:%08x>", last_dynchain_id++); 2279 } while (dict_check(conf->sc_filters_dict, buffer)); 2280 2281 listen_opts.options |= LO_FILTER; 2282 listen_opts.filtername = xstrdup(buffer); 2283 filter_config = xcalloc(1, sizeof *filter_config); 2284 filter_config->filter_type = FILTER_TYPE_CHAIN; 2285 filter_config->filter_subsystem |= FILTER_SUBSYSTEM_SMTP_IN; 2286 dict_init(&filter_config->chain_procs); 2287 } '{' optnl filter_list '}' { 2288 dict_set(conf->sc_filters_dict, listen_opts.filtername, filter_config); 2289 filter_config = NULL; 2290 } 2291 | SMTPS { 2292 if (listen_opts.options & LO_SSL) { 2293 yyerror("TLS mode already specified"); 2294 YYERROR; 2295 } 2296 listen_opts.options |= LO_SSL; 2297 listen_opts.ssl = F_SMTPS; 2298 } 2299 | SMTPS VERIFY { 2300 if (listen_opts.options & LO_SSL) { 2301 yyerror("TLS mode already specified"); 2302 YYERROR; 2303 } 2304 listen_opts.options |= LO_SSL; 2305 listen_opts.ssl = F_SMTPS|F_TLS_VERIFY; 2306 } 2307 | TLS { 2308 if (listen_opts.options & LO_SSL) { 2309 yyerror("TLS mode already specified"); 2310 YYERROR; 2311 } 2312 listen_opts.options |= LO_SSL; 2313 listen_opts.ssl = F_STARTTLS; 2314 } 2315 | TLS_REQUIRE { 2316 if (listen_opts.options & LO_SSL) { 2317 yyerror("TLS mode already specified"); 2318 YYERROR; 2319 } 2320 listen_opts.options |= LO_SSL; 2321 listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE; 2322 } 2323 | TLS_REQUIRE VERIFY { 2324 if (listen_opts.options & LO_SSL) { 2325 yyerror("TLS mode already specified"); 2326 YYERROR; 2327 } 2328 listen_opts.options |= LO_SSL; 2329 listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY; 2330 } 2331 | CIPHERS STRING { 2332 if (listen_opts.tls_ciphers) { 2333 yyerror("ciphers already specified"); 2334 YYERROR; 2335 } 2336 listen_opts.tls_ciphers = $2; 2337 } 2338 | PROTOCOLS STRING { 2339 if (listen_opts.tls_protocols) { 2340 yyerror("protocols already specified"); 2341 YYERROR; 2342 } 2343 listen_opts.tls_protocols = $2; 2344 } 2345 | PKI STRING { 2346 if (listen_opts.pkicount == PKI_MAX) { 2347 yyerror("too many pki specified"); 2348 YYERROR; 2349 } 2350 listen_opts.pki[listen_opts.pkicount++] = $2; 2351 } 2352 | CA STRING { 2353 if (listen_opts.options & LO_CA) { 2354 yyerror("ca already specified"); 2355 YYERROR; 2356 } 2357 listen_opts.options |= LO_CA; 2358 listen_opts.ca = $2; 2359 } 2360 | AUTH { 2361 if (listen_opts.options & LO_AUTH) { 2362 yyerror("auth already specified"); 2363 YYERROR; 2364 } 2365 listen_opts.options |= LO_AUTH; 2366 listen_opts.auth = F_AUTH|F_AUTH_REQUIRE; 2367 } 2368 | AUTH_OPTIONAL { 2369 if (listen_opts.options & LO_AUTH) { 2370 yyerror("auth already specified"); 2371 YYERROR; 2372 } 2373 listen_opts.options |= LO_AUTH; 2374 listen_opts.auth = F_AUTH; 2375 } 2376 | AUTH tables { 2377 if (listen_opts.options & LO_AUTH) { 2378 yyerror("auth already specified"); 2379 YYERROR; 2380 } 2381 listen_opts.options |= LO_AUTH; 2382 listen_opts.authtable = $2; 2383 listen_opts.auth = F_AUTH|F_AUTH_REQUIRE; 2384 } 2385 | AUTH_OPTIONAL tables { 2386 if (listen_opts.options & LO_AUTH) { 2387 yyerror("auth already specified"); 2388 YYERROR; 2389 } 2390 listen_opts.options |= LO_AUTH; 2391 listen_opts.authtable = $2; 2392 listen_opts.auth = F_AUTH; 2393 } 2394 | TAG STRING { 2395 if (listen_opts.options & LO_TAG) { 2396 yyerror("tag already specified"); 2397 YYERROR; 2398 } 2399 listen_opts.options |= LO_TAG; 2400 2401 if (strlen($2) >= SMTPD_TAG_SIZE) { 2402 yyerror("tag name too long"); 2403 free($2); 2404 YYERROR; 2405 } 2406 listen_opts.tag = $2; 2407 } 2408 | HOSTNAME STRING { 2409 if (listen_opts.options & LO_HOSTNAME) { 2410 yyerror("hostname already specified"); 2411 YYERROR; 2412 } 2413 listen_opts.options |= LO_HOSTNAME; 2414 2415 listen_opts.hostname = $2; 2416 } 2417 | HOSTNAMES tables { 2418 struct table *t = $2; 2419 2420 if (listen_opts.options & LO_HOSTNAMES) { 2421 yyerror("hostnames already specified"); 2422 YYERROR; 2423 } 2424 listen_opts.options |= LO_HOSTNAMES; 2425 2426 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) { 2427 yyerror("invalid use of table \"%s\" as " 2428 "HOSTNAMES parameter", t->t_name); 2429 YYERROR; 2430 } 2431 listen_opts.hostnametable = t; 2432 } 2433 | MASK_SRC { 2434 if (config_lo_mask_source(&listen_opts)) { 2435 YYERROR; 2436 } 2437 } 2438 | RECEIVEDAUTH { 2439 if (listen_opts.options & LO_RECEIVEDAUTH) { 2440 yyerror("received-auth already specified"); 2441 YYERROR; 2442 } 2443 listen_opts.options |= LO_RECEIVEDAUTH; 2444 listen_opts.flags |= F_RECEIVEDAUTH; 2445 } 2446 | NO_DSN { 2447 if (listen_opts.options & LO_NODSN) { 2448 yyerror("no-dsn already specified"); 2449 YYERROR; 2450 } 2451 listen_opts.options |= LO_NODSN; 2452 listen_opts.flags &= ~F_EXT_DSN; 2453 } 2454 | PROXY_V2 { 2455 if (listen_opts.options & LO_PROXY) { 2456 yyerror("proxy-v2 already specified"); 2457 YYERROR; 2458 } 2459 listen_opts.options |= LO_PROXY; 2460 listen_opts.flags |= F_PROXY; 2461 } 2462 | SENDERS tables { 2463 struct table *t = $2; 2464 2465 if (listen_opts.options & LO_SENDERS) { 2466 yyerror("senders already specified"); 2467 YYERROR; 2468 } 2469 listen_opts.options |= LO_SENDERS; 2470 2471 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) { 2472 yyerror("invalid use of table \"%s\" as " 2473 "SENDERS parameter", t->t_name); 2474 YYERROR; 2475 } 2476 listen_opts.sendertable = t; 2477 } 2478 | SENDERS tables MASQUERADE { 2479 struct table *t = $2; 2480 2481 if (listen_opts.options & LO_SENDERS) { 2482 yyerror("senders already specified"); 2483 YYERROR; 2484 } 2485 listen_opts.options |= LO_SENDERS|LO_MASQUERADE; 2486 2487 if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) { 2488 yyerror("invalid use of table \"%s\" as " 2489 "SENDERS parameter", t->t_name); 2490 YYERROR; 2491 } 2492 listen_opts.sendertable = t; 2493 } 2494 ; 2495 2496 listener_type : socket_listener 2497 | if_listener 2498 ; 2499 2500 socket_listener : SOCKET sock_listen { 2501 if (conf->sc_sock_listener) { 2502 yyerror("socket listener already configured"); 2503 YYERROR; 2504 } 2505 create_sock_listener(&listen_opts); 2506 } 2507 ; 2508 2509 if_listener : STRING if_listen { 2510 listen_opts.ifx = $1; 2511 create_if_listener(&listen_opts); 2512 } 2513 ; 2514 2515 sock_listen : opt_sock_listen sock_listen 2516 | /* empty */ 2517 ; 2518 2519 if_listen : opt_if_listen if_listen 2520 | /* empty */ 2521 ; 2522 2523 2524 listen : LISTEN { 2525 memset(&listen_opts, 0, sizeof listen_opts); 2526 listen_opts.family = AF_UNSPEC; 2527 listen_opts.flags |= F_EXT_DSN; 2528 } ON listener_type { 2529 free(listen_opts.tls_protocols); 2530 free(listen_opts.tls_ciphers); 2531 memset(&listen_opts, 0, sizeof listen_opts); 2532 } 2533 ; 2534 2535 table : TABLE STRING STRING { 2536 char *p, *backend, *config; 2537 2538 p = $3; 2539 if (*p == '/') { 2540 backend = "static"; 2541 config = $3; 2542 } 2543 else { 2544 backend = $3; 2545 config = NULL; 2546 for (p = $3; *p && *p != ':'; p++) 2547 ; 2548 if (*p == ':') { 2549 *p = '\0'; 2550 backend = $3; 2551 config = p+1; 2552 } 2553 } 2554 if (config != NULL && *config != '/') { 2555 yyerror("invalid backend parameter for table: %s", 2556 $2); 2557 free($2); 2558 free($3); 2559 YYERROR; 2560 } 2561 table = table_create(conf, backend, $2, config); 2562 if (!table_config(table)) { 2563 yyerror("invalid configuration file %s for table %s", 2564 config, table->t_name); 2565 free($2); 2566 free($3); 2567 YYERROR; 2568 } 2569 table = NULL; 2570 free($2); 2571 free($3); 2572 } 2573 | TABLE STRING { 2574 table = table_create(conf, "static", $2, NULL); 2575 free($2); 2576 } '{' optnl tableval_list '}' { 2577 table = NULL; 2578 } 2579 ; 2580 2581 tablenew : STRING { 2582 struct table *t; 2583 2584 t = table_create(conf, "static", NULL, NULL); 2585 table_add(t, $1, NULL); 2586 free($1); 2587 $$ = t; 2588 } 2589 | '{' optnl { 2590 table = table_create(conf, "static", NULL, NULL); 2591 } tableval_list '}' { 2592 $$ = table; 2593 table = NULL; 2594 } 2595 ; 2596 2597 tableref : '<' STRING '>' { 2598 struct table *t; 2599 2600 if ((t = table_find(conf, $2)) == NULL) { 2601 yyerror("no such table: %s", $2); 2602 free($2); 2603 YYERROR; 2604 } 2605 free($2); 2606 $$ = t; 2607 } 2608 ; 2609 2610 tables : tablenew { $$ = $1; } 2611 | tableref { $$ = $1; } 2612 ; 2613 2614 2615 %% 2616 2617 struct keywords { 2618 const char *k_name; 2619 int k_val; 2620 }; 2621 2622 int 2623 yyerror(const char *fmt, ...) 2624 { 2625 va_list ap; 2626 char *msg; 2627 2628 file->errors++; 2629 va_start(ap, fmt); 2630 if (vasprintf(&msg, fmt, ap) == -1) 2631 fatalx("yyerror vasprintf"); 2632 va_end(ap); 2633 logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg); 2634 free(msg); 2635 return (0); 2636 } 2637 2638 int 2639 kw_cmp(const void *k, const void *e) 2640 { 2641 return (strcmp(k, ((const struct keywords *)e)->k_name)); 2642 } 2643 2644 int 2645 lookup(char *s) 2646 { 2647 /* this has to be sorted always */ 2648 static const struct keywords keywords[] = { 2649 { "action", ACTION }, 2650 { "admd", ADMD }, 2651 { "alias", ALIAS }, 2652 { "any", ANY }, 2653 { "auth", AUTH }, 2654 { "auth-optional", AUTH_OPTIONAL }, 2655 { "backup", BACKUP }, 2656 { "bounce", BOUNCE }, 2657 { "bypass", BYPASS }, 2658 { "ca", CA }, 2659 { "cert", CERT }, 2660 { "chain", CHAIN }, 2661 { "chroot", CHROOT }, 2662 { "ciphers", CIPHERS }, 2663 { "commit", COMMIT }, 2664 { "compression", COMPRESSION }, 2665 { "connect", CONNECT }, 2666 { "data", DATA }, 2667 { "data-line", DATA_LINE }, 2668 { "dhe", DHE }, 2669 { "disconnect", DISCONNECT }, 2670 { "domain", DOMAIN }, 2671 { "ehlo", EHLO }, 2672 { "encryption", ENCRYPTION }, 2673 { "expand-only", EXPAND_ONLY }, 2674 { "fcrdns", FCRDNS }, 2675 { "filter", FILTER }, 2676 { "for", FOR }, 2677 { "forward-only", FORWARD_ONLY }, 2678 { "from", FROM }, 2679 { "group", GROUP }, 2680 { "helo", HELO }, 2681 { "helo-src", HELO_SRC }, 2682 { "host", HOST }, 2683 { "hostname", HOSTNAME }, 2684 { "hostnames", HOSTNAMES }, 2685 { "include", INCLUDE }, 2686 { "inet4", INET4 }, 2687 { "inet6", INET6 }, 2688 { "junk", JUNK }, 2689 { "key", KEY }, 2690 { "limit", LIMIT }, 2691 { "listen", LISTEN }, 2692 { "lmtp", LMTP }, 2693 { "local", LOCAL }, 2694 { "mail-from", MAIL_FROM }, 2695 { "maildir", MAILDIR }, 2696 { "mask-src", MASK_SRC }, 2697 { "masquerade", MASQUERADE }, 2698 { "match", MATCH }, 2699 { "max-deferred", MAX_DEFERRED }, 2700 { "max-message-size", MAX_MESSAGE_SIZE }, 2701 { "mbox", MBOX }, 2702 { "mda", MDA }, 2703 { "mta", MTA }, 2704 { "mx", MX }, 2705 { "no-dsn", NO_DSN }, 2706 { "no-verify", NO_VERIFY }, 2707 { "noop", NOOP }, 2708 { "on", ON }, 2709 { "phase", PHASE }, 2710 { "pki", PKI }, 2711 { "port", PORT }, 2712 { "proc", PROC }, 2713 { "proc-exec", PROC_EXEC }, 2714 { "protocols", PROTOCOLS }, 2715 { "proxy-v2", PROXY_V2 }, 2716 { "queue", QUEUE }, 2717 { "quit", QUIT }, 2718 { "rcpt-to", RCPT_TO }, 2719 { "rdns", RDNS }, 2720 { "received-auth", RECEIVEDAUTH }, 2721 { "recipient", RECIPIENT }, 2722 { "regex", REGEX }, 2723 { "reject", REJECT }, 2724 { "relay", RELAY }, 2725 { "report", REPORT }, 2726 { "rewrite", REWRITE }, 2727 { "rset", RSET }, 2728 { "scheduler", SCHEDULER }, 2729 { "senders", SENDERS }, 2730 { "smtp", SMTP }, 2731 { "smtp-in", SMTP_IN }, 2732 { "smtp-out", SMTP_OUT }, 2733 { "smtps", SMTPS }, 2734 { "socket", SOCKET }, 2735 { "src", SRC }, 2736 { "srs", SRS }, 2737 { "sub-addr-delim", SUB_ADDR_DELIM }, 2738 { "table", TABLE }, 2739 { "tag", TAG }, 2740 { "tagged", TAGGED }, 2741 { "tls", TLS }, 2742 { "tls-require", TLS_REQUIRE }, 2743 { "ttl", TTL }, 2744 { "user", USER }, 2745 { "userbase", USERBASE }, 2746 { "verify", VERIFY }, 2747 { "virtual", VIRTUAL }, 2748 { "warn-interval", WARN_INTERVAL }, 2749 { "wrapper", WRAPPER }, 2750 }; 2751 const struct keywords *p; 2752 2753 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 2754 sizeof(keywords[0]), kw_cmp); 2755 2756 if (p) 2757 return (p->k_val); 2758 else 2759 return (STRING); 2760 } 2761 2762 #define START_EXPAND 1 2763 #define DONE_EXPAND 2 2764 2765 static int expanding; 2766 2767 int 2768 igetc(void) 2769 { 2770 int c; 2771 2772 while (1) { 2773 if (file->ungetpos > 0) 2774 c = file->ungetbuf[--file->ungetpos]; 2775 else 2776 c = getc(file->stream); 2777 2778 if (c == START_EXPAND) 2779 expanding = 1; 2780 else if (c == DONE_EXPAND) 2781 expanding = 0; 2782 else 2783 break; 2784 } 2785 return (c); 2786 } 2787 2788 int 2789 lgetc(int quotec) 2790 { 2791 int c, next; 2792 2793 if (quotec) { 2794 if ((c = igetc()) == EOF) { 2795 yyerror("reached end of file while parsing " 2796 "quoted string"); 2797 if (file == topfile || popfile() == EOF) 2798 return (EOF); 2799 return (quotec); 2800 } 2801 return (c); 2802 } 2803 2804 while ((c = igetc()) == '\\') { 2805 next = igetc(); 2806 if (next != '\n') { 2807 c = next; 2808 break; 2809 } 2810 yylval.lineno = file->lineno; 2811 file->lineno++; 2812 } 2813 2814 if (c == EOF) { 2815 /* 2816 * Fake EOL when hit EOF for the first time. This gets line 2817 * count right if last line in included file is syntactically 2818 * invalid and has no newline. 2819 */ 2820 if (file->eof_reached == 0) { 2821 file->eof_reached = 1; 2822 return ('\n'); 2823 } 2824 while (c == EOF) { 2825 if (file == topfile || popfile() == EOF) 2826 return (EOF); 2827 c = igetc(); 2828 } 2829 } 2830 return (c); 2831 } 2832 2833 void 2834 lungetc(int c) 2835 { 2836 if (c == EOF) 2837 return; 2838 2839 if (file->ungetpos >= file->ungetsize) { 2840 void *p = reallocarray(file->ungetbuf, file->ungetsize, 2); 2841 if (p == NULL) 2842 fatal("%s", __func__); 2843 file->ungetbuf = p; 2844 file->ungetsize *= 2; 2845 } 2846 file->ungetbuf[file->ungetpos++] = c; 2847 } 2848 2849 int 2850 findeol(void) 2851 { 2852 int c; 2853 2854 /* skip to either EOF or the first real EOL */ 2855 while (1) { 2856 c = lgetc(0); 2857 if (c == '\n') { 2858 file->lineno++; 2859 break; 2860 } 2861 if (c == EOF) 2862 break; 2863 } 2864 return (ERROR); 2865 } 2866 2867 int 2868 yylex(void) 2869 { 2870 char buf[8096]; 2871 char *p, *val; 2872 int quotec, next, c; 2873 int token; 2874 2875 top: 2876 p = buf; 2877 while ((c = lgetc(0)) == ' ' || c == '\t') 2878 ; /* nothing */ 2879 2880 yylval.lineno = file->lineno; 2881 if (c == '#') 2882 while ((c = lgetc(0)) != '\n' && c != EOF) 2883 ; /* nothing */ 2884 if (c == '$' && !expanding) { 2885 while (1) { 2886 if ((c = lgetc(0)) == EOF) 2887 return (0); 2888 2889 if (p + 1 >= buf + sizeof(buf) - 1) { 2890 yyerror("string too long"); 2891 return (findeol()); 2892 } 2893 if (isalnum(c) || c == '_') { 2894 *p++ = c; 2895 continue; 2896 } 2897 *p = '\0'; 2898 lungetc(c); 2899 break; 2900 } 2901 val = symget(buf); 2902 if (val == NULL) { 2903 yyerror("macro '%s' not defined", buf); 2904 return (findeol()); 2905 } 2906 p = val + strlen(val) - 1; 2907 lungetc(DONE_EXPAND); 2908 while (p >= val) { 2909 lungetc((unsigned char)*p); 2910 p--; 2911 } 2912 lungetc(START_EXPAND); 2913 goto top; 2914 } 2915 2916 switch (c) { 2917 case '\'': 2918 case '"': 2919 quotec = c; 2920 while (1) { 2921 if ((c = lgetc(quotec)) == EOF) 2922 return (0); 2923 if (c == '\n') { 2924 file->lineno++; 2925 continue; 2926 } else if (c == '\\') { 2927 if ((next = lgetc(quotec)) == EOF) 2928 return (0); 2929 if (next == quotec || next == ' ' || 2930 next == '\t') 2931 c = next; 2932 else if (next == '\n') { 2933 file->lineno++; 2934 continue; 2935 } else 2936 lungetc(next); 2937 } else if (c == quotec) { 2938 *p = '\0'; 2939 break; 2940 } else if (c == '\0') { 2941 yyerror("syntax error"); 2942 return (findeol()); 2943 } 2944 if (p + 1 >= buf + sizeof(buf) - 1) { 2945 yyerror("string too long"); 2946 return (findeol()); 2947 } 2948 *p++ = c; 2949 } 2950 yylval.v.string = strdup(buf); 2951 if (yylval.v.string == NULL) 2952 fatal("%s", __func__); 2953 return (STRING); 2954 } 2955 2956 #define allowed_to_end_number(x) \ 2957 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 2958 2959 if (c == '-' || isdigit(c)) { 2960 do { 2961 *p++ = c; 2962 if ((size_t)(p-buf) >= sizeof(buf)) { 2963 yyerror("string too long"); 2964 return (findeol()); 2965 } 2966 } while ((c = lgetc(0)) != EOF && isdigit(c)); 2967 lungetc(c); 2968 if (p == buf + 1 && buf[0] == '-') 2969 goto nodigits; 2970 if (c == EOF || allowed_to_end_number(c)) { 2971 const char *errstr = NULL; 2972 2973 *p = '\0'; 2974 yylval.v.number = strtonum(buf, LLONG_MIN, 2975 LLONG_MAX, &errstr); 2976 if (errstr) { 2977 yyerror("\"%s\" invalid number: %s", 2978 buf, errstr); 2979 return (findeol()); 2980 } 2981 return (NUMBER); 2982 } else { 2983 nodigits: 2984 while (p > buf + 1) 2985 lungetc((unsigned char)*--p); 2986 c = (unsigned char)*--p; 2987 if (c == '-') 2988 return (c); 2989 } 2990 } 2991 2992 if (c == '=') { 2993 if ((c = lgetc(0)) != EOF && c == '>') 2994 return (ARROW); 2995 lungetc(c); 2996 c = '='; 2997 } 2998 2999 #define allowed_in_string(x) \ 3000 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 3001 x != '{' && x != '}' && x != '<' && x != '>' && \ 3002 x != '!' && x != '=' && x != '#' && \ 3003 x != ',')) 3004 3005 if (isalnum(c) || c == ':' || c == '_') { 3006 do { 3007 *p++ = c; 3008 if ((size_t)(p-buf) >= sizeof(buf)) { 3009 yyerror("string too long"); 3010 return (findeol()); 3011 } 3012 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 3013 lungetc(c); 3014 *p = '\0'; 3015 if ((token = lookup(buf)) == STRING) 3016 if ((yylval.v.string = strdup(buf)) == NULL) 3017 fatal("%s", __func__); 3018 return (token); 3019 } 3020 if (c == '\n') { 3021 yylval.lineno = file->lineno; 3022 file->lineno++; 3023 } 3024 if (c == EOF) 3025 return (0); 3026 return (c); 3027 } 3028 3029 int 3030 check_file_secrecy(int fd, const char *fname) 3031 { 3032 struct stat st; 3033 3034 if (fstat(fd, &st)) { 3035 log_warn("warn: cannot stat %s", fname); 3036 return (-1); 3037 } 3038 if (st.st_uid != 0 && st.st_uid != getuid()) { 3039 log_warnx("warn: %s: owner not root or current user", fname); 3040 return (-1); 3041 } 3042 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 3043 log_warnx("warn: %s: group/world readable/writeable", fname); 3044 return (-1); 3045 } 3046 return (0); 3047 } 3048 3049 struct file * 3050 pushfile(const char *name, int secret) 3051 { 3052 struct file *nfile; 3053 3054 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 3055 log_warn("%s", __func__); 3056 return (NULL); 3057 } 3058 if ((nfile->name = strdup(name)) == NULL) { 3059 log_warn("%s", __func__); 3060 free(nfile); 3061 return (NULL); 3062 } 3063 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 3064 log_warn("%s: %s", __func__, nfile->name); 3065 free(nfile->name); 3066 free(nfile); 3067 return (NULL); 3068 } else if (secret && 3069 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 3070 fclose(nfile->stream); 3071 free(nfile->name); 3072 free(nfile); 3073 return (NULL); 3074 } 3075 nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0; 3076 nfile->ungetsize = 16; 3077 nfile->ungetbuf = malloc(nfile->ungetsize); 3078 if (nfile->ungetbuf == NULL) { 3079 log_warn("%s", __func__); 3080 fclose(nfile->stream); 3081 free(nfile->name); 3082 free(nfile); 3083 return (NULL); 3084 } 3085 TAILQ_INSERT_TAIL(&files, nfile, entry); 3086 return (nfile); 3087 } 3088 3089 int 3090 popfile(void) 3091 { 3092 struct file *prev; 3093 3094 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 3095 prev->errors += file->errors; 3096 3097 TAILQ_REMOVE(&files, file, entry); 3098 fclose(file->stream); 3099 free(file->name); 3100 free(file->ungetbuf); 3101 free(file); 3102 file = prev; 3103 return (file ? 0 : EOF); 3104 } 3105 3106 int 3107 parse_config(struct smtpd *x_conf, const char *filename, int opts) 3108 { 3109 struct sym *sym, *next; 3110 3111 conf = x_conf; 3112 errors = 0; 3113 3114 if ((file = pushfile(filename, 0)) == NULL) { 3115 purge_config(PURGE_EVERYTHING); 3116 return (-1); 3117 } 3118 topfile = file; 3119 3120 /* 3121 * parse configuration 3122 */ 3123 setservent(1); 3124 yyparse(); 3125 errors = file->errors; 3126 popfile(); 3127 endservent(); 3128 3129 /* If the socket listener was not configured, create a default one. */ 3130 if (!conf->sc_sock_listener) { 3131 memset(&listen_opts, 0, sizeof listen_opts); 3132 listen_opts.family = AF_UNSPEC; 3133 listen_opts.flags |= F_EXT_DSN; 3134 create_sock_listener(&listen_opts); 3135 } 3136 3137 /* Free macros and check which have not been used. */ 3138 TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) { 3139 if ((conf->sc_opts & SMTPD_OPT_VERBOSE) && !sym->used) 3140 fprintf(stderr, "warning: macro '%s' not " 3141 "used\n", sym->nam); 3142 if (!sym->persist) { 3143 free(sym->nam); 3144 free(sym->val); 3145 TAILQ_REMOVE(&symhead, sym, entry); 3146 free(sym); 3147 } 3148 } 3149 3150 if (TAILQ_EMPTY(conf->sc_rules)) { 3151 log_warnx("warn: no rules, nothing to do"); 3152 errors++; 3153 } 3154 3155 if (errors) { 3156 purge_config(PURGE_EVERYTHING); 3157 return (-1); 3158 } 3159 3160 return (0); 3161 } 3162 3163 int 3164 symset(const char *nam, const char *val, int persist) 3165 { 3166 struct sym *sym; 3167 3168 TAILQ_FOREACH(sym, &symhead, entry) { 3169 if (strcmp(nam, sym->nam) == 0) 3170 break; 3171 } 3172 3173 if (sym != NULL) { 3174 if (sym->persist == 1) 3175 return (0); 3176 else { 3177 free(sym->nam); 3178 free(sym->val); 3179 TAILQ_REMOVE(&symhead, sym, entry); 3180 free(sym); 3181 } 3182 } 3183 if ((sym = calloc(1, sizeof(*sym))) == NULL) 3184 return (-1); 3185 3186 sym->nam = strdup(nam); 3187 if (sym->nam == NULL) { 3188 free(sym); 3189 return (-1); 3190 } 3191 sym->val = strdup(val); 3192 if (sym->val == NULL) { 3193 free(sym->nam); 3194 free(sym); 3195 return (-1); 3196 } 3197 sym->used = 0; 3198 sym->persist = persist; 3199 TAILQ_INSERT_TAIL(&symhead, sym, entry); 3200 return (0); 3201 } 3202 3203 int 3204 cmdline_symset(char *s) 3205 { 3206 char *sym, *val; 3207 int ret; 3208 3209 if ((val = strrchr(s, '=')) == NULL) 3210 return (-1); 3211 sym = strndup(s, val - s); 3212 if (sym == NULL) 3213 fatalx("%s: strndup", __func__); 3214 ret = symset(sym, val + 1, 1); 3215 free(sym); 3216 3217 return (ret); 3218 } 3219 3220 char * 3221 symget(const char *nam) 3222 { 3223 struct sym *sym; 3224 3225 TAILQ_FOREACH(sym, &symhead, entry) { 3226 if (strcmp(nam, sym->nam) == 0) { 3227 sym->used = 1; 3228 return (sym->val); 3229 } 3230 } 3231 return (NULL); 3232 } 3233 3234 static void 3235 create_sock_listener(struct listen_opts *lo) 3236 { 3237 struct listener *l = xcalloc(1, sizeof(*l)); 3238 lo->hostname = conf->sc_hostname; 3239 l->ss.ss_family = AF_LOCAL; 3240 l->ss.ss_len = sizeof(struct sockaddr *); 3241 l->local = 1; 3242 conf->sc_sock_listener = l; 3243 config_listener(l, lo); 3244 } 3245 3246 static void 3247 create_if_listener(struct listen_opts *lo) 3248 { 3249 uint16_t flags; 3250 3251 if (lo->port != 0 && lo->ssl == F_SSL) 3252 fatalx("invalid listen option: tls/smtps on same port"); 3253 3254 if (lo->auth != 0 && !lo->ssl) 3255 fatalx("invalid listen option: auth requires tls/smtps"); 3256 3257 if (lo->pkicount && !lo->ssl) 3258 fatalx("invalid listen option: pki requires tls/smtps"); 3259 if (lo->pkicount == 0 && lo->ssl) 3260 fatalx("invalid listen option: pki required for tls/smtps"); 3261 3262 flags = lo->flags; 3263 3264 if (lo->port) { 3265 lo->flags = lo->ssl|lo->auth|flags; 3266 lo->port = htons(lo->port); 3267 } 3268 else { 3269 if (lo->ssl & F_SMTPS) { 3270 lo->port = htons(465); 3271 lo->flags = F_SMTPS|lo->auth|flags; 3272 } 3273 3274 if (!lo->ssl || (lo->ssl & F_STARTTLS)) { 3275 lo->port = htons(25); 3276 lo->flags = lo->auth|flags; 3277 if (lo->ssl & F_STARTTLS) 3278 lo->flags |= F_STARTTLS; 3279 } 3280 } 3281 3282 if (interface(lo)) 3283 return; 3284 if (host_v4(lo)) 3285 return; 3286 if (host_v6(lo)) 3287 return; 3288 if (host_dns(lo)) 3289 return; 3290 3291 fatalx("invalid virtual ip or interface: %s", lo->ifx); 3292 } 3293 3294 static void 3295 config_listener(struct listener *h, struct listen_opts *lo) 3296 { 3297 int i; 3298 3299 h->fd = -1; 3300 h->port = lo->port; 3301 h->flags = lo->flags; 3302 3303 if (lo->hostname == NULL) 3304 lo->hostname = conf->sc_hostname; 3305 3306 if (lo->options & LO_FILTER) { 3307 h->flags |= F_FILTERED; 3308 (void)strlcpy(h->filter_name, 3309 lo->filtername, 3310 sizeof(h->filter_name)); 3311 } 3312 3313 if (lo->authtable != NULL) 3314 (void)strlcpy(h->authtable, lo->authtable->t_name, sizeof(h->authtable)); 3315 3316 h->pkicount = lo->pkicount; 3317 if (h->pkicount) { 3318 h->pki = calloc(h->pkicount, sizeof(*h->pki)); 3319 if (h->pki == NULL) 3320 fatal("calloc"); 3321 } 3322 for (i = 0; i < lo->pkicount; i++) { 3323 h->pki[i] = dict_get(conf->sc_pki_dict, lo->pki[i]); 3324 if (h->pki[i] == NULL) { 3325 log_warnx("pki name not found: %s", lo->pki[i]); 3326 fatalx(NULL); 3327 } 3328 } 3329 3330 if (lo->tls_ciphers != NULL && 3331 (h->tls_ciphers = strdup(lo->tls_ciphers)) == NULL) { 3332 fatal("strdup"); 3333 } 3334 3335 if (lo->tls_protocols != NULL && 3336 (h->tls_protocols = strdup(lo->tls_protocols)) == NULL) { 3337 fatal("strdup"); 3338 } 3339 3340 if (lo->ca != NULL) { 3341 if (!lowercase(h->ca_name, lo->ca, sizeof(h->ca_name))) { 3342 log_warnx("ca name too long: %s", lo->ca); 3343 fatalx(NULL); 3344 } 3345 if (dict_get(conf->sc_ca_dict, h->ca_name) == NULL) { 3346 log_warnx("ca name not found: %s", lo->ca); 3347 fatalx(NULL); 3348 } 3349 } 3350 if (lo->tag != NULL) 3351 (void)strlcpy(h->tag, lo->tag, sizeof(h->tag)); 3352 3353 (void)strlcpy(h->hostname, lo->hostname, sizeof(h->hostname)); 3354 if (lo->hostnametable) 3355 (void)strlcpy(h->hostnametable, lo->hostnametable->t_name, sizeof(h->hostnametable)); 3356 if (lo->sendertable) { 3357 (void)strlcpy(h->sendertable, lo->sendertable->t_name, sizeof(h->sendertable)); 3358 if (lo->options & LO_MASQUERADE) 3359 h->flags |= F_MASQUERADE; 3360 } 3361 3362 if (lo->ssl & F_TLS_VERIFY) 3363 h->flags |= F_TLS_VERIFY; 3364 3365 if (lo->ssl & F_STARTTLS_REQUIRE) 3366 h->flags |= F_STARTTLS_REQUIRE; 3367 3368 if (h != conf->sc_sock_listener) 3369 TAILQ_INSERT_TAIL(conf->sc_listeners, h, entry); 3370 } 3371 3372 static int 3373 host_v4(struct listen_opts *lo) 3374 { 3375 struct in_addr ina; 3376 struct sockaddr_in *sain; 3377 struct listener *h; 3378 3379 if (lo->family != AF_UNSPEC && lo->family != AF_INET) 3380 return (0); 3381 3382 memset(&ina, 0, sizeof(ina)); 3383 if (inet_pton(AF_INET, lo->ifx, &ina) != 1) 3384 return (0); 3385 3386 h = xcalloc(1, sizeof(*h)); 3387 sain = (struct sockaddr_in *)&h->ss; 3388 sain->sin_len = sizeof(struct sockaddr_in); 3389 sain->sin_family = AF_INET; 3390 sain->sin_addr.s_addr = ina.s_addr; 3391 sain->sin_port = lo->port; 3392 3393 if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) 3394 h->local = 1; 3395 config_listener(h, lo); 3396 3397 return (1); 3398 } 3399 3400 static int 3401 host_v6(struct listen_opts *lo) 3402 { 3403 struct in6_addr ina6; 3404 struct sockaddr_in6 *sin6; 3405 struct listener *h; 3406 3407 if (lo->family != AF_UNSPEC && lo->family != AF_INET6) 3408 return (0); 3409 3410 memset(&ina6, 0, sizeof(ina6)); 3411 if (inet_pton(AF_INET6, lo->ifx, &ina6) != 1) 3412 return (0); 3413 3414 h = xcalloc(1, sizeof(*h)); 3415 sin6 = (struct sockaddr_in6 *)&h->ss; 3416 sin6->sin6_len = sizeof(struct sockaddr_in6); 3417 sin6->sin6_family = AF_INET6; 3418 sin6->sin6_port = lo->port; 3419 memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6)); 3420 3421 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 3422 h->local = 1; 3423 config_listener(h, lo); 3424 3425 return (1); 3426 } 3427 3428 static int 3429 host_dns(struct listen_opts *lo) 3430 { 3431 struct addrinfo hints, *res0, *res; 3432 int error, cnt = 0; 3433 struct sockaddr_in *sain; 3434 struct sockaddr_in6 *sin6; 3435 struct listener *h; 3436 3437 memset(&hints, 0, sizeof(hints)); 3438 hints.ai_family = lo->family; 3439 hints.ai_socktype = SOCK_STREAM; 3440 hints.ai_flags = AI_ADDRCONFIG; 3441 error = getaddrinfo(lo->ifx, NULL, &hints, &res0); 3442 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 3443 return (0); 3444 if (error) { 3445 log_warnx("warn: host_dns: could not parse \"%s\": %s", lo->ifx, 3446 gai_strerror(error)); 3447 return (-1); 3448 } 3449 3450 for (res = res0; res; res = res->ai_next) { 3451 if (res->ai_family != AF_INET && 3452 res->ai_family != AF_INET6) 3453 continue; 3454 h = xcalloc(1, sizeof(*h)); 3455 3456 h->ss.ss_family = res->ai_family; 3457 if (res->ai_family == AF_INET) { 3458 sain = (struct sockaddr_in *)&h->ss; 3459 sain->sin_len = sizeof(struct sockaddr_in); 3460 sain->sin_addr.s_addr = ((struct sockaddr_in *) 3461 res->ai_addr)->sin_addr.s_addr; 3462 sain->sin_port = lo->port; 3463 if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) 3464 h->local = 1; 3465 } else { 3466 sin6 = (struct sockaddr_in6 *)&h->ss; 3467 sin6->sin6_len = sizeof(struct sockaddr_in6); 3468 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 3469 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 3470 sin6->sin6_port = lo->port; 3471 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 3472 h->local = 1; 3473 } 3474 3475 config_listener(h, lo); 3476 3477 cnt++; 3478 } 3479 3480 freeaddrinfo(res0); 3481 return (cnt); 3482 } 3483 3484 static int 3485 interface(struct listen_opts *lo) 3486 { 3487 struct ifaddrs *ifap, *p; 3488 struct sockaddr_in *sain; 3489 struct sockaddr_in6 *sin6; 3490 struct listener *h; 3491 int ret = 0; 3492 3493 if (getifaddrs(&ifap) == -1) 3494 fatal("getifaddrs"); 3495 3496 for (p = ifap; p != NULL; p = p->ifa_next) { 3497 if (p->ifa_addr == NULL) 3498 continue; 3499 if (strcmp(p->ifa_name, lo->ifx) != 0 && 3500 !is_if_in_group(p->ifa_name, lo->ifx)) 3501 continue; 3502 if (lo->family != AF_UNSPEC && lo->family != p->ifa_addr->sa_family) 3503 continue; 3504 3505 h = xcalloc(1, sizeof(*h)); 3506 3507 switch (p->ifa_addr->sa_family) { 3508 case AF_INET: 3509 sain = (struct sockaddr_in *)&h->ss; 3510 *sain = *(struct sockaddr_in *)p->ifa_addr; 3511 sain->sin_len = sizeof(struct sockaddr_in); 3512 sain->sin_port = lo->port; 3513 if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) 3514 h->local = 1; 3515 break; 3516 3517 case AF_INET6: 3518 sin6 = (struct sockaddr_in6 *)&h->ss; 3519 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 3520 sin6->sin6_len = sizeof(struct sockaddr_in6); 3521 sin6->sin6_port = lo->port; 3522 #ifdef __KAME__ 3523 if ((IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 3524 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr) || 3525 IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) && 3526 sin6->sin6_scope_id == 0) { 3527 sin6->sin6_scope_id = ntohs( 3528 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 3529 sin6->sin6_addr.s6_addr[2] = 0; 3530 sin6->sin6_addr.s6_addr[3] = 0; 3531 } 3532 #endif 3533 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 3534 h->local = 1; 3535 break; 3536 3537 default: 3538 free(h); 3539 continue; 3540 } 3541 3542 config_listener(h, lo); 3543 ret = 1; 3544 } 3545 3546 freeifaddrs(ifap); 3547 3548 return ret; 3549 } 3550 3551 int 3552 delaytonum(char *str) 3553 { 3554 unsigned int factor; 3555 size_t len; 3556 const char *errstr = NULL; 3557 int delay; 3558 3559 /* we need at least 1 digit and 1 unit */ 3560 len = strlen(str); 3561 if (len < 2) 3562 goto bad; 3563 3564 switch(str[len - 1]) { 3565 3566 case 's': 3567 factor = 1; 3568 break; 3569 3570 case 'm': 3571 factor = 60; 3572 break; 3573 3574 case 'h': 3575 factor = 60 * 60; 3576 break; 3577 3578 case 'd': 3579 factor = 24 * 60 * 60; 3580 break; 3581 3582 default: 3583 goto bad; 3584 } 3585 3586 str[len - 1] = '\0'; 3587 delay = strtonum(str, 1, INT_MAX / factor, &errstr); 3588 if (errstr) 3589 goto bad; 3590 3591 return (delay * factor); 3592 3593 bad: 3594 return (-1); 3595 } 3596 3597 int 3598 is_if_in_group(const char *ifname, const char *groupname) 3599 { 3600 unsigned int len; 3601 struct ifgroupreq ifgr; 3602 struct ifg_req *ifg; 3603 int s; 3604 int ret = 0; 3605 3606 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 3607 fatal("socket"); 3608 3609 memset(&ifgr, 0, sizeof(ifgr)); 3610 if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ) 3611 fatalx("interface name too large"); 3612 3613 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 3614 if (errno == EINVAL || errno == ENOTTY) 3615 goto end; 3616 fatal("SIOCGIFGROUP"); 3617 } 3618 3619 len = ifgr.ifgr_len; 3620 ifgr.ifgr_groups = xcalloc(len/sizeof(struct ifg_req), 3621 sizeof(struct ifg_req)); 3622 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 3623 fatal("SIOCGIFGROUP"); 3624 3625 ifg = ifgr.ifgr_groups; 3626 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 3627 len -= sizeof(struct ifg_req); 3628 if (strcmp(ifg->ifgrq_group, groupname) == 0) { 3629 ret = 1; 3630 break; 3631 } 3632 } 3633 free(ifgr.ifgr_groups); 3634 3635 end: 3636 close(s); 3637 return ret; 3638 } 3639 3640 static int 3641 config_lo_mask_source(struct listen_opts *lo) { 3642 if (lo->options & LO_MASKSOURCE) { 3643 yyerror("mask-source already specified"); 3644 return -1; 3645 } 3646 lo->options |= LO_MASKSOURCE; 3647 lo->flags |= F_MASK_SOURCE; 3648 3649 return 0; 3650 } 3651 3652