Home | History | Annotate | Line # | Download | only in smtp
      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