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