xref: /netbsd-src/external/ibm-public/postfix/dist/src/smtp/smtp.h (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: smtp.h,v 1.1.1.3 2011/03/02 19:32:31 tron 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   * State information associated with each SMTP delivery request.
45   * Session-specific state is stored separately.
46   */
47 typedef struct SMTP_STATE {
48     int     misc_flags;			/* processing flags, see below */
49     VSTREAM *src;			/* queue file stream */
50     const char *service;		/* transport name */
51     DELIVER_REQUEST *request;		/* envelope info, offsets */
52     struct SMTP_SESSION *session;	/* network connection */
53     int     status;			/* delivery status */
54     ssize_t space_left;			/* output length control */
55 
56     /*
57      * Connection cache support. The (nexthop_lookup_mx, nexthop_domain,
58      * nexthop_port) triple is a parsed next-hop specification, and should be
59      * a data type by itself. The (service, nexthop_mumble) members specify
60      * the name under which the first good connection should be cached. The
61      * nexthop_mumble members are initialized by the connection management
62      * module. nexthop_domain is reset to null after one connection is saved
63      * under the (service, nexthop_mumble) label, or upon exit from the
64      * connection management module.
65      */
66     HTABLE *cache_used;			/* cached addresses that were used */
67     VSTRING *dest_label;		/* cached logical/physical binding */
68     VSTRING *dest_prop;			/* binding properties, passivated */
69     VSTRING *endp_label;		/* cached session physical endpoint */
70     VSTRING *endp_prop;			/* endpoint properties, passivated */
71     int     nexthop_lookup_mx;		/* do/don't MX expand nexthop_domain */
72     char   *nexthop_domain;		/* next-hop name or bare address */
73     unsigned nexthop_port;		/* next-hop TCP port, network order */
74 
75     /*
76      * Flags and counters to control the handling of mail delivery errors.
77      * There is some redundancy for sanity checking. At the end of an SMTP
78      * session all recipients should be marked one way or the other.
79      */
80     int     rcpt_left;			/* recipients left over */
81     int     rcpt_drop;			/* recipients marked as drop */
82     int     rcpt_keep;			/* recipients marked as keep */
83 
84     /*
85      * DSN Support introduced major bloat in error processing.
86      */
87     DSN_BUF *why;			/* on-the-fly formatting buffer */
88 } SMTP_STATE;
89 
90 #define SET_NEXTHOP_STATE(state, lookup_mx, domain, port) { \
91 	(state)->nexthop_lookup_mx = lookup_mx; \
92 	(state)->nexthop_domain = mystrdup(domain); \
93 	(state)->nexthop_port = port; \
94     }
95 
96 #define FREE_NEXTHOP_STATE(state) { \
97 	myfree((state)->nexthop_domain); \
98 	(state)->nexthop_domain = 0; \
99     }
100 
101 #define HAVE_NEXTHOP_STATE(state) ((state)->nexthop_domain != 0)
102 
103 
104  /*
105   * Server features.
106   */
107 #define SMTP_FEATURE_ESMTP		(1<<0)
108 #define SMTP_FEATURE_8BITMIME		(1<<1)
109 #define SMTP_FEATURE_PIPELINING		(1<<2)
110 #define SMTP_FEATURE_SIZE		(1<<3)
111 #define SMTP_FEATURE_STARTTLS		(1<<4)
112 #define SMTP_FEATURE_AUTH		(1<<5)
113 #define SMTP_FEATURE_XFORWARD_NAME	(1<<7)
114 #define SMTP_FEATURE_XFORWARD_ADDR	(1<<8)
115 #define SMTP_FEATURE_XFORWARD_PROTO	(1<<9)
116 #define SMTP_FEATURE_XFORWARD_HELO	(1<<10)
117 #define SMTP_FEATURE_XFORWARD_DOMAIN	(1<<11)
118 #define SMTP_FEATURE_BEST_MX		(1<<12)	/* for next-hop or fall-back */
119 #define SMTP_FEATURE_RSET_REJECTED	(1<<13)	/* RSET probe rejected */
120 #define SMTP_FEATURE_FROM_CACHE		(1<<14)	/* cached connection */
121 #define SMTP_FEATURE_DSN		(1<<15)	/* DSN supported */
122 #define SMTP_FEATURE_PIX_NO_ESMTP	(1<<16)	/* PIX smtp fixup mode */
123 #define SMTP_FEATURE_PIX_DELAY_DOTCRLF	(1<<17)	/* PIX smtp fixup mode */
124 #define SMTP_FEATURE_XFORWARD_PORT	(1<<18)
125 #define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19)	/* CVE-2009-3555 */
126 #define SMTP_FEATURE_XFORWARD_IDENT	(1<<20)
127 
128  /*
129   * Features that passivate under the endpoint.
130   */
131 #define SMTP_FEATURE_ENDPOINT_MASK \
132 	(~(SMTP_FEATURE_BEST_MX | SMTP_FEATURE_RSET_REJECTED \
133 	| SMTP_FEATURE_FROM_CACHE))
134 
135  /*
136   * Features that passivate under the logical destination.
137   */
138 #define SMTP_FEATURE_DESTINATION_MASK (SMTP_FEATURE_BEST_MX)
139 
140  /*
141   * Misc flags.
142   */
143 #define SMTP_MISC_FLAG_LOOP_DETECT	(1<<0)
144 #define	SMTP_MISC_FLAG_IN_STARTTLS	(1<<1)
145 #define SMTP_MISC_FLAG_USE_LMTP		(1<<2)
146 #define SMTP_MISC_FLAG_FIRST_NEXTHOP	(1<<3)
147 #define SMTP_MISC_FLAG_FINAL_NEXTHOP	(1<<4)
148 #define SMTP_MISC_FLAG_FINAL_SERVER	(1<<5)
149 #define SMTP_MISC_FLAG_CONN_LOAD	(1<<6)
150 #define SMTP_MISC_FLAG_CONN_STORE	(1<<7)
151 #define SMTP_MISC_FLAG_COMPLETE_SESSION	(1<<8)
152 #define SMTP_MISC_FLAG_PREF_IPV6	(1<<9)
153 #define SMTP_MISC_FLAG_PREF_IPV4	(1<<10)
154 
155 #define SMTP_MISC_FLAG_CONN_CACHE_MASK \
156 	(SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE)
157 
158  /*
159   * smtp.c
160   */
161 #define SMTP_HAS_DSN(why)	(STR((why)->status)[0] != 0)
162 #define SMTP_HAS_SOFT_DSN(why)	(STR((why)->status)[0] == '4')
163 #define SMTP_HAS_HARD_DSN(why)	(STR((why)->status)[0] == '5')
164 #define SMTP_HAS_LOOP_DSN(why) \
165     (SMTP_HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
166 
167 #define SMTP_SET_SOFT_DSN(why)	(STR((why)->status)[0] = '4')
168 #define SMTP_SET_HARD_DSN(why)	(STR((why)->status)[0] = '5')
169 
170 extern int smtp_host_lookup_mask;	/* host lookup methods to use */
171 
172 #define SMTP_HOST_FLAG_DNS	(1<<0)
173 #define SMTP_HOST_FLAG_NATIVE	(1<<1)
174 
175 extern SCACHE *smtp_scache;		/* connection cache instance */
176 extern STRING_LIST *smtp_cache_dest;	/* cached destinations */
177 
178 extern MAPS *smtp_ehlo_dis_maps;	/* ehlo keyword filter */
179 
180 extern MAPS *smtp_pix_bug_maps;		/* PIX workarounds */
181 
182 extern MAPS *smtp_generic_maps;		/* make internal address valid */
183 extern int smtp_ext_prop_mask;		/* address externsion propagation */
184 extern unsigned smtp_dns_res_opt;	/* DNS query flags */
185 
186 #ifdef USE_TLS
187 
188 extern TLS_APPL_STATE *smtp_tls_ctx;	/* client-side TLS engine */
189 
190 #endif
191 
192 extern HBC_CHECKS *smtp_header_checks;	/* limited header checks */
193 extern HBC_CHECKS *smtp_body_checks;	/* limited body checks */
194 
195  /*
196   * smtp_session.c
197   */
198 typedef struct SMTP_SESSION {
199     VSTREAM *stream;			/* network connection */
200     char   *dest;			/* nexthop or fallback */
201     char   *host;			/* mail exchanger */
202     char   *addr;			/* mail exchanger */
203     char   *namaddr;			/* mail exchanger */
204     char   *helo;			/* helo response */
205     unsigned port;			/* network byte order */
206     char   *namaddrport;		/* mail exchanger, incl. port */
207 
208     VSTRING *buffer;			/* I/O buffer */
209     VSTRING *scratch;			/* scratch buffer */
210     VSTRING *scratch2;			/* scratch buffer */
211 
212     int     features;			/* server features */
213     off_t   size_limit;			/* server limit or unknown */
214 
215     ARGV   *history;			/* transaction log */
216     int     error_mask;			/* error classes */
217     struct MIME_STATE *mime_state;	/* mime state machine */
218 
219     int     send_proto_helo;		/* XFORWARD support */
220 
221     time_t  expire_time;		/* session reuse expiration time */
222     int     reuse_count;		/* # of times reused (for logging) */
223     int     dead;			/* No further I/O allowed */
224 
225 #ifdef USE_SASL_AUTH
226     char   *sasl_mechanism_list;	/* server mechanism list */
227     char   *sasl_username;		/* client username */
228     char   *sasl_passwd;		/* client password */
229     struct XSASL_CLIENT *sasl_client;	/* SASL internal state */
230     VSTRING *sasl_reply;		/* client response */
231 #endif
232 
233     /*
234      * TLS related state, don't forget to initialize in session_tls_init()!
235      */
236 #ifdef USE_TLS
237     TLS_SESS_STATE *tls_context;	/* TLS session state */
238     char   *tls_nexthop;		/* Nexthop domain for cert checks */
239     int     tls_level;			/* TLS enforcement level */
240     int     tls_retry_plain;		/* Try plain when TLS handshake fails */
241     char   *tls_protocols;		/* Acceptable SSL protocols */
242     char   *tls_grade;			/* Cipher grade: "export", ... */
243     VSTRING *tls_exclusions;		/* Excluded SSL ciphers */
244     ARGV   *tls_matchargv;		/* Cert match patterns */
245 #endif
246 
247     SMTP_STATE *state;			/* back link */
248 } SMTP_SESSION;
249 
250 extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, const char *, const char *,
251 			               const char *, unsigned, time_t, int);
252 extern void smtp_session_free(SMTP_SESSION *);
253 extern int smtp_session_passivate(SMTP_SESSION *, VSTRING *, VSTRING *);
254 extern SMTP_SESSION *smtp_session_activate(int, VSTRING *, VSTRING *);
255 
256 #ifdef USE_TLS
257 extern void smtp_tls_list_init(void);
258 
259 #endif
260 
261  /*
262   * What's in a name?
263   */
264 #define SMTP_HNAME(rr) (var_smtp_cname_overr ? (rr)->rname : (rr)->qname)
265 
266  /*
267   * smtp_connect.c
268   */
269 extern int smtp_connect(SMTP_STATE *);
270 
271  /*
272   * smtp_proto.c
273   */
274 extern int smtp_helo(SMTP_STATE *);
275 extern int smtp_xfer(SMTP_STATE *);
276 extern int smtp_rset(SMTP_STATE *);
277 extern int smtp_quit(SMTP_STATE *);
278 
279 extern HBC_CALL_BACKS smtp_hbc_callbacks[];
280 
281  /*
282   * A connection is re-usable if session->expire_time is > 0 and the
283   * expiration time has not been reached.  This is subtle because the timer
284   * can expire between sending a command and receiving the reply for that
285   * command.
286   *
287   * But wait, there is more! When SMTP command pipelining is enabled, there are
288   * two protocol loops that execute at very different times: one loop that
289   * generates commands, and one loop that receives replies to those commands.
290   * These will be called "sender loop" and "receiver loop", respectively. At
291   * well-defined protocol synchronization points, the sender loop pauses to
292   * let the receiver loop catch up.
293   *
294   * When we choose to reuse a connection, both the sender and receiver protocol
295   * loops end with "." (mail delivery) or "RSET" (address probe). When we
296   * choose not to reuse, both the sender and receiver protocol loops end with
297   * "QUIT". The problem is that we must make the same protocol choices in
298   * both the sender and receiver loops, even though those loops may execute
299   * at completely different times.
300   *
301   * We "freeze" the choice in the sender loop, just before we generate "." or
302   * "RSET". The reader loop leaves the connection cachable even if the timer
303   * expires by the time the response arrives. The connection cleanup code
304   * will call smtp_quit() for connections with an expired cache expiration
305   * timer.
306   *
307   * We could have made the programmer's life a lot simpler by not making a
308   * choice at all, and always leaving it up to the connection cleanup code to
309   * call smtp_quit() for connections with an expired cache expiration timer.
310   *
311   * As a general principle, neither the sender loop nor the receiver loop must
312   * modify the connection caching state, if that can affect the receiver
313   * state machine for not-yet processed replies to already-generated
314   * commands. This restriction does not apply when we have to exit the
315   * protocol loops prematurely due to e.g., timeout or connection loss, so
316   * that those pending replies will never be received.
317   *
318   * But wait, there is even more! Only the first good connection for a specific
319   * destination may be cached under both the next-hop destination name and
320   * the server address; connections to alternate servers must be cached under
321   * the server address alone. This means we must distinguish between bad
322   * connections and other reasons why connections cannot be cached.
323   */
324 #define THIS_SESSION_IS_CACHED \
325 	(!THIS_SESSION_IS_DEAD && session->expire_time > 0)
326 
327 #define THIS_SESSION_IS_EXPIRED \
328 	(THIS_SESSION_IS_CACHED \
329 	    && session->expire_time < vstream_ftime(session->stream))
330 
331 #define THIS_SESSION_IS_BAD \
332 	(!THIS_SESSION_IS_DEAD && session->expire_time < 0)
333 
334 #define THIS_SESSION_IS_DEAD \
335 	(session->dead != 0)
336 
337  /* Bring the bad news. */
338 
339 #define DONT_CACHE_THIS_SESSION \
340 	(session->expire_time = 0)
341 
342 #define DONT_CACHE_BAD_SESSION \
343 	(session->expire_time = -1)
344 
345 #define DONT_USE_DEAD_SESSION \
346 	(session->dead = 1)
347 
348  /* Initialization. */
349 
350 #define USE_NEWBORN_SESSION \
351 	(session->dead = 0)
352 
353 #define CACHE_THIS_SESSION_UNTIL(when) \
354 	(session->expire_time = (when))
355 
356  /*
357   * Encapsulate the following so that we don't expose details of of
358   * connection management and error handling to the SMTP protocol engine.
359   */
360 #define RETRY_AS_PLAINTEXT do { \
361 	session->tls_retry_plain = 1; \
362 	state->misc_flags &= ~SMTP_MISC_FLAG_FINAL_SERVER; \
363     } while (0)
364 
365  /*
366   * smtp_chat.c
367   */
368 typedef struct SMTP_RESP {		/* server response */
369     int     code;			/* SMTP code */
370     const char *dsn;			/* enhanced status */
371     char   *str;			/* full reply */
372     VSTRING *dsn_buf;			/* status buffer */
373     VSTRING *str_buf;			/* reply buffer */
374 } SMTP_RESP;
375 
376 extern void PRINTFLIKE(2, 3) smtp_chat_cmd(SMTP_SESSION *, const char *,...);
377 extern DICT *smtp_chat_resp_filter;
378 extern SMTP_RESP *smtp_chat_resp(SMTP_SESSION *);
379 extern void smtp_chat_init(SMTP_SESSION *);
380 extern void smtp_chat_reset(SMTP_SESSION *);
381 extern void smtp_chat_notify(SMTP_SESSION *);
382 
383 #define SMTP_RESP_FAKE(resp, _dsn) \
384     ((resp)->code = 0, \
385      (resp)->dsn = (_dsn), \
386      (resp)->str = DSN_BY_LOCAL_MTA, \
387      (resp))
388 
389 #define DSN_BY_LOCAL_MTA	((char *) 0)	/* DSN issued by local MTA */
390 
391  /*
392   * These operations implement a redundant mark-and-sweep algorithm that
393   * explicitly accounts for the fate of every recipient. The interface is
394   * documented in smtp_rcpt.c, which also implements the sweeping. The
395   * smtp_trouble.c module does most of the marking after failure.
396   *
397   * When a delivery fails or succeeds, take one of the following actions:
398   *
399   * - Mark the recipient as KEEP (deliver to alternate MTA) and do not update
400   * the delivery request status.
401   *
402   * - Mark the recipient as DROP (remove from delivery request), log whether
403   * delivery succeeded or failed, delete the recipient from the queue file
404   * and/or update defer or bounce logfiles, and update the delivery request
405   * status.
406   *
407   * At the end of a delivery attempt, all recipients must be marked one way or
408   * the other. Failure to do so will trigger a panic.
409   */
410 #define SMTP_RCPT_STATE_KEEP	1	/* send to backup host */
411 #define SMTP_RCPT_STATE_DROP	2	/* remove from request */
412 #define SMTP_RCPT_INIT(state) do { \
413 	    (state)->rcpt_drop = (state)->rcpt_keep = 0; \
414 	    (state)->rcpt_left = state->request->rcpt_list.len; \
415 	} while (0)
416 
417 #define SMTP_RCPT_DROP(state, rcpt) do { \
418 	    (rcpt)->u.status = SMTP_RCPT_STATE_DROP; (state)->rcpt_drop++; \
419 	} while (0)
420 
421 #define SMTP_RCPT_KEEP(state, rcpt) do { \
422 	    (rcpt)->u.status = SMTP_RCPT_STATE_KEEP; (state)->rcpt_keep++; \
423 	} while (0)
424 
425 #define SMTP_RCPT_ISMARKED(rcpt) ((rcpt)->u.status != 0)
426 
427 #define SMTP_RCPT_LEFT(state) (state)->rcpt_left
428 
429 extern void smtp_rcpt_cleanup(SMTP_STATE *);
430 extern void smtp_rcpt_done(SMTP_STATE *, SMTP_RESP *, RECIPIENT *);
431 
432  /*
433   * smtp_trouble.c
434   */
435 extern int smtp_sess_fail(SMTP_STATE *);
436 extern int PRINTFLIKE(4, 5) smtp_site_fail(SMTP_STATE *, const char *,
437 				             SMTP_RESP *, const char *,...);
438 extern int PRINTFLIKE(4, 5) smtp_mesg_fail(SMTP_STATE *, const char *,
439 				             SMTP_RESP *, const char *,...);
440 extern void PRINTFLIKE(5, 6) smtp_rcpt_fail(SMTP_STATE *, RECIPIENT *,
441 					          const char *, SMTP_RESP *,
442 					            const char *,...);
443 extern int smtp_stream_except(SMTP_STATE *, int, const char *);
444 
445  /*
446   * smtp_unalias.c
447   */
448 extern const char *smtp_unalias_name(const char *);
449 extern VSTRING *smtp_unalias_addr(VSTRING *, const char *);
450 
451  /*
452   * smtp_state.c
453   */
454 extern SMTP_STATE *smtp_state_alloc(void);
455 extern void smtp_state_free(SMTP_STATE *);
456 
457  /*
458   * smtp_map11.c
459   */
460 extern int smtp_map11_external(VSTRING *, MAPS *, int);
461 extern int smtp_map11_tree(TOK822 *, MAPS *, int);
462 extern int smtp_map11_internal(VSTRING *, MAPS *, int);
463 
464  /*
465   * Silly little macros.
466   */
467 #define STR(s) vstring_str(s)
468 #define LEN(s) VSTRING_LEN(s)
469 
470 /* LICENSE
471 /* .ad
472 /* .fi
473 /*	The Secure Mailer license must be distributed with this software.
474 /* AUTHOR(S)
475 /*	Wietse Venema
476 /*	IBM T.J. Watson Research
477 /*	P.O. Box 704
478 /*	Yorktown Heights, NY 10598, USA
479 /*
480 /*	TLS support originally by:
481 /*	Lutz Jaenicke
482 /*	BTU Cottbus
483 /*	Allgemeine Elektrotechnik
484 /*	Universitaetsplatz 3-4
485 /*	D-03044 Cottbus, Germany
486 /*--*/
487