1 /* $NetBSD: smtp.h,v 1.7 2026/05/09 18:49:20 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* smtp 3h 6 /* SUMMARY 7 /* smtp client program 8 /* SYNOPSIS 9 /* #include "smtp.h" 10 /* DESCRIPTION 11 /* .nf 12 13 /* 14 * System library. 15 */ 16 #include <string.h> 17 18 /* 19 * Utility library. 20 */ 21 #include <vstream.h> 22 #include <vstring.h> 23 #include <argv.h> 24 #include <htable.h> 25 #include <dict.h> 26 27 /* 28 * Global library. 29 */ 30 #include <deliver_request.h> 31 #include <scache.h> 32 #include <string_list.h> 33 #include <maps.h> 34 #include <tok822.h> 35 #include <dsn_buf.h> 36 #include <header_body_checks.h> 37 #include <sendopts.h> 38 #include <pol_stats.h> 39 40 /* 41 * Postfix TLS library. 42 */ 43 #include <tls.h> 44 45 /* 46 * tlsproxy client. 47 */ 48 #include <tls_proxy.h> 49 50 /* 51 * This application. 52 */ 53 #include <smtp_reqtls_policy.h> 54 55 /* 56 * Global iterator support. This is updated by the connection-management 57 * loop, and contains dynamic context that appears in lookup keys for SASL 58 * passwords, TLS policy, cached SMTP connections, and cached TLS session 59 * keys. 60 * 61 * For consistency and maintainability, context that is used in more than one 62 * lookup key is formatted with smtp_key_format(). 63 */ 64 typedef struct SMTP_ITERATOR { 65 /* Public members. */ 66 VSTRING *request_nexthop; /* delivery request nexhop or empty */ 67 VSTRING *dest; /* current nexthop */ 68 VSTRING *host; /* hostname or empty */ 69 VSTRING *addr; /* printable address or empty */ 70 unsigned port; /* network byte order or null */ 71 struct DNS_RR *rr; /* DNS resource record or null */ 72 struct DNS_RR *mx; /* DNS resource record or null */ 73 /* Private members. */ 74 VSTRING *saved_dest; /* saved current nexthop */ 75 struct SMTP_STATE *parent; /* parent linkage */ 76 } SMTP_ITERATOR; 77 78 #define SMTP_ITER_INIT(iter, _dest, _host, _addr, _port, state) do { \ 79 vstring_strcpy((iter)->dest, (_dest)); \ 80 vstring_strcpy((iter)->host, (_host)); \ 81 vstring_strcpy((iter)->addr, (_addr)); \ 82 (iter)->port = (_port); \ 83 (iter)->mx = (iter)->rr = 0; \ 84 vstring_strcpy((iter)->saved_dest, ""); \ 85 (iter)->parent = (state); \ 86 } while (0) 87 88 #define SMTP_ITER_SAVE_DEST(iter) do { \ 89 vstring_strcpy((iter)->saved_dest, STR((iter)->dest)); \ 90 } while (0) 91 92 #define SMTP_ITER_RESTORE_DEST(iter) do { \ 93 vstring_strcpy((iter)->dest, STR((iter)->saved_dest)); \ 94 } while (0) 95 96 #define SMTP_ITER_UPDATE_HOST(iter, _host, _addr, _rr) do { \ 97 vstring_strcpy((iter)->host, (_host)); \ 98 vstring_strcpy((iter)->addr, (_addr)); \ 99 (iter)->rr = (_rr); \ 100 if ((_rr)->port) \ 101 (iter)->port = htons((_rr)->port); /* SRV port override */ \ 102 } while (0) 103 104 /* 105 * TLS Policy support. 106 */ 107 #ifdef USE_TLS 108 109 typedef struct SMTP_TLS_POLICY { 110 int level; /* TLS enforcement level */ 111 char *protocols; /* Acceptable SSL protocols */ 112 char *grade; /* Cipher grade: "export", ... */ 113 VSTRING *exclusions; /* Excluded SSL ciphers */ 114 ARGV *matchargv; /* Cert match patterns */ 115 DSN_BUF *why; /* Lookup error status */ 116 TLS_DANE *dane; /* DANE TLSA digests */ 117 char *sni; /* Optional SNI name when not DANE */ 118 int conn_reuse; /* enable connection reuse */ 119 int enable_rpk; /* Enable server->client RPK */ 120 /* External policy info, for TLSRPT. */ 121 int ext_policy_ttl; /* TTL from DNS etc. */ 122 char *ext_policy_type; /* (sts) */ 123 ARGV *ext_policy_strings; /* policy strings from DNS etc. */ 124 char *ext_policy_domain; /* policy scope */ 125 ARGV *ext_mx_host_patterns; /* (sts) MX host patterns */ 126 char *ext_policy_failure; /* (sts) policy failure */ 127 } SMTP_TLS_POLICY; 128 129 /* 130 * Names and values for external policy attributes in smtp_tls_policy_maps. 131 * These are not #ifdef USE_TLSRPT, so that a TLSRPT-aware STS plugin can be 132 * used whether or not Postfix was built with TLSRPT support. 133 */ 134 #define EXT_POLICY_TTL "policy_ttl" 135 #define EXT_POLICY_TTL_UNSET (-1) 136 #define EXT_POLICY_TYPE "policy_type" 137 #define EXT_POLICY_DOMAIN "policy_domain" 138 #define EXT_POLICY_STRING "policy_string" 139 #define EXT_MX_HOST_PATTERN "mx_host_pattern" 140 #define EXT_POLICY_FAILURE "policy_failure" 141 142 /* 143 * smtp_tls_policy.c 144 */ 145 extern void smtp_tls_list_init(void); 146 extern int smtp_tls_policy_cache_query(DSN_BUF *, SMTP_TLS_POLICY *, SMTP_ITERATOR *); 147 extern void smtp_tls_policy_cache_flush(void); 148 extern int smtp_tls_authorize_mx_hostname(SMTP_TLS_POLICY *, const char *); 149 150 /* 151 * Macros must use distinct names for local temporary variables, otherwise 152 * there will be bugs due to shadowing. This happened when an earlier 153 * version of smtp_tls_policy_dummy() invoked smtp_tls_policy_init(), but it 154 * could also happen without macro nesting. 155 * 156 * General principle: use all or part of the macro name in each temporary 157 * variable name. Then, append suffixes to the names if needed. 158 */ 159 #define smtp_tls_policy_dummy(t) do { \ 160 SMTP_TLS_POLICY *_tls_policy_dummy_tmp = (t); \ 161 smtp_tls_policy_init(_tls_policy_dummy_tmp, (DSN_BUF *) 0); \ 162 _tls_policy_dummy_tmp->level = TLS_LEV_NONE; \ 163 } while (0) 164 165 /* This macro is not part of the module external interface. */ 166 #define smtp_tls_policy_init(t, w) do { \ 167 SMTP_TLS_POLICY *_tls_policy_init_tmp = (t); \ 168 _tls_policy_init_tmp->protocols = 0; \ 169 _tls_policy_init_tmp->grade = 0; \ 170 _tls_policy_init_tmp->exclusions = 0; \ 171 _tls_policy_init_tmp->matchargv = 0; \ 172 _tls_policy_init_tmp->why = (w); \ 173 _tls_policy_init_tmp->dane = 0; \ 174 _tls_policy_init_tmp->sni = 0; \ 175 _tls_policy_init_tmp->conn_reuse = 0; \ 176 _tls_policy_init_tmp->enable_rpk = 0; \ 177 _tls_policy_init_tmp->ext_policy_ttl = EXT_POLICY_TTL_UNSET; \ 178 _tls_policy_init_tmp->ext_policy_type = 0; \ 179 _tls_policy_init_tmp->ext_policy_domain = 0; \ 180 _tls_policy_init_tmp->ext_policy_strings = 0; \ 181 _tls_policy_init_tmp->ext_mx_host_patterns = 0; \ 182 _tls_policy_init_tmp->ext_policy_failure = 0; \ 183 } while (0) 184 185 #endif 186 187 /* 188 * State information associated with each SMTP delivery request. 189 * Session-specific state is stored separately. 190 */ 191 typedef struct SMTP_STATE { 192 int misc_flags; /* processing flags, see below */ 193 VSTREAM *src; /* queue file stream */ 194 const char *service; /* transport name */ 195 DELIVER_REQUEST *request; /* envelope info, offsets */ 196 struct SMTP_SESSION *session; /* network connection */ 197 int status; /* delivery status */ 198 ssize_t space_left; /* output length control */ 199 200 /* 201 * Global iterator. 202 */ 203 SMTP_ITERATOR iterator[1]; /* Usage: state->iterator->member */ 204 205 /* 206 * TLS policy related. 207 */ 208 #ifdef USE_TLS 209 SMTP_TLS_POLICY tls[1]; /* Usage: state->tls->member */ 210 #ifdef USE_TLSRPT 211 struct TLSRPT_WRAPPER *tlsrpt; 212 #endif 213 int reqtls_level; /* from smtp_reqtls_policy */ 214 #endif 215 POL_STATS *tls_stats; /* TLS feature policy compliance */ 216 217 /* 218 * Connection cache support. 219 */ 220 HTABLE *cache_used; /* cached addresses that were used */ 221 VSTRING *dest_label; /* cached logical/physical binding */ 222 VSTRING *dest_prop; /* binding properties, passivated */ 223 VSTRING *endp_label; /* cached session physical endpoint */ 224 VSTRING *endp_prop; /* endpoint properties, passivated */ 225 226 /* 227 * Flags and counters to control the handling of mail delivery errors. 228 * There is some redundancy for sanity checking. At the end of an SMTP 229 * session all recipients should be marked one way or the other. 230 */ 231 int rcpt_left; /* recipients left over */ 232 int rcpt_drop; /* recipients marked as drop */ 233 int rcpt_keep; /* recipients marked as keep */ 234 235 /* 236 * DSN Support introduced major bloat in error processing. 237 */ 238 DSN_BUF *why; /* on-the-fly formatting buffer */ 239 240 /* 241 * Whether per-nexthop debug_peer support was requested. Otherwise, 242 * assume per-server debug_peer support. 243 */ 244 int debug_peer_per_nexthop; 245 246 /* 247 * One-bit counters to avoid logging the same warning multiple times per 248 * delivery request. 249 */ 250 unsigned logged_line_length_limit:1; 251 } SMTP_STATE; 252 253 #define SMTP_TLS_STAT_IDX_SEC_LEVEL 0 254 #define SMTP_TLS_STAT_IDX_REQTLS 1 255 256 /* Use the TLS policy name for the TLS security level status feature. */ 257 #define SMTP_TLS_STAT_NAME_REQTLS "requiretls" 258 #define SMTP_TLS_STAT_NAME_NOCMATCH "nocertmatch" 259 #define SMTP_TLS_STAT_NAME_NOSTTLS "nostarttls" 260 #define SMTP_TLS_STAT_NAME_NOTLS "noencryption" 261 #define SMTP_TLS_STAT_NAME_NONE "none" 262 #define SMTP_TLS_STAT_NAME_UNKNOWN "unknown" 263 264 #define smtp_tls_stat_activate_sec_level(tstats, level) \ 265 pol_stat_activate((tstats), SMTP_TLS_STAT_IDX_SEC_LEVEL, \ 266 str_tls_level(level)) 267 268 #define smtp_tls_stat_activate_sec_unknown(tstats) \ 269 pol_stat_activate((tstats), SMTP_TLS_STAT_IDX_SEC_LEVEL, \ 270 SMTP_TLS_STAT_NAME_UNKNOWN) 271 272 #define smtp_tls_stat_decide_sec_level(tstats, level, status) \ 273 pol_stat_decide((tstats), SMTP_TLS_STAT_IDX_SEC_LEVEL, \ 274 str_tls_level(level), (status)) 275 276 #define smtp_tls_stat_activate_reqtls(tstats, name) \ 277 pol_stat_activate((tstats), SMTP_TLS_STAT_IDX_REQTLS, \ 278 (name)) 279 280 #define smtp_tls_stat_decide_reqtls(tstats, name, status) \ 281 pol_stat_decide((tstats), SMTP_TLS_STAT_IDX_REQTLS, \ 282 (name), (status)) 283 284 #ifdef USE_TLS 285 #define STATE_TLS_NOT_REQUIRED(state) \ 286 (var_tls_required_enable \ 287 && (var_reqtls_enable == 0 \ 288 || ((state)->request->sendopts & SOPT_REQUIRETLS_ESMTP) == 0) \ 289 && ((state)->request->sendopts & SOPT_REQUIRETLS_HEADER)) 290 #endif 291 292 /* 293 * Primitives to enable/disable/test connection caching and reuse based on 294 * the delivery request next-hop destination (i.e. not smtp_fallback_relay). 295 * 296 * Connection cache lookup by the delivery request next-hop destination allows 297 * a reuse request to skip over bad hosts, and may result in a connection to 298 * a fall-back relay. Once we have found a 'good' host for a delivery 299 * request next-hop, clear the delivery request next-hop destination, to 300 * avoid caching less-preferred connections under that same delivery request 301 * next-hop. 302 */ 303 #define SET_SCACHE_REQUEST_NEXTHOP(state, nexthop) do { \ 304 vstring_strcpy((state)->iterator->request_nexthop, nexthop); \ 305 } while (0) 306 307 #define CLEAR_SCACHE_REQUEST_NEXTHOP(state) do { \ 308 STR((state)->iterator->request_nexthop)[0] = 0; \ 309 } while (0) 310 311 #define HAVE_SCACHE_REQUEST_NEXTHOP(state) \ 312 (STR((state)->iterator->request_nexthop)[0] != 0) 313 314 315 /* 316 * Server features. 317 */ 318 #define SMTP_FEATURE_ESMTP (1<<0) 319 #define SMTP_FEATURE_8BITMIME (1<<1) 320 #define SMTP_FEATURE_PIPELINING (1<<2) 321 #define SMTP_FEATURE_SIZE (1<<3) 322 #define SMTP_FEATURE_STARTTLS (1<<4) 323 #define SMTP_FEATURE_AUTH (1<<5) 324 #define SMTP_FEATURE_XFORWARD_NAME (1<<7) 325 #define SMTP_FEATURE_XFORWARD_ADDR (1<<8) 326 #define SMTP_FEATURE_XFORWARD_PROTO (1<<9) 327 #define SMTP_FEATURE_XFORWARD_HELO (1<<10) 328 #define SMTP_FEATURE_XFORWARD_DOMAIN (1<<11) 329 #define SMTP_FEATURE_BEST_MX (1<<12) /* for next-hop or fall-back */ 330 #define SMTP_FEATURE_RSET_REJECTED (1<<13) /* RSET probe rejected */ 331 #define SMTP_FEATURE_FROM_CACHE (1<<14) /* cached connection */ 332 #define SMTP_FEATURE_DSN (1<<15) /* DSN supported */ 333 #define SMTP_FEATURE_PIX_NO_ESMTP (1<<16) /* PIX smtp fixup mode */ 334 #define SMTP_FEATURE_PIX_DELAY_DOTCRLF (1<<17) /* PIX smtp fixup mode */ 335 #define SMTP_FEATURE_XFORWARD_PORT (1<<18) 336 #define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */ 337 #define SMTP_FEATURE_XFORWARD_IDENT (1<<20) 338 #define SMTP_FEATURE_SMTPUTF8 (1<<21) /* RFC 6531 */ 339 #define SMTP_FEATURE_FROM_PROXY (1<<22) /* proxied connection */ 340 #define SMTP_FEATURE_REQTLS (1<<23) /* RFC 8689 */ 341 342 /* 343 * Features that passivate under the endpoint. Be sure to passivate all 344 * features that are needed in SMTP_KEY_MASK_SCACHE_DEST_LABEL, otherwise a 345 * reused connection may be stored under the wrong key. 346 */ 347 #define SMTP_FEATURE_ENDPOINT_MASK \ 348 (~(SMTP_FEATURE_BEST_MX | SMTP_FEATURE_RSET_REJECTED \ 349 | SMTP_FEATURE_FROM_CACHE)) 350 351 /* 352 * Features that passivate under the logical destination. 353 */ 354 #define SMTP_FEATURE_DESTINATION_MASK (SMTP_FEATURE_BEST_MX) 355 356 /* 357 * Misc flags. 358 */ 359 #define SMTP_MISC_FLAG_LOOP_DETECT (1<<0) 360 #define SMTP_MISC_FLAG_IN_STARTTLS (1<<1) 361 #define SMTP_MISC_FLAG_FIRST_NEXTHOP (1<<2) 362 #define SMTP_MISC_FLAG_FINAL_NEXTHOP (1<<3) 363 #define SMTP_MISC_FLAG_FINAL_SERVER (1<<4) 364 #define SMTP_MISC_FLAG_CONN_LOAD (1<<5) 365 #define SMTP_MISC_FLAG_CONN_STORE (1<<6) 366 #define SMTP_MISC_FLAG_COMPLETE_SESSION (1<<7) 367 #define SMTP_MISC_FLAG_PREF_IPV6 (1<<8) 368 #define SMTP_MISC_FLAG_PREF_IPV4 (1<<9) 369 #define SMTP_MISC_FLAG_FALLBACK_SRV_TO_MX (1<<10) 370 371 #define SMTP_MISC_FLAG_CONN_CACHE_MASK \ 372 (SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE) 373 374 /* 375 * smtp.c 376 */ 377 #define SMTP_HAS_DSN(why) (STR((why)->status)[0] != 0) 378 #define SMTP_HAS_SOFT_DSN(why) (STR((why)->status)[0] == '4') 379 #define SMTP_HAS_HARD_DSN(why) (STR((why)->status)[0] == '5') 380 #define SMTP_HAS_LOOP_DSN(why) \ 381 (SMTP_HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0) 382 383 #define SMTP_SET_SOFT_DSN(why) (STR((why)->status)[0] = '4') 384 #define SMTP_SET_HARD_DSN(why) (STR((why)->status)[0] = '5') 385 386 extern int smtp_host_lookup_mask; /* host lookup methods to use */ 387 388 #define SMTP_HOST_FLAG_DNS (1<<0) 389 #define SMTP_HOST_FLAG_NATIVE (1<<1) 390 391 extern int smtp_dns_support; /* dns support level */ 392 393 #define SMTP_DNS_INVALID (-1) /* smtp_dns_support_level = <bogus> */ 394 #define SMTP_DNS_DISABLED 0 /* smtp_dns_support_level = disabled */ 395 #define SMTP_DNS_ENABLED 1 /* smtp_dns_support_level = enabled */ 396 #define SMTP_DNS_DNSSEC 2 /* smtp_dns_support_level = dnssec */ 397 398 extern SCACHE *smtp_scache; /* connection cache instance */ 399 extern STRING_LIST *smtp_cache_dest; /* cached destinations */ 400 401 extern MAPS *smtp_ehlo_dis_maps; /* ehlo keyword filter */ 402 403 extern MAPS *smtp_pix_bug_maps; /* PIX workarounds */ 404 405 extern MAPS *smtp_generic_maps; /* make internal address valid */ 406 extern int smtp_ext_prop_mask; /* address extension propagation */ 407 extern unsigned smtp_dns_res_opt; /* DNS query flags */ 408 409 extern STRING_LIST *smtp_use_srv_lookup;/* services with SRV record lookup */ 410 411 #ifdef USE_TLS 412 413 extern TLS_APPL_STATE *smtp_tls_ctx; /* client-side TLS engine */ 414 extern int smtp_tls_insecure_mx_policy; /* DANE post insecure MX? */ 415 extern SMTP_REQTLS_POLICY *smtp_reqtls_policy; /* parsed list */ 416 417 #endif 418 419 extern HBC_CHECKS *smtp_header_checks; /* limited header checks */ 420 extern HBC_CHECKS *smtp_body_checks; /* limited body checks */ 421 422 /* 423 * smtp_session.c 424 */ 425 426 typedef struct SMTP_SESSION { 427 VSTREAM *stream; /* network connection */ 428 SMTP_ITERATOR *iterator; /* dest, host, addr, port */ 429 char *namaddr; /* mail exchanger */ 430 char *helo; /* helo response */ 431 unsigned port; /* network byte order */ 432 char *namaddrport; /* mail exchanger, incl. port */ 433 434 VSTRING *buffer; /* I/O buffer */ 435 VSTRING *scratch; /* scratch buffer */ 436 VSTRING *scratch2; /* scratch buffer */ 437 438 int features; /* server features */ 439 off_t size_limit; /* server limit or unknown */ 440 441 ARGV *history; /* transaction log */ 442 int error_mask; /* error classes */ 443 struct MIME_STATE *mime_state; /* mime state machine */ 444 445 int send_proto_helo; /* XFORWARD support */ 446 447 time_t expire_time; /* session reuse expiration time */ 448 int reuse_count; /* # of times reused (for logging) */ 449 int forbidden; /* No further I/O allowed */ 450 451 #ifdef USE_SASL_AUTH 452 char *sasl_mechanism_list; /* server mechanism list */ 453 char *sasl_username; /* client username */ 454 char *sasl_passwd; /* client password */ 455 struct XSASL_CLIENT *sasl_client; /* SASL internal state */ 456 VSTRING *sasl_reply; /* client response */ 457 #endif 458 459 /* 460 * TLS related state, don't forget to initialize in session_tls_init()! 461 */ 462 #ifdef USE_TLS 463 TLS_SESS_STATE *tls_context; /* TLS library session state */ 464 char *tls_nexthop; /* Nexthop domain for cert checks */ 465 int tls_retry_plain; /* Try plain when TLS handshake fails */ 466 #endif 467 468 SMTP_STATE *state; /* back link */ 469 } SMTP_SESSION; 470 471 extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, SMTP_ITERATOR *, time_t, int); 472 extern void smtp_session_new_stream(SMTP_SESSION *, VSTREAM *, time_t, int); 473 extern int smtp_sess_plaintext_ok(SMTP_ITERATOR *, int); 474 extern void smtp_session_free(SMTP_SESSION *); 475 extern int smtp_session_passivate(SMTP_SESSION *, VSTRING *, VSTRING *); 476 extern SMTP_SESSION *smtp_session_activate(int, SMTP_ITERATOR *, VSTRING *, VSTRING *); 477 478 /* 479 * What's in a name? 480 */ 481 #define SMTP_HNAME(rr) (var_smtp_cname_overr ? (rr)->rname : (rr)->qname) 482 483 /* 484 * smtp_connect.c 485 */ 486 extern int smtp_connect(SMTP_STATE *); 487 488 /* 489 * smtp_proto.c 490 */ 491 extern void smtp_vrfy_init(void); 492 extern int smtp_helo(SMTP_STATE *); 493 extern int smtp_xfer(SMTP_STATE *); 494 extern int smtp_rset(SMTP_STATE *); 495 extern int smtp_quit(SMTP_STATE *); 496 497 extern HBC_CALL_BACKS smtp_hbc_callbacks[]; 498 499 /* 500 * A connection is re-usable if session->expire_time is > 0 and the 501 * expiration time has not been reached. This is subtle because the timer 502 * can expire between sending a command and receiving the reply for that 503 * command. 504 * 505 * But wait, there is more! When SMTP command pipelining is enabled, there are 506 * two protocol loops that execute at very different times: one loop that 507 * generates commands, and one loop that receives replies to those commands. 508 * These will be called "sender loop" and "receiver loop", respectively. At 509 * well-defined protocol synchronization points, the sender loop pauses to 510 * let the receiver loop catch up. 511 * 512 * When we choose to reuse a connection, both the sender and receiver protocol 513 * loops end with "." (mail delivery) or "RSET" (address probe). When we 514 * choose not to reuse, both the sender and receiver protocol loops end with 515 * "QUIT". The problem is that we must make the same protocol choices in 516 * both the sender and receiver loops, even though those loops may execute 517 * at completely different times. 518 * 519 * We "freeze" the choice in the sender loop, just before we generate "." or 520 * "RSET". The reader loop leaves the connection cacheable even if the timer 521 * expires by the time the response arrives. The connection cleanup code 522 * will call smtp_quit() for connections with an expired cache expiration 523 * timer. 524 * 525 * We could have made the programmer's life a lot simpler by not making a 526 * choice at all, and always leaving it up to the connection cleanup code to 527 * call smtp_quit() for connections with an expired cache expiration timer. 528 * 529 * As a general principle, neither the sender loop nor the receiver loop must 530 * modify the connection caching state, if that can affect the receiver 531 * state machine for not-yet processed replies to already-generated 532 * commands. This restriction does not apply when we have to exit the 533 * protocol loops prematurely due to e.g., timeout or connection loss, so 534 * that those pending replies will never be received. 535 * 536 * But wait, there is even more! Only the first good connection for a specific 537 * destination may be cached under both the next-hop destination name and 538 * the server address; connections to alternate servers must be cached under 539 * the server address alone. This means we must distinguish between bad 540 * connections and other reasons why connections cannot be cached. 541 */ 542 #define THIS_SESSION_IS_CACHED \ 543 (!THIS_SESSION_IS_FORBIDDEN && session->expire_time > 0) 544 545 #define THIS_SESSION_IS_EXPIRED \ 546 (THIS_SESSION_IS_CACHED \ 547 && (session->expire_time < vstream_ftime(session->stream) \ 548 || (var_smtp_reuse_count > 0 \ 549 && session->reuse_count >= var_smtp_reuse_count))) 550 551 #define THIS_SESSION_IS_THROTTLED \ 552 (!THIS_SESSION_IS_FORBIDDEN && session->expire_time < 0) 553 554 #define THIS_SESSION_IS_FORBIDDEN \ 555 (session->forbidden != 0) 556 557 /* Bring the bad news. */ 558 559 #define DONT_CACHE_THIS_SESSION \ 560 (session->expire_time = 0) 561 562 #define DONT_CACHE_THROTTLED_SESSION \ 563 (session->expire_time = -1) 564 565 #define DONT_USE_FORBIDDEN_SESSION \ 566 (session->forbidden = 1) 567 568 /* Initialization. */ 569 570 #define USE_NEWBORN_SESSION \ 571 (session->forbidden = 0) 572 573 #define CACHE_THIS_SESSION_UNTIL(when) \ 574 (session->expire_time = (when)) 575 576 /* 577 * Encapsulate the following so that we don't expose details of connection 578 * management and error handling to the SMTP protocol engine. 579 */ 580 #ifdef USE_SASL_AUTH 581 #define HAVE_SASL_CREDENTIALS \ 582 (var_smtp_sasl_enable \ 583 && *var_smtp_sasl_passwd \ 584 && smtp_sasl_passwd_lookup(session)) 585 #else 586 #define HAVE_SASL_CREDENTIALS (0) 587 #endif 588 589 #define PREACTIVE_DELAY \ 590 (session->state->request->msg_stats.active_arrival.tv_sec - \ 591 session->state->request->msg_stats.incoming_arrival.tv_sec) 592 593 #define TRACE_REQ_ONLY (DEL_REQ_TRACE_ONLY(state->request->flags)) 594 595 #define PLAINTEXT_FALLBACK_OK_AFTER_STARTTLS_FAILURE \ 596 (session->tls_context == 0 \ 597 && state->tls->level == TLS_LEV_MAY \ 598 && !TLS_REQUIRED_BY_REQTLS_POLICY(state->reqtls_level) \ 599 && (TRACE_REQ_ONLY || PREACTIVE_DELAY >= var_min_backoff_time) \ 600 && !HAVE_SASL_CREDENTIALS) 601 602 #define PLAINTEXT_FALLBACK_OK_AFTER_TLS_SESSION_FAILURE \ 603 (session->tls_context != 0 \ 604 && SMTP_RCPT_LEFT(state) > SMTP_RCPT_MARK_COUNT(state) \ 605 && state->tls->level == TLS_LEV_MAY \ 606 && !TLS_REQUIRED_BY_REQTLS_POLICY(state->reqtls_level) \ 607 && (TRACE_REQ_ONLY || PREACTIVE_DELAY >= var_min_backoff_time) \ 608 && !HAVE_SASL_CREDENTIALS) 609 610 /* 611 * XXX The following will not retry recipients that were deferred while the 612 * SMTP_MISC_FLAG_FINAL_SERVER flag was already set. This includes the case 613 * when TLS fails in the middle of a delivery. 614 */ 615 #define RETRY_AS_PLAINTEXT do { \ 616 session->tls_retry_plain = 1; \ 617 state->misc_flags &= ~SMTP_MISC_FLAG_FINAL_SERVER; \ 618 } while (0) 619 620 /* 621 * smtp_chat.c 622 */ 623 typedef struct SMTP_RESP { /* server response */ 624 int code; /* SMTP code */ 625 const char *dsn; /* enhanced status */ 626 char *str; /* full reply */ 627 VSTRING *dsn_buf; /* status buffer */ 628 VSTRING *str_buf; /* reply buffer */ 629 } SMTP_RESP; 630 631 extern void PRINTFLIKE(2, 3) smtp_chat_cmd(SMTP_SESSION *, const char *,...); 632 extern DICT *smtp_chat_resp_filter; 633 extern SMTP_RESP *smtp_chat_resp(SMTP_SESSION *); 634 extern void smtp_chat_init(SMTP_SESSION *); 635 extern void smtp_chat_reset(SMTP_SESSION *); 636 extern void smtp_chat_notify(SMTP_SESSION *); 637 638 #define SMTP_RESP_FAKE(resp, _dsn) \ 639 ((resp)->code = 0, \ 640 (resp)->dsn = (_dsn), \ 641 (resp)->str = DSN_BY_LOCAL_MTA, \ 642 (resp)) 643 644 #define DSN_BY_LOCAL_MTA ((char *) 0) /* DSN issued by local MTA */ 645 646 #define SMTP_RESP_SET_DSN(resp, _dsn) do { \ 647 vstring_strcpy((resp)->dsn_buf, (_dsn)); \ 648 (resp)->dsn = STR((resp)->dsn_buf); \ 649 } while (0) 650 651 /* 652 * These operations implement a redundant mark-and-sweep algorithm that 653 * explicitly accounts for the fate of every recipient. The interface is 654 * documented in smtp_rcpt.c, which also implements the sweeping. The 655 * smtp_trouble.c module does most of the marking after failure. 656 * 657 * When a delivery fails or succeeds, take one of the following actions: 658 * 659 * - Mark the recipient as KEEP (deliver to alternate MTA) and do not update 660 * the delivery request status. 661 * 662 * - Mark the recipient as DROP (remove from delivery request), log whether 663 * delivery succeeded or failed, delete the recipient from the queue file 664 * and/or update defer or bounce logfiles, and update the delivery request 665 * status. 666 * 667 * At the end of a delivery attempt, all recipients must be marked one way or 668 * the other. Failure to do so will trigger a panic. 669 */ 670 #define SMTP_RCPT_STATE_KEEP 1 /* send to backup host */ 671 #define SMTP_RCPT_STATE_DROP 2 /* remove from request */ 672 #define SMTP_RCPT_INIT(state) do { \ 673 (state)->rcpt_drop = (state)->rcpt_keep = 0; \ 674 (state)->rcpt_left = state->request->rcpt_list.len; \ 675 } while (0) 676 677 #define SMTP_RCPT_DROP(state, rcpt) do { \ 678 (rcpt)->u.status = SMTP_RCPT_STATE_DROP; (state)->rcpt_drop++; \ 679 } while (0) 680 681 #define SMTP_RCPT_KEEP(state, rcpt) do { \ 682 (rcpt)->u.status = SMTP_RCPT_STATE_KEEP; (state)->rcpt_keep++; \ 683 } while (0) 684 685 #define SMTP_RCPT_ISMARKED(rcpt) ((rcpt)->u.status != 0) 686 687 #define SMTP_RCPT_LEFT(state) (state)->rcpt_left 688 689 #define SMTP_RCPT_MARK_COUNT(state) ((state)->rcpt_drop + (state)->rcpt_keep) 690 691 extern void smtp_rcpt_cleanup(SMTP_STATE *); 692 extern void smtp_rcpt_done(SMTP_STATE *, SMTP_RESP *, RECIPIENT *); 693 694 /* 695 * smtp_trouble.c 696 */ 697 #define SMTP_MISC_FAIL_NONE 0 698 #define SMTP_MISC_FAIL_THROTTLE (1<<0) 699 #define SMTP_MISC_FAIL_SOFT_NON_FINAL (1<<1) 700 #define SMTP_MISC_FAIL_DONT_CACHE (1<<2) 701 extern int smtp_sess_fail(SMTP_STATE *); 702 extern int PRINTFLIKE(5, 6) smtp_misc_fail(SMTP_STATE *, int, const char *, 703 SMTP_RESP *, const char *,...); 704 extern void PRINTFLIKE(5, 6) smtp_rcpt_fail(SMTP_STATE *, RECIPIENT *, 705 const char *, SMTP_RESP *, 706 const char *,...); 707 extern int smtp_stream_except(SMTP_STATE *, int, const char *); 708 709 #define smtp_site_fail(state, mta, resp, ...) \ 710 smtp_misc_fail((state), SMTP_MISC_FAIL_THROTTLE, (mta), (resp), __VA_ARGS__) 711 #define smtp_mesg_fail(state, mta, resp, ...) \ 712 smtp_misc_fail((state), SMTP_MISC_FAIL_NONE, (mta), (resp), __VA_ARGS__) 713 714 /* 715 * smtp_unalias.c 716 */ 717 extern const char *smtp_unalias_name(const char *); 718 extern VSTRING *smtp_unalias_addr(VSTRING *, const char *); 719 720 /* 721 * smtp_state.c 722 */ 723 extern SMTP_STATE *smtp_state_alloc(void); 724 extern void smtp_state_free(SMTP_STATE *); 725 726 /* 727 * smtp_map11.c 728 */ 729 extern int smtp_map11_external(VSTRING *, MAPS *, int); 730 extern int smtp_map11_tree(TOK822 *, MAPS *, int); 731 extern int smtp_map11_internal(VSTRING *, MAPS *, int); 732 733 /* 734 * smtp_key.c 735 */ 736 char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); 737 738 #define SMTP_KEY_FLAG_SERVICE (1<<0) /* service name */ 739 #define SMTP_KEY_FLAG_SENDER (1<<1) /* sender address */ 740 #define SMTP_KEY_FLAG_REQ_NEXTHOP (1<<2) /* delivery request nexthop */ 741 #define SMTP_KEY_FLAG_CUR_NEXTHOP (1<<3) /* current nexthop */ 742 #define SMTP_KEY_FLAG_HOSTNAME (1<<4) /* remote host name */ 743 #define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */ 744 #define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */ 745 #define SMTP_KEY_FLAG_TLS_LEVEL (1<<7) /* requested TLS level */ 746 #define SMTP_KEY_FLAG_REQ_SMTPUTF8 (1<<8) /* SMTPUTF8 is required */ 747 #define SMTP_KEY_FLAG_REQTLS_LEVEL (1<<9) /* REQUIRETLS enforcement */ 748 749 #define SMTP_KEY_MASK_ALL \ 750 (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \ 751 SMTP_KEY_FLAG_REQ_NEXTHOP | \ 752 SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \ 753 SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL | \ 754 SMTP_KEY_FLAG_REQ_SMTPUTF8 | SMTP_KEY_FLAG_REQTLS_LEVEL) 755 756 /* 757 * Conditional lookup-key flags for cached connections that may be 758 * SASL-authenticated with a per-{sender, nexthop, or hostname} credential. 759 * Each bit corresponds to one type of smtp_sasl_password_file lookup key, 760 * and is turned on only when the corresponding main.cf parameter is turned 761 * on. 762 */ 763 #define COND_SASL_SMTP_KEY_FLAG_SENDER \ 764 ((var_smtp_sender_auth && *var_smtp_sasl_passwd) ? \ 765 SMTP_KEY_FLAG_SENDER : 0) 766 767 #define COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \ 768 (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0) 769 770 #ifdef USE_TLS 771 #define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \ 772 (TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0) 773 #else 774 #define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \ 775 (0) 776 #endif 777 778 #define COND_SASL_SMTP_KEY_FLAG_HOSTNAME \ 779 (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_HOSTNAME : 0) 780 781 /* 782 * Connection-cache destination lookup key, based on the delivery request 783 * nexthop. The SENDER attribute is a proxy for sender-dependent SASL 784 * credentials (or absence thereof), and prevents false connection sharing 785 * when different SASL credentials may be required for different deliveries 786 * to the same domain and port. Likewise, the delivery request nexthop 787 * (REQ_NEXTHOP) prevents false sharing of TLS identities (the destination 788 * key links only to appropriate endpoint lookup keys). The SERVICE 789 * attribute is a proxy for all request-independent configuration details. 790 * 791 * Be sure to include all features that are preserved in 792 * SMTP_FEATURE_ENDPOINT_MASK, otherwise a reused connection may be stored 793 * under the wrong key. 794 */ 795 #define SMTP_KEY_MASK_SCACHE_DEST_LABEL \ 796 (SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \ 797 | SMTP_KEY_FLAG_REQ_NEXTHOP | SMTP_KEY_FLAG_TLS_LEVEL \ 798 | SMTP_KEY_FLAG_REQ_SMTPUTF8 | SMTP_KEY_FLAG_REQTLS_LEVEL) 799 800 /* 801 * Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME, 802 * PORT and TLS_LEVEL attributes are proxies for SASL credentials and TLS 803 * authentication (or absence thereof), and prevent false connection sharing 804 * when different SASL credentials or TLS identities may be required for 805 * different deliveries to the same IP address and port. The SERVICE 806 * attribute is a proxy for all request-independent configuration details. 807 * 808 * Be sure to include all features that are preserved in 809 * SMTP_FEATURE_ENDPOINT_MASK, otherwise a reused connection may be stored 810 * under the wrong key. 811 */ 812 #define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \ 813 (SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \ 814 | COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \ 815 | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \ 816 | COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_ADDR \ 817 | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL \ 818 | SMTP_KEY_FLAG_REQ_SMTPUTF8 | SMTP_KEY_FLAG_REQTLS_LEVEL) 819 820 /* 821 * Silly little macros. 822 */ 823 #define STR(s) vstring_str(s) 824 #define LEN(s) VSTRING_LEN(s) 825 826 extern int smtp_mode; 827 828 #define VAR_LMTP_SMTP(x) (smtp_mode ? VAR_SMTP_##x : VAR_LMTP_##x) 829 #define LMTP_SMTP_SUFFIX(x) (smtp_mode ? x##_SMTP : x##_LMTP) 830 #define WARN_COMPAT_BREAK_LMTP_SMTP(x) \ 831 (smtp_mode ? warn_compat_break_smtp_##x : warn_compat_break_lmtp_##x) 832 833 /* 834 * Parsed command-line attributes. These do not change during the process 835 * lifetime. 836 */ 837 typedef struct { 838 int flags; /* from flags=, see below */ 839 } SMTP_CLI_ATTR; 840 841 #define SMTP_CLI_FLAG_DELIVERED_TO (1<<0) /* prepend Delivered-To: */ 842 #define SMTP_CLI_FLAG_ORIG_RCPT (1<<1) /* prepend X-Original-To: */ 843 #define SMTP_CLI_FLAG_RETURN_PATH (1<<2) /* prepend Return-Path: */ 844 #define SMTP_CLI_FLAG_FINAL_DELIVERY (1<<3) /* final, not relay */ 845 846 #define SMTP_CLI_MASK_ADD_HEADERS (SMTP_CLI_FLAG_DELIVERED_TO | \ 847 SMTP_CLI_FLAG_ORIG_RCPT | SMTP_CLI_FLAG_RETURN_PATH) 848 849 extern SMTP_CLI_ATTR smtp_cli_attr; 850 851 /* 852 * smtp_misc.c. 853 */ 854 extern void smtp_rewrite_generic_internal(VSTRING *, const char *); 855 extern void smtp_quote_822_address_flags(VSTRING *, const char *, int); 856 extern void smtp_quote_821_address(VSTRING *, const char *); 857 858 /* 859 * header_from_format support, for postmaster notifications. 860 */ 861 extern int smtp_hfrom_format; 862 863 /* 864 * smtp_tlsrpt.c. 865 */ 866 #if defined(USE_TLS) && defined(USE_TLSRPT) 867 extern int smtp_tlsrpt_post_jail(const char *sockname_pname, const char *sockname_pval); 868 extern void smtp_tlsrpt_create_wrapper(SMTP_STATE *state, const char *domain); 869 extern void smtp_tlsrpt_set_tls_policy(SMTP_STATE *state); 870 extern void smtp_tlsrpt_set_tcp_connection(SMTP_STATE *state); 871 extern void smtp_tlsrpt_set_ehlo_resp(SMTP_STATE *, const char *ehlo_resp); 872 873 #endif /* USE_TLSRPT && USE_TLS */ 874 875 /* 876 * This delivery requires SMTPUTF8 server support if the sender requested 877 * SMTPUTF8 support AND the delivery request involves at least one UTF-8 878 * envelope address or header value. 879 * 880 * If the sender requested SMTPUTF8 support but the delivery request involves 881 * no UTF-8 envelope address or header value, then we could still deliver 882 * such mail to a non-SMTPUTF8 server, except that we must either 883 * uxtext-encode ORCPT parameters or not send them. We cannot encode the 884 * ORCPT in xtext, because legacy SMTP requires that the unencoded address 885 * consist entirely of printable (graphic and white space) characters from 886 * the US-ASCII repertoire (RFC 3461 section 4). A correct uxtext encoder 887 * will produce a result that an xtext decoder will pass through unchanged. 888 */ 889 #define DELIVERY_REQUIRES_SMTPUTF8(request) \ 890 (((request)->sendopts & SMTPUTF8_FLAG_REQUESTED) \ 891 && ((request)->sendopts & SMTPUTF8_FLAG_DERIVED)) 892 893 /* LICENSE 894 /* .ad 895 /* .fi 896 /* The Secure Mailer license must be distributed with this software. 897 /* AUTHOR(S) 898 /* Wietse Venema 899 /* IBM T.J. Watson Research 900 /* P.O. Box 704 901 /* Yorktown Heights, NY 10598, USA 902 /* 903 /* Wietse Venema 904 /* Google, Inc. 905 /* 111 8th Avenue 906 /* New York, NY 10011, USA 907 /* 908 /* TLS support originally by: 909 /* Lutz Jaenicke 910 /* BTU Cottbus 911 /* Allgemeine Elektrotechnik 912 /* Universitaetsplatz 3-4 913 /* D-03044 Cottbus, Germany 914 /* 915 /* Victor Duchovni 916 /* Morgan Stanley 917 /*--*/ 918