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