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