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