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