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