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