1 /* $OpenBSD: parse.y,v 1.138 2014/03/25 10:28:58 gilles 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 <netdb.h> 44 #include <paths.h> 45 #include <pwd.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <syslog.h> 50 #include <unistd.h> 51 #include <util.h> 52 53 #include <openssl/ssl.h> 54 55 #include "smtpd.h" 56 #include "ssl.h" 57 #include "log.h" 58 59 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 60 static struct file { 61 TAILQ_ENTRY(file) entry; 62 FILE *stream; 63 char *name; 64 int lineno; 65 int errors; 66 } *file, *topfile; 67 struct file *pushfile(const char *, int); 68 int popfile(void); 69 int check_file_secrecy(int, const char *); 70 int yyparse(void); 71 int yylex(void); 72 int kw_cmp(const void *, const void *); 73 int lookup(char *); 74 int lgetc(int); 75 int lungetc(int); 76 int findeol(void); 77 int yyerror(const char *, ...) 78 __attribute__ ((format (printf, 1, 2))); 79 80 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 81 struct sym { 82 TAILQ_ENTRY(sym) entry; 83 int used; 84 int persist; 85 char *nam; 86 char *val; 87 }; 88 int symset(const char *, const char *, int); 89 char *symget(const char *); 90 91 struct smtpd *conf = NULL; 92 static int errors = 0; 93 94 struct filter *filter = NULL; 95 struct table *table = NULL; 96 struct rule *rule = NULL; 97 struct listener l; 98 struct mta_limits *limits; 99 static struct pki *pki; 100 101 static struct listen_opts { 102 char *ifx; 103 int family; 104 in_port_t port; 105 uint16_t ssl; 106 char *pki; 107 uint16_t auth; 108 struct table *authtable; 109 char *tag; 110 char *hostname; 111 struct table *hostnametable; 112 uint16_t flags; 113 } listen_opts; 114 115 static void create_listener(struct listenerlist *, struct listen_opts *); 116 static void config_listener(struct listener *, struct listen_opts *); 117 118 struct listener *host_v4(const char *, in_port_t); 119 struct listener *host_v6(const char *, in_port_t); 120 int host_dns(struct listenerlist *, struct listen_opts *); 121 int host(struct listenerlist *, struct listen_opts *); 122 int interface(struct listenerlist *, struct listen_opts *); 123 void set_localaddrs(void); 124 int delaytonum(char *); 125 int is_if_in_group(const char *, const char *); 126 127 static struct filter *create_filter(const char *, const char *); 128 static struct filter *create_filter_chain(const char *); 129 static int extend_filter_chain(struct filter *, const char *); 130 131 typedef struct { 132 union { 133 int64_t number; 134 struct table *table; 135 char *string; 136 struct host *host; 137 struct mailaddr *maddr; 138 } v; 139 int lineno; 140 } YYSTYPE; 141 142 %} 143 144 %token AS QUEUE COMPRESSION ENCRYPTION MAXMESSAGESIZE MAXMTADEFERRED LISTEN ON ANY PORT EXPIRE 145 %token TABLE SECURE SMTPS CERTIFICATE DOMAIN BOUNCEWARN LIMIT INET4 INET6 146 %token RELAY BACKUP VIA DELIVER TO LMTP MAILDIR MBOX HOSTNAME HOSTNAMES 147 %token ACCEPT REJECT INCLUDE ERROR MDA FROM FOR SOURCE MTA PKI SCHEDULER 148 %token ARROW AUTH TLS LOCAL VIRTUAL TAG TAGGED ALIAS FILTER FILTERCHAIN KEY CA DHPARAMS 149 %token AUTH_OPTIONAL TLS_REQUIRE USERBASE SENDER MASK_SOURCE VERIFY FORWARDONLY RECIPIENT 150 %token <v.string> STRING 151 %token <v.number> NUMBER 152 %type <v.table> table 153 %type <v.number> size negation 154 %type <v.table> tables tablenew tableref alias virtual userbase 155 %type <v.string> tagged 156 %% 157 158 grammar : /* empty */ 159 | grammar '\n' 160 | grammar include '\n' 161 | grammar varset '\n' 162 | grammar main '\n' 163 | grammar table '\n' 164 | grammar rule '\n' 165 | grammar error '\n' { file->errors++; } 166 ; 167 168 include : INCLUDE STRING { 169 struct file *nfile; 170 171 if ((nfile = pushfile($2, 0)) == NULL) { 172 yyerror("failed to include file %s", $2); 173 free($2); 174 YYERROR; 175 } 176 free($2); 177 178 file = nfile; 179 lungetc('\n'); 180 } 181 ; 182 183 varset : STRING '=' STRING { 184 if (symset($1, $3, 0) == -1) 185 fatal("cannot store variable"); 186 free($1); 187 free($3); 188 } 189 ; 190 191 comma : ',' 192 | nl 193 | /* empty */ 194 ; 195 196 optnl : '\n' optnl 197 | 198 ; 199 200 nl : '\n' optnl 201 ; 202 203 size : NUMBER { 204 if ($1 < 0) { 205 yyerror("invalid size: %" PRId64, $1); 206 YYERROR; 207 } 208 $$ = $1; 209 } 210 | STRING { 211 long long result; 212 213 if (scan_scaled($1, &result) == -1 || result < 0) { 214 yyerror("invalid size: %s", $1); 215 free($1); 216 YYERROR; 217 } 218 free($1); 219 $$ = result; 220 } 221 ; 222 223 tagged : TAGGED negation STRING { 224 if (strlcpy(rule->r_tag, $3, sizeof rule->r_tag) 225 >= sizeof rule->r_tag) { 226 yyerror("tag name too long: %s", $3); 227 free($3); 228 YYERROR; 229 } 230 free($3); 231 rule->r_nottag = $2; 232 } 233 ; 234 235 bouncedelay : STRING { 236 time_t d; 237 int i; 238 239 d = delaytonum($1); 240 if (d < 0) { 241 yyerror("invalid bounce delay: %s", $1); 242 free($1); 243 YYERROR; 244 } 245 free($1); 246 for (i = 0; i < MAX_BOUNCE_WARN; i++) { 247 if (conf->sc_bounce_warn[i] != 0) 248 continue; 249 conf->sc_bounce_warn[i] = d; 250 break; 251 } 252 } 253 254 bouncedelays : bouncedelays ',' bouncedelay 255 | bouncedelay 256 | /* EMPTY */ 257 ; 258 259 opt_limit_mda : STRING NUMBER { 260 if (!strcmp($1, "max-session")) { 261 conf->sc_mda_max_session = $2; 262 } 263 else if (!strcmp($1, "max-session-per-user")) { 264 conf->sc_mda_max_user_session = $2; 265 } 266 else if (!strcmp($1, "task-lowat")) { 267 conf->sc_mda_task_lowat = $2; 268 } 269 else if (!strcmp($1, "task-hiwat")) { 270 conf->sc_mda_task_hiwat = $2; 271 } 272 else if (!strcmp($1, "task-release")) { 273 conf->sc_mda_task_release = $2; 274 } 275 else { 276 yyerror("invalid scheduler limit keyword: %s", $1); 277 free($1); 278 YYERROR; 279 } 280 free($1); 281 } 282 ; 283 284 limits_mda : opt_limit_mda limits_mda 285 | /* empty */ 286 ; 287 288 opt_limit_mta : INET4 { 289 limits->family = AF_INET; 290 } 291 | INET6 { 292 limits->family = AF_INET6; 293 } 294 | STRING NUMBER { 295 if (!limit_mta_set(limits, $1, $2)) { 296 yyerror("invalid mta limit keyword: %s", $1); 297 free($1); 298 YYERROR; 299 } 300 free($1); 301 } 302 ; 303 304 limits_mta : opt_limit_mta limits_mta 305 | /* empty */ 306 ; 307 308 opt_limit_scheduler : STRING NUMBER { 309 if (!strcmp($1, "max-inflight")) { 310 conf->sc_scheduler_max_inflight = $2; 311 } 312 else if (!strcmp($1, "max-evp-batch-size")) { 313 conf->sc_scheduler_max_evp_batch_size = $2; 314 } 315 else if (!strcmp($1, "max-msg-batch-size")) { 316 conf->sc_scheduler_max_msg_batch_size = $2; 317 } 318 else if (!strcmp($1, "max-schedule")) { 319 conf->sc_scheduler_max_schedule = $2; 320 } 321 else { 322 yyerror("invalid scheduler limit keyword: %s", $1); 323 free($1); 324 YYERROR; 325 } 326 free($1); 327 } 328 ; 329 330 limits_scheduler: opt_limit_scheduler limits_scheduler 331 | /* empty */ 332 ; 333 334 opt_pki : CERTIFICATE STRING { 335 pki->pki_cert_file = $2; 336 } 337 | KEY STRING { 338 pki->pki_key_file = $2; 339 } 340 | CA STRING { 341 pki->pki_ca_file = $2; 342 } 343 | DHPARAMS STRING { 344 pki->pki_dhparams_file = $2; 345 } 346 ; 347 348 pki : opt_pki pki 349 | /* empty */ 350 ; 351 352 opt_listen : INET4 { listen_opts.family = AF_INET; } 353 | INET6 { listen_opts.family = AF_INET6; } 354 | PORT STRING { 355 struct servent *servent; 356 357 servent = getservbyname($2, "tcp"); 358 if (servent == NULL) { 359 yyerror("invalid port: %s", $2); 360 free($2); 361 YYERROR; 362 } 363 free($2); 364 listen_opts.port = ntohs(servent->s_port); 365 } 366 | PORT NUMBER { 367 if ($2 <= 0 || $2 >= (int)USHRT_MAX) { 368 yyerror("invalid port: %" PRId64, $2); 369 YYERROR; 370 } 371 listen_opts.port = $2; 372 } 373 | SMTPS { listen_opts.ssl = F_SMTPS; } 374 | SMTPS VERIFY { listen_opts.ssl = F_SMTPS|F_TLS_VERIFY; } 375 | TLS { listen_opts.ssl = F_STARTTLS; } 376 | SECURE { listen_opts.ssl = F_SSL; } 377 | TLS_REQUIRE { listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE; } 378 | TLS_REQUIRE VERIFY { listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY; } 379 | PKI STRING { listen_opts.pki = $2; } 380 | AUTH { listen_opts.auth = F_AUTH|F_AUTH_REQUIRE; } 381 | AUTH_OPTIONAL { listen_opts.auth = F_AUTH; } 382 | AUTH tables { 383 listen_opts.authtable = $2; 384 listen_opts.auth = F_AUTH|F_AUTH_REQUIRE; 385 } 386 | AUTH_OPTIONAL tables { 387 listen_opts.authtable = $2; 388 listen_opts.auth = F_AUTH; 389 } 390 | TAG STRING { 391 if (strlen($2) >= MAX_TAG_SIZE) { 392 yyerror("tag name too long"); 393 free($2); 394 YYERROR; 395 } 396 listen_opts.tag = $2; 397 } 398 | HOSTNAME STRING { listen_opts.hostname = $2; } 399 | HOSTNAMES tables { 400 struct table *t = $2; 401 if (! table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) { 402 yyerror("invalid use of table \"%s\" as " 403 "HOSTNAMES parameter", t->t_name); 404 YYERROR; 405 } 406 listen_opts.hostnametable = t; 407 } 408 | MASK_SOURCE { listen_opts.flags |= F_MASK_SOURCE; } 409 ; 410 411 listen : opt_listen listen 412 | /* empty */ 413 ; 414 415 opt_relay_common: AS STRING { 416 struct mailaddr maddr, *maddrp; 417 418 if (! text_to_mailaddr(&maddr, $2)) { 419 yyerror("invalid parameter to AS: %s", $2); 420 free($2); 421 YYERROR; 422 } 423 free($2); 424 425 if (maddr.user[0] == '\0' && maddr.domain[0] == '\0') { 426 yyerror("invalid empty parameter to AS"); 427 YYERROR; 428 } 429 else if (maddr.domain[0] == '\0') { 430 if (strlcpy(maddr.domain, conf->sc_hostname, 431 sizeof (maddr.domain)) 432 >= sizeof (maddr.domain)) { 433 yyerror("hostname too long for AS parameter: %s", 434 conf->sc_hostname); 435 YYERROR; 436 } 437 } 438 rule->r_as = xmemdup(&maddr, sizeof (*maddrp), "parse relay_as: AS"); 439 } 440 | SOURCE tables { 441 struct table *t = $2; 442 if (! table_check_use(t, T_DYNAMIC|T_LIST, K_SOURCE)) { 443 yyerror("invalid use of table \"%s\" as " 444 "SOURCE parameter", t->t_name); 445 YYERROR; 446 } 447 strlcpy(rule->r_value.relayhost.sourcetable, t->t_name, 448 sizeof rule->r_value.relayhost.sourcetable); 449 } 450 | HOSTNAME STRING { 451 strlcat(rule->r_value.relayhost.heloname, $2, 452 sizeof rule->r_value.relayhost.heloname); 453 free($2); 454 } 455 | HOSTNAMES tables { 456 struct table *t = $2; 457 if (! table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) { 458 yyerror("invalid use of table \"%s\" as " 459 "HOSTNAMES parameter", t->t_name); 460 YYERROR; 461 } 462 strlcpy(rule->r_value.relayhost.helotable, t->t_name, 463 sizeof rule->r_value.relayhost.helotable); 464 } 465 | PKI STRING { 466 if (! lowercase(rule->r_value.relayhost.pki_name, $2, 467 sizeof(rule->r_value.relayhost.pki_name))) { 468 yyerror("pki name too long: %s", $2); 469 free($2); 470 YYERROR; 471 } 472 if (dict_get(conf->sc_pki_dict, 473 rule->r_value.relayhost.pki_name) == NULL) { 474 log_warnx("pki name not found: %s", $2); 475 free($2); 476 YYERROR; 477 } 478 free($2); 479 } 480 ; 481 482 opt_relay : BACKUP STRING { 483 rule->r_value.relayhost.flags |= F_BACKUP; 484 strlcpy(rule->r_value.relayhost.hostname, $2, 485 sizeof (rule->r_value.relayhost.hostname)); 486 } 487 | BACKUP { 488 rule->r_value.relayhost.flags |= F_BACKUP; 489 strlcpy(rule->r_value.relayhost.hostname, 490 conf->sc_hostname, 491 sizeof (rule->r_value.relayhost.hostname)); 492 } 493 | TLS { 494 rule->r_value.relayhost.flags |= F_STARTTLS; 495 } 496 | TLS VERIFY { 497 rule->r_value.relayhost.flags |= F_STARTTLS|F_TLS_VERIFY; 498 } 499 ; 500 501 relay : opt_relay_common relay 502 | opt_relay relay 503 | /* empty */ 504 ; 505 506 opt_relay_via : AUTH tables { 507 struct table *t = $2; 508 509 if (! table_check_use(t, T_DYNAMIC|T_HASH, K_CREDENTIALS)) { 510 yyerror("invalid use of table \"%s\" as AUTH parameter", 511 t->t_name); 512 YYERROR; 513 } 514 strlcpy(rule->r_value.relayhost.authtable, t->t_name, 515 sizeof(rule->r_value.relayhost.authtable)); 516 } 517 | VERIFY { 518 if (!(rule->r_value.relayhost.flags & F_SSL)) { 519 yyerror("cannot \"verify\" with insecure protocol"); 520 YYERROR; 521 } 522 rule->r_value.relayhost.flags |= F_TLS_VERIFY; 523 } 524 ; 525 526 relay_via : opt_relay_common relay_via 527 | opt_relay_via relay_via 528 | /* empty */ 529 ; 530 531 main : BOUNCEWARN { 532 memset(conf->sc_bounce_warn, 0, sizeof conf->sc_bounce_warn); 533 } bouncedelays 534 | QUEUE COMPRESSION { 535 conf->sc_queue_flags |= QUEUE_COMPRESSION; 536 } 537 | QUEUE ENCRYPTION { 538 char *password; 539 540 password = getpass("queue key: "); 541 if (password == NULL) { 542 yyerror("getpass() error"); 543 YYERROR; 544 } 545 conf->sc_queue_key = strdup(password); 546 memset(password, 0, strlen(password)); 547 if (conf->sc_queue_key == NULL) { 548 yyerror("memory exhausted"); 549 YYERROR; 550 } 551 conf->sc_queue_flags |= QUEUE_ENCRYPTION; 552 553 } 554 | QUEUE ENCRYPTION KEY STRING { 555 char *buf; 556 char *lbuf; 557 size_t len; 558 559 if (strcasecmp($4, "stdin") == 0 || 560 strcasecmp($4, "-") == 0) { 561 lbuf = NULL; 562 buf = fgetln(stdin, &len); 563 if (buf[len - 1] == '\n') { 564 lbuf = calloc(len, 1); 565 memcpy(lbuf, buf, len-1); 566 } 567 else { 568 lbuf = calloc(len+1, 1); 569 memcpy(lbuf, buf, len); 570 } 571 conf->sc_queue_key = lbuf; 572 } 573 else 574 conf->sc_queue_key = $4; 575 conf->sc_queue_flags |= QUEUE_ENCRYPTION; 576 } 577 | EXPIRE STRING { 578 conf->sc_qexpire = delaytonum($2); 579 if (conf->sc_qexpire == -1) { 580 yyerror("invalid expire delay: %s", $2); 581 free($2); 582 YYERROR; 583 } 584 free($2); 585 } 586 | MAXMESSAGESIZE size { 587 conf->sc_maxsize = $2; 588 } 589 | MAXMTADEFERRED NUMBER { 590 conf->sc_mta_max_deferred = $2; 591 } 592 | LIMIT MDA limits_mda 593 | LIMIT MTA FOR DOMAIN STRING { 594 struct mta_limits *d; 595 596 limits = dict_get(conf->sc_limits_dict, $5); 597 if (limits == NULL) { 598 limits = xcalloc(1, sizeof(*limits), "mta_limits"); 599 dict_xset(conf->sc_limits_dict, $5, limits); 600 d = dict_xget(conf->sc_limits_dict, "default"); 601 memmove(limits, d, sizeof(*limits)); 602 } 603 free($5); 604 } limits_mta 605 | LIMIT MTA { 606 limits = dict_get(conf->sc_limits_dict, "default"); 607 } limits_mta 608 | LIMIT SCHEDULER limits_scheduler 609 | LISTEN { 610 memset(&l, 0, sizeof l); 611 memset(&listen_opts, 0, sizeof listen_opts); 612 listen_opts.family = AF_UNSPEC; 613 } ON STRING listen { 614 listen_opts.ifx = $4; 615 create_listener(conf->sc_listeners, &listen_opts); 616 } 617 | FILTER STRING STRING { 618 if (!create_filter($2, $3)) { 619 free($2); 620 free($3); 621 YYERROR; 622 } 623 free($2); 624 free($3); 625 } 626 | FILTERCHAIN STRING { 627 if ((filter = create_filter_chain($2)) == NULL) { 628 free($2); 629 YYERROR; 630 } 631 } filter_list 632 | PKI STRING { 633 char buf[MAXHOSTNAMELEN]; 634 xlowercase(buf, $2, sizeof(buf)); 635 free($2); 636 pki = dict_get(conf->sc_pki_dict, buf); 637 if (pki == NULL) { 638 pki = xcalloc(1, sizeof *pki, "parse:pki"); 639 strlcpy(pki->pki_name, buf, sizeof(pki->pki_name)); 640 dict_set(conf->sc_pki_dict, pki->pki_name, pki); 641 } 642 } pki 643 ; 644 645 table : TABLE STRING STRING { 646 char *p, *backend, *config; 647 648 p = $3; 649 if (*p == '/') { 650 backend = "static"; 651 config = $3; 652 } 653 else { 654 backend = $3; 655 config = NULL; 656 for (p = $3; *p && *p != ':'; p++) 657 ; 658 if (*p == ':') { 659 *p = '\0'; 660 backend = $3; 661 config = p+1; 662 } 663 } 664 if (config != NULL && *config != '/') { 665 yyerror("invalid backend parameter for table: %s", 666 $2); 667 free($2); 668 free($3); 669 YYERROR; 670 } 671 table = table_create(backend, $2, NULL, config); 672 if (!table_config(table)) { 673 yyerror("invalid configuration file %s for table %s", 674 config, table->t_name); 675 free($2); 676 free($3); 677 YYERROR; 678 } 679 free($2); 680 free($3); 681 } 682 | TABLE STRING { 683 table = table_create("static", $2, NULL, NULL); 684 free($2); 685 } '{' tableval_list '}' { 686 table = NULL; 687 } 688 ; 689 690 assign : '=' | ARROW; 691 692 keyval : STRING assign STRING { 693 table->t_type = T_HASH; 694 table_add(table, $1, $3); 695 free($1); 696 free($3); 697 } 698 ; 699 700 keyval_list : keyval 701 | keyval comma keyval_list 702 ; 703 704 stringel : STRING { 705 table->t_type = T_LIST; 706 table_add(table, $1, NULL); 707 free($1); 708 } 709 ; 710 711 string_list : stringel 712 | stringel comma string_list 713 ; 714 715 filter_list : 716 | STRING { 717 if (!extend_filter_chain(filter, $1)) { 718 free($1); 719 YYERROR; 720 } 721 } filter_list 722 ; 723 724 tableval_list : string_list { } 725 | keyval_list { } 726 ; 727 728 tablenew : STRING { 729 struct table *t; 730 731 t = table_create("static", NULL, NULL, NULL); 732 t->t_type = T_LIST; 733 table_add(t, $1, NULL); 734 free($1); 735 $$ = t; 736 } 737 | '{' { 738 table = table_create("static", NULL, NULL, NULL); 739 } tableval_list '}' { 740 $$ = table; 741 } 742 ; 743 744 tableref : '<' STRING '>' { 745 struct table *t; 746 747 if ((t = table_find($2, NULL)) == NULL) { 748 yyerror("no such table: %s", $2); 749 free($2); 750 YYERROR; 751 } 752 free($2); 753 $$ = t; 754 } 755 ; 756 757 tables : tablenew { $$ = $1; } 758 | tableref { $$ = $1; } 759 ; 760 761 alias : ALIAS tables { 762 struct table *t = $2; 763 764 if (! table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) { 765 yyerror("invalid use of table \"%s\" as ALIAS parameter", 766 t->t_name); 767 YYERROR; 768 } 769 770 $$ = t; 771 } 772 ; 773 774 virtual : VIRTUAL tables { 775 struct table *t = $2; 776 777 if (! table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) { 778 yyerror("invalid use of table \"%s\" as VIRTUAL parameter", 779 t->t_name); 780 YYERROR; 781 } 782 $$ = t; 783 } 784 ; 785 786 usermapping : alias { 787 if (rule->r_mapping) { 788 yyerror("alias specified multiple times"); 789 YYERROR; 790 } 791 rule->r_desttype = DEST_DOM; 792 rule->r_mapping = $1; 793 } 794 | virtual { 795 if (rule->r_mapping) { 796 yyerror("virtual specified multiple times"); 797 YYERROR; 798 } 799 rule->r_desttype = DEST_VDOM; 800 rule->r_mapping = $1; 801 } 802 ; 803 804 userbase : USERBASE tables { 805 struct table *t = $2; 806 807 if (rule->r_userbase) { 808 yyerror("userbase specified multiple times"); 809 YYERROR; 810 } 811 if (! table_check_use(t, T_DYNAMIC|T_HASH, K_USERINFO)) { 812 yyerror("invalid use of table \"%s\" as USERBASE parameter", 813 t->t_name); 814 YYERROR; 815 } 816 rule->r_userbase = t; 817 } 818 ; 819 820 deliver_action : DELIVER TO MAILDIR { 821 rule->r_action = A_MAILDIR; 822 if (strlcpy(rule->r_value.buffer, "~/Maildir", 823 sizeof(rule->r_value.buffer)) >= 824 sizeof(rule->r_value.buffer)) 825 fatal("pathname too long"); 826 } 827 | DELIVER TO MAILDIR STRING { 828 rule->r_action = A_MAILDIR; 829 if (strlcpy(rule->r_value.buffer, $4, 830 sizeof(rule->r_value.buffer)) >= 831 sizeof(rule->r_value.buffer)) 832 fatal("pathname too long"); 833 free($4); 834 } 835 | DELIVER TO LMTP STRING { 836 rule->r_action = A_LMTP; 837 if (strchr($4, ':') || $4[0] == '/') { 838 if (strlcpy(rule->r_value.buffer, $4, 839 sizeof(rule->r_value.buffer)) 840 >= sizeof(rule->r_value.buffer)) 841 fatal("lmtp destination too long"); 842 } else 843 fatal("invalid lmtp destination"); 844 free($4); 845 } 846 | DELIVER TO MBOX { 847 rule->r_action = A_MBOX; 848 if (strlcpy(rule->r_value.buffer, _PATH_MAILDIR "/%u", 849 sizeof(rule->r_value.buffer)) 850 >= sizeof(rule->r_value.buffer)) 851 fatal("pathname too long"); 852 } 853 | DELIVER TO MDA STRING { 854 rule->r_action = A_MDA; 855 if (strlcpy(rule->r_value.buffer, $4, 856 sizeof(rule->r_value.buffer)) 857 >= sizeof(rule->r_value.buffer)) 858 fatal("command too long"); 859 free($4); 860 } 861 ; 862 863 relay_action : RELAY relay { 864 rule->r_action = A_RELAY; 865 } 866 | RELAY VIA STRING { 867 rule->r_action = A_RELAYVIA; 868 if (! text_to_relayhost(&rule->r_value.relayhost, $3)) { 869 yyerror("error: invalid url: %s", $3); 870 free($3); 871 YYERROR; 872 } 873 free($3); 874 } relay_via { 875 /* no worries, F_AUTH cant be set without SSL */ 876 if (rule->r_value.relayhost.flags & F_AUTH) { 877 if (rule->r_value.relayhost.authtable[0] == '\0') { 878 yyerror("error: auth without auth table"); 879 YYERROR; 880 } 881 } 882 } 883 ; 884 885 negation : '!' { $$ = 1; } 886 | /* empty */ { $$ = 0; } 887 ; 888 889 from : FROM negation SOURCE tables { 890 struct table *t = $4; 891 892 if (rule->r_sources) { 893 yyerror("from specified multiple times"); 894 YYERROR; 895 } 896 if (! table_check_use(t, T_DYNAMIC|T_LIST, K_NETADDR)) { 897 yyerror("invalid use of table \"%s\" as FROM parameter", 898 t->t_name); 899 YYERROR; 900 } 901 rule->r_notsources = $2; 902 rule->r_sources = t; 903 } 904 | FROM negation ANY { 905 if (rule->r_sources) { 906 yyerror("from specified multiple times"); 907 YYERROR; 908 } 909 rule->r_sources = table_find("<anyhost>", NULL); 910 rule->r_notsources = $2; 911 } 912 | FROM negation LOCAL { 913 if (rule->r_sources) { 914 yyerror("from specified multiple times"); 915 YYERROR; 916 } 917 rule->r_sources = table_find("<localhost>", NULL); 918 rule->r_notsources = $2; 919 } 920 ; 921 922 for : FOR negation DOMAIN tables { 923 struct table *t = $4; 924 925 if (rule->r_destination) { 926 yyerror("for specified multiple times"); 927 YYERROR; 928 } 929 if (! table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) { 930 yyerror("invalid use of table \"%s\" as DOMAIN parameter", 931 t->t_name); 932 YYERROR; 933 } 934 rule->r_notdestination = $2; 935 rule->r_destination = t; 936 } 937 | FOR negation ANY { 938 if (rule->r_destination) { 939 yyerror("for specified multiple times"); 940 YYERROR; 941 } 942 rule->r_notdestination = $2; 943 rule->r_destination = table_find("<anydestination>", NULL); 944 } 945 | FOR negation LOCAL { 946 if (rule->r_destination) { 947 yyerror("for specified multiple times"); 948 YYERROR; 949 } 950 rule->r_notdestination = $2; 951 rule->r_destination = table_find("<localnames>", NULL); 952 } 953 ; 954 955 sender : SENDER negation tables { 956 struct table *t = $3; 957 958 if (rule->r_senders) { 959 yyerror("sender specified multiple times"); 960 YYERROR; 961 } 962 963 if (! table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 964 yyerror("invalid use of table \"%s\" as SENDER parameter", 965 t->t_name); 966 YYERROR; 967 } 968 rule->r_notsenders = $2; 969 rule->r_senders = t; 970 } 971 ; 972 973 recipient : RECIPIENT negation tables { 974 struct table *t = $3; 975 976 if (rule->r_recipients) { 977 yyerror("recipient specified multiple times"); 978 YYERROR; 979 } 980 981 if (! table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) { 982 yyerror("invalid use of table \"%s\" as RECIPIENT parameter", 983 t->t_name); 984 YYERROR; 985 } 986 rule->r_notrecipients = $2; 987 rule->r_recipients = t; 988 } 989 ; 990 991 forwardonly : FORWARDONLY { 992 if (rule->r_forwardonly) { 993 yyerror("forward-only specified multiple times"); 994 YYERROR; 995 } 996 rule->r_forwardonly = 1; 997 } 998 ; 999 1000 expire : EXPIRE STRING { 1001 if (rule->r_qexpire != -1) { 1002 yyerror("expire specified multiple times"); 1003 YYERROR; 1004 } 1005 rule->r_qexpire = delaytonum($2); 1006 if (rule->r_qexpire == -1) { 1007 yyerror("invalid expire delay: %s", $2); 1008 free($2); 1009 YYERROR; 1010 } 1011 free($2); 1012 } 1013 ; 1014 1015 opt_decision : sender 1016 | recipient 1017 | from 1018 | for 1019 | tagged 1020 ; 1021 decision : opt_decision decision 1022 | 1023 ; 1024 1025 opt_lookup : userbase 1026 | usermapping 1027 ; 1028 lookup : opt_lookup lookup 1029 | 1030 ; 1031 1032 action : deliver_action 1033 | relay_action 1034 | 1035 ; 1036 1037 opt_accept : expire 1038 | forwardonly 1039 ; 1040 1041 accept_params : opt_accept accept_params 1042 | 1043 ; 1044 1045 rule : ACCEPT { 1046 rule = xcalloc(1, sizeof(*rule), "parse rule: ACCEPT"); 1047 rule->r_action = A_NONE; 1048 rule->r_decision = R_ACCEPT; 1049 rule->r_desttype = DEST_DOM; 1050 rule->r_qexpire = -1; 1051 } decision lookup action accept_params { 1052 if (! rule->r_sources) 1053 rule->r_sources = table_find("<localhost>", NULL); 1054 if (! rule->r_destination) 1055 rule->r_destination = table_find("<localnames>", NULL); 1056 if (! rule->r_userbase) 1057 rule->r_userbase = table_find("<getpwnam>", NULL); 1058 if (rule->r_qexpire == -1) 1059 rule->r_qexpire = conf->sc_qexpire; 1060 if (rule->r_action == A_RELAY || rule->r_action == A_RELAYVIA) { 1061 if (rule->r_userbase != table_find("<getpwnam>", NULL)) { 1062 yyerror("userbase may not be used with a relay rule"); 1063 YYERROR; 1064 } 1065 if (rule->r_mapping) { 1066 yyerror("aliases/virtual may not be used with a relay rule"); 1067 YYERROR; 1068 } 1069 } 1070 if (rule->r_forwardonly && rule->r_action != A_NONE) { 1071 yyerror("forward-only may not be used with a default action"); 1072 YYERROR; 1073 } 1074 TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry); 1075 rule = NULL; 1076 } 1077 | REJECT { 1078 rule = xcalloc(1, sizeof(*rule), "parse rule: REJECT"); 1079 rule->r_decision = R_REJECT; 1080 rule->r_desttype = DEST_DOM; 1081 } decision { 1082 if (! rule->r_sources) 1083 rule->r_sources = table_find("<localhost>", NULL); 1084 if (! rule->r_destination) 1085 rule->r_destination = table_find("<localnames>", NULL); 1086 TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry); 1087 rule = NULL; 1088 } 1089 ; 1090 %% 1091 1092 struct keywords { 1093 const char *k_name; 1094 int k_val; 1095 }; 1096 1097 int 1098 yyerror(const char *fmt, ...) 1099 { 1100 va_list ap; 1101 char *nfmt; 1102 1103 file->errors++; 1104 va_start(ap, fmt); 1105 if (asprintf(&nfmt, "%s:%d: %s", file->name, yylval.lineno, fmt) == -1) 1106 fatalx("yyerror asprintf"); 1107 vlog(LOG_CRIT, nfmt, ap); 1108 va_end(ap); 1109 free(nfmt); 1110 return (0); 1111 } 1112 1113 int 1114 kw_cmp(const void *k, const void *e) 1115 { 1116 return (strcmp(k, ((const struct keywords *)e)->k_name)); 1117 } 1118 1119 int 1120 lookup(char *s) 1121 { 1122 /* this has to be sorted always */ 1123 static const struct keywords keywords[] = { 1124 { "accept", ACCEPT }, 1125 { "alias", ALIAS }, 1126 { "any", ANY }, 1127 { "as", AS }, 1128 { "auth", AUTH }, 1129 { "auth-optional", AUTH_OPTIONAL }, 1130 { "backup", BACKUP }, 1131 { "bounce-warn", BOUNCEWARN }, 1132 { "ca", CA }, 1133 { "certificate", CERTIFICATE }, 1134 { "compression", COMPRESSION }, 1135 { "deliver", DELIVER }, 1136 { "dhparams", DHPARAMS }, 1137 { "domain", DOMAIN }, 1138 { "encryption", ENCRYPTION }, 1139 { "expire", EXPIRE }, 1140 { "filter", FILTER }, 1141 { "filterchain", FILTERCHAIN }, 1142 { "for", FOR }, 1143 { "forward-only", FORWARDONLY }, 1144 { "from", FROM }, 1145 { "hostname", HOSTNAME }, 1146 { "hostnames", HOSTNAMES }, 1147 { "include", INCLUDE }, 1148 { "inet4", INET4 }, 1149 { "inet6", INET6 }, 1150 { "key", KEY }, 1151 { "limit", LIMIT }, 1152 { "listen", LISTEN }, 1153 { "lmtp", LMTP }, 1154 { "local", LOCAL }, 1155 { "maildir", MAILDIR }, 1156 { "mask-source", MASK_SOURCE }, 1157 { "max-message-size", MAXMESSAGESIZE }, 1158 { "max-mta-deferred", MAXMTADEFERRED }, 1159 { "mbox", MBOX }, 1160 { "mda", MDA }, 1161 { "mta", MTA }, 1162 { "on", ON }, 1163 { "pki", PKI }, 1164 { "port", PORT }, 1165 { "queue", QUEUE }, 1166 { "recipient", RECIPIENT }, 1167 { "reject", REJECT }, 1168 { "relay", RELAY }, 1169 { "scheduler", SCHEDULER }, 1170 { "secure", SECURE }, 1171 { "sender", SENDER }, 1172 { "smtps", SMTPS }, 1173 { "source", SOURCE }, 1174 { "table", TABLE }, 1175 { "tag", TAG }, 1176 { "tagged", TAGGED }, 1177 { "tls", TLS }, 1178 { "tls-require", TLS_REQUIRE }, 1179 { "to", TO }, 1180 { "userbase", USERBASE }, 1181 { "verify", VERIFY }, 1182 { "via", VIA }, 1183 { "virtual", VIRTUAL }, 1184 }; 1185 const struct keywords *p; 1186 1187 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 1188 sizeof(keywords[0]), kw_cmp); 1189 1190 if (p) 1191 return (p->k_val); 1192 else 1193 return (STRING); 1194 } 1195 1196 #define MAXPUSHBACK 128 1197 1198 u_char *parsebuf; 1199 int parseindex; 1200 u_char pushback_buffer[MAXPUSHBACK]; 1201 int pushback_index = 0; 1202 1203 int 1204 lgetc(int quotec) 1205 { 1206 int c, next; 1207 1208 if (parsebuf) { 1209 /* Read character from the parsebuffer instead of input. */ 1210 if (parseindex >= 0) { 1211 c = parsebuf[parseindex++]; 1212 if (c != '\0') 1213 return (c); 1214 parsebuf = NULL; 1215 } else 1216 parseindex++; 1217 } 1218 1219 if (pushback_index) 1220 return (pushback_buffer[--pushback_index]); 1221 1222 if (quotec) { 1223 if ((c = getc(file->stream)) == EOF) { 1224 yyerror("reached end of file while parsing " 1225 "quoted string"); 1226 if (file == topfile || popfile() == EOF) 1227 return (EOF); 1228 return (quotec); 1229 } 1230 return (c); 1231 } 1232 1233 while ((c = getc(file->stream)) == '\\') { 1234 next = getc(file->stream); 1235 if (next != '\n') { 1236 c = next; 1237 break; 1238 } 1239 yylval.lineno = file->lineno; 1240 file->lineno++; 1241 } 1242 1243 while (c == EOF) { 1244 if (file == topfile || popfile() == EOF) 1245 return (EOF); 1246 c = getc(file->stream); 1247 } 1248 return (c); 1249 } 1250 1251 int 1252 lungetc(int c) 1253 { 1254 if (c == EOF) 1255 return (EOF); 1256 if (parsebuf) { 1257 parseindex--; 1258 if (parseindex >= 0) 1259 return (c); 1260 } 1261 if (pushback_index < MAXPUSHBACK-1) 1262 return (pushback_buffer[pushback_index++] = c); 1263 else 1264 return (EOF); 1265 } 1266 1267 int 1268 findeol(void) 1269 { 1270 int c; 1271 1272 parsebuf = NULL; 1273 pushback_index = 0; 1274 1275 /* skip to either EOF or the first real EOL */ 1276 while (1) { 1277 c = lgetc(0); 1278 if (c == '\n') { 1279 file->lineno++; 1280 break; 1281 } 1282 if (c == EOF) 1283 break; 1284 } 1285 return (ERROR); 1286 } 1287 1288 int 1289 yylex(void) 1290 { 1291 u_char buf[8096]; 1292 u_char *p, *val; 1293 int quotec, next, c; 1294 int token; 1295 1296 top: 1297 p = buf; 1298 while ((c = lgetc(0)) == ' ' || c == '\t') 1299 ; /* nothing */ 1300 1301 yylval.lineno = file->lineno; 1302 if (c == '#') 1303 while ((c = lgetc(0)) != '\n' && c != EOF) 1304 ; /* nothing */ 1305 if (c == '$' && parsebuf == NULL) { 1306 while (1) { 1307 if ((c = lgetc(0)) == EOF) 1308 return (0); 1309 1310 if (p + 1 >= buf + sizeof(buf) - 1) { 1311 yyerror("string too long"); 1312 return (findeol()); 1313 } 1314 if (isalnum(c) || c == '_') { 1315 *p++ = c; 1316 continue; 1317 } 1318 *p = '\0'; 1319 lungetc(c); 1320 break; 1321 } 1322 val = symget(buf); 1323 if (val == NULL) { 1324 yyerror("macro '%s' not defined", buf); 1325 return (findeol()); 1326 } 1327 parsebuf = val; 1328 parseindex = 0; 1329 goto top; 1330 } 1331 1332 switch (c) { 1333 case '\'': 1334 case '"': 1335 quotec = c; 1336 while (1) { 1337 if ((c = lgetc(quotec)) == EOF) 1338 return (0); 1339 if (c == '\n') { 1340 file->lineno++; 1341 continue; 1342 } else if (c == '\\') { 1343 if ((next = lgetc(quotec)) == EOF) 1344 return (0); 1345 if (next == quotec || c == ' ' || c == '\t') 1346 c = next; 1347 else if (next == '\n') { 1348 file->lineno++; 1349 continue; 1350 } else 1351 lungetc(next); 1352 } else if (c == quotec) { 1353 *p = '\0'; 1354 break; 1355 } 1356 if (p + 1 >= buf + sizeof(buf) - 1) { 1357 yyerror("string too long"); 1358 return (findeol()); 1359 } 1360 *p++ = c; 1361 } 1362 yylval.v.string = strdup(buf); 1363 if (yylval.v.string == NULL) 1364 err(1, "yylex: strdup"); 1365 return (STRING); 1366 } 1367 1368 #define allowed_to_end_number(x) \ 1369 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 1370 1371 if (c == '-' || isdigit(c)) { 1372 do { 1373 *p++ = c; 1374 if ((unsigned)(p-buf) >= sizeof(buf)) { 1375 yyerror("string too long"); 1376 return (findeol()); 1377 } 1378 } while ((c = lgetc(0)) != EOF && isdigit(c)); 1379 lungetc(c); 1380 if (p == buf + 1 && buf[0] == '-') 1381 goto nodigits; 1382 if (c == EOF || allowed_to_end_number(c)) { 1383 const char *errstr = NULL; 1384 1385 *p = '\0'; 1386 yylval.v.number = strtonum(buf, LLONG_MIN, 1387 LLONG_MAX, &errstr); 1388 if (errstr) { 1389 yyerror("\"%s\" invalid number: %s", 1390 buf, errstr); 1391 return (findeol()); 1392 } 1393 return (NUMBER); 1394 } else { 1395 nodigits: 1396 while (p > buf + 1) 1397 lungetc(*--p); 1398 c = *--p; 1399 if (c == '-') 1400 return (c); 1401 } 1402 } 1403 1404 if (c == '=') { 1405 if ((c = lgetc(0)) != EOF && c == '>') 1406 return (ARROW); 1407 lungetc(c); 1408 c = '='; 1409 } 1410 1411 #define allowed_in_string(x) \ 1412 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1413 x != '{' && x != '}' && x != '<' && x != '>' && \ 1414 x != '!' && x != '=' && x != '#' && \ 1415 x != ',')) 1416 1417 if (isalnum(c) || c == ':' || c == '_') { 1418 do { 1419 *p++ = c; 1420 if ((unsigned)(p-buf) >= sizeof(buf)) { 1421 yyerror("string too long"); 1422 return (findeol()); 1423 } 1424 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 1425 lungetc(c); 1426 *p = '\0'; 1427 if ((token = lookup(buf)) == STRING) 1428 if ((yylval.v.string = strdup(buf)) == NULL) 1429 err(1, "yylex: strdup"); 1430 return (token); 1431 } 1432 if (c == '\n') { 1433 yylval.lineno = file->lineno; 1434 file->lineno++; 1435 } 1436 if (c == EOF) 1437 return (0); 1438 return (c); 1439 } 1440 1441 int 1442 check_file_secrecy(int fd, const char *fname) 1443 { 1444 struct stat st; 1445 1446 if (fstat(fd, &st)) { 1447 log_warn("warn: cannot stat %s", fname); 1448 return (-1); 1449 } 1450 if (st.st_uid != 0 && st.st_uid != getuid()) { 1451 log_warnx("warn: %s: owner not root or current user", fname); 1452 return (-1); 1453 } 1454 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 1455 log_warnx("warn: %s: group/world readable/writeable", fname); 1456 return (-1); 1457 } 1458 return (0); 1459 } 1460 1461 struct file * 1462 pushfile(const char *name, int secret) 1463 { 1464 struct file *nfile; 1465 1466 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 1467 log_warn("warn: malloc"); 1468 return (NULL); 1469 } 1470 if ((nfile->name = strdup(name)) == NULL) { 1471 log_warn("warn: malloc"); 1472 free(nfile); 1473 return (NULL); 1474 } 1475 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 1476 log_warn("warn: %s", nfile->name); 1477 free(nfile->name); 1478 free(nfile); 1479 return (NULL); 1480 } else if (secret && 1481 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 1482 fclose(nfile->stream); 1483 free(nfile->name); 1484 free(nfile); 1485 return (NULL); 1486 } 1487 nfile->lineno = 1; 1488 TAILQ_INSERT_TAIL(&files, nfile, entry); 1489 return (nfile); 1490 } 1491 1492 int 1493 popfile(void) 1494 { 1495 struct file *prev; 1496 1497 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 1498 prev->errors += file->errors; 1499 1500 TAILQ_REMOVE(&files, file, entry); 1501 fclose(file->stream); 1502 free(file->name); 1503 free(file); 1504 file = prev; 1505 return (file ? 0 : EOF); 1506 } 1507 1508 int 1509 parse_config(struct smtpd *x_conf, const char *filename, int opts) 1510 { 1511 struct sym *sym, *next; 1512 struct table *t; 1513 char hostname[SMTPD_MAXHOSTNAMELEN]; 1514 char hostname_copy[SMTPD_MAXHOSTNAMELEN]; 1515 1516 if (! getmailname(hostname, sizeof hostname)) 1517 return (-1); 1518 1519 conf = x_conf; 1520 memset(conf, 0, sizeof(*conf)); 1521 1522 strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname)); 1523 1524 conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE; 1525 1526 conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict)); 1527 conf->sc_rules = calloc(1, sizeof(*conf->sc_rules)); 1528 conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners)); 1529 conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict)); 1530 conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict)); 1531 conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict)); 1532 1533 /* Report mails delayed for more than 4 hours */ 1534 conf->sc_bounce_warn[0] = 3600 * 4; 1535 1536 if (conf->sc_tables_dict == NULL || 1537 conf->sc_rules == NULL || 1538 conf->sc_listeners == NULL || 1539 conf->sc_pki_dict == NULL || 1540 conf->sc_limits_dict == NULL) { 1541 log_warn("warn: cannot allocate memory"); 1542 free(conf->sc_tables_dict); 1543 free(conf->sc_rules); 1544 free(conf->sc_listeners); 1545 free(conf->sc_pki_dict); 1546 free(conf->sc_ssl_dict); 1547 free(conf->sc_limits_dict); 1548 return (-1); 1549 } 1550 1551 errors = 0; 1552 1553 table = NULL; 1554 rule = NULL; 1555 1556 dict_init(&conf->sc_filters); 1557 1558 dict_init(conf->sc_pki_dict); 1559 dict_init(conf->sc_ssl_dict); 1560 dict_init(conf->sc_tables_dict); 1561 1562 dict_init(conf->sc_limits_dict); 1563 limits = xcalloc(1, sizeof(*limits), "mta_limits"); 1564 limit_mta_set_defaults(limits); 1565 dict_xset(conf->sc_limits_dict, "default", limits); 1566 1567 TAILQ_INIT(conf->sc_listeners); 1568 TAILQ_INIT(conf->sc_rules); 1569 1570 conf->sc_qexpire = SMTPD_QUEUE_EXPIRY; 1571 conf->sc_opts = opts; 1572 1573 conf->sc_mta_max_deferred = 100; 1574 conf->sc_scheduler_max_inflight = 5000; 1575 conf->sc_scheduler_max_schedule = 10; 1576 conf->sc_scheduler_max_evp_batch_size = 256; 1577 conf->sc_scheduler_max_msg_batch_size = 1024; 1578 1579 conf->sc_mda_max_session = 50; 1580 conf->sc_mda_max_user_session = 7; 1581 conf->sc_mda_task_hiwat = 50; 1582 conf->sc_mda_task_lowat = 30; 1583 conf->sc_mda_task_release = 10; 1584 1585 if ((file = pushfile(filename, 0)) == NULL) { 1586 purge_config(PURGE_EVERYTHING); 1587 return (-1); 1588 } 1589 topfile = file; 1590 1591 /* 1592 * declare special "localhost", "anyhost" and "localnames" tables 1593 */ 1594 set_localaddrs(); 1595 1596 t = table_create("static", "<localnames>", NULL, NULL); 1597 t->t_type = T_LIST; 1598 table_add(t, "localhost", NULL); 1599 table_add(t, hostname, NULL); 1600 1601 t = table_create("static", "<anydestination>", NULL, NULL); 1602 t->t_type = T_LIST; 1603 table_add(t, "*", NULL); 1604 1605 /* can't truncate here */ 1606 (void)strlcpy(hostname_copy, hostname, sizeof hostname_copy); 1607 1608 hostname_copy[strcspn(hostname_copy, ".")] = '\0'; 1609 if (strcmp(hostname, hostname_copy) != 0) 1610 table_add(t, hostname_copy, NULL); 1611 1612 table_create("getpwnam", "<getpwnam>", NULL, NULL); 1613 1614 /* 1615 * parse configuration 1616 */ 1617 setservent(1); 1618 yyparse(); 1619 errors = file->errors; 1620 popfile(); 1621 endservent(); 1622 1623 /* Free macros and check which have not been used. */ 1624 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 1625 next = TAILQ_NEXT(sym, entry); 1626 if ((conf->sc_opts & SMTPD_OPT_VERBOSE) && !sym->used) 1627 fprintf(stderr, "warning: macro '%s' not " 1628 "used\n", sym->nam); 1629 if (!sym->persist) { 1630 free(sym->nam); 1631 free(sym->val); 1632 TAILQ_REMOVE(&symhead, sym, entry); 1633 free(sym); 1634 } 1635 } 1636 1637 if (TAILQ_EMPTY(conf->sc_rules)) { 1638 log_warnx("warn: no rules, nothing to do"); 1639 errors++; 1640 } 1641 1642 if (errors) { 1643 purge_config(PURGE_EVERYTHING); 1644 return (-1); 1645 } 1646 1647 return (0); 1648 } 1649 1650 int 1651 symset(const char *nam, const char *val, int persist) 1652 { 1653 struct sym *sym; 1654 1655 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 1656 sym = TAILQ_NEXT(sym, entry)) 1657 ; /* nothing */ 1658 1659 if (sym != NULL) { 1660 if (sym->persist == 1) 1661 return (0); 1662 else { 1663 free(sym->nam); 1664 free(sym->val); 1665 TAILQ_REMOVE(&symhead, sym, entry); 1666 free(sym); 1667 } 1668 } 1669 if ((sym = calloc(1, sizeof(*sym))) == NULL) 1670 return (-1); 1671 1672 sym->nam = strdup(nam); 1673 if (sym->nam == NULL) { 1674 free(sym); 1675 return (-1); 1676 } 1677 sym->val = strdup(val); 1678 if (sym->val == NULL) { 1679 free(sym->nam); 1680 free(sym); 1681 return (-1); 1682 } 1683 sym->used = 0; 1684 sym->persist = persist; 1685 TAILQ_INSERT_TAIL(&symhead, sym, entry); 1686 return (0); 1687 } 1688 1689 int 1690 cmdline_symset(char *s) 1691 { 1692 char *sym, *val; 1693 int ret; 1694 size_t len; 1695 1696 if ((val = strrchr(s, '=')) == NULL) 1697 return (-1); 1698 1699 len = strlen(s) - strlen(val) + 1; 1700 if ((sym = malloc(len)) == NULL) 1701 errx(1, "cmdline_symset: malloc"); 1702 1703 (void)strlcpy(sym, s, len); 1704 1705 ret = symset(sym, val + 1, 1); 1706 free(sym); 1707 1708 return (ret); 1709 } 1710 1711 char * 1712 symget(const char *nam) 1713 { 1714 struct sym *sym; 1715 1716 TAILQ_FOREACH(sym, &symhead, entry) 1717 if (strcmp(nam, sym->nam) == 0) { 1718 sym->used = 1; 1719 return (sym->val); 1720 } 1721 return (NULL); 1722 } 1723 1724 static void 1725 create_listener(struct listenerlist *ll, struct listen_opts *lo) 1726 { 1727 uint16_t flags; 1728 1729 if (lo->port != 0 && lo->ssl == F_SSL) 1730 errx(1, "invalid listen option: tls/smtps on same port"); 1731 1732 if (lo->auth != 0 && !lo->ssl) 1733 errx(1, "invalid listen option: auth requires tls/smtps"); 1734 1735 if (lo->pki && !lo->ssl) 1736 errx(1, "invalid listen option: pki requires tls/smtps"); 1737 1738 flags = lo->flags; 1739 1740 if (lo->port) { 1741 lo->flags = lo->ssl|lo->auth|flags; 1742 lo->port = htons(lo->port); 1743 if (! interface(ll, lo)) 1744 if (host(ll, lo) <= 0) 1745 errx(1, "invalid virtual ip or interface: %s", lo->ifx); 1746 } 1747 else { 1748 if (lo->ssl & F_SMTPS) { 1749 lo->port = htons(465); 1750 lo->flags = F_SMTPS|lo->auth|flags; 1751 if (! interface(ll, lo)) 1752 if (host(ll, lo) <= 0) 1753 errx(1, "invalid virtual ip or interface: %s", lo->ifx); 1754 } 1755 1756 if (! lo->ssl || (lo->ssl & F_STARTTLS)) { 1757 lo->port = htons(25); 1758 lo->flags = lo->auth|flags; 1759 if (lo->ssl & F_STARTTLS) 1760 lo->flags |= F_STARTTLS; 1761 if (! interface(ll, lo)) 1762 if (host(ll, lo) <= 0) 1763 errx(1, "invalid virtual ip or interface: %s", lo->ifx); 1764 } 1765 } 1766 } 1767 1768 static void 1769 config_listener(struct listener *h, struct listen_opts *lo) 1770 { 1771 h->fd = -1; 1772 h->port = lo->port; 1773 h->flags = lo->flags; 1774 1775 if (lo->hostname == NULL) 1776 lo->hostname = conf->sc_hostname; 1777 1778 h->pki_name[0] = '\0'; 1779 1780 if (lo->authtable != NULL) 1781 (void)strlcpy(h->authtable, lo->authtable->t_name, sizeof(h->authtable)); 1782 if (lo->pki != NULL) { 1783 if (! lowercase(h->pki_name, lo->pki, sizeof(h->pki_name))) { 1784 log_warnx("pki name too long: %s", lo->pki); 1785 fatalx(NULL); 1786 } 1787 if (dict_get(conf->sc_pki_dict, h->pki_name) == NULL) { 1788 log_warnx("pki name not found: %s", lo->pki); 1789 fatalx(NULL); 1790 } 1791 } 1792 if (lo->tag != NULL) 1793 (void)strlcpy(h->tag, lo->tag, sizeof(h->tag)); 1794 1795 (void)strlcpy(h->hostname, lo->hostname, sizeof(h->hostname)); 1796 if (lo->hostnametable) 1797 (void)strlcpy(h->hostnametable, lo->hostnametable->t_name, sizeof(h->hostnametable)); 1798 1799 if (lo->ssl & F_TLS_VERIFY) 1800 h->flags |= F_TLS_VERIFY; 1801 } 1802 1803 struct listener * 1804 host_v4(const char *s, in_port_t port) 1805 { 1806 struct in_addr ina; 1807 struct sockaddr_in *sain; 1808 struct listener *h; 1809 1810 memset(&ina, 0, sizeof(ina)); 1811 if (inet_pton(AF_INET, s, &ina) != 1) 1812 return (NULL); 1813 1814 h = xcalloc(1, sizeof(*h), "host_v4"); 1815 sain = (struct sockaddr_in *)&h->ss; 1816 sain->sin_len = sizeof(struct sockaddr_in); 1817 sain->sin_family = AF_INET; 1818 sain->sin_addr.s_addr = ina.s_addr; 1819 sain->sin_port = port; 1820 1821 return (h); 1822 } 1823 1824 struct listener * 1825 host_v6(const char *s, in_port_t port) 1826 { 1827 struct in6_addr ina6; 1828 struct sockaddr_in6 *sin6; 1829 struct listener *h; 1830 1831 memset(&ina6, 0, sizeof(ina6)); 1832 if (inet_pton(AF_INET6, s, &ina6) != 1) 1833 return (NULL); 1834 1835 h = xcalloc(1, sizeof(*h), "host_v6"); 1836 sin6 = (struct sockaddr_in6 *)&h->ss; 1837 sin6->sin6_len = sizeof(struct sockaddr_in6); 1838 sin6->sin6_family = AF_INET6; 1839 sin6->sin6_port = port; 1840 memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6)); 1841 1842 return (h); 1843 } 1844 1845 int 1846 host_dns(struct listenerlist *al, struct listen_opts *lo) 1847 { 1848 struct addrinfo hints, *res0, *res; 1849 int error, cnt = 0; 1850 struct sockaddr_in *sain; 1851 struct sockaddr_in6 *sin6; 1852 struct listener *h; 1853 1854 memset(&hints, 0, sizeof(hints)); 1855 hints.ai_family = PF_UNSPEC; 1856 hints.ai_socktype = SOCK_STREAM; 1857 error = getaddrinfo(lo->ifx, NULL, &hints, &res0); 1858 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 1859 return (0); 1860 if (error) { 1861 log_warnx("warn: host_dns: could not parse \"%s\": %s", lo->ifx, 1862 gai_strerror(error)); 1863 return (-1); 1864 } 1865 1866 for (res = res0; res; res = res->ai_next) { 1867 if (res->ai_family != AF_INET && 1868 res->ai_family != AF_INET6) 1869 continue; 1870 h = xcalloc(1, sizeof(*h), "host_dns"); 1871 1872 h->ss.ss_family = res->ai_family; 1873 if (res->ai_family == AF_INET) { 1874 sain = (struct sockaddr_in *)&h->ss; 1875 sain->sin_len = sizeof(struct sockaddr_in); 1876 sain->sin_addr.s_addr = ((struct sockaddr_in *) 1877 res->ai_addr)->sin_addr.s_addr; 1878 sain->sin_port = lo->port; 1879 } else { 1880 sin6 = (struct sockaddr_in6 *)&h->ss; 1881 sin6->sin6_len = sizeof(struct sockaddr_in6); 1882 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 1883 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 1884 sin6->sin6_port = lo->port; 1885 } 1886 1887 config_listener(h, lo); 1888 1889 TAILQ_INSERT_HEAD(al, h, entry); 1890 cnt++; 1891 } 1892 1893 freeaddrinfo(res0); 1894 return (cnt); 1895 } 1896 1897 int 1898 host(struct listenerlist *al, struct listen_opts *lo) 1899 { 1900 struct listener *h; 1901 1902 h = host_v4(lo->ifx, lo->port); 1903 1904 /* IPv6 address? */ 1905 if (h == NULL) 1906 h = host_v6(lo->ifx, lo->port); 1907 1908 if (h != NULL) { 1909 config_listener(h, lo); 1910 TAILQ_INSERT_HEAD(al, h, entry); 1911 return (1); 1912 } 1913 1914 return (host_dns(al, lo)); 1915 } 1916 1917 int 1918 interface(struct listenerlist *al, struct listen_opts *lo) 1919 { 1920 struct ifaddrs *ifap, *p; 1921 struct sockaddr_in *sain; 1922 struct sockaddr_in6 *sin6; 1923 struct listener *h; 1924 int ret = 0; 1925 1926 if (getifaddrs(&ifap) == -1) 1927 fatal("getifaddrs"); 1928 1929 for (p = ifap; p != NULL; p = p->ifa_next) { 1930 if (p->ifa_addr == NULL) 1931 continue; 1932 if (strcmp(p->ifa_name, lo->ifx) != 0 && 1933 ! is_if_in_group(p->ifa_name, lo->ifx)) 1934 continue; 1935 if (lo->family != AF_UNSPEC && lo->family != p->ifa_addr->sa_family) 1936 continue; 1937 1938 h = xcalloc(1, sizeof(*h), "interface"); 1939 1940 switch (p->ifa_addr->sa_family) { 1941 case AF_INET: 1942 sain = (struct sockaddr_in *)&h->ss; 1943 *sain = *(struct sockaddr_in *)p->ifa_addr; 1944 sain->sin_len = sizeof(struct sockaddr_in); 1945 sain->sin_port = lo->port; 1946 break; 1947 1948 case AF_INET6: 1949 sin6 = (struct sockaddr_in6 *)&h->ss; 1950 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 1951 sin6->sin6_len = sizeof(struct sockaddr_in6); 1952 sin6->sin6_port = lo->port; 1953 break; 1954 1955 default: 1956 free(h); 1957 continue; 1958 } 1959 1960 config_listener(h, lo); 1961 ret = 1; 1962 TAILQ_INSERT_HEAD(al, h, entry); 1963 } 1964 1965 freeifaddrs(ifap); 1966 1967 return ret; 1968 } 1969 1970 void 1971 set_localaddrs(void) 1972 { 1973 struct ifaddrs *ifap, *p; 1974 struct sockaddr_storage ss; 1975 struct sockaddr_in *sain; 1976 struct sockaddr_in6 *sin6; 1977 struct table *t; 1978 1979 t = table_create("static", "<anyhost>", NULL, NULL); 1980 table_add(t, "local", NULL); 1981 table_add(t, "0.0.0.0/0", NULL); 1982 table_add(t, "::/0", NULL); 1983 1984 if (getifaddrs(&ifap) == -1) 1985 fatal("getifaddrs"); 1986 1987 t = table_create("static", "<localhost>", NULL, NULL); 1988 table_add(t, "local", NULL); 1989 1990 for (p = ifap; p != NULL; p = p->ifa_next) { 1991 if (p->ifa_addr == NULL) 1992 continue; 1993 switch (p->ifa_addr->sa_family) { 1994 case AF_INET: 1995 sain = (struct sockaddr_in *)&ss; 1996 *sain = *(struct sockaddr_in *)p->ifa_addr; 1997 sain->sin_len = sizeof(struct sockaddr_in); 1998 table_add(t, ss_to_text(&ss), NULL); 1999 break; 2000 2001 case AF_INET6: 2002 sin6 = (struct sockaddr_in6 *)&ss; 2003 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 2004 sin6->sin6_len = sizeof(struct sockaddr_in6); 2005 table_add(t, ss_to_text(&ss), NULL); 2006 break; 2007 } 2008 } 2009 2010 freeifaddrs(ifap); 2011 } 2012 2013 int 2014 delaytonum(char *str) 2015 { 2016 unsigned int factor; 2017 size_t len; 2018 const char *errstr = NULL; 2019 int delay; 2020 2021 /* we need at least 1 digit and 1 unit */ 2022 len = strlen(str); 2023 if (len < 2) 2024 goto bad; 2025 2026 switch(str[len - 1]) { 2027 2028 case 's': 2029 factor = 1; 2030 break; 2031 2032 case 'm': 2033 factor = 60; 2034 break; 2035 2036 case 'h': 2037 factor = 60 * 60; 2038 break; 2039 2040 case 'd': 2041 factor = 24 * 60 * 60; 2042 break; 2043 2044 default: 2045 goto bad; 2046 } 2047 2048 str[len - 1] = '\0'; 2049 delay = strtonum(str, 1, INT_MAX / factor, &errstr); 2050 if (errstr) 2051 goto bad; 2052 2053 return (delay * factor); 2054 2055 bad: 2056 return (-1); 2057 } 2058 2059 int 2060 is_if_in_group(const char *ifname, const char *groupname) 2061 { 2062 unsigned int len; 2063 struct ifgroupreq ifgr; 2064 struct ifg_req *ifg; 2065 int s; 2066 int ret = 0; 2067 2068 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 2069 err(1, "socket"); 2070 2071 memset(&ifgr, 0, sizeof(ifgr)); 2072 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); 2073 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 2074 if (errno == EINVAL || errno == ENOTTY) 2075 goto end; 2076 err(1, "SIOCGIFGROUP"); 2077 } 2078 2079 len = ifgr.ifgr_len; 2080 ifgr.ifgr_groups = 2081 (struct ifg_req *)xcalloc(len/sizeof(struct ifg_req), 2082 sizeof(struct ifg_req), "is_if_in_group"); 2083 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 2084 err(1, "SIOCGIFGROUP"); 2085 2086 ifg = ifgr.ifgr_groups; 2087 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 2088 len -= sizeof(struct ifg_req); 2089 if (strcmp(ifg->ifgrq_group, groupname) == 0) { 2090 ret = 1; 2091 break; 2092 } 2093 } 2094 free(ifgr.ifgr_groups); 2095 2096 end: 2097 close(s); 2098 return ret; 2099 } 2100 2101 struct filter * 2102 create_filter(const char *name, const char *path) 2103 { 2104 struct filter *f; 2105 2106 if (dict_get(&conf->sc_filters, name)) { 2107 yyerror("filter \"%s\" already defined", name); 2108 return (NULL); 2109 } 2110 2111 f = xcalloc(1, sizeof(*f), "create_filter"); 2112 strlcpy(f->name, name, sizeof(f->name)); 2113 strlcpy(f->path, path, sizeof(f->path)); 2114 2115 dict_xset(&conf->sc_filters, name, f); 2116 2117 return (f); 2118 } 2119 2120 static struct filter * 2121 create_filter_chain(const char *name) 2122 { 2123 struct filter *f; 2124 2125 if (dict_get(&conf->sc_filters, name)) { 2126 yyerror("filter \"%s\" already defined", name); 2127 return (NULL); 2128 } 2129 f = xcalloc(1, sizeof(*f), "create_filter_chain"); 2130 strlcpy(f->name, name, sizeof(f->name)); 2131 f->chain = 1; 2132 2133 dict_xset(&conf->sc_filters, name, f); 2134 2135 return (f); 2136 } 2137 2138 static int 2139 extend_filter_chain(struct filter *f, const char *name) 2140 { 2141 int i; 2142 2143 if (!f->chain) { 2144 yyerror("filter \"%s\" is not a chain", f->name); 2145 return (0); 2146 } 2147 2148 if (dict_get(&conf->sc_filters, name) == NULL) { 2149 yyerror("undefined filter \"%s\"", name); 2150 return (0); 2151 } 2152 if (dict_get(&conf->sc_filters, name) == f) { 2153 yyerror("filter chain cannot contain itself"); 2154 return (0); 2155 } 2156 2157 for (i = 0; i < MAX_FILTER_PER_CHAIN; i++) { 2158 if (f->filters[i][0] == '\0') { 2159 strlcpy(f->filters[i], name, sizeof(f->filters[i])); 2160 return (1); 2161 } 2162 } 2163 yyerror("filter chain \"%s\" is full", f->name); 2164 return (0); 2165 } 2166