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