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