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