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