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