1/*++ 2/* NAME 3/* smtpd_check 3 4/* SUMMARY 5/* SMTP client request filtering 6/* SYNOPSIS 7/* #include "smtpd.h" 8/* #include "smtpd_check.h" 9/* 10/* void smtpd_check_init() 11/* 12/* int smtpd_check_addr(address) 13/* const char *address; 14/* 15/* char *smtpd_check_rewrite(state) 16/* SMTPD_STATE *state; 17/* 18/* char *smtpd_check_client(state) 19/* SMTPD_STATE *state; 20/* 21/* char *smtpd_check_helo(state, helohost) 22/* SMTPD_STATE *state; 23/* char *helohost; 24/* 25/* char *smtpd_check_mail(state, sender) 26/* SMTPD_STATE *state; 27/* char *sender; 28/* 29/* char *smtpd_check_rcpt(state, recipient) 30/* SMTPD_STATE *state; 31/* char *recipient; 32/* 33/* char *smtpd_check_etrn(state, destination) 34/* SMTPD_STATE *state; 35/* char *destination; 36/* 37/* char *smtpd_check_data(state) 38/* SMTPD_STATE *state; 39/* 40/* char *smtpd_check_eod(state) 41/* SMTPD_STATE *state; 42/* 43/* char *smtpd_check_size(state, size) 44/* SMTPD_STATE *state; 45/* off_t size; 46/* 47/* char *smtpd_check_queue(state) 48/* SMTPD_STATE *state; 49/* DESCRIPTION 50/* This module implements additional checks on SMTP client requests. 51/* A client request is validated in the context of the session state. 52/* The result is either an error response (including the numerical 53/* code) or the result is a null pointer in case of success. 54/* 55/* smtpd_check_init() initializes. This function should be called 56/* once during the process life time. 57/* 58/* smtpd_check_addr() sanity checks an email address and returns 59/* non-zero in case of badness. 60/* 61/* smtpd_check_rewrite() should be called before opening a queue 62/* file or proxy connection, in order to establish the proper 63/* header address rewriting context. 64/* 65/* Each of the following routines scrutinizes the argument passed to 66/* an SMTP command such as HELO, MAIL FROM, RCPT TO, or scrutinizes 67/* the initial client connection request. The administrator can 68/* specify what restrictions apply. 69/* 70/* Restrictions are specified via configuration parameters named 71/* \fIsmtpd_{client,helo,sender,recipient}_restrictions.\fR Each 72/* configuration parameter specifies a list of zero or more 73/* restrictions that are applied in the order as specified. 74/* .PP 75/* smtpd_check_client() validates the client host name or address. 76/* Relevant configuration parameters: 77/* .IP smtpd_client_restrictions 78/* Restrictions on the names or addresses of clients that may connect 79/* to this SMTP server. 80/* .PP 81/* smtpd_check_helo() validates the hostname provided with the 82/* HELO/EHLO commands. Relevant configuration parameters: 83/* .IP smtpd_helo_restrictions 84/* Restrictions on the hostname that is sent with the HELO/EHLO 85/* command. 86/* .PP 87/* smtpd_check_mail() validates the sender address provided with 88/* a MAIL FROM request. Relevant configuration parameters: 89/* .IP smtpd_sender_restrictions 90/* Restrictions on the sender address that is sent with the MAIL FROM 91/* command. 92/* .PP 93/* smtpd_check_rcpt() validates the recipient address provided 94/* with an RCPT TO request. Relevant configuration parameters: 95/* .IP smtpd_recipient_restrictions 96/* Restrictions on the recipient address that is sent with the RCPT 97/* TO command. 98/* .IP local_recipient_maps 99/* Tables of user names (not addresses) that exist in $mydestination. 100/* Mail for local users not in these tables is rejected. 101/* .PP 102/* smtpd_check_etrn() validates the domain name provided with the 103/* ETRN command, and other client-provided information. Relevant 104/* configuration parameters: 105/* .IP smtpd_etrn_restrictions 106/* Restrictions on the hostname that is sent with the HELO/EHLO 107/* command. 108/* .PP 109/* smtpd_check_size() checks if a message with the given size can 110/* be received (zero means that the message size is unknown). The 111/* message is rejected when 112/* the message size exceeds the non-zero bound specified with the 113/* \fImessage_size_limit\fR configuration parameter. This is a 114/* permanent error. 115/* 116/* smtpd_check_queue() checks the available queue file system 117/* space. The message is rejected when: 118/* .IP \(bu 119/* The available queue file system space is less than the amount 120/* specified with the \fImin_queue_free\fR configuration parameter. 121/* This is a temporary error. 122/* .IP \(bu 123/* The available queue file system space is less than twice the 124/* message size limit. This is a temporary error. 125/* .PP 126/* smtpd_check_data() enforces generic restrictions after the 127/* client has sent the DATA command. 128/* 129/* smtpd_check_eod() enforces generic restrictions after the 130/* client has sent the END-OF-DATA command. 131/* 132/* Arguments: 133/* .IP name 134/* The client hostname, or \fIunknown\fR. 135/* .IP addr 136/* The client address. 137/* .IP helohost 138/* The hostname given with the HELO command. 139/* .IP sender 140/* The sender address given with the MAIL FROM command. 141/* .IP recipient 142/* The recipient address given with the RCPT TO or VRFY command. 143/* .IP size 144/* The message size given with the MAIL FROM command (zero if unknown). 145/* BUGS 146/* Policies like these should not be hard-coded in C, but should 147/* be user-programmable instead. 148/* SEE ALSO 149/* namadr_list(3) host access control 150/* domain_list(3) domain access control 151/* fsspace(3) free file system space 152/* LICENSE 153/* .ad 154/* .fi 155/* The Secure Mailer license must be distributed with this software. 156/* AUTHOR(S) 157/* Wietse Venema 158/* IBM T.J. Watson Research 159/* P.O. Box 704 160/* Yorktown Heights, NY 10598, USA 161/* 162/* TLS support originally by: 163/* Lutz Jaenicke 164/* BTU Cottbus 165/* Allgemeine Elektrotechnik 166/* Universitaetsplatz 3-4 167/* D-03044 Cottbus, Germany 168/*--*/ 169 170/* System library. */ 171 172#include <sys_defs.h> 173#include <sys/socket.h> 174#include <netinet/in.h> 175#include <arpa/inet.h> 176#include <string.h> 177#include <ctype.h> 178#include <stdarg.h> 179#include <netdb.h> 180#include <setjmp.h> 181#include <stdlib.h> 182#include <unistd.h> 183#include <errno.h> 184 185#ifdef STRCASECMP_IN_STRINGS_H 186#include <strings.h> 187#endif 188 189/* Utility library. */ 190 191#include <msg.h> 192#include <vstring.h> 193#include <split_at.h> 194#include <fsspace.h> 195#include <stringops.h> 196#include <valid_hostname.h> 197#include <argv.h> 198#include <mymalloc.h> 199#include <dict.h> 200#include <htable.h> 201#include <ctable.h> 202#include <mac_expand.h> 203#include <attr_clnt.h> 204#include <myaddrinfo.h> 205#include <inet_proto.h> 206#include <ip_match.h> 207 208/* DNS library. */ 209 210#include <dns.h> 211 212/* Global library. */ 213 214#include <string_list.h> 215#include <namadr_list.h> 216#include <domain_list.h> 217#include <mail_params.h> 218#include <resolve_clnt.h> 219#include <mail_error.h> 220#include <resolve_local.h> 221#include <own_inet_addr.h> 222#include <mail_conf.h> 223#include <maps.h> 224#include <mail_addr_find.h> 225#include <match_parent_style.h> 226#include <strip_addr.h> 227#include <cleanup_user.h> 228#include <record.h> 229#include <rec_type.h> 230#include <mail_proto.h> 231#include <mail_addr.h> 232#include <verify_clnt.h> 233#include <input_transp.h> 234#include <is_header.h> 235#include <valid_mailhost_addr.h> 236#include <dsn_util.h> 237#include <conv_time.h> 238#include <xtext.h> 239 240/* Application-specific. */ 241 242#include "smtpd.h" 243#include "smtpd_sasl_glue.h" 244#include "smtpd_check.h" 245#include "smtpd_dsn_fix.h" 246#include "smtpd_resolve.h" 247#include "smtpd_expand.h" 248 249#define RESTRICTION_SEPARATORS ", \t\r\n" 250 251 /* 252 * Eject seat in case of parsing problems. 253 */ 254static jmp_buf smtpd_check_buf; 255 256 /* 257 * Results of restrictions. Errors are negative; see dict.h. 258 */ 259#define SMTPD_CHECK_DUNNO 0 /* indifferent */ 260#define SMTPD_CHECK_OK 1 /* explicitly permit */ 261#define SMTPD_CHECK_REJECT 2 /* explicitly reject */ 262 263 /* 264 * Intermediate results. These are static to avoid unnecessary stress on the 265 * memory manager routines. 266 */ 267static VSTRING *error_text; 268static CTABLE *smtpd_rbl_cache; 269static CTABLE *smtpd_rbl_byte_cache; 270 271 /* 272 * Pre-opened SMTP recipient maps so we can reject mail for unknown users. 273 * XXX This does not belong here and will eventually become part of the 274 * trivial-rewrite resolver. 275 */ 276static MAPS *local_rcpt_maps; 277static MAPS *rcpt_canon_maps; 278static MAPS *canonical_maps; 279static MAPS *virt_alias_maps; 280static MAPS *virt_mailbox_maps; 281static MAPS *relay_rcpt_maps; 282 283#ifdef TEST 284 285static STRING_LIST *virt_alias_doms; 286static STRING_LIST *virt_mailbox_doms; 287 288#endif 289 290 /* 291 * Response templates for various rbl domains. 292 */ 293static MAPS *rbl_reply_maps; 294 295 /* 296 * Pre-opened sender to login name mapping. 297 */ 298static MAPS *smtpd_sender_login_maps; 299 300 /* 301 * Pre-opened access control lists. 302 */ 303static DOMAIN_LIST *relay_domains; 304static NAMADR_LIST *mynetworks; 305static NAMADR_LIST *perm_mx_networks; 306 307#ifdef USE_TLS 308static MAPS *relay_ccerts; 309 310#endif 311 312 /* 313 * How to do parent domain wildcard matching, if any. 314 */ 315static int access_parent_style; 316 317 /* 318 * Pre-parsed restriction lists. 319 */ 320static ARGV *client_restrctions; 321static ARGV *helo_restrctions; 322static ARGV *mail_restrctions; 323static ARGV *relay_restrctions; 324static ARGV *rcpt_restrctions; 325static ARGV *etrn_restrctions; 326static ARGV *data_restrctions; 327static ARGV *eod_restrictions; 328 329static HTABLE *smtpd_rest_classes; 330static HTABLE *policy_clnt_table; 331 332static ARGV *local_rewrite_clients; 333 334 /* 335 * The routine that recursively applies restrictions. 336 */ 337static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, const char *); 338 339 /* 340 * Recipient table check. 341 */ 342static int check_sender_rcpt_maps(SMTPD_STATE *, const char *); 343static int check_recipient_rcpt_maps(SMTPD_STATE *, const char *); 344static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *); 345 346 /* 347 * Tempfail actions; 348 */ 349static int unk_name_tf_act; 350static int unk_addr_tf_act; 351static int unv_rcpt_tf_act; 352static int unv_from_tf_act; 353 354 /* 355 * Optional permit logging. 356 */ 357static STRING_LIST *smtpd_acl_perm_log; 358 359 /* 360 * YASLM. 361 */ 362#define STR vstring_str 363#define CONST_STR(x) ((const char *) vstring_str(x)) 364#define UPDATE_STRING(ptr,val) { if (ptr) myfree(ptr); ptr = mystrdup(val); } 365 366 /* 367 * If some decision can't be made due to a temporary error, then change 368 * other decisions into deferrals. 369 * 370 * XXX Deferrals can be postponed only with restrictions that are based on 371 * client-specified information: this restricts their use to parameters 372 * given in HELO, MAIL FROM, RCPT TO commands. 373 * 374 * XXX Deferrals must not be postponed after client hostname lookup failure. 375 * The reason is that the effect of access tables may depend on whether a 376 * client hostname is available or not. Thus, the reject_unknown_client 377 * restriction must defer immediately when lookup fails, otherwise incorrect 378 * results happen with: 379 * 380 * reject_unknown_client, hostname-based white-list, reject 381 * 382 * XXX With warn_if_reject, don't raise the defer_if_permit flag when a 383 * reject-style restriction fails. Instead, log the warning for the 384 * resulting defer message. 385 * 386 * XXX With warn_if_reject, do raise the defer_if_reject flag when a 387 * permit-style restriction fails. Otherwise, we could reject legitimate 388 * mail. 389 */ 390static int PRINTFLIKE(5, 6) defer_if(SMTPD_DEFER *, int, int, const char *, const char *,...); 391static int PRINTFLIKE(5, 6) smtpd_check_reject(SMTPD_STATE *, int, int, const char *, const char *,...); 392 393#define DEFER_IF_REJECT2(state, class, code, dsn, fmt, a1, a2) \ 394 defer_if(&(state)->defer_if_reject, (class), (code), (dsn), (fmt), (a1), (a2)) 395#define DEFER_IF_REJECT3(state, class, code, dsn, fmt, a1, a2, a3) \ 396 defer_if(&(state)->defer_if_reject, (class), (code), (dsn), (fmt), (a1), (a2), (a3)) 397#define DEFER_IF_REJECT4(state, class, code, dsn, fmt, a1, a2, a3, a4) \ 398 defer_if(&(state)->defer_if_reject, (class), (code), (dsn), (fmt), (a1), (a2), (a3), (a4)) 399 400 /* 401 * The following choose between DEFER_IF_PERMIT (only if warn_if_reject is 402 * turned off) and plain DEFER. See tempfail_actions[] below for the mapping 403 * from names to numeric action code. 404 */ 405#define DEFER_ALL_ACT 0 406#define DEFER_IF_PERMIT_ACT 1 407 408#define DEFER_IF_PERMIT2(type, state, class, code, dsn, fmt, a1, a2) \ 409 (((state)->warn_if_reject == 0 && (type) != 0) ? \ 410 defer_if(&(state)->defer_if_permit, (class), (code), (dsn), (fmt), (a1), (a2)) \ 411 : \ 412 smtpd_check_reject((state), (class), (code), (dsn), (fmt), (a1), (a2))) 413#define DEFER_IF_PERMIT3(type, state, class, code, dsn, fmt, a1, a2, a3) \ 414 (((state)->warn_if_reject == 0 && (type) != 0) ? \ 415 defer_if(&(state)->defer_if_permit, (class), (code), (dsn), (fmt), (a1), (a2), (a3)) \ 416 : \ 417 smtpd_check_reject((state), (class), (code), (dsn), (fmt), (a1), (a2), (a3))) 418#define DEFER_IF_PERMIT4(type, state, class, code, dsn, fmt, a1, a2, a3, a4) \ 419 (((state)->warn_if_reject == 0 && (type) != 0) ? \ 420 defer_if(&(state)->defer_if_permit, (class), (code), (dsn), (fmt), (a1), (a2), (a3), (a4)) \ 421 : \ 422 smtpd_check_reject((state), (class), (code), (dsn), (fmt), (a1), (a2), (a3), (a4))) 423 424 /* 425 * Cached RBL lookup state. 426 */ 427typedef struct { 428 char *txt; /* TXT content or NULL */ 429 DNS_RR *a; /* A records */ 430} SMTPD_RBL_STATE; 431 432static void *rbl_pagein(const char *, void *); 433static void rbl_pageout(void *, void *); 434static void *rbl_byte_pagein(const char *, void *); 435static void rbl_byte_pageout(void *, void *); 436 437 /* 438 * Context for RBL $name expansion. 439 */ 440typedef struct { 441 SMTPD_STATE *state; /* general state */ 442 char *domain; /* query domain */ 443 const char *what; /* rejected value */ 444 const char *class; /* name of rejected value */ 445 const char *txt; /* randomly selected trimmed TXT rr */ 446} SMTPD_RBL_EXPAND_CONTEXT; 447 448 /* 449 * Multiplication factor for free space check. Free space must be at least 450 * smtpd_space_multf * message_size_limit. 451 */ 452double smtpd_space_multf = 1.5; 453 454/* policy_client_register - register policy service endpoint */ 455 456static void policy_client_register(const char *name) 457{ 458 if (policy_clnt_table == 0) 459 policy_clnt_table = htable_create(1); 460 461 if (htable_find(policy_clnt_table, name) == 0) 462 htable_enter(policy_clnt_table, name, 463 (char *) attr_clnt_create(name, 464 var_smtpd_policy_tmout, 465 var_smtpd_policy_idle, 466 var_smtpd_policy_ttl)); 467} 468 469/* smtpd_check_parse - pre-parse restrictions */ 470 471static ARGV *smtpd_check_parse(int flags, const char *checks) 472{ 473 char *saved_checks = mystrdup(checks); 474 ARGV *argv = argv_alloc(1); 475 char *bp = saved_checks; 476 char *name; 477 char *last = 0; 478 479 /* 480 * Pre-parse the restriction list, and open any dictionaries that we 481 * encounter. Dictionaries must be opened before entering the chroot 482 * jail. 483 */ 484#define SMTPD_CHECK_PARSE_POLICY (1<<0) 485#define SMTPD_CHECK_PARSE_MAPS (1<<1) 486#define SMTPD_CHECK_PARSE_ALL (~0) 487 488 while ((name = mystrtok(&bp, RESTRICTION_SEPARATORS)) != 0) { 489 argv_add(argv, name, (char *) 0); 490 if ((flags & SMTPD_CHECK_PARSE_POLICY) 491 && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0) 492 policy_client_register(name); 493 else if ((flags & SMTPD_CHECK_PARSE_MAPS) 494 && strchr(name, ':') && dict_handle(name) == 0) { 495 dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK 496 | DICT_FLAG_FOLD_FIX)); 497 } 498 last = name; 499 } 500 argv_terminate(argv); 501 502 /* 503 * Cleanup. 504 */ 505 myfree(saved_checks); 506 return (argv); 507} 508 509/* has_required - make sure required restriction is present */ 510 511static int has_required(ARGV *restrictions, const char **required) 512{ 513 char **rest; 514 const char **reqd; 515 ARGV *expansion; 516 517 /* 518 * Recursively check list membership. 519 */ 520 for (rest = restrictions->argv; *rest; rest++) { 521 if (strcasecmp(*rest, WARN_IF_REJECT) == 0 && rest[1] != 0) { 522 rest += 1; 523 continue; 524 } 525 if (strcasecmp(*rest, PERMIT_ALL) == 0) { 526 if (rest[1] != 0) 527 msg_warn("restriction `%s' after `%s' is ignored", 528 rest[1], rest[0]); 529 return (0); 530 } 531 for (reqd = required; *reqd; reqd++) 532 if (strcasecmp(*rest, *reqd) == 0) 533 return (1); 534 /* XXX This lookup operation should not be case-sensitive. */ 535 if ((expansion = (ARGV *) htable_find(smtpd_rest_classes, *rest)) != 0) 536 if (has_required(expansion, required)) 537 return (1); 538 } 539 return (0); 540} 541 542/* fail_required - handle failure to use required restriction */ 543 544static void fail_required(const char *name, const char **required) 545{ 546 const char *myname = "fail_required"; 547 const char **reqd; 548 VSTRING *example; 549 550 /* 551 * Sanity check. 552 */ 553 if (required[0] == 0) 554 msg_panic("%s: null required list", myname); 555 556 /* 557 * Go bust. 558 */ 559 example = vstring_alloc(10); 560 for (reqd = required; *reqd; reqd++) 561 vstring_sprintf_append(example, "%s%s", *reqd, 562 reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", "); 563 msg_fatal("in parameter %s, specify at least one working instance of: %s", 564 name, STR(example)); 565} 566 567/* smtpd_check_init - initialize once during process lifetime */ 568 569void smtpd_check_init(void) 570{ 571 char *saved_classes; 572 const char *name; 573 const char *value; 574 char *cp; 575 static const char *rcpt_required[] = { 576 REJECT_UNAUTH_DEST, 577 DEFER_UNAUTH_DEST, 578 REJECT_ALL, 579 DEFER_ALL, 580 DEFER_IF_PERMIT, 581 CHECK_RELAY_DOMAINS, 582 0, 583 }; 584 static NAME_CODE tempfail_actions[] = { 585 DEFER_ALL, DEFER_ALL_ACT, 586 DEFER_IF_PERMIT, DEFER_IF_PERMIT_ACT, 587 0, -1, 588 }; 589 590 /* 591 * Pre-open access control lists before going to jail. 592 */ 593 mynetworks = 594 namadr_list_init(MATCH_FLAG_RETURN | match_parent_style(VAR_MYNETWORKS), 595 var_mynetworks); 596 relay_domains = 597 domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), 598 var_relay_domains); 599 perm_mx_networks = 600 namadr_list_init(MATCH_FLAG_RETURN 601 | match_parent_style(VAR_PERM_MX_NETWORKS), 602 var_perm_mx_networks); 603#ifdef USE_TLS 604 relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_smtpd_relay_ccerts, 605 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 606#endif 607 608 /* 609 * Pre-parse and pre-open the recipient maps. 610 */ 611 local_rcpt_maps = maps_create(VAR_LOCAL_RCPT_MAPS, var_local_rcpt_maps, 612 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 613 rcpt_canon_maps = maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps, 614 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 615 canonical_maps = maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, 616 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 617 virt_alias_maps = maps_create(VAR_VIRT_ALIAS_MAPS, var_virt_alias_maps, 618 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 619 virt_mailbox_maps = maps_create(VAR_VIRT_MAILBOX_MAPS, 620 var_virt_mailbox_maps, 621 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 622 relay_rcpt_maps = maps_create(VAR_RELAY_RCPT_MAPS, var_relay_rcpt_maps, 623 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 624 625#ifdef TEST 626 virt_alias_doms = string_list_init(MATCH_FLAG_NONE, var_virt_alias_doms); 627 virt_mailbox_doms = string_list_init(MATCH_FLAG_NONE, var_virt_mailbox_doms); 628#endif 629 630 access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS); 631 632 /* 633 * Templates for RBL rejection replies. 634 */ 635 rbl_reply_maps = maps_create(VAR_RBL_REPLY_MAPS, var_rbl_reply_maps, 636 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 637 638 /* 639 * Sender to login name mapping. 640 */ 641 smtpd_sender_login_maps = maps_create(VAR_SMTPD_SND_AUTH_MAPS, 642 var_smtpd_snd_auth_maps, 643 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 644 645 /* 646 * error_text is used for returning error responses. 647 */ 648 error_text = vstring_alloc(10); 649 650 /* 651 * Initialize the resolved address cache. Note: the cache persists across 652 * SMTP sessions so we cannot make it dependent on session state. 653 */ 654 smtpd_resolve_init(100); 655 656 /* 657 * Initialize the RBL lookup cache. Note: the cache persists across SMTP 658 * sessions so we cannot make it dependent on session state. 659 */ 660 smtpd_rbl_cache = ctable_create(100, rbl_pagein, rbl_pageout, (void *) 0); 661 smtpd_rbl_byte_cache = ctable_create(1000, rbl_byte_pagein, 662 rbl_byte_pageout, (void *) 0); 663 664 /* 665 * Pre-parse the restriction lists. At the same time, pre-open tables 666 * before going to jail. 667 */ 668 client_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 669 var_client_checks); 670 helo_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 671 var_helo_checks); 672 mail_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 673 var_mail_checks); 674 relay_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 675 var_relay_checks); 676 rcpt_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 677 var_rcpt_checks); 678 etrn_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 679 var_etrn_checks); 680 data_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 681 var_data_checks); 682 eod_restrictions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 683 var_eod_checks); 684 685 /* 686 * Parse the pre-defined restriction classes. 687 */ 688 smtpd_rest_classes = htable_create(1); 689 if (*var_rest_classes) { 690 cp = saved_classes = mystrdup(var_rest_classes); 691 while ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) != 0) { 692 if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0) 693 msg_fatal("restriction class `%s' needs a definition", name); 694 /* XXX This store operation should not be case-sensitive. */ 695 htable_enter(smtpd_rest_classes, name, 696 (char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 697 value)); 698 } 699 myfree(saved_classes); 700 } 701 702 /* 703 * This is the place to specify definitions for complex restrictions such 704 * as check_relay_domains in terms of more elementary restrictions. 705 */ 706#if 0 707 htable_enter(smtpd_rest_classes, "check_relay_domains", 708 smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 709 "permit_mydomain reject_unauth_destination")); 710#endif 711 htable_enter(smtpd_rest_classes, REJECT_SENDER_LOGIN_MISMATCH, 712 (char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, 713 REJECT_AUTH_SENDER_LOGIN_MISMATCH 714 " " REJECT_UNAUTH_SENDER_LOGIN_MISMATCH)); 715 716 /* 717 * People screw up the relay restrictions too often. Require that they 718 * list at least one restriction that rejects mail by default. We allow 719 * relay restrictions to be empty for sites that require backwards 720 * compatibility. 721 */ 722#ifndef TEST 723 if (!has_required(rcpt_restrctions, rcpt_required) 724 && !has_required(relay_restrctions, rcpt_required)) 725 fail_required(VAR_RELAY_CHECKS " or " VAR_RCPT_CHECKS, rcpt_required); 726#endif 727 728 /* 729 * Local rewrite policy. 730 */ 731 local_rewrite_clients = smtpd_check_parse(SMTPD_CHECK_PARSE_MAPS, 732 var_local_rwr_clients); 733 734 /* 735 * Tempfail_actions. 736 * 737 * XXX This name-to-number mapping should be encapsulated in a separate 738 * mail_conf_name_code.c module. 739 */ 740 if ((unk_name_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE, 741 var_unk_name_tf_act)) < 0) 742 msg_fatal("bad configuration: %s = %s", 743 VAR_UNK_NAME_TF_ACT, var_unk_name_tf_act); 744 if ((unk_addr_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE, 745 var_unk_addr_tf_act)) < 0) 746 msg_fatal("bad configuration: %s = %s", 747 VAR_UNK_ADDR_TF_ACT, var_unk_addr_tf_act); 748 if ((unv_rcpt_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE, 749 var_unv_rcpt_tf_act)) < 0) 750 msg_fatal("bad configuration: %s = %s", 751 VAR_UNV_RCPT_TF_ACT, var_unv_rcpt_tf_act); 752 if ((unv_from_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE, 753 var_unv_from_tf_act)) < 0) 754 msg_fatal("bad configuration: %s = %s", 755 VAR_UNV_FROM_TF_ACT, var_unv_from_tf_act); 756 if (msg_verbose) { 757 msg_info("%s = %s", VAR_UNK_NAME_TF_ACT, tempfail_actions[unk_name_tf_act].name); 758 msg_info("%s = %s", VAR_UNK_ADDR_TF_ACT, tempfail_actions[unk_addr_tf_act].name); 759 msg_info("%s = %s", VAR_UNV_RCPT_TF_ACT, tempfail_actions[unv_rcpt_tf_act].name); 760 msg_info("%s = %s", VAR_UNV_FROM_TF_ACT, tempfail_actions[unv_from_tf_act].name); 761 } 762 763 /* 764 * Optional permit logging. 765 */ 766 smtpd_acl_perm_log = string_list_init(MATCH_FLAG_RETURN, 767 var_smtpd_acl_perm_log); 768} 769 770/* log_whatsup - log as much context as we have */ 771 772static void log_whatsup(SMTPD_STATE *state, const char *whatsup, 773 const char *text) 774{ 775 VSTRING *buf = vstring_alloc(100); 776 777 vstring_sprintf(buf, "%s: %s: %s from %s: %s;", 778 state->queue_id ? state->queue_id : "NOQUEUE", 779 whatsup, state->where, state->namaddr, text); 780 if (state->sender) 781 vstring_sprintf_append(buf, " from=<%s>", state->sender); 782 if (state->recipient) 783 vstring_sprintf_append(buf, " to=<%s>", state->recipient); 784 if (state->protocol) 785 vstring_sprintf_append(buf, " proto=%s", state->protocol); 786 if (state->helo_name) 787 vstring_sprintf_append(buf, " helo=<%s>", state->helo_name); 788 msg_info("%s", STR(buf)); 789 vstring_free(buf); 790} 791 792/* smtpd_acl_permit - permit request with optional logging */ 793 794static int PRINTFLIKE(5, 6) smtpd_acl_permit(SMTPD_STATE *state, 795 const char *action, 796 const char *reply_class, 797 const char *reply_name, 798 const char *format,...) 799{ 800 va_list ap; 801 const char *whatsup; 802 803#ifdef notdef 804#define NO_PRINT_ARGS "" 805#else 806#define NO_PRINT_ARGS "%s", "" 807#endif 808 809 /* 810 * First, find out if (and how) this permit action should be logged. 811 */ 812 if (state->defer_if_permit.active) { 813 /* This action is overruled. Do not log. */ 814 whatsup = 0; 815 } else if (string_list_match(smtpd_acl_perm_log, action) != 0) { 816 /* This is not a test. Logging is enabled. */ 817 whatsup = "permit"; 818 } else { 819 /* This is not a test. Logging is disabled. */ 820 whatsup = 0; 821 } 822 if (whatsup != 0) { 823 vstring_sprintf(error_text, "action=%s for %s=%s", 824 action, reply_class, reply_name); 825 if (format && *format) { 826 vstring_strcat(error_text, " "); 827 va_start(ap, format); 828 vstring_vsprintf_append(error_text, format, ap); 829 va_end(ap); 830 } 831 log_whatsup(state, whatsup, STR(error_text)); 832 } 833 return (SMTPD_CHECK_OK); 834} 835 836/* smtpd_check_reject - do the boring things that must be done */ 837 838static int smtpd_check_reject(SMTPD_STATE *state, int error_class, 839 int code, const char *dsn, 840 const char *format,...) 841{ 842 va_list ap; 843 int warn_if_reject; 844 const char *whatsup; 845 846 /* 847 * Do not reject mail if we were asked to warn only. However, 848 * configuration errors cannot be converted into warnings. 849 */ 850 if (state->warn_if_reject && error_class != MAIL_ERROR_SOFTWARE 851 && error_class != MAIL_ERROR_RESOURCE) { 852 warn_if_reject = 1; 853 whatsup = "reject_warning"; 854 } else { 855 warn_if_reject = 0; 856 whatsup = "reject"; 857 } 858 859 /* 860 * Update the error class mask, and format the response. XXX What about 861 * multi-line responses? For now we cheat and send whitespace. 862 * 863 * Format the response before complaining about configuration errors, so 864 * that we can show the error in context. 865 */ 866 state->error_mask |= error_class; 867 vstring_sprintf(error_text, "%d %s ", code, dsn); 868 va_start(ap, format); 869 vstring_vsprintf_append(error_text, format, ap); 870 va_end(ap); 871 872 /* 873 * Validate the response, that is, the response must begin with a 874 * three-digit status code, and the first digit must be 4 or 5. If the 875 * response is bad, log a warning and send a generic response instead. 876 */ 877 if (code < 400 || code > 599) { 878 msg_warn("SMTP reply code configuration error: %s", STR(error_text)); 879 vstring_strcpy(error_text, "450 4.7.1 Service unavailable"); 880 } 881 if (!dsn_valid(STR(error_text) + 4)) { 882 msg_warn("DSN detail code configuration error: %s", STR(error_text)); 883 vstring_strcpy(error_text, "450 4.7.1 Service unavailable"); 884 } 885 886 /* 887 * Ensure RFC compliance. We could do this inside smtpd_chat_reply() and 888 * switch to multi-line for long replies. 889 */ 890 vstring_truncate(error_text, 510); 891 printable(STR(error_text), ' '); 892 893 /* 894 * Force this rejection into deferral because of some earlier temporary 895 * error that may have prevented us from accepting mail, and report the 896 * earlier problem instead. 897 */ 898 if (!warn_if_reject && state->defer_if_reject.active && STR(error_text)[0] == '5') { 899 state->warn_if_reject = state->defer_if_reject.active = 0; 900 return (smtpd_check_reject(state, state->defer_if_reject.class, 901 state->defer_if_reject.code, 902 STR(state->defer_if_reject.dsn), 903 "%s", STR(state->defer_if_reject.reason))); 904 } 905 906 /* 907 * Soft bounce safety net. 908 * 909 * XXX The code below also appears in the Postfix SMTP server reply output 910 * routine. It is duplicated here in order to avoid discrepancies between 911 * the reply codes that are shown in "reject" logging and the reply codes 912 * that are actually sent to the SMTP client. 913 * 914 * Implementing the soft_bounce safety net in the SMTP server reply output 915 * routine has the advantage that it covers all 5xx replies, including 916 * SMTP protocol or syntax errors, which makes soft_bounce great for 917 * non-destructive tests (especially by people who are paranoid about 918 * losing mail). 919 * 920 * We could eliminate the code duplication and implement the soft_bounce 921 * safety net only in the code below. But then the safety net would cover 922 * the UCE restrictions only. This would be at odds with documentation 923 * which says soft_bounce changes all 5xx replies into 4xx ones. 924 */ 925 if (var_soft_bounce && STR(error_text)[0] == '5') 926 STR(error_text)[0] = '4'; 927 928 /* 929 * In any case, enforce consistency between the SMTP code and DSN code. 930 * SMTP has the higher precedence since it came here first. 931 */ 932 STR(error_text)[4] = STR(error_text)[0]; 933 934 /* 935 * Log what is happening. When the sysadmin discards policy violation 936 * postmaster notices, this may be the only trace left that service was 937 * rejected. Print the request, client name/address, and response. 938 */ 939 log_whatsup(state, whatsup, STR(error_text)); 940 941 return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT); 942} 943 944/* defer_if - prepare to change our mind */ 945 946static int defer_if(SMTPD_DEFER *defer, int error_class, 947 int code, const char *dsn, 948 const char *fmt,...) 949{ 950 va_list ap; 951 952 /* 953 * Keep the first reason for this type of deferral, to minimize 954 * confusion. 955 */ 956 if (defer->active == 0) { 957 defer->active = 1; 958 defer->class = error_class; 959 defer->code = code; 960 if (defer->dsn == 0) 961 defer->dsn = vstring_alloc(10); 962 vstring_strcpy(defer->dsn, dsn); 963 if (defer->reason == 0) 964 defer->reason = vstring_alloc(10); 965 va_start(ap, fmt); 966 vstring_vsprintf(defer->reason, fmt, ap); 967 va_end(ap); 968 } 969 return (SMTPD_CHECK_DUNNO); 970} 971 972/* reject_dict_retry - reject with temporary failure if dict lookup fails */ 973 974static NORETURN reject_dict_retry(SMTPD_STATE *state, const char *reply_name) 975{ 976 longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_DATA, 977 451, "4.3.0", 978 "<%s>: Temporary lookup failure", 979 reply_name)); 980} 981 982/* reject_server_error - reject with temporary failure after non-dict error */ 983 984static NORETURN reject_server_error(SMTPD_STATE *state) 985{ 986 longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_SOFTWARE, 987 451, "4.3.5", 988 "Server configuration error")); 989} 990 991/* check_mail_addr_find - reject with temporary failure if dict lookup fails */ 992 993static const char *check_mail_addr_find(SMTPD_STATE *state, 994 const char *reply_name, 995 MAPS *maps, const char *key, 996 char **ext) 997{ 998 const char *result; 999 1000 if ((result = mail_addr_find(maps, key, ext)) != 0 || maps->error == 0) 1001 return (result); 1002 if (maps->error == DICT_ERR_RETRY) 1003 reject_dict_retry(state, reply_name); 1004 else 1005 reject_server_error(state); 1006} 1007 1008/* reject_unknown_reverse_name - fail if reverse client hostname is unknown */ 1009 1010static int reject_unknown_reverse_name(SMTPD_STATE *state) 1011{ 1012 const char *myname = "reject_unknown_reverse_name"; 1013 1014 if (msg_verbose) 1015 msg_info("%s: %s", myname, state->reverse_name); 1016 1017 if (state->reverse_name_status != SMTPD_PEER_CODE_OK) 1018 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1019 state->reverse_name_status == SMTPD_PEER_CODE_PERM ? 1020 var_unk_client_code : 450, "4.7.1", 1021 "Client host rejected: cannot find your reverse hostname, [%s]", 1022 state->addr)); 1023 return (SMTPD_CHECK_DUNNO); 1024} 1025 1026/* reject_unknown_client - fail if client hostname is unknown */ 1027 1028static int reject_unknown_client(SMTPD_STATE *state) 1029{ 1030 const char *myname = "reject_unknown_client"; 1031 1032 if (msg_verbose) 1033 msg_info("%s: %s %s", myname, state->name, state->addr); 1034 1035 if (state->name_status != SMTPD_PEER_CODE_OK) 1036 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1037 state->name_status >= SMTPD_PEER_CODE_PERM ? 1038 var_unk_client_code : 450, "4.7.1", 1039 "Client host rejected: cannot find your hostname, [%s]", 1040 state->addr)); 1041 return (SMTPD_CHECK_DUNNO); 1042} 1043 1044/* reject_plaintext_session - fail if session is not encrypted */ 1045 1046static int reject_plaintext_session(SMTPD_STATE *state) 1047{ 1048 const char *myname = "reject_plaintext_session"; 1049 1050 if (msg_verbose) 1051 msg_info("%s: %s %s", myname, state->name, state->addr); 1052 1053#ifdef USE_TLS 1054 if (state->tls_context == 0) 1055#endif 1056 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1057 var_plaintext_code, "4.7.1", 1058 "Session encryption is required")); 1059 return (SMTPD_CHECK_DUNNO); 1060} 1061 1062/* permit_inet_interfaces - succeed if client my own address */ 1063 1064static int permit_inet_interfaces(SMTPD_STATE *state) 1065{ 1066 const char *myname = "permit_inet_interfaces"; 1067 1068 if (msg_verbose) 1069 msg_info("%s: %s %s", myname, state->name, state->addr); 1070 1071 if (own_inet_addr((struct sockaddr *) & (state->sockaddr))) 1072 /* Permit logging in generic_checks() only. */ 1073 return (SMTPD_CHECK_OK); 1074 return (SMTPD_CHECK_DUNNO); 1075} 1076 1077/* permit_mynetworks - succeed if client is in a trusted network */ 1078 1079static int permit_mynetworks(SMTPD_STATE *state) 1080{ 1081 const char *myname = "permit_mynetworks"; 1082 1083 if (msg_verbose) 1084 msg_info("%s: %s %s", myname, state->name, state->addr); 1085 1086 if (namadr_list_match(mynetworks, state->name, state->addr)) 1087 /* Permit logging in generic_checks() only. */ 1088 return (SMTPD_CHECK_OK); 1089 else if (mynetworks->error == 0) 1090 return (SMTPD_CHECK_DUNNO); 1091 else 1092 return (mynetworks->error); 1093} 1094 1095/* dup_if_truncate - save hostname and truncate if it ends in dot */ 1096 1097static char *dup_if_truncate(char *name) 1098{ 1099 ssize_t len; 1100 char *result; 1101 1102 /* 1103 * Truncate hostnames ending in dot but not dot-dot. 1104 * 1105 * XXX This should not be distributed all over the code. Problem is, 1106 * addresses can enter the system via multiple paths: networks, local 1107 * forward/alias/include files, even as the result of address rewriting. 1108 */ 1109 if ((len = strlen(name)) > 1 1110 && name[len - 1] == '.' 1111 && name[len - 2] != '.') { 1112 result = mystrndup(name, len - 1); 1113 } else 1114 result = name; 1115 return (result); 1116} 1117 1118/* reject_invalid_hostaddr - fail if host address is incorrect */ 1119 1120static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr, 1121 char *reply_name, char *reply_class) 1122{ 1123 const char *myname = "reject_invalid_hostaddr"; 1124 ssize_t len; 1125 char *test_addr; 1126 int stat; 1127 1128 if (msg_verbose) 1129 msg_info("%s: %s", myname, addr); 1130 1131 if (addr[0] == '[' && (len = strlen(addr)) > 2 && addr[len - 1] == ']') { 1132 test_addr = mystrndup(addr + 1, len - 2); 1133 } else 1134 test_addr = addr; 1135 1136 /* 1137 * Validate the address. 1138 */ 1139 if (!valid_mailhost_addr(test_addr, DONT_GRIPE)) 1140 stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, 1141 var_bad_name_code, "5.5.2", 1142 "<%s>: %s rejected: invalid ip address", 1143 reply_name, reply_class); 1144 else 1145 stat = SMTPD_CHECK_DUNNO; 1146 1147 /* 1148 * Cleanup. 1149 */ 1150 if (test_addr != addr) 1151 myfree(test_addr); 1152 1153 return (stat); 1154} 1155 1156/* reject_invalid_hostname - fail if host/domain syntax is incorrect */ 1157 1158static int reject_invalid_hostname(SMTPD_STATE *state, char *name, 1159 char *reply_name, char *reply_class) 1160{ 1161 const char *myname = "reject_invalid_hostname"; 1162 char *test_name; 1163 int stat; 1164 1165 if (msg_verbose) 1166 msg_info("%s: %s", myname, name); 1167 1168 /* 1169 * Truncate hostnames ending in dot but not dot-dot. 1170 */ 1171 test_name = dup_if_truncate(name); 1172 1173 /* 1174 * Validate the hostname. 1175 */ 1176 if (!valid_hostname(test_name, DONT_GRIPE) 1177 && !valid_hostaddr(test_name, DONT_GRIPE)) /* XXX back compat */ 1178 stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, 1179 var_bad_name_code, "5.5.2", 1180 "<%s>: %s rejected: Invalid name", 1181 reply_name, reply_class); 1182 else 1183 stat = SMTPD_CHECK_DUNNO; 1184 1185 /* 1186 * Cleanup. 1187 */ 1188 if (test_name != name) 1189 myfree(test_name); 1190 1191 return (stat); 1192} 1193 1194/* reject_non_fqdn_hostname - fail if host name is not in fqdn form */ 1195 1196static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name, 1197 char *reply_name, char *reply_class) 1198{ 1199 const char *myname = "reject_non_fqdn_hostname"; 1200 char *test_name; 1201 int stat; 1202 1203 if (msg_verbose) 1204 msg_info("%s: %s", myname, name); 1205 1206 /* 1207 * Truncate hostnames ending in dot but not dot-dot. 1208 */ 1209 test_name = dup_if_truncate(name); 1210 1211 /* 1212 * Validate the hostname. 1213 */ 1214 if (!valid_hostname(test_name, DONT_GRIPE) || !strchr(test_name, '.')) 1215 stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, 1216 var_non_fqdn_code, "5.5.2", 1217 "<%s>: %s rejected: need fully-qualified hostname", 1218 reply_name, reply_class); 1219 else 1220 stat = SMTPD_CHECK_DUNNO; 1221 1222 /* 1223 * Cleanup. 1224 */ 1225 if (test_name != name) 1226 myfree(test_name); 1227 1228 return (stat); 1229} 1230 1231/* reject_unknown_hostname - fail if name has no A, AAAA or MX record */ 1232 1233static int reject_unknown_hostname(SMTPD_STATE *state, char *name, 1234 char *reply_name, char *reply_class) 1235{ 1236 const char *myname = "reject_unknown_hostname"; 1237 int dns_status; 1238 DNS_RR *dummy; 1239 1240 if (msg_verbose) 1241 msg_info("%s: %s", myname, name); 1242 1243#ifdef T_AAAA 1244#define RR_ADDR_TYPES T_A, T_AAAA 1245#else 1246#define RR_ADDR_TYPES T_A 1247#endif 1248 1249 dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0, 1250 (VSTRING *) 0, DNS_REQ_FLAG_STOP_OK, 1251 RR_ADDR_TYPES, T_MX, 0); 1252 if (dummy) 1253 dns_rr_free(dummy); 1254 if (dns_status != DNS_OK) { /* incl. DNS_INVAL */ 1255 if (dns_status != DNS_RETRY) 1256 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1257 var_unk_name_code, "4.7.1", 1258 "<%s>: %s rejected: %s", 1259 reply_name, reply_class, 1260 dns_status == DNS_INVAL ? 1261 "Malformed DNS server reply" : 1262 "Host not found")); 1263 else 1264 return (DEFER_IF_PERMIT2(unk_name_tf_act, state, MAIL_ERROR_POLICY, 1265 450, "4.7.1", 1266 "<%s>: %s rejected: Host not found", 1267 reply_name, reply_class)); 1268 } 1269 return (SMTPD_CHECK_DUNNO); 1270} 1271 1272/* reject_unknown_mailhost - fail if name has no A, AAAA or MX record */ 1273 1274static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name, 1275 const char *reply_name, const char *reply_class) 1276{ 1277 const char *myname = "reject_unknown_mailhost"; 1278 int dns_status; 1279 DNS_RR *dummy; 1280 1281 if (msg_verbose) 1282 msg_info("%s: %s", myname, name); 1283 1284#define MAILHOST_LOOKUP_FLAGS (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL) 1285 1286 dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0, 1287 (VSTRING *) 0, MAILHOST_LOOKUP_FLAGS, 1288 T_MX, RR_ADDR_TYPES, 0); 1289 if (dummy) 1290 dns_rr_free(dummy); 1291 if (dns_status != DNS_OK) { /* incl. DNS_INVAL */ 1292 if (dns_status != DNS_RETRY) 1293 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1294 var_unk_addr_code, 1295 strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 1296 "4.1.8" : "4.1.2", 1297 "<%s>: %s rejected: %s", 1298 reply_name, reply_class, 1299 dns_status == DNS_INVAL ? 1300 "Malformed DNS server reply" : 1301 "Domain not found")); 1302 else 1303 return (DEFER_IF_PERMIT2(unk_addr_tf_act, state, MAIL_ERROR_POLICY, 1304 450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 1305 "4.1.8" : "4.1.2", 1306 "<%s>: %s rejected: Domain not found", 1307 reply_name, reply_class)); 1308 } 1309 return (SMTPD_CHECK_DUNNO); 1310} 1311 1312static int permit_auth_destination(SMTPD_STATE *state, char *recipient); 1313 1314/* permit_tls_clientcerts - OK/DUNNO for message relaying, or set dict_errno */ 1315 1316static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) 1317{ 1318#ifdef USE_TLS 1319 const char *found = 0; 1320 1321 if (!state->tls_context) 1322 return SMTPD_CHECK_DUNNO; 1323 1324 if (TLS_CERT_IS_TRUSTED(state->tls_context) && permit_all_certs) { 1325 if (msg_verbose) 1326 msg_info("Relaying allowed for all verified client certificates"); 1327 /* Permit logging in generic_checks() only. */ 1328 return (SMTPD_CHECK_OK); 1329 } 1330 1331 /* 1332 * When directly checking the fingerprint, it is OK if the issuing CA is 1333 * not trusted. 1334 */ 1335 if (TLS_CERT_IS_PRESENT(state->tls_context)) { 1336 int i; 1337 char *prints[2]; 1338 1339 prints[0] = state->tls_context->peer_cert_fprint; 1340 prints[1] = state->tls_context->peer_pkey_fprint; 1341 1342 /* After lookup error, leave relay_ccerts->error at non-zero value. */ 1343 for (i = 0; i < 2; ++i) { 1344 found = maps_find(relay_ccerts, prints[i], DICT_FLAG_NONE); 1345 if (found != 0) { 1346 if (msg_verbose) 1347 msg_info("Relaying allowed for certified client: %s", found); 1348 /* Permit logging in generic_checks() only. */ 1349 return (SMTPD_CHECK_OK); 1350 } else if (relay_ccerts->error != 0) { 1351 msg_warn("relay_clientcerts: lookup error for fingerprint '%s', " 1352 "pkey fingerprint %s", prints[0], prints[1]); 1353 return (relay_ccerts->error); 1354 } 1355 } 1356 if (msg_verbose) 1357 msg_info("relay_clientcerts: No match for fingerprint '%s', " 1358 "pkey fingerprint %s", prints[0], prints[1]); 1359 } 1360#endif 1361 return (SMTPD_CHECK_DUNNO); 1362} 1363 1364/* check_relay_domains - OK/FAIL for message relaying */ 1365 1366static int check_relay_domains(SMTPD_STATE *state, char *recipient, 1367 char *reply_name, char *reply_class) 1368{ 1369 const char *myname = "check_relay_domains"; 1370 1371#if 1 1372 static int once; 1373 1374 if (once == 0) { 1375 once = 1; 1376 msg_warn("support for restriction \"%s\" will be removed from %s; " 1377 "use \"%s\" instead", 1378 CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST); 1379 } 1380#endif 1381 1382 if (msg_verbose) 1383 msg_info("%s: %s", myname, recipient); 1384 1385 /* 1386 * Permit if the client matches the relay_domains list. 1387 */ 1388 if (domain_list_match(relay_domains, state->name)) 1389 return (SMTPD_CHECK_OK); 1390 1391 /* 1392 * Permit authorized destinations. 1393 */ 1394 if (permit_auth_destination(state, recipient) == SMTPD_CHECK_OK) 1395 return (SMTPD_CHECK_OK); 1396 1397 /* 1398 * Deny relaying between sites that both are not in relay_domains. 1399 */ 1400 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1401 var_relay_code, "5.7.1", 1402 "<%s>: %s rejected: Relay access denied", 1403 reply_name, reply_class)); 1404} 1405 1406/* permit_auth_destination - OK for message relaying */ 1407 1408static int permit_auth_destination(SMTPD_STATE *state, char *recipient) 1409{ 1410 const char *myname = "permit_auth_destination"; 1411 const RESOLVE_REPLY *reply; 1412 1413 if (msg_verbose) 1414 msg_info("%s: %s", myname, recipient); 1415 1416 /* 1417 * Resolve the address. 1418 */ 1419 reply = smtpd_resolve_addr(recipient); 1420 if (reply->flags & RESOLVE_FLAG_FAIL) 1421 reject_dict_retry(state, recipient); 1422 1423 /* 1424 * Handle special case that is not supposed to happen. 1425 */ 1426 if (strrchr(CONST_STR(reply->recipient), '@') == 0) 1427 return (SMTPD_CHECK_OK); 1428 1429 /* 1430 * Skip source-routed non-local or virtual mail (uncertain destination). 1431 */ 1432 if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED)) 1433 return (SMTPD_CHECK_DUNNO); 1434 1435 /* 1436 * Permit final delivery: the destination matches mydestination, 1437 * virtual_alias_domains, or virtual_mailbox_domains. 1438 */ 1439 if (reply->flags & RESOLVE_CLASS_FINAL) 1440 return (SMTPD_CHECK_OK); 1441 1442 /* 1443 * Permit if the destination matches the relay_domains list. 1444 */ 1445 if (reply->flags & RESOLVE_CLASS_RELAY) 1446 return (SMTPD_CHECK_OK); 1447 1448 /* 1449 * Skip when not matched 1450 */ 1451 return (SMTPD_CHECK_DUNNO); 1452} 1453 1454/* reject_unauth_destination - FAIL for message relaying */ 1455 1456static int reject_unauth_destination(SMTPD_STATE *state, char *recipient, 1457 int reply_code, const char *reply_dsn) 1458{ 1459 const char *myname = "reject_unauth_destination"; 1460 1461 if (msg_verbose) 1462 msg_info("%s: %s", myname, recipient); 1463 1464 /* 1465 * Skip authorized destination. 1466 */ 1467 if (permit_auth_destination(state, recipient) == SMTPD_CHECK_OK) 1468 return (SMTPD_CHECK_DUNNO); 1469 1470 /* 1471 * Reject relaying to sites that are not listed in relay_domains. 1472 */ 1473 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 1474 reply_code, reply_dsn, 1475 "<%s>: Relay access denied", 1476 recipient)); 1477} 1478 1479/* reject_unauth_pipelining - reject improper use of SMTP command pipelining */ 1480 1481static int reject_unauth_pipelining(SMTPD_STATE *state, 1482 const char *reply_name, const char *reply_class) 1483{ 1484 const char *myname = "reject_unauth_pipelining"; 1485 1486 if (msg_verbose) 1487 msg_info("%s: %s", myname, state->where); 1488 1489 if (state->flags & SMTPD_FLAG_ILL_PIPELINING) 1490 return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL, 1491 503, "5.5.0", 1492 "<%s>: %s rejected: Improper use of SMTP command pipelining", 1493 reply_name, reply_class)); 1494 1495 return (SMTPD_CHECK_DUNNO); 1496} 1497 1498/* all_auth_mx_addr - match host addresses against permit_mx_backup_networks */ 1499 1500static int all_auth_mx_addr(SMTPD_STATE *state, char *host, 1501 const char *reply_name, const char *reply_class) 1502{ 1503 const char *myname = "all_auth_mx_addr"; 1504 MAI_HOSTADDR_STR hostaddr; 1505 DNS_RR *rr; 1506 DNS_RR *addr_list; 1507 int dns_status; 1508 1509 if (msg_verbose) 1510 msg_info("%s: host %s", myname, host); 1511 1512 /* 1513 * If we can't lookup the host, defer. 1514 */ 1515#define NOPE 0 1516#define YUP 1 1517 1518 /* 1519 * Verify that all host addresses are within permit_mx_backup_networks. 1520 */ 1521 dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0, 1522 DNS_REQ_FLAG_NONE, inet_proto_info()->dns_atype_list); 1523 if (dns_status != DNS_OK) { /* incl. DNS_INVAL */ 1524 DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY, 1525 450, "4.4.4", 1526 "<%s>: %s rejected: Unable to look up host %s as mail exchanger", 1527 reply_name, reply_class, host); 1528 return (NOPE); 1529 } 1530 for (rr = addr_list; rr != 0; rr = rr->next) { 1531 if (dns_rr_to_pa(rr, &hostaddr) == 0) { 1532 msg_warn("%s: skipping record type %s for host %s: %m", 1533 myname, dns_strtype(rr->type), host); 1534 continue; 1535 } 1536 if (msg_verbose) 1537 msg_info("%s: checking: %s", myname, hostaddr.buf); 1538 1539 if (!namadr_list_match(perm_mx_networks, host, hostaddr.buf)) { 1540 if (perm_mx_networks->error == 0) { 1541 1542 /* 1543 * Reject: at least one IP address is not listed in 1544 * permit_mx_backup_networks. 1545 */ 1546 if (msg_verbose) 1547 msg_info("%s: address %s for %s does not match %s", 1548 myname, hostaddr.buf, host, VAR_PERM_MX_NETWORKS); 1549 } else { 1550 msg_warn("%s: %s lookup error for address %s for %s", 1551 myname, VAR_PERM_MX_NETWORKS, hostaddr.buf, host); 1552 DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY, 1553 450, "4.4.4", 1554 "<%s>: %s rejected: Unable to verify host %s as mail exchanger", 1555 reply_name, reply_class, host); 1556 } 1557 dns_rr_free(addr_list); 1558 return (NOPE); 1559 } 1560 } 1561 dns_rr_free(addr_list); 1562 return (YUP); 1563} 1564 1565/* has_my_addr - see if this host name lists one of my network addresses */ 1566 1567static int has_my_addr(SMTPD_STATE *state, const char *host, 1568 const char *reply_name, const char *reply_class) 1569{ 1570 const char *myname = "has_my_addr"; 1571 struct addrinfo *res; 1572 struct addrinfo *res0; 1573 int aierr; 1574 MAI_HOSTADDR_STR hostaddr; 1575 INET_PROTO_INFO *proto_info = inet_proto_info(); 1576 1577 if (msg_verbose) 1578 msg_info("%s: host %s", myname, host); 1579 1580 /* 1581 * If we can't lookup the host, defer rather than reject. 1582 */ 1583#define YUP 1 1584#define NOPE 0 1585 1586 aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0); 1587 if (aierr) { 1588 DEFER_IF_REJECT4(state, MAIL_ERROR_POLICY, 1589 450, "4.4.4", 1590 "<%s>: %s rejected: Unable to look up mail exchanger host %s: %s", 1591 reply_name, reply_class, host, MAI_STRERROR(aierr)); 1592 return (NOPE); 1593 } 1594#define HAS_MY_ADDR_RETURN(x) { freeaddrinfo(res0); return (x); } 1595 1596 for (res = res0; res != 0; res = res->ai_next) { 1597 if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) { 1598 if (msg_verbose) 1599 msg_info("skipping address family %d for host %s", 1600 res->ai_family, host); 1601 continue; 1602 } 1603 if (msg_verbose) { 1604 SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen, 1605 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 1606 msg_info("%s: addr %s", myname, hostaddr.buf); 1607 } 1608 if (own_inet_addr(res->ai_addr)) 1609 HAS_MY_ADDR_RETURN(YUP); 1610 if (proxy_inet_addr(res->ai_addr)) 1611 HAS_MY_ADDR_RETURN(YUP); 1612 } 1613 if (msg_verbose) 1614 msg_info("%s: host %s: no match", myname, host); 1615 1616 HAS_MY_ADDR_RETURN(NOPE); 1617} 1618 1619/* i_am_mx - is this machine listed as MX relay */ 1620 1621static int i_am_mx(SMTPD_STATE *state, DNS_RR *mx_list, 1622 const char *reply_name, const char *reply_class) 1623{ 1624 const char *myname = "i_am_mx"; 1625 DNS_RR *mx; 1626 1627 /* 1628 * Compare hostnames first. Only if no name match is found, go through 1629 * the trouble of host address lookups. 1630 */ 1631 for (mx = mx_list; mx != 0; mx = mx->next) { 1632 if (msg_verbose) 1633 msg_info("%s: resolve hostname: %s", myname, (char *) mx->data); 1634 if (resolve_local((char *) mx->data) > 0) 1635 return (YUP); 1636 /* if no match or error, match interface addresses instead. */ 1637 } 1638 1639 /* 1640 * Argh. Do further DNS lookups and match interface addresses. 1641 */ 1642 for (mx = mx_list; mx != 0; mx = mx->next) { 1643 if (msg_verbose) 1644 msg_info("%s: address lookup: %s", myname, (char *) mx->data); 1645 if (has_my_addr(state, (char *) mx->data, reply_name, reply_class)) 1646 return (YUP); 1647 } 1648 1649 /* 1650 * This machine is not listed as MX relay. 1651 */ 1652 if (msg_verbose) 1653 msg_info("%s: I am not listed as MX relay", myname); 1654 return (NOPE); 1655} 1656 1657/* permit_mx_primary - authorize primary MX relays */ 1658 1659static int permit_mx_primary(SMTPD_STATE *state, DNS_RR *mx_list, 1660 const char *reply_name, const char *reply_class) 1661{ 1662 const char *myname = "permit_mx_primary"; 1663 DNS_RR *mx; 1664 1665 if (msg_verbose) 1666 msg_info("%s", myname); 1667 1668 /* 1669 * See if each best MX host has all IP addresses in 1670 * permit_mx_backup_networks. 1671 */ 1672 for (mx = mx_list; mx != 0; mx = mx->next) { 1673 if (!all_auth_mx_addr(state, (char *) mx->data, reply_name, reply_class)) 1674 return (NOPE); 1675 } 1676 1677 /* 1678 * All IP addresses of the best MX hosts are within 1679 * permit_mx_backup_networks. 1680 */ 1681 return (YUP); 1682} 1683 1684/* permit_mx_backup - permit use of me as MX backup for recipient domain */ 1685 1686static int permit_mx_backup(SMTPD_STATE *state, const char *recipient, 1687 const char *reply_name, const char *reply_class) 1688{ 1689 const char *myname = "permit_mx_backup"; 1690 const RESOLVE_REPLY *reply; 1691 const char *domain; 1692 DNS_RR *mx_list; 1693 DNS_RR *middle; 1694 DNS_RR *rest; 1695 int dns_status; 1696 1697 if (msg_verbose) 1698 msg_info("%s: %s", myname, recipient); 1699 1700 /* 1701 * Resolve the address. 1702 */ 1703 reply = smtpd_resolve_addr(recipient); 1704 if (reply->flags & RESOLVE_FLAG_FAIL) 1705 reject_dict_retry(state, recipient); 1706 1707 /* 1708 * For backwards compatibility, emulate permit_auth_destination. However, 1709 * old permit_mx_backup implementations allow source routing with local 1710 * address class. 1711 */ 1712 if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) 1713 return (SMTPD_CHECK_OK); 1714 domain += 1; 1715#if 0 1716 if (reply->flags & RESOLVE_CLASS_LOCAL) 1717 return (SMTPD_CHECK_OK); 1718#endif 1719 if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED)) 1720 return (SMTPD_CHECK_DUNNO); 1721 if (reply->flags & RESOLVE_CLASS_FINAL) 1722 return (SMTPD_CHECK_OK); 1723 if (reply->flags & RESOLVE_CLASS_RELAY) 1724 return (SMTPD_CHECK_OK); 1725 1726 if (msg_verbose) 1727 msg_info("%s: not local: %s", myname, recipient); 1728 1729 /* 1730 * Skip numerical forms that didn't match the local system. 1731 */ 1732 if (domain[0] == '[' && domain[strlen(domain) - 1] == ']') 1733 return (SMTPD_CHECK_DUNNO); 1734 1735 /* 1736 * Look up the list of MX host names for this domain. If no MX host is 1737 * found, perhaps it is a CNAME for the local machine. Clients aren't 1738 * supposed to send CNAMEs in SMTP commands, but it happens anyway. If we 1739 * can't look up the destination, play safe and turn reject into defer. 1740 */ 1741 dns_status = dns_lookup(domain, T_MX, 0, &mx_list, 1742 (VSTRING *) 0, (VSTRING *) 0); 1743#if 0 1744 if (dns_status == DNS_NOTFOUND) 1745 return (has_my_addr(state, domain, reply_name, reply_class) ? 1746 SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO); 1747#endif 1748 if (dns_status != DNS_OK) { /* incl. DNS_INVAL */ 1749 if (dns_status == DNS_RETRY) 1750 DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY, 1751 450, "4.4.4", 1752 "<%s>: %s rejected: Unable to look up mail exchanger information", 1753 reply_name, reply_class); 1754 return (SMTPD_CHECK_DUNNO); 1755 } 1756 1757 /* 1758 * Separate MX list into primaries and backups. 1759 */ 1760 mx_list = dns_rr_sort(mx_list, dns_rr_compare_pref_any); 1761 for (middle = mx_list; /* see below */ ; middle = rest) { 1762 rest = middle->next; 1763 if (rest == 0) 1764 break; 1765 if (rest->pref != mx_list->pref) { 1766 middle->next = 0; 1767 break; 1768 } 1769 } 1770 /* postcondition: middle->next = 0, rest may be 0. */ 1771 1772#define PERMIT_MX_BACKUP_RETURN(x) do { \ 1773 middle->next = rest; \ 1774 dns_rr_free(mx_list); \ 1775 return (x); \ 1776 } while (0) 1777 1778 /* 1779 * First, see if we match any of the primary MX servers. 1780 */ 1781 if (i_am_mx(state, mx_list, reply_name, reply_class)) 1782 PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_DUNNO); 1783 1784 /* 1785 * Then, see if we match any of the backup MX servers. 1786 */ 1787 if (rest == 0 || !i_am_mx(state, rest, reply_name, reply_class)) 1788 PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_DUNNO); 1789 1790 /* 1791 * Optionally, see if the primary MX hosts are in a restricted list of 1792 * networks. 1793 */ 1794 if (*var_perm_mx_networks 1795 && !permit_mx_primary(state, mx_list, reply_name, reply_class)) 1796 PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_DUNNO); 1797 1798 /* 1799 * The destination passed all requirements. 1800 */ 1801 PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_OK); 1802} 1803 1804/* reject_non_fqdn_address - fail if address is not in fqdn form */ 1805 1806static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr, 1807 char *reply_name, char *reply_class) 1808{ 1809 const char *myname = "reject_non_fqdn_address"; 1810 char *domain; 1811 char *test_dom; 1812 int stat; 1813 1814 if (msg_verbose) 1815 msg_info("%s: %s", myname, addr); 1816 1817 /* 1818 * Locate the domain information. 1819 */ 1820 if ((domain = strrchr(addr, '@')) != 0) 1821 domain++; 1822 else 1823 domain = ""; 1824 1825 /* 1826 * Skip forms that we can't handle yet. 1827 */ 1828 if (domain[0] == '[' && domain[strlen(domain) - 1] == ']') 1829 return (SMTPD_CHECK_DUNNO); 1830 1831 /* 1832 * Truncate names ending in dot but not dot-dot. 1833 */ 1834 test_dom = dup_if_truncate(domain); 1835 1836 /* 1837 * Validate the domain. 1838 */ 1839 if (!*test_dom || !valid_hostname(test_dom, DONT_GRIPE) || !strchr(test_dom, '.')) 1840 stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, 1841 var_non_fqdn_code, "4.5.2", 1842 "<%s>: %s rejected: need fully-qualified address", 1843 reply_name, reply_class); 1844 else 1845 stat = SMTPD_CHECK_DUNNO; 1846 1847 /* 1848 * Cleanup. 1849 */ 1850 if (test_dom != domain) 1851 myfree(test_dom); 1852 1853 return (stat); 1854} 1855 1856/* reject_unknown_address - fail if address does not resolve */ 1857 1858static int reject_unknown_address(SMTPD_STATE *state, const char *addr, 1859 const char *reply_name, const char *reply_class) 1860{ 1861 const char *myname = "reject_unknown_address"; 1862 const RESOLVE_REPLY *reply; 1863 const char *domain; 1864 1865 if (msg_verbose) 1866 msg_info("%s: %s", myname, addr); 1867 1868 /* 1869 * Resolve the address. 1870 */ 1871 reply = smtpd_resolve_addr(addr); 1872 if (reply->flags & RESOLVE_FLAG_FAIL) 1873 reject_dict_retry(state, addr); 1874 1875 /* 1876 * Skip local destinations and non-DNS forms. 1877 */ 1878 if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) 1879 return (SMTPD_CHECK_DUNNO); 1880 domain += 1; 1881 if (reply->flags & RESOLVE_CLASS_FINAL) 1882 return (SMTPD_CHECK_DUNNO); 1883 if (domain[0] == '[' && domain[strlen(domain) - 1] == ']') 1884 return (SMTPD_CHECK_DUNNO); 1885 1886 /* 1887 * Look up the name in the DNS. 1888 */ 1889 return (reject_unknown_mailhost(state, domain, reply_name, reply_class)); 1890} 1891 1892/* reject_unverified_address - fail if address bounces */ 1893 1894static int reject_unverified_address(SMTPD_STATE *state, const char *addr, 1895 const char *reply_name, const char *reply_class, 1896 int unv_addr_dcode, int unv_addr_rcode, 1897 int unv_addr_tf_act, 1898 const char *alt_reply) 1899{ 1900 const char *myname = "reject_unverified_address"; 1901 VSTRING *why = vstring_alloc(10); 1902 int rqst_status = SMTPD_CHECK_DUNNO; 1903 int rcpt_status; 1904 int verify_status; 1905 int count; 1906 int reject_code = 0; 1907 1908 if (msg_verbose) 1909 msg_info("%s: %s", myname, addr); 1910 1911 /* 1912 * Verify the address. Don't waste too much of their or our time. 1913 */ 1914 for (count = 0; /* see below */ ; /* see below */ ) { 1915 verify_status = verify_clnt_query(addr, &rcpt_status, why); 1916 if (verify_status != VRFY_STAT_OK || rcpt_status != DEL_RCPT_STAT_TODO) 1917 break; 1918 if (++count >= var_verify_poll_count) 1919 break; 1920 sleep(var_verify_poll_delay); 1921 } 1922 if (verify_status != VRFY_STAT_OK) { 1923 msg_warn("%s service failure", var_verify_service); 1924 rqst_status = 1925 DEFER_IF_PERMIT2(unv_addr_tf_act, state, MAIL_ERROR_POLICY, 1926 450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 1927 SND_DSN : "4.1.1", 1928 "<%s>: %s rejected: address verification problem", 1929 reply_name, reply_class); 1930 } else { 1931 switch (rcpt_status) { 1932 default: 1933 msg_warn("unknown address verification status %d", rcpt_status); 1934 break; 1935 case DEL_RCPT_STAT_TODO: 1936 case DEL_RCPT_STAT_DEFER: 1937 reject_code = unv_addr_dcode; 1938 break; 1939 case DEL_RCPT_STAT_OK: 1940 break; 1941 case DEL_RCPT_STAT_BOUNCE: 1942 reject_code = unv_addr_rcode; 1943 break; 1944 } 1945 if (reject_code >= 400 && *alt_reply) 1946 vstring_strcpy(why, alt_reply); 1947 switch (reject_code / 100) { 1948 case 2: 1949 break; 1950 case 4: 1951 rqst_status = 1952 DEFER_IF_PERMIT3(unv_addr_tf_act, state, MAIL_ERROR_POLICY, 1953 reject_code, 1954 strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 1955 SND_DSN : "4.1.1", 1956 "<%s>: %s rejected: unverified address: %.250s", 1957 reply_name, reply_class, STR(why)); 1958 break; 1959 default: 1960 if (reject_code != 0) 1961 rqst_status = 1962 smtpd_check_reject(state, MAIL_ERROR_POLICY, 1963 reject_code, 1964 strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 1965 SND_DSN : "4.1.1", 1966 "<%s>: %s rejected: undeliverable address: %s", 1967 reply_name, reply_class, STR(why)); 1968 break; 1969 } 1970 } 1971 vstring_free(why); 1972 return (rqst_status); 1973} 1974 1975/* can_delegate_action - can we delegate this to the cleanup server */ 1976 1977#ifndef TEST 1978 1979static int not_in_client_helo(SMTPD_STATE *, const char *, const char *, const char *); 1980 1981static int can_delegate_action(SMTPD_STATE *state, const char *table, 1982 const char *action, const char *reply_class) 1983{ 1984 1985 /* 1986 * If we're not using the cleanup server, then there is no way that we 1987 * can support actions such as FILTER or HOLD that are delegated to the 1988 * cleanup server. 1989 */ 1990 if (USE_SMTPD_PROXY(state)) { 1991 msg_warn("access table %s: with %s specified, action %s is unavailable", 1992 table, VAR_SMTPD_PROXY_FILT, action); 1993 return (0); 1994 } 1995 1996 /* 1997 * ETRN does not receive mail so we can't store queue file records. 1998 */ 1999 if (strcmp(state->where, SMTPD_CMD_ETRN) == 0) { 2000 msg_warn("access table %s: action %s is unavailable in %s", 2001 table, action, VAR_ETRN_CHECKS); 2002 return (0); 2003 } 2004 return (not_in_client_helo(state, table, action, reply_class)); 2005} 2006 2007/* not_in_client_helo - not in client or helo restriction context */ 2008 2009static int not_in_client_helo(SMTPD_STATE *state, const char *table, 2010 const char *action, 2011 const char *unused_reply_class) 2012{ 2013 2014 /* 2015 * If delay_reject=no, then client and helo restrictions take effect 2016 * immediately, outside any particular mail transaction context. For 2017 * example, rejecting HELO does not affect subsequent mail deliveries. 2018 * Thus, if delay_reject=no, client and helo actions such as FILTER or 2019 * HOLD also should not affect subsequent mail deliveries. Hmm... 2020 * 2021 * XXX If the MAIL FROM command is rejected then we have to reset access map 2022 * side effects such as FILTER. 2023 */ 2024 if (state->sender == 0) { 2025 msg_warn("access table %s: with %s=%s, " 2026 "action %s is always skipped in %s or %s restrictions", 2027 table, VAR_SMTPD_DELAY_REJECT, CONFIG_BOOL_NO, 2028 action, SMTPD_NAME_CLIENT, SMTPD_NAME_HELO); 2029 /* XXX What about ETRN? */ 2030 return (0); 2031 } 2032 return (1); 2033} 2034 2035#endif 2036 2037/* check_table_result - translate table lookup result into pass/reject */ 2038 2039static int check_table_result(SMTPD_STATE *state, const char *table, 2040 const char *value, const char *datum, 2041 const char *reply_name, 2042 const char *reply_class, 2043 const char *def_acl) 2044{ 2045 const char *myname = "check_table_result"; 2046 int code; 2047 ARGV *restrictions; 2048 jmp_buf savebuf; 2049 int status; 2050 const char *cmd_text; 2051 int cmd_len; 2052 static char def_dsn[] = "5.7.1"; 2053 DSN_SPLIT dp; 2054 static VSTRING *buf; 2055 2056#ifdef DELAY_ACTION 2057 int defer_delay; 2058 2059#endif 2060 2061 if (buf == 0) 2062 buf = vstring_alloc(10); 2063 2064 /* 2065 * Parse into command and text. Do not change the input. 2066 */ 2067 cmd_text = value + strcspn(value, " \t"); 2068 cmd_len = cmd_text - value; 2069 vstring_strncpy(buf, value, cmd_len); 2070 while (*cmd_text && ISSPACE(*cmd_text)) 2071 cmd_text++; 2072 2073 if (msg_verbose) 2074 msg_info("%s: %s %s %s", myname, table, value, datum); 2075 2076#define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0) 2077 2078 /* 2079 * DUNNO means skip this table. Silently ignore optional text. 2080 */ 2081 if (STREQUAL(value, "DUNNO", cmd_len)) 2082 return (SMTPD_CHECK_DUNNO); 2083 2084 /* 2085 * REJECT means NO. Use optional text or generate a generic error 2086 * response. 2087 */ 2088 if (STREQUAL(value, "REJECT", cmd_len)) { 2089 dsn_split(&dp, "5.7.1", cmd_text); 2090 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 2091 var_map_reject_code, 2092 smtpd_dsn_fix(DSN_STATUS(dp.dsn), 2093 reply_class), 2094 "<%s>: %s rejected: %s", 2095 reply_name, reply_class, 2096 *dp.text ? dp.text : "Access denied")); 2097 } 2098 2099 /* 2100 * DEFER means "try again". Use optional text or generate a generic error 2101 * response. 2102 */ 2103 if (STREQUAL(value, "DEFER", cmd_len)) { 2104 dsn_split(&dp, "4.7.1", cmd_text); 2105 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 2106 var_map_defer_code, 2107 smtpd_dsn_fix(DSN_STATUS(dp.dsn), 2108 reply_class), 2109 "<%s>: %s rejected: %s", 2110 reply_name, reply_class, 2111 *dp.text ? dp.text : "Access denied")); 2112 } 2113 2114 /* 2115 * WARN. Text is optional. 2116 */ 2117 if (STREQUAL(value, "WARN", cmd_len)) { 2118 log_whatsup(state, "warn", cmd_text); 2119 return (SMTPD_CHECK_DUNNO); 2120 } 2121 2122 /* 2123 * FILTER means deliver to content filter. But we may still change our 2124 * mind, and reject/discard the message for other reasons. 2125 */ 2126 if (STREQUAL(value, "FILTER", cmd_len)) { 2127#ifndef TEST 2128 if (can_delegate_action(state, table, "FILTER", reply_class) == 0) 2129 return (SMTPD_CHECK_DUNNO); 2130#endif 2131 if (*cmd_text == 0) { 2132 msg_warn("access table %s entry \"%s\" has FILTER entry without value", 2133 table, datum); 2134 return (SMTPD_CHECK_DUNNO); 2135 } else if (strchr(cmd_text, ':') == 0) { 2136 msg_warn("access table %s entry \"%s\" requires transport:destination", 2137 table, datum); 2138 return (SMTPD_CHECK_DUNNO); 2139 } else { 2140 vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s", 2141 reply_name, reply_class, cmd_text); 2142 log_whatsup(state, "filter", STR(error_text)); 2143#ifndef TEST 2144 UPDATE_STRING(state->saved_filter, cmd_text); 2145#endif 2146 return (SMTPD_CHECK_DUNNO); 2147 } 2148 } 2149 2150 /* 2151 * HOLD means deliver later. But we may still change our mind, and 2152 * reject/discard the message for other reasons. 2153 */ 2154 if (STREQUAL(value, "HOLD", cmd_len)) { 2155#ifndef TEST 2156 if (can_delegate_action(state, table, "HOLD", reply_class) == 0 2157 || (state->saved_flags & CLEANUP_FLAG_HOLD)) 2158 return (SMTPD_CHECK_DUNNO); 2159#endif 2160 vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class, 2161 *cmd_text ? cmd_text : "triggers HOLD action"); 2162 log_whatsup(state, "hold", STR(error_text)); 2163#ifndef TEST 2164 state->saved_flags |= CLEANUP_FLAG_HOLD; 2165#endif 2166 return (SMTPD_CHECK_DUNNO); 2167 } 2168 2169 /* 2170 * DELAY means deliver later. But we may still change our mind, and 2171 * reject/discard the message for other reasons. 2172 * 2173 * This feature is deleted because it has too many problems. 1) It does not 2174 * work on some remote file systems; 2) mail will be delivered anyway 2175 * with "sendmail -q" etc.; 3) while the mail is queued it bogs down the 2176 * deferred queue scan with huge amounts of useless disk I/O operations. 2177 */ 2178#ifdef DELAY_ACTION 2179 if (STREQUAL(value, "DELAY", cmd_len)) { 2180#ifndef TEST 2181 if (can_delegate_action(state, table, "DELAY", reply_class) == 0) 2182 return (SMTPD_CHECK_DUNNO); 2183#endif 2184 if (*cmd_text == 0) { 2185 msg_warn("access table %s entry \"%s\" has DELAY entry without value", 2186 table, datum); 2187 return (SMTPD_CHECK_DUNNO); 2188 } 2189 if (conv_time(cmd_text, &defer_delay, 's') == 0) { 2190 msg_warn("access table %s entry \"%s\" has invalid DELAY argument \"%s\"", 2191 table, datum, cmd_text); 2192 return (SMTPD_CHECK_DUNNO); 2193 } 2194 vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class, 2195 *cmd_text ? cmd_text : "triggers DELAY action"); 2196 log_whatsup(state, "delay", STR(error_text)); 2197#ifndef TEST 2198 state->saved_delay = defer_delay; 2199#endif 2200 return (SMTPD_CHECK_DUNNO); 2201 } 2202#endif 2203 2204 /* 2205 * DISCARD means silently discard and claim successful delivery. 2206 */ 2207 if (STREQUAL(value, "DISCARD", cmd_len)) { 2208#ifndef TEST 2209 if (can_delegate_action(state, table, "DISCARD", reply_class) == 0) 2210 return (SMTPD_CHECK_DUNNO); 2211#endif 2212 vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class, 2213 *cmd_text ? cmd_text : "triggers DISCARD action"); 2214 log_whatsup(state, "discard", STR(error_text)); 2215#ifndef TEST 2216 state->saved_flags |= CLEANUP_FLAG_DISCARD; 2217 state->discard = 1; 2218#endif 2219 return (smtpd_acl_permit(state, STR(buf), reply_class, reply_name, 2220 "from %s", table)); 2221 } 2222 2223 /* 2224 * REDIRECT means deliver to designated recipient. But we may still 2225 * change our mind, and reject/discard the message for other reasons. 2226 */ 2227 if (STREQUAL(value, "REDIRECT", cmd_len)) { 2228#ifndef TEST 2229 if (can_delegate_action(state, table, "REDIRECT", reply_class) == 0) 2230 return (SMTPD_CHECK_DUNNO); 2231#endif 2232 if (strchr(cmd_text, '@') == 0) { 2233 msg_warn("access table %s entry \"%s\" requires user@domain target", 2234 table, datum); 2235 return (SMTPD_CHECK_DUNNO); 2236 } else { 2237 vstring_sprintf(error_text, "<%s>: %s triggers REDIRECT %s", 2238 reply_name, reply_class, cmd_text); 2239 log_whatsup(state, "redirect", STR(error_text)); 2240#ifndef TEST 2241 UPDATE_STRING(state->saved_redirect, cmd_text); 2242#endif 2243 return (SMTPD_CHECK_DUNNO); 2244 } 2245 } 2246 2247 /* 2248 * BCC means deliver to designated recipient. But we may still change our 2249 * mind, and reject/discard the message for other reasons. 2250 */ 2251#ifdef SNAPSHOT 2252 if (STREQUAL(value, "BCC", cmd_len)) { 2253#ifndef TEST 2254 if (can_delegate_action(state, table, "BCC", reply_class) == 0) 2255 return (SMTPD_CHECK_DUNNO); 2256#endif 2257 if (strchr(cmd_text, '@') == 0) { 2258 msg_warn("access table %s entry \"%s\" requires user@domain target", 2259 table, datum); 2260 return (SMTPD_CHECK_DUNNO); 2261 } else { 2262 vstring_sprintf(error_text, "<%s>: %s triggers BCC %s", 2263 reply_name, reply_class, cmd_text); 2264 log_whatsup(state, "bcc", STR(error_text)); 2265#ifndef TEST 2266 UPDATE_STRING(state->saved_bcc, cmd_text); 2267#endif 2268 return (SMTPD_CHECK_DUNNO); 2269 } 2270 } 2271#endif 2272 2273 /* 2274 * DEFER_IF_PERMIT changes "permit" into "maybe". Use optional text or 2275 * generate a generic error response. 2276 */ 2277 if (STREQUAL(value, DEFER_IF_PERMIT, cmd_len)) { 2278 dsn_split(&dp, "4.7.1", cmd_text); 2279 return (DEFER_IF_PERMIT3(DEFER_IF_PERMIT_ACT, state, MAIL_ERROR_POLICY, 2280 var_map_defer_code, 2281 smtpd_dsn_fix(DSN_STATUS(dp.dsn), reply_class), 2282 "<%s>: %s rejected: %s", 2283 reply_name, reply_class, 2284 *dp.text ? dp.text : "Service unavailable")); 2285 } 2286 2287 /* 2288 * DEFER_IF_REJECT changes "reject" into "maybe". Use optional text or 2289 * generate a generic error response. 2290 */ 2291 if (STREQUAL(value, DEFER_IF_REJECT, cmd_len)) { 2292 dsn_split(&dp, "4.7.1", cmd_text); 2293 DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY, 2294 var_map_defer_code, 2295 smtpd_dsn_fix(DSN_STATUS(dp.dsn), reply_class), 2296 "<%s>: %s rejected: %s", 2297 reply_name, reply_class, 2298 *dp.text ? dp.text : "Service unavailable"); 2299 return (SMTPD_CHECK_DUNNO); 2300 } 2301 2302 /* 2303 * PREPEND prepends the specified message header text. 2304 */ 2305 if (STREQUAL(value, "PREPEND", cmd_len)) { 2306#ifndef TEST 2307 /* XXX what about ETRN. */ 2308 if (not_in_client_helo(state, table, "PREPEND", reply_class) == 0) 2309 return (SMTPD_CHECK_DUNNO); 2310#endif 2311 if (strcmp(state->where, SMTPD_AFTER_DOT) == 0) { 2312 msg_warn("access table %s: action PREPEND must be used before %s", 2313 table, VAR_EOD_CHECKS); 2314 return (SMTPD_CHECK_DUNNO); 2315 } 2316 if (*cmd_text == 0 || is_header(cmd_text) == 0) { 2317 msg_warn("access table %s entry \"%s\" requires header: text", 2318 table, datum); 2319 return (SMTPD_CHECK_DUNNO); 2320 } else { 2321 if (state->prepend == 0) 2322 state->prepend = argv_alloc(1); 2323 argv_add(state->prepend, cmd_text, (char *) 0); 2324 return (SMTPD_CHECK_DUNNO); 2325 } 2326 } 2327 2328 /* 2329 * All-numeric result probably means OK - some out-of-band authentication 2330 * mechanism uses this as time stamp. 2331 */ 2332 if (alldig(value)) 2333 return (smtpd_acl_permit(state, STR(buf), reply_class, reply_name, 2334 "from %s", table)); 2335 2336 /* 2337 * 4xx or 5xx means NO as well. smtpd_check_reject() will validate the 2338 * response status code. 2339 * 2340 * If the caller specifies an RFC 3463 enhanced status code, put it 2341 * immediately after the SMTP status code as described in RFC 2034. 2342 */ 2343 if (cmd_len == 3 && *cmd_text 2344 && (value[0] == '4' || value[0] == '5') 2345 && ISDIGIT(value[1]) && ISDIGIT(value[2])) { 2346 code = atoi(value); 2347 def_dsn[0] = value[0]; 2348 dsn_split(&dp, def_dsn, cmd_text); 2349 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 2350 code, 2351 smtpd_dsn_fix(DSN_STATUS(dp.dsn), 2352 reply_class), 2353 "<%s>: %s rejected: %s", 2354 reply_name, reply_class, 2355 *dp.text ? dp.text : "Access denied")); 2356 } 2357 2358 /* 2359 * OK or RELAY means YES. Ignore trailing text. 2360 */ 2361 if (STREQUAL(value, "OK", cmd_len) || STREQUAL(value, "RELAY", cmd_len)) 2362 return (smtpd_acl_permit(state, STR(buf), reply_class, reply_name, 2363 "from %s", table)); 2364 2365 /* 2366 * Unfortunately, maps must be declared ahead of time so they can be 2367 * opened before we go to jail. We could insist that the RHS can only 2368 * contain a pre-defined restriction class name, but that would be too 2369 * restrictive. Instead we warn if an access table references any map. 2370 * 2371 * XXX Don't use passwd files or address rewriting maps as access tables. 2372 */ 2373 if (strchr(value, ':') != 0) { 2374 msg_warn("access table %s has entry with lookup table: %s", 2375 table, value); 2376 msg_warn("do not specify lookup tables inside SMTPD access maps"); 2377 msg_warn("define a restriction class and specify its name instead."); 2378 reject_server_error(state); 2379 } 2380 2381 /* 2382 * Don't get carried away with recursion. 2383 */ 2384 if (state->recursion > 100) { 2385 msg_warn("access table %s entry %s causes unreasonable recursion", 2386 table, value); 2387 reject_server_error(state); 2388 } 2389 2390 /* 2391 * Recursively evaluate the restrictions given in the right-hand side. In 2392 * the dark ages, an empty right-hand side meant OK. Make some 2393 * discouraging comments. 2394 * 2395 * XXX Jump some hoops to avoid a minute memory leak in case of a file 2396 * configuration error. 2397 */ 2398#define ADDROF(x) ((char *) &(x)) 2399 2400 restrictions = argv_split(value, RESTRICTION_SEPARATORS); 2401 memcpy(ADDROF(savebuf), ADDROF(smtpd_check_buf), sizeof(savebuf)); 2402 status = setjmp(smtpd_check_buf); 2403 if (status != 0) { 2404 argv_free(restrictions); 2405 memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf), 2406 sizeof(smtpd_check_buf)); 2407 longjmp(smtpd_check_buf, status); 2408 } 2409 if (restrictions->argc == 0) { 2410 msg_warn("access table %s entry %s has empty value", 2411 table, value); 2412 status = SMTPD_CHECK_OK; 2413 } else { 2414 status = generic_checks(state, restrictions, reply_name, 2415 reply_class, def_acl); 2416 } 2417 argv_free(restrictions); 2418 memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf), sizeof(smtpd_check_buf)); 2419 return (status); 2420} 2421 2422/* check_access - table lookup without substring magic */ 2423 2424static int check_access(SMTPD_STATE *state, const char *table, const char *name, 2425 int flags, int *found, const char *reply_name, 2426 const char *reply_class, const char *def_acl) 2427{ 2428 const char *myname = "check_access"; 2429 const char *value; 2430 DICT *dict; 2431 2432#define CHK_ACCESS_RETURN(x,y) \ 2433 { *found = y; return(x); } 2434#define FULL 0 2435#define PARTIAL DICT_FLAG_FIXED 2436#define FOUND 1 2437#define MISSED 0 2438 2439 if (msg_verbose) 2440 msg_info("%s: %s", myname, name); 2441 2442 if ((dict = dict_handle(table)) == 0) { 2443 msg_warn("%s: unexpected dictionary: %s", myname, table); 2444 value = "451 4.3.5 Server configuration error"; 2445 CHK_ACCESS_RETURN(check_table_result(state, table, value, name, 2446 reply_name, reply_class, 2447 def_acl), FOUND); 2448 } 2449 if (flags == 0 || (flags & dict->flags) != 0) { 2450 if ((value = dict_get(dict, name)) != 0) 2451 CHK_ACCESS_RETURN(check_table_result(state, table, value, name, 2452 reply_name, reply_class, 2453 def_acl), FOUND); 2454 if (dict->error != 0) { 2455 msg_warn("%s: table lookup problem", table); 2456 value = "451 4.3.5 Server configuration error"; 2457 CHK_ACCESS_RETURN(check_table_result(state, table, value, name, 2458 reply_name, reply_class, 2459 def_acl), FOUND); 2460 } 2461 } 2462 CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO, MISSED); 2463} 2464 2465/* check_domain_access - domainname-based table lookup */ 2466 2467static int check_domain_access(SMTPD_STATE *state, const char *table, 2468 const char *domain, int flags, 2469 int *found, const char *reply_name, 2470 const char *reply_class, 2471 const char *def_acl) 2472{ 2473 const char *myname = "check_domain_access"; 2474 const char *name; 2475 const char *next; 2476 const char *value; 2477 DICT *dict; 2478 int maybe_numerical = 1; 2479 2480 if (msg_verbose) 2481 msg_info("%s: %s", myname, domain); 2482 2483 /* 2484 * Try the name and its parent domains. Including top-level domains. 2485 * 2486 * Helo names can end in ".". The test below avoids lookups of the empty 2487 * key, because Berkeley DB cannot deal with it. [Victor Duchovni, Morgan 2488 * Stanley]. 2489 */ 2490#define CHK_DOMAIN_RETURN(x,y) { *found = y; return(x); } 2491 2492 if ((dict = dict_handle(table)) == 0) { 2493 msg_warn("%s: unexpected dictionary: %s", myname, table); 2494 value = "451 4.3.5 Server configuration error"; 2495 CHK_DOMAIN_RETURN(check_table_result(state, table, value, 2496 domain, reply_name, reply_class, 2497 def_acl), FOUND); 2498 } 2499 for (name = domain; *name != 0; name = next) { 2500 if (flags == 0 || (flags & dict->flags) != 0) { 2501 if ((value = dict_get(dict, name)) != 0) 2502 CHK_DOMAIN_RETURN(check_table_result(state, table, value, 2503 domain, reply_name, reply_class, 2504 def_acl), FOUND); 2505 if (dict->error != 0) { 2506 msg_warn("%s: table lookup problem", table); 2507 value = "451 4.3.5 Server configuration error"; 2508 CHK_DOMAIN_RETURN(check_table_result(state, table, value, 2509 domain, reply_name, reply_class, 2510 def_acl), FOUND); 2511 } 2512 } 2513 /* Don't apply subdomain magic to numerical hostnames. */ 2514 if (maybe_numerical 2515 && (maybe_numerical = valid_hostaddr(domain, DONT_GRIPE)) != 0) 2516 break; 2517 if ((next = strchr(name + 1, '.')) == 0) 2518 break; 2519 if (access_parent_style == MATCH_FLAG_PARENT) 2520 next += 1; 2521 flags = PARTIAL; 2522 } 2523 CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED); 2524} 2525 2526/* check_addr_access - address-based table lookup */ 2527 2528static int check_addr_access(SMTPD_STATE *state, const char *table, 2529 const char *address, int flags, 2530 int *found, const char *reply_name, 2531 const char *reply_class, 2532 const char *def_acl) 2533{ 2534 const char *myname = "check_addr_access"; 2535 char *addr; 2536 const char *value; 2537 DICT *dict; 2538 int delim; 2539 2540 if (msg_verbose) 2541 msg_info("%s: %s", myname, address); 2542 2543 /* 2544 * Try the address and its parent networks. 2545 */ 2546#define CHK_ADDR_RETURN(x,y) { *found = y; return(x); } 2547 2548 addr = STR(vstring_strcpy(error_text, address)); 2549#ifdef HAS_IPV6 2550 if (strchr(addr, ':') != 0) 2551 delim = ':'; 2552 else 2553#endif 2554 delim = '.'; 2555 2556 if ((dict = dict_handle(table)) == 0) { 2557 msg_warn("%s: unexpected dictionary: %s", myname, table); 2558 value = "451 4.3.5 Server configuration error"; 2559 CHK_ADDR_RETURN(check_table_result(state, table, value, address, 2560 reply_name, reply_class, 2561 def_acl), FOUND); 2562 } 2563 do { 2564 if (flags == 0 || (flags & dict->flags) != 0) { 2565 if ((value = dict_get(dict, addr)) != 0) 2566 CHK_ADDR_RETURN(check_table_result(state, table, value, address, 2567 reply_name, reply_class, 2568 def_acl), FOUND); 2569 if (dict->error != 0) { 2570 msg_warn("%s: table lookup problem", table); 2571 value = "451 4.3.5 Server configuration error"; 2572 CHK_ADDR_RETURN(check_table_result(state, table, value, address, 2573 reply_name, reply_class, 2574 def_acl), FOUND); 2575 } 2576 } 2577 flags = PARTIAL; 2578 } while (split_at_right(addr, delim)); 2579 2580 CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED); 2581} 2582 2583/* check_namadr_access - OK/FAIL based on host name/address lookup */ 2584 2585static int check_namadr_access(SMTPD_STATE *state, const char *table, 2586 const char *name, const char *addr, 2587 int flags, int *found, 2588 const char *reply_name, 2589 const char *reply_class, 2590 const char *def_acl) 2591{ 2592 const char *myname = "check_namadr_access"; 2593 int status; 2594 2595 if (msg_verbose) 2596 msg_info("%s: name %s addr %s", myname, name, addr); 2597 2598 /* 2599 * Look up the host name, or parent domains thereof. XXX A domain 2600 * wildcard may pre-empt a more specific address table entry. 2601 */ 2602 if ((status = check_domain_access(state, table, name, flags, 2603 found, reply_name, reply_class, 2604 def_acl)) != 0 || *found) 2605 return (status); 2606 2607 /* 2608 * Look up the network address, or parent networks thereof. 2609 */ 2610 if ((status = check_addr_access(state, table, addr, flags, 2611 found, reply_name, reply_class, 2612 def_acl)) != 0 || *found) 2613 return (status); 2614 2615 /* 2616 * Undecided when the host was not found. 2617 */ 2618 return (SMTPD_CHECK_DUNNO); 2619} 2620 2621/* check_server_access - access control by server host name or address */ 2622 2623static int check_server_access(SMTPD_STATE *state, const char *table, 2624 const char *name, 2625 int type, 2626 const char *reply_name, 2627 const char *reply_class, 2628 const char *def_acl) 2629{ 2630 const char *myname = "check_server_access"; 2631 const char *domain; 2632 int dns_status; 2633 DNS_RR *server_list; 2634 DNS_RR *server; 2635 int found = 0; 2636 MAI_HOSTADDR_STR addr_string; 2637 int aierr; 2638 struct addrinfo *res0; 2639 struct addrinfo *res; 2640 int status; 2641 INET_PROTO_INFO *proto_info; 2642 2643 /* 2644 * Sanity check. 2645 */ 2646 if (type != T_MX && type != T_NS) 2647 msg_panic("%s: unexpected resource type \"%s\" in request", 2648 myname, dns_strtype(type)); 2649 2650 if (msg_verbose) 2651 msg_info("%s: %s %s", myname, dns_strtype(type), name); 2652 2653 /* 2654 * Skip over local-part. 2655 */ 2656 if ((domain = strrchr(name, '@')) != 0) 2657 domain += 1; 2658 else 2659 domain = name; 2660 2661 /* 2662 * Treat an address literal as its own MX server, just like we treat a 2663 * name without MX record as its own MX server. There is, however, no 2664 * applicable NS server equivalent. 2665 */ 2666 if (*domain == '[') { 2667 char *saved_addr; 2668 const char *bare_addr; 2669 ssize_t len; 2670 2671 if (type != T_MX) 2672 return (SMTPD_CHECK_DUNNO); 2673 len = strlen(domain); 2674 if (domain[len - 1] != ']') 2675 return (SMTPD_CHECK_DUNNO); 2676 /* Memory leak alert: no early returns after this point. */ 2677 saved_addr = mystrndup(domain + 1, len - 2); 2678 if ((bare_addr = valid_mailhost_addr(saved_addr, DONT_GRIPE)) == 0) 2679 status = SMTPD_CHECK_DUNNO; 2680 else 2681 status = check_addr_access(state, table, bare_addr, FULL, 2682 &found, reply_name, reply_class, 2683 def_acl); 2684 myfree(saved_addr); 2685 return (status); 2686 } 2687 2688 /* 2689 * If the domain name does not exist then we apply no restriction. 2690 * 2691 * If the domain name exists but no MX record exists, fabricate an MX record 2692 * that points to the domain name itself. 2693 * 2694 * If the domain name exists but no NS record exists, look up parent domain 2695 * NS records. 2696 */ 2697 dns_status = dns_lookup(domain, type, 0, &server_list, 2698 (VSTRING *) 0, (VSTRING *) 0); 2699 if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) { 2700 if (type == T_MX) { 2701 server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0, 2702 domain, strlen(domain) + 1); 2703 dns_status = DNS_OK; 2704 } else if (type == T_NS && h_errno == NO_DATA) { 2705 while ((domain = strchr(domain, '.')) != 0 && domain[1]) { 2706 domain += 1; 2707 dns_status = dns_lookup(domain, type, 0, &server_list, 2708 (VSTRING *) 0, (VSTRING *) 0); 2709 if (dns_status != DNS_NOTFOUND || h_errno != NO_DATA) 2710 break; 2711 } 2712 } 2713 } 2714 if (dns_status != DNS_OK) { 2715 msg_warn("Unable to look up %s host for %s: %s", dns_strtype(type), 2716 domain && domain[1] ? domain : name, dns_strerror(h_errno)); 2717 return (SMTPD_CHECK_DUNNO); 2718 } 2719 2720 /* 2721 * No bare returns after this point or we have a memory leak. 2722 */ 2723#define CHECK_SERVER_RETURN(x) { dns_rr_free(server_list); return(x); } 2724 2725 /* 2726 * Check the hostnames first, then the addresses. 2727 */ 2728 proto_info = inet_proto_info(); 2729 for (server = server_list; server != 0; server = server->next) { 2730 if (msg_verbose) 2731 msg_info("%s: %s hostname check: %s", 2732 myname, dns_strtype(type), (char *) server->data); 2733 if (valid_hostaddr((char *) server->data, DONT_GRIPE)) { 2734 if ((status = check_addr_access(state, table, (char *) server->data, 2735 FULL, &found, reply_name, reply_class, 2736 def_acl)) != 0 || found) 2737 CHECK_SERVER_RETURN(status); 2738 continue; 2739 } 2740 if ((status = check_domain_access(state, table, (char *) server->data, 2741 FULL, &found, reply_name, reply_class, 2742 def_acl)) != 0 || found) 2743 CHECK_SERVER_RETURN(status); 2744 if ((aierr = hostname_to_sockaddr((char *) server->data, 2745 (char *) 0, 0, &res0)) != 0) { 2746 msg_warn("Unable to look up %s host %s for %s %s: %s", 2747 dns_strtype(type), (char *) server->data, 2748 reply_class, reply_name, MAI_STRERROR(aierr)); 2749 continue; 2750 } 2751 /* Now we must also free the addrinfo result. */ 2752 if (msg_verbose) 2753 msg_info("%s: %s host address check: %s", 2754 myname, dns_strtype(type), (char *) server->data); 2755 for (res = res0; res != 0; res = res->ai_next) { 2756 if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) { 2757 if (msg_verbose) 2758 msg_info("skipping address family %d for host %s", 2759 res->ai_family, server->data); 2760 continue; 2761 } 2762 SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen, 2763 &addr_string, (MAI_SERVPORT_STR *) 0, 0); 2764 status = check_addr_access(state, table, addr_string.buf, FULL, 2765 &found, reply_name, reply_class, 2766 def_acl); 2767 if (status != 0 || found) { 2768 freeaddrinfo(res0); /* 200412 */ 2769 CHECK_SERVER_RETURN(status); 2770 } 2771 } 2772 freeaddrinfo(res0); /* 200412 */ 2773 } 2774 CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO); 2775} 2776 2777/* check_ccert_access - access for TLS clients by certificate fingerprint */ 2778 2779 2780static int check_ccert_access(SMTPD_STATE *state, const char *table, 2781 const char *def_acl) 2782{ 2783 int result = SMTPD_CHECK_DUNNO; 2784 2785#ifdef USE_TLS 2786 const char *myname = "check_ccert_access"; 2787 int found; 2788 2789 /* 2790 * When directly checking the fingerprint, it is OK if the issuing CA is 2791 * not trusted. 2792 */ 2793 if (TLS_CERT_IS_PRESENT(state->tls_context)) { 2794 int i; 2795 char *prints[2]; 2796 2797 prints[0] = state->tls_context->peer_cert_fprint; 2798 prints[1] = state->tls_context->peer_pkey_fprint; 2799 2800 for (i = 0; i < 2; ++i) { 2801 if (msg_verbose) 2802 msg_info("%s: %s", myname, prints[i]); 2803 2804 /* 2805 * Regexp tables don't make sense for certificate fingerprints. 2806 * That may be so, but we can't ignore the entire 2807 * check_ccert_access request without logging a warning. 2808 * 2809 * Log the peer CommonName when access is denied. Non-printable 2810 * characters will be neutered by smtpd_check_reject(). The SMTP 2811 * client name and address are always syslogged as part of a 2812 * "reject" event. 2813 */ 2814 result = check_access(state, table, prints[i], 2815 DICT_FLAG_NONE, &found, 2816 state->tls_context->peer_CN, 2817 SMTPD_NAME_CCERT, def_acl); 2818 if (result != SMTPD_CHECK_DUNNO) 2819 break; 2820 } 2821 } 2822#endif 2823 return (result); 2824} 2825 2826/* check_sasl_access - access by SASL user name */ 2827 2828#ifdef USE_SASL_AUTH 2829 2830static int check_sasl_access(SMTPD_STATE *state, const char *table, 2831 const char *def_acl) 2832{ 2833 int result; 2834 int unused_found; 2835 char *sane_username = printable(mystrdup(state->sasl_username), '_'); 2836 2837 result = check_access(state, table, state->sasl_username, 2838 DICT_FLAG_NONE, &unused_found, sane_username, 2839 SMTPD_NAME_SASL_USER, def_acl); 2840 myfree(sane_username); 2841 return (result); 2842} 2843 2844#endif 2845 2846/* check_mail_access - OK/FAIL based on mail address lookup */ 2847 2848static int check_mail_access(SMTPD_STATE *state, const char *table, 2849 const char *addr, int *found, 2850 const char *reply_name, 2851 const char *reply_class, 2852 const char *def_acl) 2853{ 2854 const char *myname = "check_mail_access"; 2855 const RESOLVE_REPLY *reply; 2856 const char *domain; 2857 int status; 2858 char *local_at; 2859 char *bare_addr; 2860 char *bare_at; 2861 2862 if (msg_verbose) 2863 msg_info("%s: %s", myname, addr); 2864 2865 /* 2866 * Resolve the address. 2867 */ 2868 reply = smtpd_resolve_addr(addr); 2869 if (reply->flags & RESOLVE_FLAG_FAIL) 2870 reject_dict_retry(state, addr); 2871 2872 /* 2873 * Garbage in, garbage out. Every address from rewrite_clnt_internal() 2874 * and from resolve_clnt_query() must be fully qualified. 2875 */ 2876 if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) { 2877 msg_warn("%s: no @domain in address: %s", myname, 2878 CONST_STR(reply->recipient)); 2879 return (0); 2880 } 2881 domain += 1; 2882 2883 /* 2884 * In case of address extensions. 2885 */ 2886 if (*var_rcpt_delim == 0) { 2887 bare_addr = 0; 2888 } else { 2889 bare_addr = strip_addr(addr, (char **) 0, var_rcpt_delim); 2890 } 2891 2892#define CHECK_MAIL_ACCESS_RETURN(x) \ 2893 { if (bare_addr) myfree(bare_addr); return(x); } 2894 2895 /* 2896 * Source-routed (non-local or virtual) recipient addresses are too 2897 * suspicious for returning an "OK" result. The complicated expression 2898 * below was brought to you by the keyboard of Victor Duchovni, Morgan 2899 * Stanley and hacked up a bit by Wietse. 2900 */ 2901#define SUSPICIOUS(reply, reply_class) \ 2902 (var_allow_untrust_route == 0 \ 2903 && (reply->flags & RESOLVE_FLAG_ROUTED) \ 2904 && strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0) 2905 2906 /* 2907 * Look up user+foo@domain if the address has an extension, user@domain 2908 * otherwise. 2909 */ 2910 if ((status = check_access(state, table, CONST_STR(reply->recipient), FULL, 2911 found, reply_name, reply_class, def_acl)) != 0 2912 || *found) 2913 CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK 2914 && SUSPICIOUS(reply, reply_class) ? 2915 SMTPD_CHECK_DUNNO : status); 2916 2917 /* 2918 * Try user@domain if the address has an extension. 2919 */ 2920 if (bare_addr) 2921 if ((status = check_access(state, table, bare_addr, PARTIAL, 2922 found, reply_name, reply_class, def_acl)) != 0 2923 || *found) 2924 CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK 2925 && SUSPICIOUS(reply, reply_class) ? 2926 SMTPD_CHECK_DUNNO : status); 2927 2928 /* 2929 * Look up the domain name, or parent domains thereof. 2930 */ 2931 if ((status = check_domain_access(state, table, domain, PARTIAL, 2932 found, reply_name, reply_class, def_acl)) != 0 2933 || *found) 2934 CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK 2935 && SUSPICIOUS(reply, reply_class) ? 2936 SMTPD_CHECK_DUNNO : status); 2937 2938 /* 2939 * Look up user+foo@ if the address has an extension, user@ otherwise. 2940 * XXX This leaks a little memory if map lookup is aborted. 2941 */ 2942 local_at = mystrndup(CONST_STR(reply->recipient), 2943 domain - CONST_STR(reply->recipient)); 2944 status = check_access(state, table, local_at, PARTIAL, found, 2945 reply_name, reply_class, def_acl); 2946 myfree(local_at); 2947 if (status != 0 || *found) 2948 CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK 2949 && SUSPICIOUS(reply, reply_class) ? 2950 SMTPD_CHECK_DUNNO : status); 2951 2952 /* 2953 * Look up user@ if the address has an extension. XXX Same problem here. 2954 */ 2955 if (bare_addr) { 2956 bare_at = strrchr(bare_addr, '@'); 2957 local_at = (bare_at ? mystrndup(bare_addr, bare_at + 1 - bare_addr) : 2958 mystrdup(bare_addr)); 2959 status = check_access(state, table, local_at, PARTIAL, found, 2960 reply_name, reply_class, def_acl); 2961 myfree(local_at); 2962 if (status != 0 || *found) 2963 CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK 2964 && SUSPICIOUS(reply, reply_class) ? 2965 SMTPD_CHECK_DUNNO : status); 2966 } 2967 2968 /* 2969 * Undecided when no match found. 2970 */ 2971 CHECK_MAIL_ACCESS_RETURN(SMTPD_CHECK_DUNNO); 2972} 2973 2974/* Support for different DNSXL lookup results. */ 2975 2976static SMTPD_RBL_STATE dnsxl_stat_soft[1]; 2977 2978#define SMTPD_DNSXL_STAT_SOFT(dnsxl_res) ((dnsxl_res) == dnsxl_stat_soft) 2979#define SMTPD_DNXSL_STAT_HARD(dnsxl_res) ((dnsxl_res) == 0) 2980#define SMTPD_DNSXL_STAT_OK(dnsxl_res) \ 2981 !(SMTPD_DNXSL_STAT_HARD(dnsxl_res) || SMTPD_DNSXL_STAT_SOFT(dnsxl_res)) 2982 2983/* rbl_pagein - look up an RBL lookup result */ 2984 2985static void *rbl_pagein(const char *query, void *unused_context) 2986{ 2987 DNS_RR *txt_list; 2988 VSTRING *why; 2989 int dns_status; 2990 SMTPD_RBL_STATE *rbl = 0; 2991 DNS_RR *addr_list; 2992 DNS_RR *rr; 2993 DNS_RR *next; 2994 VSTRING *buf; 2995 int space_left; 2996 2997 /* 2998 * Do the query. If the DNS lookup produces no definitive reply, give the 2999 * requestor the benefit of the doubt. We can't block all email simply 3000 * because an RBL server is unavailable. 3001 * 3002 * Don't do this for AAAA records. Yet. 3003 */ 3004 why = vstring_alloc(10); 3005 dns_status = dns_lookup(query, T_A, 0, &addr_list, (VSTRING *) 0, why); 3006 if (dns_status != DNS_OK && dns_status != DNS_NOTFOUND) { 3007 msg_warn("%s: RBL lookup error: %s", query, STR(why)); 3008 rbl = dnsxl_stat_soft; 3009 } 3010 vstring_free(why); 3011 if (dns_status != DNS_OK) 3012 return ((void *) rbl); 3013 3014 /* 3015 * Save the result. Yes, we cache negative results as well as positive 3016 * results. Concatenate multiple TXT records, up to some limit. 3017 */ 3018#define RBL_TXT_LIMIT 500 3019 3020 rbl = (SMTPD_RBL_STATE *) mymalloc(sizeof(*rbl)); 3021 if (dns_lookup(query, T_TXT, 0, &txt_list, 3022 (VSTRING *) 0, (VSTRING *) 0) == DNS_OK) { 3023 buf = vstring_alloc(1); 3024 space_left = RBL_TXT_LIMIT; 3025 for (rr = txt_list; rr != 0 && space_left > 0; rr = next) { 3026 vstring_strncat(buf, rr->data, (int) rr->data_len > space_left ? 3027 space_left : rr->data_len); 3028 space_left = RBL_TXT_LIMIT - VSTRING_LEN(buf); 3029 next = rr->next; 3030 if (next && space_left > 3) { 3031 vstring_strcat(buf, " / "); 3032 space_left -= 3; 3033 } 3034 } 3035 rbl->txt = vstring_export(buf); 3036 dns_rr_free(txt_list); 3037 } else 3038 rbl->txt = 0; 3039 rbl->a = addr_list; 3040 return ((void *) rbl); 3041} 3042 3043/* rbl_pageout - discard an RBL lookup result */ 3044 3045static void rbl_pageout(void *data, void *unused_context) 3046{ 3047 SMTPD_RBL_STATE *rbl = (SMTPD_RBL_STATE *) data; 3048 3049 if (SMTPD_DNSXL_STAT_OK(rbl)) { 3050 if (rbl->txt) 3051 myfree(rbl->txt); 3052 if (rbl->a) 3053 dns_rr_free(rbl->a); 3054 myfree((char *) rbl); 3055 } 3056} 3057 3058/* rbl_byte_pagein - parse RBL reply pattern, save byte codes */ 3059 3060static void *rbl_byte_pagein(const char *query, void *unused_context) 3061{ 3062 VSTRING *byte_codes = vstring_alloc(100); 3063 char *saved_query = mystrdup(query); 3064 char *saved_byte_codes; 3065 char *err; 3066 3067 if ((err = ip_match_parse(byte_codes, saved_query)) != 0) 3068 msg_fatal("RBL reply error: %s", err); 3069 saved_byte_codes = ip_match_save(byte_codes); 3070 myfree(saved_query); 3071 vstring_free(byte_codes); 3072 return (saved_byte_codes); 3073} 3074 3075/* rbl_byte_pageout - discard parsed RBL reply byte codes */ 3076 3077static void rbl_byte_pageout(void *data, void *unused_context) 3078{ 3079 myfree(data); 3080} 3081 3082/* rbl_expand_lookup - RBL specific $name expansion */ 3083 3084static const char *rbl_expand_lookup(const char *name, int mode, 3085 char *context) 3086{ 3087 SMTPD_RBL_EXPAND_CONTEXT *rbl_exp = (SMTPD_RBL_EXPAND_CONTEXT *) context; 3088 SMTPD_STATE *state = rbl_exp->state; 3089 3090#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0) 3091 3092 if (state->expand_buf == 0) 3093 state->expand_buf = vstring_alloc(10); 3094 3095 if (msg_verbose > 1) 3096 msg_info("rbl_expand_lookup: ${%s}", name); 3097 3098 /* 3099 * Be sure to return NULL only for non-existent names. 3100 */ 3101 if (STREQ(name, MAIL_ATTR_RBL_CODE)) { 3102 vstring_sprintf(state->expand_buf, "%d", var_maps_rbl_code); 3103 return (STR(state->expand_buf)); 3104 } else if (STREQ(name, MAIL_ATTR_RBL_DOMAIN)) { 3105 return (rbl_exp->domain); 3106 } else if (STREQ(name, MAIL_ATTR_RBL_REASON)) { 3107 return (rbl_exp->txt); 3108 } else if (STREQ(name, MAIL_ATTR_RBL_TXT)) {/* LaMont compat */ 3109 return (rbl_exp->txt); 3110 } else if (STREQ(name, MAIL_ATTR_RBL_WHAT)) { 3111 return (rbl_exp->what); 3112 } else if (STREQ(name, MAIL_ATTR_RBL_CLASS)) { 3113 return (rbl_exp->class); 3114 } else { 3115 return (smtpd_expand_lookup(name, mode, (char *) state)); 3116 } 3117} 3118 3119/* rbl_reject_reply - format reply after RBL reject */ 3120 3121static int rbl_reject_reply(SMTPD_STATE *state, const SMTPD_RBL_STATE *rbl, 3122 const char *rbl_domain, 3123 const char *what, 3124 const char *reply_class) 3125{ 3126 const char *myname = "rbl_reject_reply"; 3127 VSTRING *why = 0; 3128 const char *template = 0; 3129 SMTPD_RBL_EXPAND_CONTEXT rbl_exp; 3130 int result; 3131 DSN_SPLIT dp; 3132 int code; 3133 3134 /* 3135 * Use the server-specific reply template or use the default one. 3136 */ 3137 if (*var_rbl_reply_maps) { 3138 template = maps_find(rbl_reply_maps, rbl_domain, DICT_FLAG_NONE); 3139 if (rbl_reply_maps->error) 3140 reject_server_error(state); 3141 } 3142 why = vstring_alloc(100); 3143 rbl_exp.state = state; 3144 rbl_exp.domain = mystrdup(rbl_domain); 3145 (void) split_at(rbl_exp.domain, '='); 3146 rbl_exp.what = what; 3147 rbl_exp.class = reply_class; 3148 rbl_exp.txt = (rbl->txt == 0 ? "" : rbl->txt); 3149 3150 for (;;) { 3151 if (template == 0) 3152 template = var_def_rbl_reply; 3153 if (mac_expand(why, template, MAC_EXP_FLAG_NONE, 3154 STR(smtpd_expand_filter), rbl_expand_lookup, 3155 (char *) &rbl_exp) == 0) 3156 break; 3157 if (template == var_def_rbl_reply) 3158 msg_fatal("%s: bad default rbl reply template: %s", 3159 myname, var_def_rbl_reply); 3160 msg_warn("%s: bad rbl reply template for domain %s: %s", 3161 myname, rbl_domain, template); 3162 template = 0; /* pretend not found */ 3163 } 3164 3165 /* 3166 * XXX Impedance mis-match. 3167 * 3168 * Validate the response, that is, the response must begin with a 3169 * three-digit status code, and the first digit must be 4 or 5. If the 3170 * response is bad, log a warning and send a generic response instead. 3171 */ 3172 if ((STR(why)[0] != '4' && STR(why)[0] != '5') 3173 || !ISDIGIT(STR(why)[1]) || !ISDIGIT(STR(why)[2]) 3174 || STR(why)[3] != ' ') { 3175 msg_warn("rbl response code configuration error: %s", STR(why)); 3176 result = smtpd_check_reject(state, MAIL_ERROR_POLICY, 3177 450, "4.7.1", "Service unavailable"); 3178 } else { 3179 code = atoi(STR(why)); 3180 dsn_split(&dp, "4.7.1", STR(why) + 4); 3181 result = smtpd_check_reject(state, MAIL_ERROR_POLICY, 3182 code, 3183 smtpd_dsn_fix(DSN_STATUS(dp.dsn), 3184 reply_class), 3185 "%s", *dp.text ? 3186 dp.text : "Service unavailable"); 3187 } 3188 3189 /* 3190 * Clean up. 3191 */ 3192 myfree(rbl_exp.domain); 3193 vstring_free(why); 3194 3195 return (result); 3196} 3197 3198/* rbl_match_addr - match address list */ 3199 3200static int rbl_match_addr(SMTPD_RBL_STATE *rbl, const char *byte_codes) 3201{ 3202 const char *myname = "rbl_match_addr"; 3203 DNS_RR *rr; 3204 3205 for (rr = rbl->a; rr != 0; rr = rr->next) { 3206 if (rr->type == T_A) { 3207 if (ip_match_execute(byte_codes, rr->data)) 3208 return (1); 3209 } else { 3210 msg_warn("%s: skipping record type %s for query %s", 3211 myname, dns_strtype(rr->type), rr->qname); 3212 } 3213 } 3214 return (0); 3215} 3216 3217/* find_dnsxl_addr - look up address in DNSXL */ 3218 3219static const SMTPD_RBL_STATE *find_dnsxl_addr(SMTPD_STATE *state, 3220 const char *rbl_domain, 3221 const char *addr) 3222{ 3223 const char *myname = "find_dnsxl_addr"; 3224 ARGV *octets; 3225 VSTRING *query; 3226 int i; 3227 SMTPD_RBL_STATE *rbl; 3228 const char *reply_addr; 3229 const char *byte_codes; 3230 struct addrinfo *res; 3231 unsigned char *ipv6_addr; 3232 3233 query = vstring_alloc(100); 3234 3235 /* 3236 * Reverse the client IPV6 address, represented as 32 hexadecimal 3237 * nibbles. We use the binary address to avoid tricky code. Asking for an 3238 * AAAA record makes no sense here. Just like with IPv4 we use the lookup 3239 * result as a bit mask, not as an IP address. 3240 */ 3241#ifdef HAS_IPV6 3242 if (valid_ipv6_hostaddr(addr, DONT_GRIPE)) { 3243 if (hostaddr_to_sockaddr(addr, (char *) 0, 0, &res) != 0 3244 || res->ai_family != PF_INET6) 3245 msg_fatal("%s: unable to convert address %s", myname, addr); 3246 ipv6_addr = (unsigned char *) &SOCK_ADDR_IN6_ADDR(res->ai_addr); 3247 for (i = sizeof(SOCK_ADDR_IN6_ADDR(res->ai_addr)) - 1; i >= 0; i--) 3248 vstring_sprintf_append(query, "%x.%x.", 3249 ipv6_addr[i] & 0xf, ipv6_addr[i] >> 4); 3250 freeaddrinfo(res); 3251 } else 3252#endif 3253 3254 /* 3255 * Reverse the client IPV4 address, represented as four decimal octet 3256 * values. We use the textual address for convenience. 3257 */ 3258 { 3259 octets = argv_split(addr, "."); 3260 for (i = octets->argc - 1; i >= 0; i--) { 3261 vstring_strcat(query, octets->argv[i]); 3262 vstring_strcat(query, "."); 3263 } 3264 argv_free(octets); 3265 } 3266 3267 /* 3268 * Tack on the RBL domain name and query the DNS for an A record. 3269 */ 3270 vstring_strcat(query, rbl_domain); 3271 reply_addr = split_at(STR(query), '='); 3272 rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query)); 3273 if (reply_addr != 0) 3274 byte_codes = ctable_locate(smtpd_rbl_byte_cache, reply_addr); 3275 3276 /* 3277 * If the record exists, match the result address. 3278 */ 3279 if (SMTPD_DNSXL_STAT_OK(rbl) && reply_addr != 0 3280 && !rbl_match_addr(rbl, byte_codes)) 3281 rbl = 0; 3282 vstring_free(query); 3283 return (rbl); 3284} 3285 3286/* reject_rbl_addr - reject address in real-time blackhole list */ 3287 3288static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain, 3289 const char *addr, const char *reply_class) 3290{ 3291 const char *myname = "reject_rbl_addr"; 3292 const SMTPD_RBL_STATE *rbl; 3293 3294 if (msg_verbose) 3295 msg_info("%s: %s %s", myname, reply_class, addr); 3296 3297 rbl = find_dnsxl_addr(state, rbl_domain, addr); 3298 if (!SMTPD_DNSXL_STAT_OK(rbl)) { 3299 return (SMTPD_CHECK_DUNNO); 3300 } else { 3301 return (rbl_reject_reply(state, rbl, rbl_domain, addr, reply_class)); 3302 } 3303} 3304 3305/* permit_dnswl_addr - permit address in DNSWL */ 3306 3307static int permit_dnswl_addr(SMTPD_STATE *state, const char *dnswl_domain, 3308 const char *addr, const char *reply_class) 3309{ 3310 const char *myname = "permit_dnswl_addr"; 3311 const SMTPD_RBL_STATE *dnswl_result; 3312 3313 if (msg_verbose) 3314 msg_info("%s: %s", myname, addr); 3315 3316 /* Safety: don't whitelist unauthorized recipients. */ 3317 if (strcmp(state->where, SMTPD_CMD_RCPT) == 0 && state->recipient != 0 3318 && permit_auth_destination(state, state->recipient) != SMTPD_CHECK_OK) 3319 return (SMTPD_CHECK_DUNNO); 3320 3321 dnswl_result = find_dnsxl_addr(state, dnswl_domain, addr); 3322 if (SMTPD_DNXSL_STAT_HARD(dnswl_result)) { 3323 return (SMTPD_CHECK_DUNNO); 3324 } else if (SMTPD_DNSXL_STAT_SOFT(dnswl_result)) { 3325 /* XXX: Make configurable as dnswl_tempfail_action. */ 3326 DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY, 3327 450, "4.7.1", 3328 "<%s>: %s rejected: %s", 3329 addr, reply_class, 3330 "Service unavailable"); 3331 return (SMTPD_CHECK_DUNNO); 3332 } else if (SMTPD_DNSXL_STAT_OK(dnswl_result)) { 3333 return (SMTPD_CHECK_OK); 3334 } else { 3335 /* Future proofing, in case find_dnsxl_addr() result is changed. */ 3336 msg_panic("%s: find_dnsxl_addr API failure", myname); 3337 } 3338} 3339 3340/* find_dnsxl_domain - reject if domain in real-time blackhole list */ 3341 3342static const SMTPD_RBL_STATE *find_dnsxl_domain(SMTPD_STATE *state, 3343 const char *rbl_domain, const char *what) 3344{ 3345 VSTRING *query; 3346 SMTPD_RBL_STATE *rbl; 3347 const char *domain; 3348 const char *reply_addr; 3349 const char *byte_codes; 3350 const char *suffix; 3351 3352 /* 3353 * Extract the domain, tack on the RBL domain name and query the DNS for 3354 * an A record. 3355 */ 3356 if ((domain = strrchr(what, '@')) != 0) { 3357 domain += 1; 3358 if (domain[0] == '[') 3359 return (SMTPD_CHECK_DUNNO); 3360 } else 3361 domain = what; 3362 3363 /* 3364 * XXX Some Spamhaus RHSBL rejects lookups with "No IP queries" even if 3365 * the name has an alphanumerical prefix. We play safe, and skip both 3366 * RHSBL and RHSWL queries for names ending in a numerical suffix. 3367 */ 3368 if (domain[0] == 0 || valid_hostname(domain, DONT_GRIPE) == 0) 3369 return (SMTPD_CHECK_DUNNO); 3370 suffix = strrchr(domain, '.'); 3371 if (alldig(suffix == 0 ? domain : suffix + 1)) 3372 return (SMTPD_CHECK_DUNNO); 3373 3374 query = vstring_alloc(100); 3375 vstring_sprintf(query, "%s.%s", domain, rbl_domain); 3376 reply_addr = split_at(STR(query), '='); 3377 rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query)); 3378 if (reply_addr != 0) 3379 byte_codes = ctable_locate(smtpd_rbl_byte_cache, reply_addr); 3380 3381 /* 3382 * If the record exists, match the result address. 3383 */ 3384 if (SMTPD_DNSXL_STAT_OK(rbl) && reply_addr != 0 3385 && !rbl_match_addr(rbl, byte_codes)) 3386 rbl = 0; 3387 vstring_free(query); 3388 return (rbl); 3389} 3390 3391/* reject_rbl_domain - reject if domain in real-time blackhole list */ 3392 3393static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain, 3394 const char *what, const char *reply_class) 3395{ 3396 const char *myname = "reject_rbl_domain"; 3397 const SMTPD_RBL_STATE *rbl; 3398 3399 if (msg_verbose) 3400 msg_info("%s: %s %s", myname, rbl_domain, what); 3401 3402 rbl = find_dnsxl_domain(state, rbl_domain, what); 3403 if (!SMTPD_DNSXL_STAT_OK(rbl)) { 3404 return (SMTPD_CHECK_DUNNO); 3405 } else { 3406 return (rbl_reject_reply(state, rbl, rbl_domain, what, reply_class)); 3407 } 3408} 3409 3410/* permit_dnswl_domain - permit domain in DNSWL */ 3411 3412static int permit_dnswl_domain(SMTPD_STATE *state, const char *dnswl_domain, 3413 const char *what, const char *reply_class) 3414{ 3415 const char *myname = "permit_dnswl_domain"; 3416 const SMTPD_RBL_STATE *dnswl_result; 3417 3418 if (msg_verbose) 3419 msg_info("%s: %s", myname, what); 3420 3421 /* Safety: don't whitelist unauthorized recipients. */ 3422 if (strcmp(state->where, SMTPD_CMD_RCPT) == 0 && state->recipient != 0 3423 && permit_auth_destination(state, state->recipient) != SMTPD_CHECK_OK) 3424 return (SMTPD_CHECK_DUNNO); 3425 3426 dnswl_result = find_dnsxl_domain(state, dnswl_domain, what); 3427 if (SMTPD_DNXSL_STAT_HARD(dnswl_result)) { 3428 return (SMTPD_CHECK_DUNNO); 3429 } else if (SMTPD_DNSXL_STAT_SOFT(dnswl_result)) { 3430 /* XXX: Make configurable as rhswl_tempfail_action. */ 3431 DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY, 3432 450, "4.7.1", 3433 "<%s>: %s rejected: %s", 3434 what, reply_class, 3435 "Service unavailable"); 3436 return (SMTPD_CHECK_DUNNO); 3437 } else if (SMTPD_DNSXL_STAT_OK(dnswl_result)) { 3438 return (SMTPD_CHECK_OK); 3439 } else { 3440 /* Future proofing, in case find_dnsxl_addr() result is changed. */ 3441 msg_panic("%s: find_dnsxl_addr API failure", myname); 3442 } 3443} 3444 3445/* reject_maps_rbl - reject if client address in real-time blackhole list */ 3446 3447static int reject_maps_rbl(SMTPD_STATE *state) 3448{ 3449 const char *myname = "reject_maps_rbl"; 3450 char *saved_domains = mystrdup(var_maps_rbl_domains); 3451 char *bp = saved_domains; 3452 char *rbl_domain; 3453 int result = SMTPD_CHECK_DUNNO; 3454 static int warned; 3455 3456 if (msg_verbose) 3457 msg_info("%s: %s", myname, state->addr); 3458 3459 if (warned == 0) { 3460 warned++; 3461 msg_warn("support for restriction \"%s\" will be removed from %s; " 3462 "use \"%s domain-name\" instead", 3463 REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT); 3464 } 3465 while ((rbl_domain = mystrtok(&bp, RESTRICTION_SEPARATORS)) != 0) { 3466 result = reject_rbl_addr(state, rbl_domain, state->addr, 3467 SMTPD_NAME_CLIENT); 3468 if (result != SMTPD_CHECK_DUNNO) 3469 break; 3470 } 3471 3472 /* 3473 * Clean up. 3474 */ 3475 myfree(saved_domains); 3476 3477 return (result); 3478} 3479 3480#ifdef USE_SASL_AUTH 3481 3482/* reject_auth_sender_login_mismatch - logged in client must own sender address */ 3483 3484static int reject_auth_sender_login_mismatch(SMTPD_STATE *state, const char *sender, int allow_unknown_sender) 3485{ 3486 const RESOLVE_REPLY *reply; 3487 const char *owners; 3488 char *saved_owners; 3489 char *cp; 3490 char *name; 3491 int found = 0; 3492 3493#define ALLOW_UNKNOWN_SENDER 1 3494#define FORBID_UNKNOWN_SENDER 0 3495 3496 /* 3497 * Reject if the client is logged in and does not own the sender address. 3498 */ 3499 if (smtpd_sender_login_maps && state->sasl_username) { 3500 reply = smtpd_resolve_addr(sender); 3501 if (reply->flags & RESOLVE_FLAG_FAIL) 3502 reject_dict_retry(state, sender); 3503 if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps, 3504 STR(reply->recipient), (char **) 0)) != 0) { 3505 cp = saved_owners = mystrdup(owners); 3506 while ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) != 0) { 3507 if (strcasecmp(state->sasl_username, name) == 0) { 3508 found = 1; 3509 break; 3510 } 3511 } 3512 myfree(saved_owners); 3513 } else if (allow_unknown_sender) 3514 return (SMTPD_CHECK_DUNNO); 3515 if (!found) 3516 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 553, "5.7.1", 3517 "<%s>: Sender address rejected: not owned by user %s", 3518 sender, state->sasl_username)); 3519 } 3520 return (SMTPD_CHECK_DUNNO); 3521} 3522 3523/* reject_unauth_sender_login_mismatch - sender requires client is logged in */ 3524 3525static int reject_unauth_sender_login_mismatch(SMTPD_STATE *state, const char *sender) 3526{ 3527 const RESOLVE_REPLY *reply; 3528 3529 /* 3530 * Reject if the client is not logged in and the sender address has an 3531 * owner. 3532 */ 3533 if (smtpd_sender_login_maps && !state->sasl_username) { 3534 reply = smtpd_resolve_addr(sender); 3535 if (reply->flags & RESOLVE_FLAG_FAIL) 3536 reject_dict_retry(state, sender); 3537 if (check_mail_addr_find(state, sender, smtpd_sender_login_maps, 3538 STR(reply->recipient), (char **) 0) != 0) 3539 return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 553, "5.7.1", 3540 "<%s>: Sender address rejected: not logged in", sender)); 3541 } 3542 return (SMTPD_CHECK_DUNNO); 3543} 3544 3545#endif 3546 3547/* check_policy_service - check delegated policy service */ 3548 3549static int check_policy_service(SMTPD_STATE *state, const char *server, 3550 const char *reply_name, const char *reply_class, 3551 const char *def_acl) 3552{ 3553 static VSTRING *action = 0; 3554 ATTR_CLNT *policy_clnt; 3555 3556#ifdef USE_TLS 3557 VSTRING *subject_buf; 3558 VSTRING *issuer_buf; 3559 const char *subject; 3560 const char *issuer; 3561 3562#endif 3563 int ret; 3564 3565 /* 3566 * Sanity check. 3567 */ 3568 if (!policy_clnt_table 3569 || (policy_clnt = (ATTR_CLNT *) htable_find(policy_clnt_table, server)) == 0) 3570 msg_panic("check_policy_service: no client endpoint for server %s", 3571 server); 3572 3573 /* 3574 * Initialize. 3575 */ 3576 if (action == 0) 3577 action = vstring_alloc(10); 3578 3579#ifdef USE_TLS 3580#define ENCODE_CN(coded_CN, coded_CN_buf, CN) do { \ 3581 if (!TLS_CERT_IS_TRUSTED(state->tls_context) || *(CN) == 0) { \ 3582 coded_CN_buf = 0; \ 3583 coded_CN = ""; \ 3584 } else { \ 3585 coded_CN_buf = vstring_alloc(strlen(CN) + 1); \ 3586 xtext_quote(coded_CN_buf, CN, ""); \ 3587 coded_CN = STR(coded_CN_buf); \ 3588 } \ 3589 } while (0); 3590 3591 ENCODE_CN(subject, subject_buf, state->tls_context->peer_CN); 3592 ENCODE_CN(issuer, issuer_buf, state->tls_context->issuer_CN); 3593#endif 3594 3595 if (attr_clnt_request(policy_clnt, 3596 ATTR_FLAG_NONE, /* Query attributes. */ 3597 ATTR_TYPE_STR, MAIL_ATTR_REQ, "smtpd_access_policy", 3598 ATTR_TYPE_STR, MAIL_ATTR_PROTO_STATE, state->where, 3599 ATTR_TYPE_STR, MAIL_ATTR_ACT_PROTO_NAME, state->protocol, 3600 ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, state->addr, 3601 ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_NAME, state->name, 3602 ATTR_TYPE_STR, MAIL_ATTR_ACT_REVERSE_CLIENT_NAME, 3603 state->reverse_name, 3604 ATTR_TYPE_STR, MAIL_ATTR_ACT_HELO_NAME, 3605 state->helo_name ? state->helo_name : "", 3606 ATTR_TYPE_STR, MAIL_ATTR_SENDER, 3607 state->sender ? state->sender : "", 3608 ATTR_TYPE_STR, MAIL_ATTR_RECIP, 3609 state->recipient ? state->recipient : "", 3610 ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, 3611 ((strcasecmp(state->where, SMTPD_CMD_DATA) == 0) || 3612 (strcasecmp(state->where, SMTPD_AFTER_DOT) == 0)) ? 3613 state->rcpt_count : 0, 3614 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, 3615 state->queue_id ? state->queue_id : "", 3616 ATTR_TYPE_STR, MAIL_ATTR_INSTANCE, 3617 STR(state->instance), 3618 ATTR_TYPE_LONG, MAIL_ATTR_SIZE, 3619 (unsigned long) (state->act_size > 0 ? 3620 state->act_size : state->msg_size), 3621 ATTR_TYPE_STR, MAIL_ATTR_ETRN_DOMAIN, 3622 state->etrn_name ? state->etrn_name : "", 3623 ATTR_TYPE_STR, MAIL_ATTR_STRESS, var_stress, 3624#ifdef USE_SASL_AUTH 3625 ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, 3626 state->sasl_method ? state->sasl_method : "", 3627 ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, 3628 state->sasl_username ? state->sasl_username : "", 3629 ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, 3630 state->sasl_sender ? state->sasl_sender : "", 3631#endif 3632#ifdef USE_TLS 3633#define IF_ENCRYPTED(x, y) ((state->tls_context && ((x) != 0)) ? (x) : (y)) 3634 ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT, subject, 3635 ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSUER, issuer, 3636 3637 /* 3638 * When directly checking the fingerprint, it is OK if the issuing CA is 3639 * not trusted. 3640 */ 3641 ATTR_TYPE_STR, MAIL_ATTR_CCERT_CERT_FPRINT, 3642 IF_ENCRYPTED(state->tls_context->peer_cert_fprint, ""), 3643 ATTR_TYPE_STR, MAIL_ATTR_CCERT_PKEY_FPRINT, 3644 IF_ENCRYPTED(state->tls_context->peer_pkey_fprint, ""), 3645 ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_PROTOCOL, 3646 IF_ENCRYPTED(state->tls_context->protocol, ""), 3647 ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_CIPHER, 3648 IF_ENCRYPTED(state->tls_context->cipher_name, ""), 3649 ATTR_TYPE_INT, MAIL_ATTR_CRYPTO_KEYSIZE, 3650 IF_ENCRYPTED(state->tls_context->cipher_usebits, 0), 3651#endif 3652 ATTR_TYPE_END, 3653 ATTR_FLAG_MISSING, /* Reply attributes. */ 3654 ATTR_TYPE_STR, MAIL_ATTR_ACTION, action, 3655 ATTR_TYPE_END) != 1) { 3656 ret = smtpd_check_reject(state, MAIL_ERROR_POLICY, 3657 451, "4.3.5", 3658 "Server configuration problem"); 3659 } else { 3660 3661 /* 3662 * XXX This produces bogus error messages when the reply is 3663 * malformed. 3664 */ 3665 ret = check_table_result(state, server, STR(action), 3666 "policy query", reply_name, 3667 reply_class, def_acl); 3668 } 3669#ifdef USE_TLS 3670 if (subject_buf) 3671 vstring_free(subject_buf); 3672 if (issuer_buf) 3673 vstring_free(issuer_buf); 3674#endif 3675 return (ret); 3676} 3677 3678/* is_map_command - restriction has form: check_xxx_access type:name */ 3679 3680static int is_map_command(SMTPD_STATE *state, const char *name, 3681 const char *command, char ***argp) 3682{ 3683 3684 /* 3685 * This is a three-valued function: (a) this is not a check_xxx_access 3686 * command, (b) this is a malformed check_xxx_access command, (c) this is 3687 * a well-formed check_xxx_access command. That's too clumsy for function 3688 * result values, so we use regular returns for (a) and (c), and use long 3689 * jumps for the error case (b). 3690 */ 3691 if (strcasecmp(name, command) != 0) { 3692 return (0); 3693 } else if (*(*argp + 1) == 0 || strchr(*(*argp += 1), ':') == 0) { 3694 msg_warn("restriction %s: bad argument \"%s\": need maptype:mapname", 3695 command, **argp); 3696 reject_server_error(state); 3697 } else { 3698 return (1); 3699 } 3700} 3701 3702/* forbid_whitelist - disallow whitelisting */ 3703 3704static void forbid_whitelist(SMTPD_STATE *state, const char *name, 3705 int status, const char *target) 3706{ 3707 if (status == SMTPD_CHECK_OK) { 3708 msg_warn("restriction %s returns OK for %s", name, target); 3709 msg_warn("this is not allowed for security reasons"); 3710 msg_warn("use DUNNO instead of OK if you want to make an exception"); 3711 reject_server_error(state); 3712 } 3713} 3714 3715/* generic_checks - generic restrictions */ 3716 3717static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, 3718 const char *reply_name, 3719 const char *reply_class, 3720 const char *def_acl) 3721{ 3722 const char *myname = "generic_checks"; 3723 char **cpp; 3724 const char *name; 3725 int status = 0; 3726 ARGV *list; 3727 int found; 3728 int saved_recursion = state->recursion++; 3729 3730 if (msg_verbose) 3731 msg_info(">>> START %s RESTRICTIONS <<<", reply_class); 3732 3733 for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) { 3734 3735 if (state->discard != 0) 3736 break; 3737 3738 if (msg_verbose) 3739 msg_info("%s: name=%s", myname, name); 3740 3741 /* 3742 * Pseudo restrictions. 3743 */ 3744 if (strcasecmp(name, WARN_IF_REJECT) == 0) { 3745 if (state->warn_if_reject == 0) 3746 state->warn_if_reject = state->recursion; 3747 continue; 3748 } 3749 3750 /* 3751 * Spoof the is_map_command() routine, so that we do not have to make 3752 * special cases for the implicit short-hand access map notation. 3753 */ 3754#define NO_DEF_ACL 0 3755 3756 if (strchr(name, ':') != 0) { 3757 if (def_acl == NO_DEF_ACL) { 3758 msg_warn("specify one of (%s, %s, %s, %s, %s, %s) before %s restriction \"%s\"", 3759 CHECK_CLIENT_ACL, CHECK_REVERSE_CLIENT_ACL, CHECK_HELO_ACL, CHECK_SENDER_ACL, 3760 CHECK_RECIP_ACL, CHECK_ETRN_ACL, reply_class, name); 3761 reject_server_error(state); 3762 } 3763 name = def_acl; 3764 cpp -= 1; 3765 } 3766 3767 /* 3768 * Generic restrictions. 3769 */ 3770 if (strcasecmp(name, PERMIT_ALL) == 0) { 3771 status = smtpd_acl_permit(state, name, reply_class, 3772 reply_name, NO_PRINT_ARGS); 3773 if (status == SMTPD_CHECK_OK && cpp[1] != 0) 3774 msg_warn("restriction `%s' after `%s' is ignored", 3775 cpp[1], PERMIT_ALL); 3776 } else if (strcasecmp(name, DEFER_ALL) == 0) { 3777 status = smtpd_check_reject(state, MAIL_ERROR_POLICY, 3778 var_defer_code, "4.3.2", 3779 "<%s>: %s rejected: Try again later", 3780 reply_name, reply_class); 3781 if (cpp[1] != 0 && state->warn_if_reject == 0) 3782 msg_warn("restriction `%s' after `%s' is ignored", 3783 cpp[1], DEFER_ALL); 3784 } else if (strcasecmp(name, REJECT_ALL) == 0) { 3785 status = smtpd_check_reject(state, MAIL_ERROR_POLICY, 3786 var_reject_code, "5.7.1", 3787 "<%s>: %s rejected: Access denied", 3788 reply_name, reply_class); 3789 if (cpp[1] != 0 && state->warn_if_reject == 0) 3790 msg_warn("restriction `%s' after `%s' is ignored", 3791 cpp[1], REJECT_ALL); 3792 } else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) { 3793 status = reject_unauth_pipelining(state, reply_name, reply_class); 3794 } else if (strcasecmp(name, CHECK_POLICY_SERVICE) == 0) { 3795 if (cpp[1] == 0 || strchr(cpp[1], ':') == 0) { 3796 msg_warn("restriction %s must be followed by transport:server", 3797 CHECK_POLICY_SERVICE); 3798 reject_server_error(state); 3799 } else 3800 status = check_policy_service(state, *++cpp, reply_name, 3801 reply_class, def_acl); 3802 } else if (strcasecmp(name, DEFER_IF_PERMIT) == 0) { 3803 status = DEFER_IF_PERMIT2(DEFER_IF_PERMIT_ACT, 3804 state, MAIL_ERROR_POLICY, 3805 450, "4.7.0", 3806 "<%s>: %s rejected: defer_if_permit requested", 3807 reply_name, reply_class); 3808 } else if (strcasecmp(name, DEFER_IF_REJECT) == 0) { 3809 DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY, 3810 450, "4.7.0", 3811 "<%s>: %s rejected: defer_if_reject requested", 3812 reply_name, reply_class); 3813 } else if (strcasecmp(name, SLEEP) == 0) { 3814 if (cpp[1] == 0 || alldig(cpp[1]) == 0) { 3815 msg_warn("restriction %s must be followed by number", SLEEP); 3816 reject_server_error(state); 3817 } else 3818 sleep(atoi(*++cpp)); 3819 } else if (strcasecmp(name, REJECT_PLAINTEXT_SESSION) == 0) { 3820 status = reject_plaintext_session(state); 3821 } 3822 3823 /* 3824 * Client name/address restrictions. 3825 */ 3826 else if (strcasecmp(name, REJECT_UNKNOWN_CLIENT_HOSTNAME) == 0 3827 || strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) { 3828 status = reject_unknown_client(state); 3829 } else if (strcasecmp(name, REJECT_UNKNOWN_REVERSE_HOSTNAME) == 0) { 3830 status = reject_unknown_reverse_name(state); 3831 } else if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) { 3832 status = permit_inet_interfaces(state); 3833 if (status == SMTPD_CHECK_OK) 3834 status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT, 3835 state->namaddr, NO_PRINT_ARGS); 3836 } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) { 3837 status = permit_mynetworks(state); 3838 if (status == SMTPD_CHECK_OK) 3839 status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT, 3840 state->namaddr, NO_PRINT_ARGS); 3841 } else if (is_map_command(state, name, CHECK_CLIENT_ACL, &cpp)) { 3842 status = check_namadr_access(state, *cpp, state->name, state->addr, 3843 FULL, &found, state->namaddr, 3844 SMTPD_NAME_CLIENT, def_acl); 3845 } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_ACL, &cpp)) { 3846 status = check_namadr_access(state, *cpp, state->reverse_name, state->addr, 3847 FULL, &found, state->namaddr, 3848 SMTPD_NAME_REV_CLIENT, def_acl); 3849 forbid_whitelist(state, name, status, state->reverse_name); 3850 } else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) { 3851 status = reject_maps_rbl(state); 3852 } else if (strcasecmp(name, REJECT_RBL_CLIENT) == 0 3853 || strcasecmp(name, REJECT_RBL) == 0) { 3854 if (cpp[1] == 0) 3855 msg_warn("restriction %s requires domain name argument", name); 3856 else 3857 status = reject_rbl_addr(state, *(cpp += 1), state->addr, 3858 SMTPD_NAME_CLIENT); 3859 } else if (strcasecmp(name, PERMIT_DNSWL_CLIENT) == 0) { 3860 if (cpp[1] == 0) 3861 msg_warn("restriction %s requires domain name argument", name); 3862 else { 3863 status = permit_dnswl_addr(state, *(cpp += 1), state->addr, 3864 SMTPD_NAME_CLIENT); 3865 if (status == SMTPD_CHECK_OK) 3866 status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT, 3867 state->namaddr, NO_PRINT_ARGS); 3868 } 3869 } else if (strcasecmp(name, REJECT_RHSBL_CLIENT) == 0) { 3870 if (cpp[1] == 0) 3871 msg_warn("restriction %s requires domain name argument", 3872 name); 3873 else { 3874 cpp += 1; 3875 if (strcasecmp(state->name, "unknown") != 0) 3876 status = reject_rbl_domain(state, *cpp, state->name, 3877 SMTPD_NAME_CLIENT); 3878 } 3879 } else if (strcasecmp(name, PERMIT_RHSWL_CLIENT) == 0) { 3880 if (cpp[1] == 0) 3881 msg_warn("restriction %s requires domain name argument", 3882 name); 3883 else { 3884 cpp += 1; 3885 if (strcasecmp(state->name, "unknown") != 0) { 3886 status = permit_dnswl_domain(state, *cpp, state->name, 3887 SMTPD_NAME_CLIENT); 3888 if (status == SMTPD_CHECK_OK) 3889 status = smtpd_acl_permit(state, name, 3890 SMTPD_NAME_CLIENT, state->namaddr, NO_PRINT_ARGS); 3891 } 3892 } 3893 } else if (strcasecmp(name, REJECT_RHSBL_REVERSE_CLIENT) == 0) { 3894 if (cpp[1] == 0) 3895 msg_warn("restriction %s requires domain name argument", 3896 name); 3897 else { 3898 cpp += 1; 3899 if (strcasecmp(state->reverse_name, "unknown") != 0) 3900 status = reject_rbl_domain(state, *cpp, state->reverse_name, 3901 SMTPD_NAME_REV_CLIENT); 3902 } 3903 } else if (is_map_command(state, name, CHECK_CCERT_ACL, &cpp)) { 3904 status = check_ccert_access(state, *cpp, def_acl); 3905#ifdef USE_SASL_AUTH 3906 } else if (is_map_command(state, name, CHECK_SASL_ACL, &cpp)) { 3907 if (var_smtpd_sasl_enable) { 3908 if (state->sasl_username && state->sasl_username[0]) 3909 status = check_sasl_access(state, *cpp, def_acl); 3910 } else 3911#endif 3912 msg_warn("restriction `%s' ignored: no SASL support", name); 3913 } else if (is_map_command(state, name, CHECK_CLIENT_NS_ACL, &cpp)) { 3914 if (strcasecmp(state->name, "unknown") != 0) { 3915 status = check_server_access(state, *cpp, state->name, 3916 T_NS, state->namaddr, 3917 SMTPD_NAME_CLIENT, def_acl); 3918 forbid_whitelist(state, name, status, state->name); 3919 } 3920 } else if (is_map_command(state, name, CHECK_CLIENT_MX_ACL, &cpp)) { 3921 if (strcasecmp(state->name, "unknown") != 0) { 3922 status = check_server_access(state, *cpp, state->name, 3923 T_MX, state->namaddr, 3924 SMTPD_NAME_CLIENT, def_acl); 3925 forbid_whitelist(state, name, status, state->name); 3926 } 3927 } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_NS_ACL, &cpp)) { 3928 if (strcasecmp(state->reverse_name, "unknown") != 0) { 3929 status = check_server_access(state, *cpp, state->reverse_name, 3930 T_NS, state->namaddr, 3931 SMTPD_NAME_REV_CLIENT, def_acl); 3932 forbid_whitelist(state, name, status, state->reverse_name); 3933 } 3934 } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_MX_ACL, &cpp)) { 3935 if (strcasecmp(state->reverse_name, "unknown") != 0) { 3936 status = check_server_access(state, *cpp, state->reverse_name, 3937 T_MX, state->namaddr, 3938 SMTPD_NAME_REV_CLIENT, def_acl); 3939 forbid_whitelist(state, name, status, state->reverse_name); 3940 } 3941 } 3942 3943 /* 3944 * HELO/EHLO parameter restrictions. 3945 */ 3946 else if (is_map_command(state, name, CHECK_HELO_ACL, &cpp)) { 3947 if (state->helo_name) 3948 status = check_domain_access(state, *cpp, state->helo_name, 3949 FULL, &found, state->helo_name, 3950 SMTPD_NAME_HELO, def_acl); 3951 } else if (strcasecmp(name, REJECT_INVALID_HELO_HOSTNAME) == 0 3952 || strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) { 3953 if (state->helo_name) { 3954 if (*state->helo_name != '[') 3955 status = reject_invalid_hostname(state, state->helo_name, 3956 state->helo_name, SMTPD_NAME_HELO); 3957 else 3958 status = reject_invalid_hostaddr(state, state->helo_name, 3959 state->helo_name, SMTPD_NAME_HELO); 3960 } 3961 } else if (strcasecmp(name, REJECT_UNKNOWN_HELO_HOSTNAME) == 0 3962 || strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) { 3963 if (state->helo_name) { 3964 if (*state->helo_name != '[') 3965 status = reject_unknown_hostname(state, state->helo_name, 3966 state->helo_name, SMTPD_NAME_HELO); 3967 else 3968 status = reject_invalid_hostaddr(state, state->helo_name, 3969 state->helo_name, SMTPD_NAME_HELO); 3970 } 3971 } else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) { 3972 msg_warn("restriction %s is deprecated. Use %s or %s instead", 3973 PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS, PERMIT_SASL_AUTH); 3974 if (state->helo_name) { 3975 if (state->helo_name[strspn(state->helo_name, "0123456789.:")] == 0 3976 && (status = reject_invalid_hostaddr(state, state->helo_name, 3977 state->helo_name, SMTPD_NAME_HELO)) == 0) 3978 status = smtpd_acl_permit(state, name, SMTPD_NAME_HELO, 3979 state->helo_name, NO_PRINT_ARGS); 3980 } 3981 } else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) { 3982 if (state->helo_name) { 3983 status = check_server_access(state, *cpp, state->helo_name, 3984 T_NS, state->helo_name, 3985 SMTPD_NAME_HELO, def_acl); 3986 forbid_whitelist(state, name, status, state->helo_name); 3987 } 3988 } else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) { 3989 if (state->helo_name) { 3990 status = check_server_access(state, *cpp, state->helo_name, 3991 T_MX, state->helo_name, 3992 SMTPD_NAME_HELO, def_acl); 3993 forbid_whitelist(state, name, status, state->helo_name); 3994 } 3995 } else if (strcasecmp(name, REJECT_NON_FQDN_HELO_HOSTNAME) == 0 3996 || strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) { 3997 if (state->helo_name) { 3998 if (*state->helo_name != '[') 3999 status = reject_non_fqdn_hostname(state, state->helo_name, 4000 state->helo_name, SMTPD_NAME_HELO); 4001 else 4002 status = reject_invalid_hostaddr(state, state->helo_name, 4003 state->helo_name, SMTPD_NAME_HELO); 4004 } 4005 } else if (strcasecmp(name, REJECT_RHSBL_HELO) == 0) { 4006 if (cpp[1] == 0) 4007 msg_warn("restriction %s requires domain name argument", 4008 name); 4009 else { 4010 cpp += 1; 4011 if (state->helo_name) 4012 status = reject_rbl_domain(state, *cpp, state->helo_name, 4013 SMTPD_NAME_HELO); 4014 } 4015 } 4016 4017 /* 4018 * Sender mail address restrictions. 4019 */ 4020 else if (is_map_command(state, name, CHECK_SENDER_ACL, &cpp)) { 4021 if (state->sender && *state->sender) 4022 status = check_mail_access(state, *cpp, state->sender, 4023 &found, state->sender, 4024 SMTPD_NAME_SENDER, def_acl); 4025 if (state->sender && !*state->sender) 4026 status = check_access(state, *cpp, var_smtpd_null_key, FULL, 4027 &found, state->sender, 4028 SMTPD_NAME_SENDER, def_acl); 4029 } else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) { 4030 if (state->sender && *state->sender) 4031 status = reject_unknown_address(state, state->sender, 4032 state->sender, SMTPD_NAME_SENDER); 4033 } else if (strcasecmp(name, REJECT_UNKNOWN_SENDDOM) == 0) { 4034 if (state->sender && *state->sender) 4035 status = reject_unknown_address(state, state->sender, 4036 state->sender, SMTPD_NAME_SENDER); 4037 } else if (strcasecmp(name, REJECT_UNVERIFIED_SENDER) == 0) { 4038 if (state->sender && *state->sender) 4039 status = reject_unverified_address(state, state->sender, 4040 state->sender, SMTPD_NAME_SENDER, 4041 var_unv_from_dcode, var_unv_from_rcode, 4042 unv_from_tf_act, 4043 var_unv_from_why); 4044 } else if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) { 4045 if (state->sender && *state->sender) 4046 status = reject_non_fqdn_address(state, state->sender, 4047 state->sender, SMTPD_NAME_SENDER); 4048 } else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) { 4049#ifdef USE_SASL_AUTH 4050 if (var_smtpd_sasl_enable) { 4051 if (state->sender && *state->sender) 4052 status = reject_auth_sender_login_mismatch(state, 4053 state->sender, FORBID_UNKNOWN_SENDER); 4054 } else 4055#endif 4056 msg_warn("restriction `%s' ignored: no SASL support", name); 4057 } else if (strcasecmp(name, REJECT_KNOWN_SENDER_LOGIN_MISMATCH) == 0) { 4058#ifdef USE_SASL_AUTH 4059 if (var_smtpd_sasl_enable) { 4060 if (state->sender && *state->sender) { 4061 if (state->sasl_username) 4062 status = reject_auth_sender_login_mismatch(state, 4063 state->sender, ALLOW_UNKNOWN_SENDER); 4064 else 4065 status = reject_unauth_sender_login_mismatch(state, state->sender); 4066 } 4067 } else 4068#endif 4069 msg_warn("restriction `%s' ignored: no SASL support", name); 4070 } else if (strcasecmp(name, REJECT_UNAUTH_SENDER_LOGIN_MISMATCH) == 0) { 4071#ifdef USE_SASL_AUTH 4072 if (var_smtpd_sasl_enable) { 4073 if (state->sender && *state->sender) 4074 status = reject_unauth_sender_login_mismatch(state, state->sender); 4075 } else 4076#endif 4077 msg_warn("restriction `%s' ignored: no SASL support", name); 4078 } else if (is_map_command(state, name, CHECK_SENDER_NS_ACL, &cpp)) { 4079 if (state->sender && *state->sender) { 4080 status = check_server_access(state, *cpp, state->sender, 4081 T_NS, state->sender, 4082 SMTPD_NAME_SENDER, def_acl); 4083 forbid_whitelist(state, name, status, state->sender); 4084 } 4085 } else if (is_map_command(state, name, CHECK_SENDER_MX_ACL, &cpp)) { 4086 if (state->sender && *state->sender) { 4087 status = check_server_access(state, *cpp, state->sender, 4088 T_MX, state->sender, 4089 SMTPD_NAME_SENDER, def_acl); 4090 forbid_whitelist(state, name, status, state->sender); 4091 } 4092 } else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) { 4093 if (cpp[1] == 0) 4094 msg_warn("restriction %s requires domain name argument", name); 4095 else { 4096 cpp += 1; 4097 if (state->sender && *state->sender) 4098 status = reject_rbl_domain(state, *cpp, state->sender, 4099 SMTPD_NAME_SENDER); 4100 } 4101 } else if (strcasecmp(name, REJECT_UNLISTED_SENDER) == 0) { 4102 if (state->sender && *state->sender) 4103 status = check_sender_rcpt_maps(state, state->sender); 4104 } 4105 4106 /* 4107 * Recipient mail address restrictions. 4108 */ 4109 else if (is_map_command(state, name, CHECK_RECIP_ACL, &cpp)) { 4110 if (state->recipient) 4111 status = check_mail_access(state, *cpp, state->recipient, 4112 &found, state->recipient, 4113 SMTPD_NAME_RECIPIENT, def_acl); 4114 } else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) { 4115 if (state->recipient) { 4116 status = permit_mx_backup(state, state->recipient, 4117 state->recipient, SMTPD_NAME_RECIPIENT); 4118 if (status == SMTPD_CHECK_OK) 4119 status = smtpd_acl_permit(state, name, SMTPD_NAME_RECIPIENT, 4120 state->recipient, NO_PRINT_ARGS); 4121 } 4122 } else if (strcasecmp(name, PERMIT_AUTH_DEST) == 0) { 4123 if (state->recipient) { 4124 status = permit_auth_destination(state, state->recipient); 4125 if (status == SMTPD_CHECK_OK) 4126 status = smtpd_acl_permit(state, name, SMTPD_NAME_RECIPIENT, 4127 state->recipient, NO_PRINT_ARGS); 4128 } 4129 } else if (strcasecmp(name, REJECT_UNAUTH_DEST) == 0) { 4130 if (state->recipient) 4131 status = reject_unauth_destination(state, state->recipient, 4132 var_relay_code, "5.7.1"); 4133 } else if (strcasecmp(name, DEFER_UNAUTH_DEST) == 0) { 4134 if (state->recipient) 4135 status = reject_unauth_destination(state, state->recipient, 4136 var_relay_code - 100, "4.7.1"); 4137 } else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) { 4138 if (state->recipient) 4139 status = check_relay_domains(state, state->recipient, 4140 state->recipient, SMTPD_NAME_RECIPIENT); 4141 if (status == SMTPD_CHECK_OK) 4142 status = smtpd_acl_permit(state, name, SMTPD_NAME_RECIPIENT, 4143 state->recipient, NO_PRINT_ARGS); 4144 if (cpp[1] != 0 && state->warn_if_reject == 0) 4145 msg_warn("restriction `%s' after `%s' is ignored", 4146 cpp[1], CHECK_RELAY_DOMAINS); 4147 } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) { 4148#ifdef USE_SASL_AUTH 4149 if (smtpd_sasl_is_active(state)) { 4150 status = permit_sasl_auth(state, 4151 SMTPD_CHECK_OK, SMTPD_CHECK_DUNNO); 4152 if (status == SMTPD_CHECK_OK) 4153 status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT, 4154 state->namaddr, NO_PRINT_ARGS); 4155 } 4156#endif 4157 } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) { 4158 status = permit_tls_clientcerts(state, 1); 4159 if (status == SMTPD_CHECK_OK) 4160 status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT, 4161 state->namaddr, NO_PRINT_ARGS); 4162 } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) { 4163 status = permit_tls_clientcerts(state, 0); 4164 if (status == SMTPD_CHECK_OK) 4165 status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT, 4166 state->namaddr, NO_PRINT_ARGS); 4167 } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) { 4168 if (state->recipient) 4169 status = reject_unknown_address(state, state->recipient, 4170 state->recipient, SMTPD_NAME_RECIPIENT); 4171 } else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) { 4172 if (state->recipient) 4173 status = reject_non_fqdn_address(state, state->recipient, 4174 state->recipient, SMTPD_NAME_RECIPIENT); 4175 } else if (is_map_command(state, name, CHECK_RECIP_NS_ACL, &cpp)) { 4176 if (state->recipient && *state->recipient) { 4177 status = check_server_access(state, *cpp, state->recipient, 4178 T_NS, state->recipient, 4179 SMTPD_NAME_RECIPIENT, def_acl); 4180 forbid_whitelist(state, name, status, state->recipient); 4181 } 4182 } else if (is_map_command(state, name, CHECK_RECIP_MX_ACL, &cpp)) { 4183 if (state->recipient && *state->recipient) { 4184 status = check_server_access(state, *cpp, state->recipient, 4185 T_MX, state->recipient, 4186 SMTPD_NAME_RECIPIENT, def_acl); 4187 forbid_whitelist(state, name, status, state->recipient); 4188 } 4189 } else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) { 4190 if (cpp[1] == 0) 4191 msg_warn("restriction %s requires domain name argument", name); 4192 else { 4193 cpp += 1; 4194 if (state->recipient) 4195 status = reject_rbl_domain(state, *cpp, state->recipient, 4196 SMTPD_NAME_RECIPIENT); 4197 } 4198 } else if (strcasecmp(name, CHECK_RCPT_MAPS) == 0 4199 || strcasecmp(name, REJECT_UNLISTED_RCPT) == 0) { 4200 if (state->recipient && *state->recipient) 4201 status = check_recipient_rcpt_maps(state, state->recipient); 4202 } else if (strcasecmp(name, REJECT_MUL_RCPT_BOUNCE) == 0) { 4203 if (state->sender && *state->sender == 0 && state->rcpt_count 4204 > (strcmp(state->where, SMTPD_CMD_DATA) ? 0 : 1)) 4205 status = smtpd_check_reject(state, MAIL_ERROR_POLICY, 4206 var_mul_rcpt_code, "5.5.3", 4207 "<%s>: %s rejected: Multi-recipient bounce", 4208 reply_name, reply_class); 4209 } else if (strcasecmp(name, REJECT_UNVERIFIED_RECIP) == 0) { 4210 if (state->recipient && *state->recipient) 4211 status = reject_unverified_address(state, state->recipient, 4212 state->recipient, SMTPD_NAME_RECIPIENT, 4213 var_unv_rcpt_dcode, var_unv_rcpt_rcode, 4214 unv_rcpt_tf_act, 4215 var_unv_rcpt_why); 4216 } 4217 4218 /* 4219 * ETRN domain name restrictions. 4220 */ 4221 else if (is_map_command(state, name, CHECK_ETRN_ACL, &cpp)) { 4222 if (state->etrn_name) 4223 status = check_domain_access(state, *cpp, state->etrn_name, 4224 FULL, &found, state->etrn_name, 4225 SMTPD_NAME_ETRN, def_acl); 4226 } 4227 4228 /* 4229 * User-defined restriction class. 4230 */ 4231 else if ((list = (ARGV *) htable_find(smtpd_rest_classes, name)) != 0) { 4232 status = generic_checks(state, list, reply_name, 4233 reply_class, def_acl); 4234 } 4235 4236 /* 4237 * Error: undefined restriction name. 4238 */ 4239 else { 4240 msg_warn("unknown smtpd restriction: \"%s\"", name); 4241 reject_server_error(state); 4242 } 4243 if (msg_verbose) 4244 msg_info("%s: name=%s status=%d", myname, name, status); 4245 4246 if (status < 0) { 4247 if (status == DICT_ERR_RETRY) 4248 reject_dict_retry(state, reply_name); 4249 else 4250 reject_server_error(state); 4251 } 4252 if (state->warn_if_reject >= state->recursion) 4253 state->warn_if_reject = 0; 4254 4255 if (status != 0) 4256 break; 4257 4258 if (state->defer_if_permit.active && state->defer_if_reject.active) 4259 break; 4260 } 4261 if (msg_verbose) 4262 msg_info(">>> END %s RESTRICTIONS <<<", reply_class); 4263 4264 state->recursion = saved_recursion; 4265 4266 /* In case the list terminated with one or more warn_if_mumble. */ 4267 if (state->warn_if_reject >= state->recursion) 4268 state->warn_if_reject = 0; 4269 4270 return (status); 4271} 4272 4273/* smtpd_check_addr - address sanity check */ 4274 4275int smtpd_check_addr(const char *addr) 4276{ 4277 const RESOLVE_REPLY *resolve_reply; 4278 const char *myname = "smtpd_check_addr"; 4279 4280 if (msg_verbose) 4281 msg_info("%s: addr=%s", myname, addr); 4282 4283 /* 4284 * Catch syntax errors early on if we can, but be prepared to re-compute 4285 * the result later when the cache fills up with lots of recipients, at 4286 * which time errors can still happen. 4287 */ 4288 if (addr == 0 || *addr == 0) 4289 return (0); 4290 resolve_reply = smtpd_resolve_addr(addr); 4291 if (resolve_reply->flags & RESOLVE_FLAG_ERROR) 4292 return (-1); 4293 return (0); 4294} 4295 4296/* smtpd_check_rewrite - choose address qualification context */ 4297 4298char *smtpd_check_rewrite(SMTPD_STATE *state) 4299{ 4300 const char *myname = "smtpd_check_rewrite"; 4301 int status; 4302 char **cpp; 4303 DICT *dict; 4304 char *name; 4305 4306 /* 4307 * We don't use generic_checks() because it produces results that aren't 4308 * applicable such as DEFER or REJECT. 4309 */ 4310 for (cpp = local_rewrite_clients->argv; *cpp != 0; cpp++) { 4311 if (msg_verbose) 4312 msg_info("%s: trying: %s", myname, *cpp); 4313 status = SMTPD_CHECK_DUNNO; 4314 if (strchr(name = *cpp, ':') != 0) { 4315 name = CHECK_ADDR_MAP; 4316 cpp -= 1; 4317 } 4318 if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) { 4319 status = permit_inet_interfaces(state); 4320 } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) { 4321 status = permit_mynetworks(state); 4322 } else if (is_map_command(state, name, CHECK_ADDR_MAP, &cpp)) { 4323 if ((dict = dict_handle(*cpp)) == 0) 4324 msg_panic("%s: dictionary not found: %s", myname, *cpp); 4325 if (dict_get(dict, state->addr) != 0) 4326 status = SMTPD_CHECK_OK; 4327 else if (dict->error != 0) { 4328 msg_warn("%s: %s: lookup error", VAR_LOC_RWR_CLIENTS, *cpp); 4329 status = dict->error; 4330 } 4331 } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) { 4332#ifdef USE_SASL_AUTH 4333 if (smtpd_sasl_is_active(state)) 4334 status = permit_sasl_auth(state, SMTPD_CHECK_OK, 4335 SMTPD_CHECK_DUNNO); 4336#endif 4337 } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) { 4338 status = permit_tls_clientcerts(state, 1); 4339 } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) { 4340 status = permit_tls_clientcerts(state, 0); 4341 } else { 4342 msg_warn("parameter %s: invalid request: %s", 4343 VAR_LOC_RWR_CLIENTS, name); 4344 continue; 4345 } 4346 if (status < 0) { 4347 if (status == DICT_ERR_RETRY) { 4348 state->error_mask |= MAIL_ERROR_RESOURCE; 4349 log_whatsup(state, "reject", 4350 "451 4.3.0 Temporary lookup error"); 4351 return ("451 4.3.0 Temporary lookup error"); 4352 } else { 4353 state->error_mask |= MAIL_ERROR_SOFTWARE; 4354 log_whatsup(state, "reject", 4355 "451 4.3.5 Server configuration error"); 4356 return ("451 4.3.5 Server configuration error"); 4357 } 4358 } 4359 if (status == SMTPD_CHECK_OK) { 4360 state->rewrite_context = MAIL_ATTR_RWR_LOCAL; 4361 return (0); 4362 } 4363 } 4364 state->rewrite_context = MAIL_ATTR_RWR_REMOTE; 4365 return (0); 4366} 4367 4368/* smtpd_check_client - validate client name or address */ 4369 4370char *smtpd_check_client(SMTPD_STATE *state) 4371{ 4372 int status; 4373 4374 /* 4375 * Initialize. 4376 */ 4377 if (state->name == 0 || state->addr == 0) 4378 return (0); 4379 4380#define SMTPD_CHECK_RESET() { \ 4381 state->recursion = 0; \ 4382 state->warn_if_reject = 0; \ 4383 state->defer_if_reject.active = 0; \ 4384 } 4385 4386 /* 4387 * Reset the defer_if_permit flag. 4388 */ 4389 state->defer_if_permit.active = 0; 4390 4391 /* 4392 * Apply restrictions in the order as specified. 4393 */ 4394 SMTPD_CHECK_RESET(); 4395 status = setjmp(smtpd_check_buf); 4396 if (status == 0 && client_restrctions->argc) 4397 status = generic_checks(state, client_restrctions, state->namaddr, 4398 SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL); 4399 state->defer_if_permit_client = state->defer_if_permit.active; 4400 4401 return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4402} 4403 4404/* smtpd_check_helo - validate HELO hostname */ 4405 4406char *smtpd_check_helo(SMTPD_STATE *state, char *helohost) 4407{ 4408 int status; 4409 char *saved_helo; 4410 4411 /* 4412 * Initialize. 4413 */ 4414 if (helohost == 0) 4415 return (0); 4416 4417 /* 4418 * Minor kluge so that we can delegate work to the generic routine and so 4419 * that we can syslog the recipient with the reject messages. 4420 */ 4421#define SMTPD_CHECK_PUSH(backup, current, new) { \ 4422 backup = current; \ 4423 current = (new ? mystrdup(new) : 0); \ 4424 } 4425 4426#define SMTPD_CHECK_POP(current, backup) { \ 4427 if (current) myfree(current); \ 4428 current = backup; \ 4429 } 4430 4431 SMTPD_CHECK_PUSH(saved_helo, state->helo_name, helohost); 4432 4433#define SMTPD_CHECK_HELO_RETURN(x) { \ 4434 SMTPD_CHECK_POP(state->helo_name, saved_helo); \ 4435 return (x); \ 4436 } 4437 4438 /* 4439 * Restore the defer_if_permit flag to its value before HELO/EHLO, and do 4440 * not set the flag when it was already raised by a previous protocol 4441 * stage. 4442 */ 4443 state->defer_if_permit.active = state->defer_if_permit_client; 4444 4445 /* 4446 * Apply restrictions in the order as specified. 4447 */ 4448 SMTPD_CHECK_RESET(); 4449 status = setjmp(smtpd_check_buf); 4450 if (status == 0 && helo_restrctions->argc) 4451 status = generic_checks(state, helo_restrctions, state->helo_name, 4452 SMTPD_NAME_HELO, CHECK_HELO_ACL); 4453 state->defer_if_permit_helo = state->defer_if_permit.active; 4454 4455 SMTPD_CHECK_HELO_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4456} 4457 4458/* smtpd_check_mail - validate sender address, driver */ 4459 4460char *smtpd_check_mail(SMTPD_STATE *state, char *sender) 4461{ 4462 int status; 4463 char *saved_sender; 4464 4465 /* 4466 * Initialize. 4467 */ 4468 if (sender == 0) 4469 return (0); 4470 4471 /* 4472 * Minor kluge so that we can delegate work to the generic routine and so 4473 * that we can syslog the recipient with the reject messages. 4474 */ 4475 SMTPD_CHECK_PUSH(saved_sender, state->sender, sender); 4476 4477#define SMTPD_CHECK_MAIL_RETURN(x) { \ 4478 SMTPD_CHECK_POP(state->sender, saved_sender); \ 4479 return (x); \ 4480 } 4481 4482 /* 4483 * Restore the defer_if_permit flag to its value before MAIL FROM, and do 4484 * not set the flag when it was already raised by a previous protocol 4485 * stage. The client may skip the helo/ehlo. 4486 */ 4487 state->defer_if_permit.active = state->defer_if_permit_client 4488 | state->defer_if_permit_helo; 4489 state->sender_rcptmap_checked = 0; 4490 4491 /* 4492 * Apply restrictions in the order as specified. 4493 */ 4494 SMTPD_CHECK_RESET(); 4495 status = setjmp(smtpd_check_buf); 4496 if (status == 0 && mail_restrctions->argc) 4497 status = generic_checks(state, mail_restrctions, sender, 4498 SMTPD_NAME_SENDER, CHECK_SENDER_ACL); 4499 state->defer_if_permit_sender = state->defer_if_permit.active; 4500 4501 /* 4502 * If the "reject_unlisted_sender" restriction still needs to be applied, 4503 * validate the sender here. 4504 */ 4505 if (var_smtpd_rej_unl_from 4506 && status != SMTPD_CHECK_REJECT && state->sender_rcptmap_checked == 0 4507 && state->discard == 0 && *sender) 4508 status = check_sender_rcpt_maps(state, sender); 4509 4510 SMTPD_CHECK_MAIL_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4511} 4512 4513/* smtpd_check_rcpt - validate recipient address, driver */ 4514 4515char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) 4516{ 4517 int status; 4518 char *saved_recipient; 4519 char *err; 4520 ARGV *restrctions[2]; 4521 int n; 4522 4523 /* 4524 * Initialize. 4525 */ 4526 if (recipient == 0) 4527 return (0); 4528 4529 /* 4530 * XXX 2821: Section 3.6 requires that "postmaster" be accepted even when 4531 * specified without a fully qualified domain name. 4532 */ 4533 if (strcasecmp(recipient, "postmaster") == 0) 4534 return (0); 4535 4536 /* 4537 * Minor kluge so that we can delegate work to the generic routine and so 4538 * that we can syslog the recipient with the reject messages. 4539 */ 4540 SMTPD_CHECK_PUSH(saved_recipient, state->recipient, recipient); 4541 4542#define SMTPD_CHECK_RCPT_RETURN(x) { \ 4543 SMTPD_CHECK_POP(state->recipient, saved_recipient); \ 4544 return (x); \ 4545 } 4546 4547 /* 4548 * The "check_recipient_maps" restriction is relevant only when 4549 * responding to RCPT TO or VRFY. 4550 */ 4551 state->recipient_rcptmap_checked = 0; 4552 4553 /* 4554 * Apply delayed restrictions. 4555 */ 4556 if (var_smtpd_delay_reject) 4557 if ((err = smtpd_check_client(state)) != 0 4558 || (err = smtpd_check_helo(state, state->helo_name)) != 0 4559 || (err = smtpd_check_mail(state, state->sender)) != 0) 4560 SMTPD_CHECK_RCPT_RETURN(err); 4561 4562 /* 4563 * Restore the defer_if_permit flag to its value before RCPT TO, and do 4564 * not set the flag when it was already raised by a previous protocol 4565 * stage. 4566 */ 4567 state->defer_if_permit.active = state->defer_if_permit_sender; 4568 4569 /* 4570 * Apply restrictions in the order as specified. We allow relay 4571 * restrictions to be empty, for sites that require backwards 4572 * compatibility. 4573 */ 4574 SMTPD_CHECK_RESET(); 4575 restrctions[0] = relay_restrctions; 4576 restrctions[1] = rcpt_restrctions; 4577 for (n = 0; n < 2; n++) { 4578 status = setjmp(smtpd_check_buf); 4579 if (status == 0 && restrctions[n]->argc) 4580 status = generic_checks(state, restrctions[n], 4581 recipient, SMTPD_NAME_RECIPIENT, CHECK_RECIP_ACL); 4582 if (status == SMTPD_CHECK_REJECT) 4583 break; 4584 } 4585 4586 /* 4587 * Force permission into deferral when some earlier temporary error may 4588 * have prevented us from rejecting mail, and report the earlier problem. 4589 */ 4590 if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active) 4591 status = smtpd_check_reject(state, state->defer_if_permit.class, 4592 state->defer_if_permit.code, 4593 STR(state->defer_if_permit.dsn), 4594 "%s", STR(state->defer_if_permit.reason)); 4595 4596 /* 4597 * If the "reject_unlisted_recipient" restriction still needs to be 4598 * applied, validate the recipient here. 4599 */ 4600 if (var_smtpd_rej_unl_rcpt 4601 && status != SMTPD_CHECK_REJECT 4602 && state->recipient_rcptmap_checked == 0 4603 && state->discard == 0) 4604 status = check_recipient_rcpt_maps(state, recipient); 4605 4606 SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4607} 4608 4609/* smtpd_check_etrn - validate ETRN request */ 4610 4611char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) 4612{ 4613 int status; 4614 char *saved_etrn_name; 4615 char *err; 4616 4617 /* 4618 * Initialize. 4619 */ 4620 if (domain == 0) 4621 return (0); 4622 4623 /* 4624 * Minor kluge so that we can delegate work to the generic routine and so 4625 * that we can syslog the recipient with the reject messages. 4626 */ 4627 SMTPD_CHECK_PUSH(saved_etrn_name, state->etrn_name, domain); 4628 4629#define SMTPD_CHECK_ETRN_RETURN(x) { \ 4630 SMTPD_CHECK_POP(state->etrn_name, saved_etrn_name); \ 4631 return (x); \ 4632 } 4633 4634 /* 4635 * Apply delayed restrictions. 4636 */ 4637 if (var_smtpd_delay_reject) 4638 if ((err = smtpd_check_client(state)) != 0 4639 || (err = smtpd_check_helo(state, state->helo_name)) != 0) 4640 SMTPD_CHECK_ETRN_RETURN(err); 4641 4642 /* 4643 * Restore the defer_if_permit flag to its value before ETRN, and do not 4644 * set the flag when it was already raised by a previous protocol stage. 4645 * The client may skip the helo/ehlo. 4646 */ 4647 state->defer_if_permit.active = state->defer_if_permit_client 4648 | state->defer_if_permit_helo; 4649 4650 /* 4651 * Apply restrictions in the order as specified. 4652 */ 4653 SMTPD_CHECK_RESET(); 4654 status = setjmp(smtpd_check_buf); 4655 if (status == 0 && etrn_restrctions->argc) 4656 status = generic_checks(state, etrn_restrctions, domain, 4657 SMTPD_NAME_ETRN, CHECK_ETRN_ACL); 4658 4659 /* 4660 * Force permission into deferral when some earlier temporary error may 4661 * have prevented us from rejecting mail, and report the earlier problem. 4662 */ 4663 if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active) 4664 status = smtpd_check_reject(state, state->defer_if_permit.class, 4665 state->defer_if_permit.code, 4666 STR(state->defer_if_permit.dsn), 4667 "%s", STR(state->defer_if_permit.reason)); 4668 4669 SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4670} 4671 4672/* check_recipient_rcpt_maps - generic_checks() recipient table check */ 4673 4674static int check_recipient_rcpt_maps(SMTPD_STATE *state, const char *recipient) 4675{ 4676 4677 /* 4678 * Duplicate suppression. There's an implicit check_recipient_maps 4679 * restriction at the end of all recipient restrictions. 4680 */ 4681 if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT) 4682 return (0); 4683 if (state->recipient_rcptmap_checked == 1) 4684 return (0); 4685 if (state->warn_if_reject == 0) 4686 /* We really validate the recipient address. */ 4687 state->recipient_rcptmap_checked = 1; 4688 return (check_rcpt_maps(state, recipient, SMTPD_NAME_RECIPIENT)); 4689} 4690 4691/* check_sender_rcpt_maps - generic_checks() sender table check */ 4692 4693static int check_sender_rcpt_maps(SMTPD_STATE *state, const char *sender) 4694{ 4695 4696 /* 4697 * Duplicate suppression. There's an implicit check_sender_maps 4698 * restriction at the end of all sender restrictions. 4699 */ 4700 if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT) 4701 return (0); 4702 if (state->sender_rcptmap_checked == 1) 4703 return (0); 4704 if (state->warn_if_reject == 0) 4705 /* We really validate the sender address. */ 4706 state->sender_rcptmap_checked = 1; 4707 return (check_rcpt_maps(state, sender, SMTPD_NAME_SENDER)); 4708} 4709 4710/* check_rcpt_maps - generic_checks() interface for recipient table check */ 4711 4712static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient, 4713 const char *reply_class) 4714{ 4715 const RESOLVE_REPLY *reply; 4716 DSN_SPLIT dp; 4717 4718 if (msg_verbose) 4719 msg_info(">>> CHECKING RECIPIENT MAPS <<<"); 4720 4721 /* 4722 * Resolve the address. 4723 */ 4724 reply = smtpd_resolve_addr(recipient); 4725 if (reply->flags & RESOLVE_FLAG_FAIL) 4726 reject_dict_retry(state, recipient); 4727 4728 /* 4729 * Make complex expressions more readable? 4730 */ 4731#define MATCH(map, rcpt) \ 4732 check_mail_addr_find(state, recipient, map, rcpt, (char **) 0) 4733 4734#define NOMATCH(map, rcpt) (MATCH(map, rcpt) == 0) 4735 4736 /* 4737 * XXX We assume the recipient address is OK if it matches a canonical 4738 * map or virtual alias map. Eventually, the address resolver should give 4739 * us the final resolved recipient address, and the SMTP server should 4740 * write the final resolved recipient address to the output record 4741 * stream. See also the next comment block on recipients in virtual alias 4742 * domains. 4743 */ 4744 if (MATCH(rcpt_canon_maps, CONST_STR(reply->recipient)) 4745 || MATCH(canonical_maps, CONST_STR(reply->recipient)) 4746 || MATCH(virt_alias_maps, CONST_STR(reply->recipient))) 4747 return (0); 4748 4749 /* 4750 * At this point, anything that resolves to the error mailer is known to 4751 * be undeliverable. 4752 * 4753 * XXX Until the address resolver does final address resolution, known and 4754 * unknown recipients in virtual alias domains will both resolve to 4755 * "error:user unknown". 4756 */ 4757 if (strcmp(STR(reply->transport), MAIL_SERVICE_ERROR) == 0) { 4758 dsn_split(&dp, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 4759 "5.1.0" : "5.1.1", STR(reply->nexthop)); 4760 return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, 4761 (reply->flags & RESOLVE_CLASS_ALIAS) ? 4762 var_virt_alias_code : 550, 4763 smtpd_dsn_fix(DSN_STATUS(dp.dsn), 4764 reply_class), 4765 "<%s>: %s rejected: %s", 4766 recipient, reply_class, 4767 dp.text)); 4768 } 4769 4770 /* 4771 * Search the recipient lookup tables of the respective address class. 4772 * 4773 * XXX Use the less expensive maps_find() (built-in case folding) instead of 4774 * the baroque mail_addr_find(). But then we have to strip the domain and 4775 * deal with address extensions ourselves. 4776 * 4777 * XXX But that would break sites that use the virtual delivery agent for 4778 * local delivery, because the virtual delivery agent requires 4779 * user@domain style addresses in its user database. 4780 */ 4781#define MATCH_LEFT(l, r, n) (strncasecmp((l), (r), (n)) == 0 && (r)[n] == '@') 4782 4783 switch (reply->flags & RESOLVE_CLASS_MASK) { 4784 4785 /* 4786 * Reject mail to unknown addresses in local domains (domains that 4787 * match $mydestination or ${proxy,inet}_interfaces). 4788 */ 4789 case RESOLVE_CLASS_LOCAL: 4790 if (*var_local_rcpt_maps 4791 /* Generated by bounce, absorbed by qmgr. */ 4792 && !MATCH_LEFT(var_double_bounce_sender, CONST_STR(reply->recipient), 4793 strlen(var_double_bounce_sender)) 4794 /* Absorbed by qmgr. */ 4795 && !MATCH_LEFT(MAIL_ADDR_POSTMASTER, CONST_STR(reply->recipient), 4796 strlen(MAIL_ADDR_POSTMASTER)) 4797 /* Generated by bounce. */ 4798 && !MATCH_LEFT(MAIL_ADDR_MAIL_DAEMON, CONST_STR(reply->recipient), 4799 strlen(MAIL_ADDR_MAIL_DAEMON)) 4800 && NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) 4801 return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, 4802 var_local_rcpt_code, 4803 strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 4804 "5.1.0" : "5.1.1", 4805 "<%s>: %s rejected: User unknown%s", 4806 recipient, reply_class, 4807 var_show_unk_rcpt_table ? 4808 " in local recipient table" : "")); 4809 break; 4810 4811 /* 4812 * Reject mail to unknown addresses in virtual mailbox domains. 4813 */ 4814 case RESOLVE_CLASS_VIRTUAL: 4815 if (*var_virt_mailbox_maps 4816 && NOMATCH(virt_mailbox_maps, CONST_STR(reply->recipient))) 4817 return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, 4818 var_virt_mailbox_code, 4819 strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 4820 "5.1.0" : "5.1.1", 4821 "<%s>: %s rejected: User unknown%s", 4822 recipient, reply_class, 4823 var_show_unk_rcpt_table ? 4824 " in virtual mailbox table" : "")); 4825 break; 4826 4827 /* 4828 * Reject mail to unknown addresses in relay domains. 4829 */ 4830 case RESOLVE_CLASS_RELAY: 4831 if (*var_relay_rcpt_maps 4832 && NOMATCH(relay_rcpt_maps, CONST_STR(reply->recipient))) 4833 return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, 4834 var_relay_rcpt_code, 4835 strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? 4836 "5.1.0" : "5.1.1", 4837 "<%s>: %s rejected: User unknown%s", 4838 recipient, reply_class, 4839 var_show_unk_rcpt_table ? 4840 " in relay recipient table" : "")); 4841 break; 4842 } 4843 4844 /* 4845 * Accept all other addresses - including addresses that passed the above 4846 * tests because of some table lookup problem. 4847 */ 4848 return (0); 4849} 4850 4851/* smtpd_check_size - check optional SIZE parameter value */ 4852 4853char *smtpd_check_size(SMTPD_STATE *state, off_t size) 4854{ 4855 int status; 4856 4857 /* 4858 * Return here in case of serious trouble. 4859 */ 4860 SMTPD_CHECK_RESET(); 4861 if ((status = setjmp(smtpd_check_buf)) != 0) 4862 return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4863 4864 /* 4865 * Check against file size limit. 4866 */ 4867 if (var_message_limit > 0 && size > var_message_limit) { 4868 (void) smtpd_check_reject(state, MAIL_ERROR_POLICY, 4869 552, "5.3.4", 4870 "Message size exceeds fixed limit"); 4871 return (STR(error_text)); 4872 } 4873 return (0); 4874} 4875 4876/* smtpd_check_queue - check queue space */ 4877 4878char *smtpd_check_queue(SMTPD_STATE *state) 4879{ 4880 const char *myname = "smtpd_check_queue"; 4881 struct fsspace fsbuf; 4882 int status; 4883 4884 /* 4885 * Return here in case of serious trouble. 4886 */ 4887 SMTPD_CHECK_RESET(); 4888 if ((status = setjmp(smtpd_check_buf)) != 0) 4889 return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4890 4891 /* 4892 * Avoid overflow/underflow when comparing message size against available 4893 * space. 4894 */ 4895#define BLOCKS(x) ((x) / fsbuf.block_size) 4896 4897 fsspace(".", &fsbuf); 4898 if (msg_verbose) 4899 msg_info("%s: blocks %lu avail %lu min_free %lu msg_size_limit %lu", 4900 myname, 4901 (unsigned long) fsbuf.block_size, 4902 (unsigned long) fsbuf.block_free, 4903 (unsigned long) var_queue_minfree, 4904 (unsigned long) var_message_limit); 4905 if (BLOCKS(var_queue_minfree) >= fsbuf.block_free 4906 || BLOCKS(var_message_limit) >= fsbuf.block_free / smtpd_space_multf) { 4907 (void) smtpd_check_reject(state, MAIL_ERROR_RESOURCE, 4908 452, "4.3.1", 4909 "Insufficient system storage"); 4910 msg_warn("not enough free space in mail queue: %lu bytes < " 4911 "%g*message size limit", 4912 (unsigned long) fsbuf.block_free * fsbuf.block_size, 4913 smtpd_space_multf); 4914 return (STR(error_text)); 4915 } 4916 return (0); 4917} 4918 4919/* smtpd_check_data - check DATA command */ 4920 4921char *smtpd_check_data(SMTPD_STATE *state) 4922{ 4923 int status; 4924 char *NOCLOBBER saved_recipient; 4925 4926 /* 4927 * Minor kluge so that we can delegate work to the generic routine. We 4928 * provide no recipient information in the case of multiple recipients, 4929 * This restriction applies to all recipients alike, and logging only one 4930 * of them would be misleading. 4931 */ 4932 if (state->rcpt_count > 1) { 4933 saved_recipient = state->recipient; 4934 state->recipient = 0; 4935 } 4936 4937 /* 4938 * Reset the defer_if_permit flag. This is necessary when some recipients 4939 * were accepted but the last one was rejected. 4940 */ 4941 state->defer_if_permit.active = 0; 4942 4943 /* 4944 * Apply restrictions in the order as specified. 4945 * 4946 * XXX We cannot specify a default target for a bare access map. 4947 */ 4948 SMTPD_CHECK_RESET(); 4949 status = setjmp(smtpd_check_buf); 4950 if (status == 0 && data_restrctions->argc) 4951 status = generic_checks(state, data_restrctions, 4952 SMTPD_CMD_DATA, SMTPD_NAME_DATA, NO_DEF_ACL); 4953 4954 /* 4955 * Force permission into deferral when some earlier temporary error may 4956 * have prevented us from rejecting mail, and report the earlier problem. 4957 */ 4958 if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active) 4959 status = smtpd_check_reject(state, state->defer_if_permit.class, 4960 state->defer_if_permit.code, 4961 STR(state->defer_if_permit.dsn), 4962 "%s", STR(state->defer_if_permit.reason)); 4963 4964 if (state->rcpt_count > 1) 4965 state->recipient = saved_recipient; 4966 4967 return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 4968} 4969 4970/* smtpd_check_eod - check end-of-data command */ 4971 4972char *smtpd_check_eod(SMTPD_STATE *state) 4973{ 4974 int status; 4975 char *NOCLOBBER saved_recipient; 4976 4977 /* 4978 * Minor kluge so that we can delegate work to the generic routine. We 4979 * provide no recipient information in the case of multiple recipients, 4980 * This restriction applies to all recipients alike, and logging only one 4981 * of them would be misleading. 4982 */ 4983 if (state->rcpt_count > 1) { 4984 saved_recipient = state->recipient; 4985 state->recipient = 0; 4986 } 4987 4988 /* 4989 * Reset the defer_if_permit flag. This is necessary when some recipients 4990 * were accepted but the last one was rejected. 4991 */ 4992 state->defer_if_permit.active = 0; 4993 4994 /* 4995 * Apply restrictions in the order as specified. 4996 * 4997 * XXX We cannot specify a default target for a bare access map. 4998 */ 4999 SMTPD_CHECK_RESET(); 5000 status = setjmp(smtpd_check_buf); 5001 if (status == 0 && eod_restrictions->argc) 5002 status = generic_checks(state, eod_restrictions, 5003 SMTPD_CMD_EOD, SMTPD_NAME_EOD, NO_DEF_ACL); 5004 5005 /* 5006 * Force permission into deferral when some earlier temporary error may 5007 * have prevented us from rejecting mail, and report the earlier problem. 5008 */ 5009 if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active) 5010 status = smtpd_check_reject(state, state->defer_if_permit.class, 5011 state->defer_if_permit.code, 5012 STR(state->defer_if_permit.dsn), 5013 "%s", STR(state->defer_if_permit.reason)); 5014 5015 if (state->rcpt_count > 1) 5016 state->recipient = saved_recipient; 5017 5018 return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); 5019} 5020 5021#ifdef TEST 5022 5023 /* 5024 * Test program to try out all these restrictions without having to go live. 5025 * This is not entirely stand-alone, as it requires access to the Postfix 5026 * rewrite/resolve service. This is just for testing code, not for debugging 5027 * configuration files. 5028 */ 5029#include <stdlib.h> 5030 5031#include <msg_vstream.h> 5032#include <vstring_vstream.h> 5033 5034#include <mail_conf.h> 5035#include <rewrite_clnt.h> 5036 5037#include <smtpd_chat.h> 5038 5039int smtpd_input_transp_mask; 5040 5041 /* 5042 * Dummies. These are never set. 5043 */ 5044char *var_client_checks = ""; 5045char *var_helo_checks = ""; 5046char *var_mail_checks = ""; 5047char *var_relay_checks = ""; 5048char *var_rcpt_checks = ""; 5049char *var_etrn_checks = ""; 5050char *var_data_checks = ""; 5051char *var_eod_checks = ""; 5052char *var_relay_domains = ""; 5053char *var_smtpd_uproxy_proto = ""; 5054int var_smtpd_uproxy_tmout = 0; 5055 5056#ifdef USE_TLS 5057char *var_relay_ccerts = ""; 5058 5059#endif 5060char *var_mynetworks = ""; 5061char *var_notify_classes = ""; 5062 5063 /* 5064 * String-valued configuration parameters. 5065 */ 5066char *var_maps_rbl_domains; 5067char *var_myorigin; 5068char *var_mydest; 5069char *var_inet_interfaces; 5070char *var_proxy_interfaces; 5071char *var_rcpt_delim; 5072char *var_rest_classes; 5073char *var_alias_maps; 5074char *var_rcpt_canon_maps; 5075char *var_canonical_maps; 5076char *var_virt_alias_maps; 5077char *var_virt_alias_doms; 5078char *var_virt_mailbox_maps; 5079char *var_virt_mailbox_doms; 5080char *var_local_rcpt_maps; 5081char *var_perm_mx_networks; 5082char *var_par_dom_match; 5083char *var_smtpd_null_key; 5084char *var_smtpd_snd_auth_maps; 5085char *var_double_bounce_sender; 5086char *var_rbl_reply_maps; 5087char *var_smtpd_exp_filter; 5088char *var_def_rbl_reply; 5089char *var_relay_rcpt_maps; 5090char *var_verify_sender; 5091char *var_smtpd_sasl_opts; 5092char *var_local_rwr_clients; 5093char *var_smtpd_relay_ccerts; 5094char *var_unv_from_why; 5095char *var_unv_rcpt_why; 5096char *var_stress; 5097char *var_unk_name_tf_act; 5098char *var_unk_addr_tf_act; 5099char *var_unv_rcpt_tf_act; 5100char *var_unv_from_tf_act; 5101char *var_smtpd_acl_perm_log; 5102 5103typedef struct { 5104 char *name; 5105 char *defval; 5106 char **target; 5107} STRING_TABLE; 5108 5109#undef DEF_VIRT_ALIAS_MAPS 5110#define DEF_VIRT_ALIAS_MAPS "" 5111 5112#undef DEF_LOCAL_RCPT_MAPS 5113#define DEF_LOCAL_RCPT_MAPS "" 5114 5115static const STRING_TABLE string_table[] = { 5116 VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 5117 VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin, 5118 VAR_MYDEST, DEF_MYDEST, &var_mydest, 5119 VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 5120 VAR_PROXY_INTERFACES, DEF_PROXY_INTERFACES, &var_proxy_interfaces, 5121 VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 5122 VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 5123 VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, 5124 VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 5125 VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 5126 VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 5127 VAR_VIRT_ALIAS_DOMS, DEF_VIRT_ALIAS_DOMS, &var_virt_alias_doms, 5128 VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 5129 VAR_VIRT_MAILBOX_DOMS, DEF_VIRT_MAILBOX_DOMS, &var_virt_mailbox_doms, 5130 VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 5131 VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 5132 VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 5133 VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 5134 VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 5135 VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender, 5136 VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps, 5137 VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 5138 VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply, 5139 VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 5140 VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender, 5141 VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, 5142 VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts, 5143 VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 5144 VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 5145 VAR_UNV_FROM_WHY, DEF_UNV_FROM_WHY, &var_unv_from_why, 5146 VAR_UNV_RCPT_WHY, DEF_UNV_RCPT_WHY, &var_unv_rcpt_why, 5147 VAR_STRESS, DEF_STRESS, &var_stress, 5148 /* XXX Can't use ``$name'' type default values below. */ 5149 VAR_UNK_NAME_TF_ACT, DEF_REJECT_TMPF_ACT, &var_unk_name_tf_act, 5150 VAR_UNK_ADDR_TF_ACT, DEF_REJECT_TMPF_ACT, &var_unk_addr_tf_act, 5151 VAR_UNV_RCPT_TF_ACT, DEF_REJECT_TMPF_ACT, &var_unv_rcpt_tf_act, 5152 VAR_UNV_FROM_TF_ACT, DEF_REJECT_TMPF_ACT, &var_unv_from_tf_act, 5153 /* XXX Can't use ``$name'' type default values above. */ 5154 VAR_SMTPD_ACL_PERM_LOG, DEF_SMTPD_ACL_PERM_LOG, &var_smtpd_acl_perm_log, 5155 0, 5156}; 5157 5158/* string_init - initialize string parameters */ 5159 5160static void string_init(void) 5161{ 5162 const STRING_TABLE *sp; 5163 5164 for (sp = string_table; sp->name; sp++) 5165 sp->target[0] = mystrdup(sp->defval); 5166} 5167 5168/* string_update - update string parameter */ 5169 5170static int string_update(char **argv) 5171{ 5172 const STRING_TABLE *sp; 5173 5174 for (sp = string_table; sp->name; sp++) { 5175 if (strcasecmp(argv[0], sp->name) == 0) { 5176 myfree(sp->target[0]); 5177 sp->target[0] = mystrdup(argv[1]); 5178 return (1); 5179 } 5180 } 5181 return (0); 5182} 5183 5184 /* 5185 * Integer parameters. 5186 */ 5187int var_queue_minfree; /* XXX use off_t */ 5188typedef struct { 5189 char *name; 5190 int defval; 5191 int *target; 5192} INT_TABLE; 5193 5194int var_unk_client_code; 5195int var_bad_name_code; 5196int var_unk_name_code; 5197int var_unk_addr_code; 5198int var_relay_code; 5199int var_maps_rbl_code; 5200int var_map_reject_code; 5201int var_map_defer_code; 5202int var_reject_code; 5203int var_defer_code; 5204int var_non_fqdn_code; 5205int var_smtpd_delay_reject; 5206int var_allow_untrust_route; 5207int var_mul_rcpt_code; 5208int var_unv_from_rcode; 5209int var_unv_from_dcode; 5210int var_unv_rcpt_rcode; 5211int var_unv_rcpt_dcode; 5212int var_local_rcpt_code; 5213int var_relay_rcpt_code; 5214int var_virt_mailbox_code; 5215int var_virt_alias_code; 5216int var_show_unk_rcpt_table; 5217int var_verify_poll_count; 5218int var_verify_poll_delay; 5219int var_smtpd_policy_tmout; 5220int var_smtpd_policy_idle; 5221int var_smtpd_policy_ttl; 5222int var_smtpd_rej_unl_from; 5223int var_smtpd_rej_unl_rcpt; 5224int var_plaintext_code; 5225bool var_smtpd_peername_lookup; 5226bool var_smtpd_client_port_log; 5227 5228static const INT_TABLE int_table[] = { 5229 "msg_verbose", 0, &msg_verbose, 5230 VAR_UNK_CLIENT_CODE, DEF_UNK_CLIENT_CODE, &var_unk_client_code, 5231 VAR_BAD_NAME_CODE, DEF_BAD_NAME_CODE, &var_bad_name_code, 5232 VAR_UNK_NAME_CODE, DEF_UNK_NAME_CODE, &var_unk_name_code, 5233 VAR_UNK_ADDR_CODE, DEF_UNK_ADDR_CODE, &var_unk_addr_code, 5234 VAR_RELAY_CODE, DEF_RELAY_CODE, &var_relay_code, 5235 VAR_MAPS_RBL_CODE, DEF_MAPS_RBL_CODE, &var_maps_rbl_code, 5236 VAR_MAP_REJECT_CODE, DEF_MAP_REJECT_CODE, &var_map_reject_code, 5237 VAR_MAP_DEFER_CODE, DEF_MAP_DEFER_CODE, &var_map_defer_code, 5238 VAR_REJECT_CODE, DEF_REJECT_CODE, &var_reject_code, 5239 VAR_DEFER_CODE, DEF_DEFER_CODE, &var_defer_code, 5240 VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 5241 VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject, 5242 VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route, 5243 VAR_MUL_RCPT_CODE, DEF_MUL_RCPT_CODE, &var_mul_rcpt_code, 5244 VAR_UNV_FROM_RCODE, DEF_UNV_FROM_RCODE, &var_unv_from_rcode, 5245 VAR_UNV_FROM_DCODE, DEF_UNV_FROM_DCODE, &var_unv_from_dcode, 5246 VAR_UNV_RCPT_RCODE, DEF_UNV_RCPT_RCODE, &var_unv_rcpt_rcode, 5247 VAR_UNV_RCPT_DCODE, DEF_UNV_RCPT_DCODE, &var_unv_rcpt_dcode, 5248 VAR_LOCAL_RCPT_CODE, DEF_LOCAL_RCPT_CODE, &var_local_rcpt_code, 5249 VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 5250 VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, 5251 VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 5252 VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table, 5253 VAR_VERIFY_POLL_COUNT, 3, &var_verify_poll_count, 5254 VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from, 5255 VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt, 5256 VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 5257 VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup, 5258 VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log, 5259 0, 5260}; 5261 5262/* int_init - initialize int parameters */ 5263 5264static void int_init(void) 5265{ 5266 const INT_TABLE *sp; 5267 5268 for (sp = int_table; sp->name; sp++) 5269 sp->target[0] = sp->defval; 5270} 5271 5272/* int_update - update int parameter */ 5273 5274static int int_update(char **argv) 5275{ 5276 const INT_TABLE *ip; 5277 5278 for (ip = int_table; ip->name; ip++) { 5279 if (strcasecmp(argv[0], ip->name) == 0) { 5280 if (!ISDIGIT(*argv[1])) 5281 msg_fatal("bad number: %s %s", ip->name, argv[1]); 5282 ip->target[0] = atoi(argv[1]); 5283 return (1); 5284 } 5285 } 5286 return (0); 5287} 5288 5289 /* 5290 * Restrictions. 5291 */ 5292typedef struct { 5293 char *name; 5294 ARGV **target; 5295} REST_TABLE; 5296 5297static const REST_TABLE rest_table[] = { 5298 "client_restrictions", &client_restrctions, 5299 "helo_restrictions", &helo_restrctions, 5300 "sender_restrictions", &mail_restrctions, 5301 "relay_restrictions", &relay_restrctions, 5302 "recipient_restrictions", &rcpt_restrctions, 5303 "etrn_restrictions", &etrn_restrctions, 5304 0, 5305}; 5306 5307/* rest_update - update restriction */ 5308 5309static int rest_update(char **argv) 5310{ 5311 const REST_TABLE *rp; 5312 5313 for (rp = rest_table; rp->name; rp++) { 5314 if (strcasecmp(rp->name, argv[0]) == 0) { 5315 argv_free(rp->target[0]); 5316 rp->target[0] = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, argv[1]); 5317 return (1); 5318 } 5319 } 5320 return (0); 5321} 5322 5323/* rest_class - (re)define a restriction class */ 5324 5325static void rest_class(char *class) 5326{ 5327 char *cp = class; 5328 char *name; 5329 HTABLE_INFO *entry; 5330 5331 if (smtpd_rest_classes == 0) 5332 smtpd_rest_classes = htable_create(1); 5333 5334 if ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) == 0) 5335 msg_panic("rest_class: null class name"); 5336 if ((entry = htable_locate(smtpd_rest_classes, name)) != 0) 5337 argv_free((ARGV *) entry->value); 5338 else 5339 entry = htable_enter(smtpd_rest_classes, name, (char *) 0); 5340 entry->value = (char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, cp); 5341} 5342 5343/* resolve_clnt_init - initialize reply */ 5344 5345void resolve_clnt_init(RESOLVE_REPLY *reply) 5346{ 5347 reply->flags = 0; 5348 reply->transport = vstring_alloc(100); 5349 reply->nexthop = vstring_alloc(100); 5350 reply->recipient = vstring_alloc(100); 5351} 5352 5353void resolve_clnt_free(RESOLVE_REPLY *reply) 5354{ 5355 vstring_free(reply->transport); 5356 vstring_free(reply->nexthop); 5357 vstring_free(reply->recipient); 5358} 5359 5360bool var_smtpd_sasl_enable = 0; 5361 5362#ifdef USE_SASL_AUTH 5363 5364/* smtpd_sasl_activate - stub */ 5365 5366void smtpd_sasl_activate(SMTPD_STATE *state, const char *opts_name, 5367 const char *opts_var) 5368{ 5369 msg_panic("smtpd_sasl_activate was called"); 5370} 5371 5372/* smtpd_sasl_deactivate - stub */ 5373 5374void smtpd_sasl_deactivate(SMTPD_STATE *state) 5375{ 5376 msg_panic("smtpd_sasl_deactivate was called"); 5377} 5378 5379/* permit_sasl_auth - stub */ 5380 5381int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot) 5382{ 5383 return (ifnot); 5384} 5385 5386/* smtpd_sasl_state_init - the real deal */ 5387 5388void smtpd_sasl_state_init(SMTPD_STATE *state) 5389{ 5390 state->sasl_username = 0; 5391 state->sasl_method = 0; 5392 state->sasl_sender = 0; 5393} 5394 5395#endif 5396 5397/* verify_clnt_query - stub */ 5398 5399int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why) 5400{ 5401 *addr_status = DEL_RCPT_STAT_OK; 5402 return (VRFY_STAT_OK); 5403} 5404 5405/* rewrite_clnt_internal - stub */ 5406 5407VSTRING *rewrite_clnt_internal(const char *context, const char *addr, 5408 VSTRING *result) 5409{ 5410 if (addr == STR(result)) 5411 msg_panic("rewrite_clnt_internal: result clobbers input"); 5412 if (*addr && strchr(addr, '@') == 0) 5413 msg_fatal("%s: address rewriting is disabled", addr); 5414 vstring_strcpy(result, addr); 5415 return (result); 5416} 5417 5418/* resolve_clnt_query - stub */ 5419 5420void resolve_clnt(const char *class, const char *unused_sender, const char *addr, 5421 RESOLVE_REPLY *reply) 5422{ 5423 const char *domain; 5424 int rc; 5425 5426 if (addr == CONST_STR(reply->recipient)) 5427 msg_panic("resolve_clnt_query: result clobbers input"); 5428 if (strchr(addr, '%')) 5429 msg_fatal("%s: address rewriting is disabled", addr); 5430 if ((domain = strrchr(addr, '@')) == 0) 5431 msg_fatal("%s: unqualified address", addr); 5432 domain += 1; 5433 if ((rc = resolve_local(domain)) > 0) { 5434 reply->flags = RESOLVE_CLASS_LOCAL; 5435 vstring_strcpy(reply->transport, MAIL_SERVICE_LOCAL); 5436 vstring_strcpy(reply->nexthop, domain); 5437 } else if (rc < 0) { 5438 reply->flags = RESOLVE_FLAG_FAIL; 5439 } else if (string_list_match(virt_alias_doms, domain)) { 5440 reply->flags = RESOLVE_CLASS_ALIAS; 5441 vstring_strcpy(reply->transport, MAIL_SERVICE_ERROR); 5442 vstring_strcpy(reply->nexthop, "user unknown"); 5443 } else if (virt_alias_doms->error) { 5444 reply->flags = RESOLVE_FLAG_FAIL; 5445 } else if (string_list_match(virt_mailbox_doms, domain)) { 5446 reply->flags = RESOLVE_CLASS_VIRTUAL; 5447 vstring_strcpy(reply->transport, MAIL_SERVICE_VIRTUAL); 5448 vstring_strcpy(reply->nexthop, domain); 5449 } else if (virt_mailbox_doms->error) { 5450 reply->flags = RESOLVE_FLAG_FAIL; 5451 } else if (domain_list_match(relay_domains, domain)) { 5452 reply->flags = RESOLVE_CLASS_RELAY; 5453 vstring_strcpy(reply->transport, MAIL_SERVICE_RELAY); 5454 vstring_strcpy(reply->nexthop, domain); 5455 } else if (relay_domains->error) { 5456 reply->flags = RESOLVE_FLAG_FAIL; 5457 } else { 5458 reply->flags = RESOLVE_CLASS_DEFAULT; 5459 vstring_strcpy(reply->transport, MAIL_SERVICE_SMTP); 5460 vstring_strcpy(reply->nexthop, domain); 5461 } 5462 vstring_strcpy(reply->recipient, addr); 5463} 5464 5465/* smtpd_chat_reset - stub */ 5466 5467void smtpd_chat_reset(SMTPD_STATE *unused_state) 5468{ 5469} 5470 5471/* usage - scream and terminate */ 5472 5473static NORETURN usage(char *myname) 5474{ 5475 msg_fatal("usage: %s", myname); 5476} 5477 5478int main(int argc, char **argv) 5479{ 5480 VSTRING *buf = vstring_alloc(100); 5481 SMTPD_STATE state; 5482 ARGV *args; 5483 char *bp; 5484 char *resp; 5485 char *addr; 5486 INET_PROTO_INFO *proto_info; 5487 5488 /* 5489 * Initialization. Use dummies for client information. 5490 */ 5491 msg_vstream_init(argv[0], VSTREAM_ERR); 5492 if (argc != 1) 5493 usage(argv[0]); 5494 string_init(); 5495 int_init(); 5496 smtpd_check_init(); 5497 smtpd_expand_init(); 5498 proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_IPV4); 5499 smtpd_state_init(&state, VSTREAM_IN, "smtpd"); 5500 state.queue_id = "<queue id>"; 5501 5502 /* 5503 * Main loop: update config parameters or test the client, helo, sender 5504 * and recipient restrictions. 5505 */ 5506 while (vstring_fgets_nonl(buf, VSTREAM_IN) != 0) { 5507 5508 /* 5509 * Tokenize the command. Note, the comma is not a separator, so that 5510 * restriction lists can be entered as comma-separated lists. 5511 */ 5512 bp = STR(buf); 5513 if (!isatty(0)) { 5514 vstream_printf(">>> %s\n", bp); 5515 vstream_fflush(VSTREAM_OUT); 5516 } 5517 if (*bp == '#') 5518 continue; 5519 5520 if (*bp == '!') { 5521 vstream_printf("exit %d\n", system(bp + 1)); 5522 continue; 5523 } 5524 args = argv_split(bp, " \t\r\n"); 5525 5526 /* 5527 * Recognize the command. 5528 */ 5529 resp = "bad command"; 5530 switch (args->argc) { 5531 5532 /* 5533 * Emtpy line. 5534 */ 5535 case 0: 5536 argv_free(args); 5537 continue; 5538 5539 /* 5540 * Special case: rewrite context. 5541 */ 5542 case 1: 5543 if (strcasecmp(args->argv[0], "rewrite") == 0) 5544 resp = smtpd_check_rewrite(&state); 5545 break; 5546 5547 /* 5548 * Special case: client identity. 5549 */ 5550 case 4: 5551 case 3: 5552 if (strcasecmp(args->argv[0], "client") == 0) { 5553 state.where = SMTPD_AFTER_CONNECT; 5554 UPDATE_STRING(state.name, args->argv[1]); 5555 UPDATE_STRING(state.reverse_name, args->argv[1]); 5556 UPDATE_STRING(state.addr, args->argv[2]); 5557 if (args->argc == 4) 5558 state.name_status = 5559 state.reverse_name_status = 5560 atoi(args->argv[3]); 5561 else if (strcmp(state.name, "unknown") == 0) 5562 state.name_status = 5563 state.reverse_name_status = 5564 SMTPD_PEER_CODE_TEMP; 5565 else 5566 state.name_status = 5567 state.reverse_name_status = 5568 SMTPD_PEER_CODE_OK; 5569 if (state.namaddr) 5570 myfree(state.namaddr); 5571 state.namaddr = concatenate(state.name, "[", state.addr, 5572 "]", (char *) 0); 5573 resp = smtpd_check_client(&state); 5574 } 5575 break; 5576 5577 /* 5578 * Try config settings. 5579 */ 5580#define UPDATE_MAPS(ptr, var, val, lock) \ 5581 { if (ptr) maps_free(ptr); ptr = maps_create(var, val, lock); } 5582 5583#define UPDATE_LIST(ptr, val) \ 5584 { if (ptr) string_list_free(ptr); \ 5585 ptr = string_list_init(MATCH_FLAG_NONE, val); } 5586 5587 case 2: 5588 if (strcasecmp(args->argv[0], VAR_MYDEST) == 0) { 5589 UPDATE_STRING(var_mydest, args->argv[1]); 5590 resolve_local_init(); 5591 resp = 0; 5592 break; 5593 } 5594 if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_MAPS) == 0) { 5595 UPDATE_STRING(var_virt_alias_maps, args->argv[1]); 5596 UPDATE_MAPS(virt_alias_maps, VAR_VIRT_ALIAS_MAPS, 5597 var_virt_alias_maps, DICT_FLAG_LOCK 5598 | DICT_FLAG_FOLD_FIX); 5599 resp = 0; 5600 break; 5601 } 5602 if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_DOMS) == 0) { 5603 UPDATE_STRING(var_virt_alias_doms, args->argv[1]); 5604 UPDATE_LIST(virt_alias_doms, var_virt_alias_doms); 5605 resp = 0; 5606 break; 5607 } 5608 if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_MAPS) == 0) { 5609 UPDATE_STRING(var_virt_mailbox_maps, args->argv[1]); 5610 UPDATE_MAPS(virt_mailbox_maps, VAR_VIRT_MAILBOX_MAPS, 5611 var_virt_mailbox_maps, DICT_FLAG_LOCK 5612 | DICT_FLAG_FOLD_FIX); 5613 resp = 0; 5614 break; 5615 } 5616 if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_DOMS) == 0) { 5617 UPDATE_STRING(var_virt_mailbox_doms, args->argv[1]); 5618 UPDATE_LIST(virt_mailbox_doms, var_virt_mailbox_doms); 5619 resp = 0; 5620 break; 5621 } 5622 if (strcasecmp(args->argv[0], VAR_LOCAL_RCPT_MAPS) == 0) { 5623 UPDATE_STRING(var_local_rcpt_maps, args->argv[1]); 5624 UPDATE_MAPS(local_rcpt_maps, VAR_LOCAL_RCPT_MAPS, 5625 var_local_rcpt_maps, DICT_FLAG_LOCK 5626 | DICT_FLAG_FOLD_FIX); 5627 resp = 0; 5628 break; 5629 } 5630 if (strcasecmp(args->argv[0], VAR_RELAY_RCPT_MAPS) == 0) { 5631 UPDATE_STRING(var_relay_rcpt_maps, args->argv[1]); 5632 UPDATE_MAPS(relay_rcpt_maps, VAR_RELAY_RCPT_MAPS, 5633 var_relay_rcpt_maps, DICT_FLAG_LOCK 5634 | DICT_FLAG_FOLD_FIX); 5635 resp = 0; 5636 break; 5637 } 5638 if (strcasecmp(args->argv[0], VAR_CANONICAL_MAPS) == 0) { 5639 UPDATE_STRING(var_canonical_maps, args->argv[1]); 5640 UPDATE_MAPS(canonical_maps, VAR_CANONICAL_MAPS, 5641 var_canonical_maps, DICT_FLAG_LOCK 5642 | DICT_FLAG_FOLD_FIX); 5643 resp = 0; 5644 break; 5645 } 5646 if (strcasecmp(args->argv[0], VAR_RBL_REPLY_MAPS) == 0) { 5647 UPDATE_STRING(var_rbl_reply_maps, args->argv[1]); 5648 UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS, 5649 var_rbl_reply_maps, DICT_FLAG_LOCK 5650 | DICT_FLAG_FOLD_FIX); 5651 resp = 0; 5652 break; 5653 } 5654 if (strcasecmp(args->argv[0], VAR_MYNETWORKS) == 0) { 5655 /* NOT: UPDATE_STRING */ 5656 namadr_list_free(mynetworks); 5657 mynetworks = 5658 namadr_list_init(MATCH_FLAG_RETURN 5659 | match_parent_style(VAR_MYNETWORKS), 5660 args->argv[1]); 5661 resp = 0; 5662 break; 5663 } 5664 if (strcasecmp(args->argv[0], VAR_RELAY_DOMAINS) == 0) { 5665 /* NOT: UPDATE_STRING */ 5666 domain_list_free(relay_domains); 5667 relay_domains = 5668 domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), 5669 args->argv[1]); 5670 resp = 0; 5671 break; 5672 } 5673 if (strcasecmp(args->argv[0], VAR_PERM_MX_NETWORKS) == 0) { 5674 UPDATE_STRING(var_perm_mx_networks, args->argv[1]); 5675 domain_list_free(perm_mx_networks); 5676 perm_mx_networks = 5677 namadr_list_init(MATCH_FLAG_RETURN 5678 | match_parent_style(VAR_PERM_MX_NETWORKS), 5679 args->argv[1]); 5680 resp = 0; 5681 break; 5682 } 5683#ifdef USE_TLS 5684 if (strcasecmp(args->argv[0], VAR_RELAY_CCERTS) == 0) { 5685 UPDATE_STRING(var_smtpd_relay_ccerts, args->argv[1]); 5686 UPDATE_MAPS(relay_ccerts, VAR_RELAY_CCERTS, 5687 var_smtpd_relay_ccerts, DICT_FLAG_LOCK 5688 | DICT_FLAG_FOLD_FIX); 5689 resp = 0; 5690 } 5691#endif 5692 if (strcasecmp(args->argv[0], "restriction_class") == 0) { 5693 rest_class(args->argv[1]); 5694 resp = 0; 5695 break; 5696 } 5697 if (strcasecmp(args->argv[0], VAR_LOC_RWR_CLIENTS) == 0) { 5698 UPDATE_STRING(var_local_rwr_clients, args->argv[1]); 5699 argv_free(local_rewrite_clients); 5700 local_rewrite_clients = smtpd_check_parse(SMTPD_CHECK_PARSE_MAPS, 5701 var_local_rwr_clients); 5702 } 5703 if (int_update(args->argv) 5704 || string_update(args->argv) 5705 || rest_update(args->argv)) { 5706 resp = 0; 5707 break; 5708 } 5709 5710 /* 5711 * Try restrictions. 5712 */ 5713#define TRIM_ADDR(src, res) { \ 5714 if (*(res = src) == '<') { \ 5715 res += strlen(res) - 1; \ 5716 if (*res == '>') \ 5717 *res = 0; \ 5718 res = src + 1; \ 5719 } \ 5720 } 5721 5722 if (strcasecmp(args->argv[0], "helo") == 0) { 5723 state.where = "HELO"; 5724 resp = smtpd_check_helo(&state, args->argv[1]); 5725 UPDATE_STRING(state.helo_name, args->argv[1]); 5726 } else if (strcasecmp(args->argv[0], "mail") == 0) { 5727 state.where = "MAIL"; 5728 TRIM_ADDR(args->argv[1], addr); 5729 UPDATE_STRING(state.sender, addr); 5730 resp = smtpd_check_mail(&state, addr); 5731 } else if (strcasecmp(args->argv[0], "rcpt") == 0) { 5732 state.where = "RCPT"; 5733 TRIM_ADDR(args->argv[1], addr); 5734 resp = smtpd_check_rcpt(&state, addr); 5735#ifdef USE_TLS 5736 } else if (strcasecmp(args->argv[0], "fingerprint") == 0) { 5737 if (state.tls_context == 0) { 5738 state.tls_context = 5739 (TLS_SESS_STATE *) mymalloc(sizeof(*state.tls_context)); 5740 memset((char *) state.tls_context, 0, 5741 sizeof(*state.tls_context)); 5742 state.tls_context->peer_cert_fprint = 5743 state.tls_context->peer_pkey_fprint = 0; 5744 } 5745 state.tls_context->peer_status |= TLS_CERT_FLAG_PRESENT; 5746 UPDATE_STRING(state.tls_context->peer_cert_fprint, 5747 args->argv[1]); 5748 state.tls_context->peer_pkey_fprint = 5749 state.tls_context->peer_cert_fprint; 5750 resp = "OK"; 5751 break; 5752#endif 5753 } 5754 break; 5755 5756 /* 5757 * Show commands. 5758 */ 5759 default: 5760 if (strcasecmp(args->argv[0], "check_rewrite") == 0) { 5761 smtpd_check_rewrite(&state); 5762 resp = state.rewrite_context; 5763 break; 5764 } 5765 resp = "Commands...\n\ 5766 client <name> <address> [<code>]\n\ 5767 helo <hostname>\n\ 5768 sender <address>\n\ 5769 recipient <address>\n\ 5770 check_rewrite\n\ 5771 msg_verbose <level>\n\ 5772 client_restrictions <restrictions>\n\ 5773 helo_restrictions <restrictions>\n\ 5774 sender_restrictions <restrictions>\n\ 5775 recipient_restrictions <restrictions>\n\ 5776 restriction_class name,<restrictions>\n\ 5777 \n\ 5778 Note: no address rewriting \n"; 5779 break; 5780 } 5781 vstream_printf("%s\n", resp ? resp : "OK"); 5782 vstream_fflush(VSTREAM_OUT); 5783 argv_free(args); 5784 } 5785 vstring_free(buf); 5786 smtpd_state_reset(&state); 5787#define FREE_STRING(s) { if (s) myfree(s); } 5788 FREE_STRING(state.helo_name); 5789 FREE_STRING(state.sender); 5790 if (state.tls_context) { 5791 FREE_STRING(state.tls_context->peer_cert_fprint); 5792 myfree((char *) state.tls_context); 5793 } 5794 exit(0); 5795} 5796 5797#endif 5798