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