1/*++
2/* NAME
3/*	cleanup_init 3
4/* SUMMARY
5/*	cleanup callable interface, initializations
6/* SYNOPSIS
7/*	#include "cleanup.h"
8/*
9/*	CONFIG_INT_TABLE cleanup_int_table[];
10/*
11/*	CONFIG_BOOL_TABLE cleanup_bool_table[];
12/*
13/*	CONFIG_STR_TABLE cleanup_str_table[];
14/*
15/*	CONFIG_TIME_TABLE cleanup_time_table[];
16/*
17/*	void	cleanup_pre_jail(service_name, argv)
18/*	char	*service_name;
19/*	char	**argv;
20/*
21/*	void	cleanup_post_jail(service_name, argv)
22/*	char	*service_name;
23/*	char	**argv;
24/*
25/*	char	*cleanup_path;
26/*	VSTRING	*cleanup_trace_path;
27/*
28/*	void	cleanup_all()
29/*
30/*	void	cleanup_sig(sigval)
31/*	int	sigval;
32/* DESCRIPTION
33/*	This module implements a callable interface to the cleanup service
34/*	for one-time initializations that must be done before any message
35/*	processing can take place.
36/*
37/*	cleanup_{int,str,time}_table[] specify configuration
38/*	parameters that must be initialized before calling any functions
39/*	in this module. These tables satisfy the interface as specified in
40/*	single_service(3).
41/*
42/*	cleanup_pre_jail() and cleanup_post_jail() perform mandatory
43/*	initializations before and after the process enters the optional
44/*	chroot jail. These functions satisfy the interface as specified
45/*	in single_service(3).
46/*
47/*	cleanup_path is either a null pointer or it is the name of a queue
48/*	file that currently is being written. This information is used
49/*	by cleanup_all() to remove incomplete files after a fatal error,
50/*	or by cleanup_sig() after arrival of a SIGTERM signal.
51/*
52/*	cleanup_trace_path is either a null pointer or the pathname of a
53/*	trace logfile with DSN SUCCESS notifications. This information is
54/*	used to remove a trace file when the mail transaction is canceled.
55/*
56/*	cleanup_all() must be called in case of fatal error, in order
57/*	to remove an incomplete queue file.
58/*
59/*	cleanup_sig() must be called in case of SIGTERM, in order
60/*	to remove an incomplete queue file.
61/* DIAGNOSTICS
62/*	Problems and transactions are logged to \fBsyslogd\fR(8).
63/* SEE ALSO
64/*	cleanup_api(3) cleanup callable interface, message processing
65/* LICENSE
66/* .ad
67/* .fi
68/*	The Secure Mailer license must be distributed with this software.
69/* AUTHOR(S)
70/*	Wietse Venema
71/*	IBM T.J. Watson Research
72/*	P.O. Box 704
73/*	Yorktown Heights, NY 10598, USA
74/*--*/
75
76/* System library. */
77
78#include <sys_defs.h>
79#include <signal.h>
80#include <string.h>
81
82/* Utility library. */
83
84#include <msg.h>
85#include <iostuff.h>
86#include <name_mask.h>
87#include <stringops.h>
88
89/* Global library. */
90
91#include <mail_addr.h>
92#include <mail_params.h>
93#include <mail_version.h>		/* milter_macro_v */
94#include <ext_prop.h>
95#include <flush_clnt.h>
96
97/* Application-specific. */
98
99#include "cleanup.h"
100
101 /*
102  * Global state: any queue files that we have open, so that the error
103  * handler can clean up in case of trouble.
104  */
105char   *cleanup_path;			/* queue file name */
106
107 /*
108  * Another piece of global state: pathnames of partial bounce or trace
109  * logfiles that need to be cleaned up when the cleanup request is aborted.
110  */
111VSTRING *cleanup_trace_path;
112
113 /*
114  * Tunable parameters.
115  */
116int     var_hopcount_limit;		/* max mailer hop count */
117char   *var_canonical_maps;		/* common canonical maps */
118char   *var_send_canon_maps;		/* sender canonical maps */
119char   *var_rcpt_canon_maps;		/* recipient canonical maps */
120char   *var_canon_classes;		/* what to canonicalize */
121char   *var_send_canon_classes;		/* what sender to canonicalize */
122char   *var_rcpt_canon_classes;		/* what recipient to canonicalize */
123char   *var_virt_alias_maps;		/* virtual alias maps */
124char   *var_masq_domains;		/* masquerade domains */
125char   *var_masq_exceptions;		/* users not masqueraded */
126char   *var_header_checks;		/* primary header checks */
127char   *var_mimehdr_checks;		/* mime header checks */
128char   *var_nesthdr_checks;		/* nested header checks */
129char   *var_body_checks;		/* any body checks */
130int     var_dup_filter_limit;		/* recipient dup filter */
131bool    var_enable_orcpt;		/* Include orcpt in dup filter? */
132char   *var_empty_addr;			/* destination of bounced bounces */
133int     var_delay_warn_time;		/* delay that triggers warning */
134char   *var_prop_extension;		/* propagate unmatched extension */
135char   *var_always_bcc;			/* big brother */
136char   *var_rcpt_witheld;		/* recipients not disclosed */
137char   *var_masq_classes;		/* what to masquerade */
138int     var_qattr_count_limit;		/* named attribute limit */
139int     var_virt_recur_limit;		/* maximum virtual alias recursion */
140int     var_virt_expan_limit;		/* maximum virtual alias expansion */
141int     var_body_check_len;		/* when to stop body scan */
142char   *var_send_bcc_maps;		/* sender auto-bcc maps */
143char   *var_rcpt_bcc_maps;		/* recipient auto-bcc maps */
144char   *var_remote_rwr_domain;		/* header-only surrogate */
145char   *var_msg_reject_chars;		/* reject these characters */
146char   *var_msg_strip_chars;		/* strip these characters */
147int     var_verp_bounce_off;		/* don't verp the bounces */
148int     var_milt_conn_time;		/* milter connect/handshake timeout */
149int     var_milt_cmd_time;		/* milter command timeout */
150int     var_milt_msg_time;		/* milter content timeout */
151char   *var_milt_protocol;		/* Sendmail 8 milter protocol */
152char   *var_milt_def_action;		/* default milter action */
153char   *var_milt_daemon_name;		/* {daemon_name} macro value */
154char   *var_milt_v;			/* {v} macro value */
155char   *var_milt_conn_macros;		/* connect macros */
156char   *var_milt_helo_macros;		/* HELO macros */
157char   *var_milt_mail_macros;		/* MAIL FROM macros */
158char   *var_milt_rcpt_macros;		/* RCPT TO macros */
159char   *var_milt_data_macros;		/* DATA macros */
160char   *var_milt_eoh_macros;		/* end-of-header macros */
161char   *var_milt_eod_macros;		/* end-of-data macros */
162char   *var_milt_unk_macros;		/* unknown command macros */
163char   *var_cleanup_milters;		/* non-SMTP mail */
164char   *var_milt_head_checks;		/* post-Milter header checks */
165int     var_auto_8bit_enc_hdr;		/* auto-detect 8bit encoding header */
166int     var_always_add_hdrs;		/* always add missing headers */
167
168CONFIG_INT_TABLE cleanup_int_table[] = {
169    VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
170    VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0,
171    VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0,
172    VAR_VIRT_RECUR_LIMIT, DEF_VIRT_RECUR_LIMIT, &var_virt_recur_limit, 1, 0,
173    VAR_VIRT_EXPAN_LIMIT, DEF_VIRT_EXPAN_LIMIT, &var_virt_expan_limit, 1, 0,
174    VAR_BODY_CHECK_LEN, DEF_BODY_CHECK_LEN, &var_body_check_len, 0, 0,
175    0,
176};
177
178CONFIG_BOOL_TABLE cleanup_bool_table[] = {
179    VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt,
180    VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off,
181    VAR_AUTO_8BIT_ENC_HDR, DEF_AUTO_8BIT_ENC_HDR, &var_auto_8bit_enc_hdr,
182    VAR_ALWAYS_ADD_HDRS, DEF_ALWAYS_ADD_HDRS, &var_always_add_hdrs,
183    0,
184};
185
186CONFIG_TIME_TABLE cleanup_time_table[] = {
187    VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0,
188    VAR_MILT_CONN_TIME, DEF_MILT_CONN_TIME, &var_milt_conn_time, 1, 0,
189    VAR_MILT_CMD_TIME, DEF_MILT_CMD_TIME, &var_milt_cmd_time, 1, 0,
190    VAR_MILT_MSG_TIME, DEF_MILT_MSG_TIME, &var_milt_msg_time, 1, 0,
191    0,
192};
193
194CONFIG_STR_TABLE cleanup_str_table[] = {
195    VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0,
196    VAR_SEND_CANON_MAPS, DEF_SEND_CANON_MAPS, &var_send_canon_maps, 0, 0,
197    VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0,
198    VAR_CANON_CLASSES, DEF_CANON_CLASSES, &var_canon_classes, 1, 0,
199    VAR_SEND_CANON_CLASSES, DEF_SEND_CANON_CLASSES, &var_send_canon_classes, 1, 0,
200    VAR_RCPT_CANON_CLASSES, DEF_RCPT_CANON_CLASSES, &var_rcpt_canon_classes, 1, 0,
201    VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0,
202    VAR_MASQ_DOMAINS, DEF_MASQ_DOMAINS, &var_masq_domains, 0, 0,
203    VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
204    VAR_MASQ_EXCEPTIONS, DEF_MASQ_EXCEPTIONS, &var_masq_exceptions, 0, 0,
205    VAR_HEADER_CHECKS, DEF_HEADER_CHECKS, &var_header_checks, 0, 0,
206    VAR_MIMEHDR_CHECKS, DEF_MIMEHDR_CHECKS, &var_mimehdr_checks, 0, 0,
207    VAR_NESTHDR_CHECKS, DEF_NESTHDR_CHECKS, &var_nesthdr_checks, 0, 0,
208    VAR_BODY_CHECKS, DEF_BODY_CHECKS, &var_body_checks, 0, 0,
209    VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
210    VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
211    VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 0, 0,
212    VAR_MASQ_CLASSES, DEF_MASQ_CLASSES, &var_masq_classes, 0, 0,
213    VAR_SEND_BCC_MAPS, DEF_SEND_BCC_MAPS, &var_send_bcc_maps, 0, 0,
214    VAR_RCPT_BCC_MAPS, DEF_RCPT_BCC_MAPS, &var_rcpt_bcc_maps, 0, 0,
215    VAR_REM_RWR_DOMAIN, DEF_REM_RWR_DOMAIN, &var_remote_rwr_domain, 0, 0,
216    VAR_MSG_REJECT_CHARS, DEF_MSG_REJECT_CHARS, &var_msg_reject_chars, 0, 0,
217    VAR_MSG_STRIP_CHARS, DEF_MSG_STRIP_CHARS, &var_msg_strip_chars, 0, 0,
218    VAR_MILT_PROTOCOL, DEF_MILT_PROTOCOL, &var_milt_protocol, 1, 0,
219    VAR_MILT_DEF_ACTION, DEF_MILT_DEF_ACTION, &var_milt_def_action, 1, 0,
220    VAR_MILT_DAEMON_NAME, DEF_MILT_DAEMON_NAME, &var_milt_daemon_name, 1, 0,
221    VAR_MILT_V, DEF_MILT_V, &var_milt_v, 1, 0,
222    VAR_MILT_CONN_MACROS, DEF_MILT_CONN_MACROS, &var_milt_conn_macros, 0, 0,
223    VAR_MILT_HELO_MACROS, DEF_MILT_HELO_MACROS, &var_milt_helo_macros, 0, 0,
224    VAR_MILT_MAIL_MACROS, DEF_MILT_MAIL_MACROS, &var_milt_mail_macros, 0, 0,
225    VAR_MILT_RCPT_MACROS, DEF_MILT_RCPT_MACROS, &var_milt_rcpt_macros, 0, 0,
226    VAR_MILT_DATA_MACROS, DEF_MILT_DATA_MACROS, &var_milt_data_macros, 0, 0,
227    VAR_MILT_EOH_MACROS, DEF_MILT_EOH_MACROS, &var_milt_eoh_macros, 0, 0,
228    VAR_MILT_EOD_MACROS, DEF_MILT_EOD_MACROS, &var_milt_eod_macros, 0, 0,
229    VAR_MILT_UNK_MACROS, DEF_MILT_UNK_MACROS, &var_milt_unk_macros, 0, 0,
230    VAR_CLEANUP_MILTERS, DEF_CLEANUP_MILTERS, &var_cleanup_milters, 0, 0,
231    VAR_MILT_HEAD_CHECKS, DEF_MILT_HEAD_CHECKS, &var_milt_head_checks, 0, 0,
232    0,
233};
234
235 /*
236  * Mappings.
237  */
238MAPS   *cleanup_comm_canon_maps;
239MAPS   *cleanup_send_canon_maps;
240MAPS   *cleanup_rcpt_canon_maps;
241int     cleanup_comm_canon_flags;
242int     cleanup_send_canon_flags;
243int     cleanup_rcpt_canon_flags;
244MAPS   *cleanup_header_checks;
245MAPS   *cleanup_mimehdr_checks;
246MAPS   *cleanup_nesthdr_checks;
247MAPS   *cleanup_body_checks;
248MAPS   *cleanup_virt_alias_maps;
249ARGV   *cleanup_masq_domains;
250STRING_LIST *cleanup_masq_exceptions;
251int     cleanup_masq_flags;
252MAPS   *cleanup_send_bcc_maps;
253MAPS   *cleanup_rcpt_bcc_maps;
254
255 /*
256  * Character filters.
257  */
258VSTRING *cleanup_reject_chars;
259VSTRING *cleanup_strip_chars;
260
261 /*
262  * Address extension propagation restrictions.
263  */
264int     cleanup_ext_prop_mask;
265
266 /*
267  * Milter support.
268  */
269MILTERS *cleanup_milters;
270
271/* cleanup_all - callback for the runtime error handler */
272
273void    cleanup_all(void)
274{
275    cleanup_sig(0);
276}
277
278/* cleanup_sig - callback for the SIGTERM handler */
279
280void    cleanup_sig(int sig)
281{
282
283    /*
284     * msg_fatal() is safe against calling itself recursively, but signals
285     * need extra safety.
286     *
287     * XXX While running as a signal handler, can't ask the memory manager to
288     * release VSTRING storage.
289     */
290    if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
291	if (cleanup_trace_path) {
292	    (void) REMOVE(vstring_str(cleanup_trace_path));
293	    cleanup_trace_path = 0;
294	}
295	if (cleanup_path) {
296	    (void) REMOVE(cleanup_path);
297	    cleanup_path = 0;
298	}
299	if (sig)
300	    _exit(sig);
301    }
302}
303
304/* cleanup_pre_jail - initialize before entering the chroot jail */
305
306void    cleanup_pre_jail(char *unused_name, char **unused_argv)
307{
308    static const NAME_MASK send_canon_class_table[] = {
309	CANON_CLASS_ENV_FROM, CLEANUP_CANON_FLAG_ENV_FROM,
310	CANON_CLASS_HDR_FROM, CLEANUP_CANON_FLAG_HDR_FROM,
311	0,
312    };
313    static const NAME_MASK rcpt_canon_class_table[] = {
314	CANON_CLASS_ENV_RCPT, CLEANUP_CANON_FLAG_ENV_RCPT,
315	CANON_CLASS_HDR_RCPT, CLEANUP_CANON_FLAG_HDR_RCPT,
316	0,
317    };
318    static const NAME_MASK canon_class_table[] = {
319	CANON_CLASS_ENV_FROM, CLEANUP_CANON_FLAG_ENV_FROM,
320	CANON_CLASS_ENV_RCPT, CLEANUP_CANON_FLAG_ENV_RCPT,
321	CANON_CLASS_HDR_FROM, CLEANUP_CANON_FLAG_HDR_FROM,
322	CANON_CLASS_HDR_RCPT, CLEANUP_CANON_FLAG_HDR_RCPT,
323	0,
324    };
325    static const NAME_MASK masq_class_table[] = {
326	MASQ_CLASS_ENV_FROM, CLEANUP_MASQ_FLAG_ENV_FROM,
327	MASQ_CLASS_ENV_RCPT, CLEANUP_MASQ_FLAG_ENV_RCPT,
328	MASQ_CLASS_HDR_FROM, CLEANUP_MASQ_FLAG_HDR_FROM,
329	MASQ_CLASS_HDR_RCPT, CLEANUP_MASQ_FLAG_HDR_RCPT,
330	0,
331    };
332
333    if (*var_canonical_maps)
334	cleanup_comm_canon_maps =
335	    maps_create(VAR_CANONICAL_MAPS, var_canonical_maps,
336			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
337    if (*var_send_canon_maps)
338	cleanup_send_canon_maps =
339	    maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps,
340			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
341    if (*var_rcpt_canon_maps)
342	cleanup_rcpt_canon_maps =
343	    maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps,
344			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
345    if (*var_virt_alias_maps)
346	cleanup_virt_alias_maps = maps_create(VAR_VIRT_ALIAS_MAPS,
347					      var_virt_alias_maps,
348					      DICT_FLAG_LOCK
349					      | DICT_FLAG_FOLD_FIX);
350    if (*var_canon_classes)
351	cleanup_comm_canon_flags =
352	    name_mask(VAR_CANON_CLASSES, canon_class_table,
353		      var_canon_classes);
354    if (*var_send_canon_classes)
355	cleanup_send_canon_flags =
356	    name_mask(VAR_CANON_CLASSES, send_canon_class_table,
357		      var_send_canon_classes);
358    if (*var_rcpt_canon_classes)
359	cleanup_rcpt_canon_flags =
360	    name_mask(VAR_CANON_CLASSES, rcpt_canon_class_table,
361		      var_rcpt_canon_classes);
362    if (*var_masq_domains)
363	cleanup_masq_domains = argv_split(var_masq_domains, " ,\t\r\n");
364    if (*var_header_checks)
365	cleanup_header_checks =
366	    maps_create(VAR_HEADER_CHECKS, var_header_checks, DICT_FLAG_LOCK);
367    if (*var_mimehdr_checks)
368	cleanup_mimehdr_checks =
369	    maps_create(VAR_MIMEHDR_CHECKS, var_mimehdr_checks, DICT_FLAG_LOCK);
370    if (*var_nesthdr_checks)
371	cleanup_nesthdr_checks =
372	    maps_create(VAR_NESTHDR_CHECKS, var_nesthdr_checks, DICT_FLAG_LOCK);
373    if (*var_body_checks)
374	cleanup_body_checks =
375	    maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
376    if (*var_masq_exceptions)
377	cleanup_masq_exceptions =
378	    string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions);
379    if (*var_masq_classes)
380	cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table,
381				       var_masq_classes);
382    if (*var_send_bcc_maps)
383	cleanup_send_bcc_maps =
384	    maps_create(VAR_SEND_BCC_MAPS, var_send_bcc_maps,
385			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
386    if (*var_rcpt_bcc_maps)
387	cleanup_rcpt_bcc_maps =
388	    maps_create(VAR_RCPT_BCC_MAPS, var_rcpt_bcc_maps,
389			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
390    if (*var_cleanup_milters)
391	cleanup_milters = milter_create(var_cleanup_milters,
392					var_milt_conn_time,
393					var_milt_cmd_time,
394					var_milt_msg_time,
395					var_milt_protocol,
396					var_milt_def_action,
397					var_milt_conn_macros,
398					var_milt_helo_macros,
399					var_milt_mail_macros,
400					var_milt_rcpt_macros,
401					var_milt_data_macros,
402					var_milt_eoh_macros,
403					var_milt_eod_macros,
404					var_milt_unk_macros);
405
406    flush_init();
407}
408
409/* cleanup_post_jail - initialize after entering the chroot jail */
410
411void    cleanup_post_jail(char *unused_name, char **unused_argv)
412{
413
414    /*
415     * Optionally set the file size resource limit. XXX This limits the
416     * message content to somewhat less than requested, because the total
417     * queue file size also includes envelope information. Unless people set
418     * really low limit, the difference is going to matter only when a queue
419     * file has lots of recipients.
420     */
421    if (var_message_limit > 0)
422	set_file_limit((off_t) var_message_limit);
423
424    /*
425     * Control how unmatched extensions are propagated.
426     */
427    cleanup_ext_prop_mask =
428	ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension);
429
430    /*
431     * Setup the filters for characters that should be rejected, and for
432     * characters that should be removed.
433     */
434    if (*var_msg_reject_chars) {
435	cleanup_reject_chars = vstring_alloc(strlen(var_msg_reject_chars));
436	unescape(cleanup_reject_chars, var_msg_reject_chars);
437    }
438    if (*var_msg_strip_chars) {
439	cleanup_strip_chars = vstring_alloc(strlen(var_msg_strip_chars));
440	unescape(cleanup_strip_chars, var_msg_strip_chars);
441    }
442}
443