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