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