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