29 #include <deliver_request.h>
31 #include <string_list.h>
35 #include <header_body_checks.h>
38 * Postfix TLS library.
43 * State information associated with each SMTP delivery request.
44 * Session-specific state is stored separately.
46 typedef struct SMTP_STATE
{
47 int misc_flags
; /* processing flags, see below */
48 VSTREAM
*src
; /* queue file stream */
49 const char *service
; /* transport name */
50 DELIVER_REQUEST
*request
; /* envelope info, offsets */
51 struct SMTP_SESSION
*session
; /* network connection */
52 int status
; /* delivery status */
53 ssize_t space_left
; /* output length control */
56 * Connection cache support. The (nexthop_lookup_mx, nexthop_domain,
57 * nexthop_port) triple is a parsed next-hop specification, and should be
58 * a data type by itself. The (service, nexthop_mumble) members specify
59 * the name under which the first good connection should be cached. The
60 * nexthop_mumble members are initialized by the connection management
61 * module. nexthop_domain is reset to null after one connection is saved
62 * under the (service, nexthop_mumble) label, or upon exit from the
63 * connection management module.
65 HTABLE
*cache_used
; /* cached addresses that were used */
66 VSTRING
*dest_label
; /* cached logical/physical binding */
67 VSTRING
*dest_prop
; /* binding properties, passivated */
68 VSTRING
*endp_label
; /* cached session physical endpoint */
69 VSTRING
*endp_prop
; /* endpoint properties, passivated */
70 int nexthop_lookup_mx
; /* do/don't MX expand nexthop_domain */
71 char *nexthop_domain
; /* next-hop name or bare address */
72 unsigned nexthop_port
; /* next-hop TCP port, network order */
75 * Flags and counters to control the handling of mail delivery errors.
76 * There is some redundancy for sanity checking. At the end of an SMTP
77 * session all recipients should be marked one way or the other.
79 int rcpt_left
; /* recipients left over */
80 int rcpt_drop
; /* recipients marked as drop */
81 int rcpt_keep
; /* recipients marked as keep */
84 * DSN Support introduced major bloat in error processing.
86 DSN_BUF
*why
; /* on-the-fly formatting buffer */
89 #define SET_NEXTHOP_STATE(state, lookup_mx, domain, port) { \
90 (state)->nexthop_lookup_mx = lookup_mx; \
91 (state)->nexthop_domain = mystrdup(domain); \
92 (state)->nexthop_port = port; \
95 #define FREE_NEXTHOP_STATE(state) { \
96 myfree((state)->nexthop_domain); \
97 (state)->nexthop_domain = 0; \
100 #define HAVE_NEXTHOP_STATE(state) ((state)->nexthop_domain != 0)
106 #define SMTP_FEATURE_ESMTP (1<<0)
107 #define SMTP_FEATURE_8BITMIME (1<<1)
108 #define SMTP_FEATURE_PIPELINING (1<<2)
109 #define SMTP_FEATURE_SIZE (1<<3)
110 #define SMTP_FEATURE_STARTTLS (1<<4)
111 #define SMTP_FEATURE_AUTH (1<<5)
112 #define SMTP_FEATURE_XFORWARD_NAME (1<<7)
113 #define SMTP_FEATURE_XFORWARD_ADDR (1<<8)
114 #define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
115 #define SMTP_FEATURE_XFORWARD_HELO (1<<10)
116 #define SMTP_FEATURE_XFORWARD_DOMAIN (1<<11)
117 #define SMTP_FEATURE_BEST_MX (1<<12) /* for next-hop or fall-back */
118 #define SMTP_FEATURE_RSET_REJECTED (1<<13) /* RSET probe rejected */
119 #define SMTP_FEATURE_FROM_CACHE (1<<14) /* cached connection */
120 #define SMTP_FEATURE_DSN (1<<15) /* DSN supported */
121 #define SMTP_FEATURE_PIX_NO_ESMTP (1<<16) /* PIX smtp fixup mode */
122 #define SMTP_FEATURE_PIX_DELAY_DOTCRLF (1<<17) /* PIX smtp fixup mode */
123 #define SMTP_FEATURE_XFORWARD_PORT (1<<18)
126 * Features that passivate under the endpoint.
128 #define SMTP_FEATURE_ENDPOINT_MASK \
129 (~(SMTP_FEATURE_BEST_MX | SMTP_FEATURE_RSET_REJECTED \
130 | SMTP_FEATURE_FROM_CACHE))
133 * Features that passivate under the logical destination.
135 #define SMTP_FEATURE_DESTINATION_MASK (SMTP_FEATURE_BEST_MX)
140 #define SMTP_MISC_FLAG_LOOP_DETECT (1<<0)
141 #define SMTP_MISC_FLAG_IN_STARTTLS (1<<1)
142 #define SMTP_MISC_FLAG_USE_LMTP (1<<2)
143 #define SMTP_MISC_FLAG_FIRST_NEXTHOP (1<<3)
144 #define SMTP_MISC_FLAG_FINAL_NEXTHOP (1<<4)
145 #define SMTP_MISC_FLAG_FINAL_SERVER (1<<5)
146 #define SMTP_MISC_FLAG_CONN_LOAD (1<<6)
147 #define SMTP_MISC_FLAG_CONN_STORE (1<<7)
148 #define SMTP_MISC_FLAG_COMPLETE_SESSION (1<<8)
150 #define SMTP_MISC_FLAG_CONN_CACHE_MASK \
151 (SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE)
156 #define SMTP_HAS_DSN(why) (STR((why)->status)[0] != 0)
157 #define SMTP_HAS_SOFT_DSN(why) (STR((why)->status)[0] == '4')
158 #define SMTP_HAS_HARD_DSN(why) (STR((why)->status)[0] == '5')
159 #define SMTP_HAS_LOOP_DSN(why) \
160 (SMTP_HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
162 #define SMTP_SET_SOFT_DSN(why) (STR((why)->status)[0] = '4')
163 #define SMTP_SET_HARD_DSN(why) (STR((why)->status)[0] = '5')
165 extern int smtp_host_lookup_mask
; /* host lookup methods to use */
167 #define SMTP_HOST_FLAG_DNS (1<<0)
168 #define SMTP_HOST_FLAG_NATIVE (1<<1)
170 extern SCACHE
*smtp_scache
; /* connection cache instance */
171 extern STRING_LIST
*smtp_cache_dest
; /* cached destinations */
173 extern MAPS
*smtp_ehlo_dis_maps
; /* ehlo keyword filter */
175 extern MAPS
*smtp_pix_bug_maps
; /* PIX workarounds */
177 extern MAPS
*smtp_generic_maps
; /* make internal address valid */
178 extern int smtp_ext_prop_mask
; /* address externsion propagation */
182 extern TLS_APPL_STATE
*smtp_tls_ctx
; /* client-side TLS engine */
186 extern HBC_CHECKS
*smtp_header_checks
; /* limited header checks */
187 extern HBC_CHECKS
*smtp_body_checks
; /* limited body checks */
192 typedef struct SMTP_SESSION
{
193 VSTREAM
*stream
; /* network connection */
194 char *dest
; /* nexthop or fallback */
195 char *host
; /* mail exchanger */
196 char *addr
; /* mail exchanger */
197 char *namaddr
; /* mail exchanger */
198 char *helo
; /* helo response */
199 unsigned port
; /* network byte order */
200 char *namaddrport
; /* mail exchanger, incl. port */
202 VSTRING
*buffer
; /* I/O buffer */
203 VSTRING
*scratch
; /* scratch buffer */
204 VSTRING
*scratch2
; /* scratch buffer */
206 int features
; /* server features */
207 off_t size_limit
; /* server limit or unknown */
209 ARGV
*history
; /* transaction log */
210 int error_mask
; /* error classes */
211 struct MIME_STATE
*mime_state
; /* mime state machine */
213 int send_proto_helo
; /* XFORWARD support */
215 time_t expire_time
; /* session reuse expiration time */
216 int reuse_count
; /* # of times reused (for logging) */
217 int dead
; /* No further I/O allowed */
220 char *sasl_mechanism_list
; /* server mechanism list */
221 char *sasl_username
; /* client username */
222 char *sasl_passwd
; /* client password */
223 struct XSASL_CLIENT
*sasl_client
; /* SASL internal state */
224 VSTRING
*sasl_reply
; /* client response */
228 * TLS related state, don't forget to initialize in session_tls_init()!
231 TLS_SESS_STATE
*tls_context
; /* TLS session state */
232 char *tls_nexthop
; /* Nexthop domain for cert checks */
233 int tls_level
; /* TLS enforcement level */
234 int tls_retry_plain
; /* Try plain when TLS handshake fails */
235 char *tls_protocols
; /* Acceptable SSL protocols */
236 char *tls_grade
; /* Cipher grade: "export", ... */
237 VSTRING
*tls_exclusions
; /* Excluded SSL ciphers */
238 ARGV
*tls_matchargv
; /* Cert match patterns */
241 SMTP_STATE
*state
; /* back link */
244 extern SMTP_SESSION
*smtp_session_alloc(VSTREAM
*, const char *, const char *,
245 const char *, unsigned, time_t, int);
246 extern void smtp_session_free(SMTP_SESSION
*);
247 extern int smtp_session_passivate(SMTP_SESSION
*, VSTRING
*, VSTRING
*);
248 extern SMTP_SESSION
*smtp_session_activate(int, VSTRING
*, VSTRING
*);
251 extern void smtp_tls_list_init(void);
258 #define SMTP_HNAME(rr) (var_smtp_cname_overr ? (rr)->rname : (rr)->qname)
263 extern int smtp_connect(SMTP_STATE
*);
268 extern int smtp_helo(SMTP_STATE
*);
269 extern int smtp_xfer(SMTP_STATE
*);
270 extern int smtp_rset(SMTP_STATE
*);
271 extern int smtp_quit(SMTP_STATE
*);
273 extern HBC_CALL_BACKS smtp_hbc_callbacks
[];
276 * A connection is re-usable if session->expire_time is > 0 and the
277 * expiration time has not been reached. This is subtle because the timer
278 * can expire between sending a command and receiving the reply for that
281 * But wait, there is more! When SMTP command pipelining is enabled, there are
282 * two protocol loops that execute at very different times: one loop that
283 * generates commands, and one loop that receives replies to those commands.
284 * These will be called "sender loop" and "receiver loop", respectively. At
285 * well-defined protocol synchronization points, the sender loop pauses to
286 * let the receiver loop catch up.
288 * When we choose to reuse a connection, both the sender and receiver protocol
289 * loops end with "." (mail delivery) or "RSET" (address probe). When we
290 * choose not to reuse, both the sender and receiver protocol loops end with
291 * "QUIT". The problem is that we must make the same protocol choices in
292 * both the sender and receiver loops, even though those loops may execute
293 * at completely different times.
295 * We "freeze" the choice in the sender loop, just before we generate "." or
296 * "RSET". The reader loop leaves the connection cachable even if the timer
297 * expires by the time the response arrives. The connection cleanup code
298 * will call smtp_quit() for connections with an expired cache expiration
301 * We could have made the programmer's life a lot simpler by not making a
302 * choice at all, and always leaving it up to the connection cleanup code to
303 * call smtp_quit() for connections with an expired cache expiration timer.
305 * As a general principle, neither the sender loop nor the receiver loop must
306 * modify the connection caching state, if that can affect the receiver
307 * state machine for not-yet processed replies to already-generated
308 * commands. This restriction does not apply when we have to exit the
309 * protocol loops prematurely due to e.g., timeout or connection loss, so
310 * that those pending replies will never be received.
312 * But wait, there is even more! Only the first good connection for a specific
313 * destination may be cached under both the next-hop destination name and
314 * the server address; connections to alternate servers must be cached under
315 * the server address alone. This means we must distinguish between bad
316 * connections and other reasons why connections cannot be cached.
318 #define THIS_SESSION_IS_CACHED \
319 (!THIS_SESSION_IS_DEAD && session->expire_time > 0)
321 #define THIS_SESSION_IS_EXPIRED \
322 (THIS_SESSION_IS_CACHED \
323 && session->expire_time < vstream_ftime(session->stream))
325 #define THIS_SESSION_IS_BAD \
326 (!THIS_SESSION_IS_DEAD && session->expire_time < 0)
328 #define THIS_SESSION_IS_DEAD \
331 /* Bring the bad news. */
333 #define DONT_CACHE_THIS_SESSION \
334 (session->expire_time = 0)
336 #define DONT_CACHE_BAD_SESSION \
337 (session->expire_time = -1)
339 #define DONT_USE_DEAD_SESSION \
342 /* Initialization. */
344 #define USE_NEWBORN_SESSION \
347 #define CACHE_THIS_SESSION_UNTIL(when) \
348 (session->expire_time = (when))
351 * Encapsulate the following so that we don't expose details of of
352 * connection management and error handling to the SMTP protocol engine.
354 #define RETRY_AS_PLAINTEXT do { \
355 session->tls_retry_plain = 1; \
356 state->misc_flags &= ~SMTP_MISC_FLAG_FINAL_SERVER; \
362 typedef struct SMTP_RESP
{ /* server response */
363 int code
; /* SMTP code */
364 const char *dsn
; /* enhanced status */
365 char *str
; /* full reply */
366 VSTRING
*dsn_buf
; /* status buffer */
367 VSTRING
*str_buf
; /* reply buffer */
370 extern void PRINTFLIKE(2, 3) smtp_chat_cmd(SMTP_SESSION
*, char *,...);
371 extern SMTP_RESP
*smtp_chat_resp(SMTP_SESSION
*);
372 extern void smtp_chat_init(SMTP_SESSION
*);
373 extern void smtp_chat_reset(SMTP_SESSION
*);
374 extern void smtp_chat_notify(SMTP_SESSION
*);
376 #define SMTP_RESP_FAKE(resp, _dsn) \
378 (resp)->dsn = (_dsn), \
379 (resp)->str = DSN_BY_LOCAL_MTA, \
382 #define DSN_BY_LOCAL_MTA ((char *) 0) /* DSN issued by local MTA */
385 * These operations implement a redundant mark-and-sweep algorithm that
386 * explicitly accounts for the fate of every recipient. The interface is
387 * documented in smtp_rcpt.c, which also implements the sweeping. The
388 * smtp_trouble.c module does most of the marking after failure.
390 * When a delivery fails or succeeds, take one of the following actions:
392 * - Mark the recipient as KEEP (deliver to alternate MTA) and do not update
393 * the delivery request status.
395 * - Mark the recipient as DROP (remove from delivery request), log whether
396 * delivery succeeded or failed, delete the recipient from the queue file
397 * and/or update defer or bounce logfiles, and update the delivery request
400 * At the end of a delivery attempt, all recipients must be marked one way or
401 * the other. Failure to do so will trigger a panic.
403 #define SMTP_RCPT_STATE_KEEP 1 /* send to backup host */
404 #define SMTP_RCPT_STATE_DROP 2 /* remove from request */
405 #define SMTP_RCPT_INIT(state) do { \
406 (state)->rcpt_drop = (state)->rcpt_keep = 0; \
407 (state)->rcpt_left = state->request->rcpt_list.len; \
410 #define SMTP_RCPT_DROP(state, rcpt) do { \
411 (rcpt)->u.status = SMTP_RCPT_STATE_DROP; (state)->rcpt_drop++; \
414 #define SMTP_RCPT_KEEP(state, rcpt) do { \
415 (rcpt)->u.status = SMTP_RCPT_STATE_KEEP; (state)->rcpt_keep++; \
418 #define SMTP_RCPT_ISMARKED(rcpt) ((rcpt)->u.status != 0)
420 #define SMTP_RCPT_LEFT(state) (state)->rcpt_left
422 extern void smtp_rcpt_cleanup(SMTP_STATE
*);
423 extern void smtp_rcpt_done(SMTP_STATE
*, SMTP_RESP
*, RECIPIENT
*);
428 extern int smtp_sess_fail(SMTP_STATE
*);
429 extern int PRINTFLIKE(4, 5) smtp_site_fail(SMTP_STATE
*, const char *,
430 SMTP_RESP
*, const char *,...);
431 extern int PRINTFLIKE(4, 5) smtp_mesg_fail(SMTP_STATE
*, const char *,
432 SMTP_RESP
*, const char *,...);
433 extern void PRINTFLIKE(5, 6) smtp_rcpt_fail(SMTP_STATE
*, RECIPIENT
*,
434 const char *, SMTP_RESP
*,
436 extern int smtp_stream_except(SMTP_STATE
*, int, const char *);
441 extern const char *smtp_unalias_name(const char *);
442 extern VSTRING
*smtp_unalias_addr(VSTRING
*, const char *);
447 extern SMTP_STATE
*smtp_state_alloc(void);
448 extern void smtp_state_free(SMTP_STATE
*);
453 extern int smtp_map11_external(VSTRING
*, MAPS
*, int);
454 extern int smtp_map11_tree(TOK822
*, MAPS
*, int);
455 extern int smtp_map11_internal(VSTRING
*, MAPS
*, int);
458 * Silly little macros.
460 #define STR(s) vstring_str(s)
461 #define LEN(s) VSTRING_LEN(s)
466 /* The Secure Mailer license must be distributed with this software.
469 /* IBM T.J. Watson Research
471 /* Yorktown Heights, NY 10598, USA
473 /* TLS support originally by:
476 /* Allgemeine Elektrotechnik
477 /* Universitaetsplatz 3-4
478 /* D-03044 Cottbus, Germany