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