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