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