57 #ifdef STRCASECMP_IN_STRINGS_H
112 for (line = start_line; line != 0; line = next_line) {
113 end_line = line + strcspn(line,
"\n");
114 if (line > start_line) {
115 if (end_line - start_line < 70) {
121 next_line = *end_line ? end_line + 1 : 0;
128 static char *cleanup_extract_internal(
VSTRING *buffer,
TOK822 *addr)
159 + strlen(hdr_opts->
name) + 1,
162 for (tpp = addr_list; *tpp; tpp++) {
186 myfree((
void *) addr_list);
190 cleanup_fold_header(state, header_buf);
216 + strlen(hdr_opts->
name) + 1,
219 for (tpp = addr_list; *tpp; tpp++) {
243 myfree((
void *) addr_list);
247 cleanup_fold_header(state, header_buf);
256 const char *action,
const char *
class,
257 const char *content,
const char *text)
264 state->
queue_id, action,
class, content, attr);
278 #define CLEANUP_ACT_CTXT_HEADER "header"
279 #define CLEANUP_ACT_CTXT_BODY "body"
280 #define CLEANUP_ACT_CTXT_ANY "content"
284 static const char *cleanup_act(
CLEANUP_STATE *state,
char *context,
285 const char *buf,
const char *value,
286 const char *map_class)
288 const char *optional_text = value + strcspn(value,
" \t");
289 int command_len = optional_text - value;
296 while (*optional_text &&
ISSPACE(*optional_text))
299 #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)
300 #define CLEANUP_ACT_DROP 0
307 if (
STREQUAL(value,
"REJECT", command_len)) {
312 if (*optional_text) {
315 msg_warn(
"bad DSN action in %s -- need 4.x.x or 5.x.x",
323 if (*state->
reason ==
'4')
328 cleanup_act_log(state,
"reject", context, buf, state->
reason);
331 if (
STREQUAL(value,
"WARN", command_len)) {
332 cleanup_act_log(state,
"warning", context, buf, optional_text);
335 if (
STREQUAL(value,
"INFO", command_len)) {
336 cleanup_act_log(state,
"info", context, buf, optional_text);
339 if (
STREQUAL(value,
"FILTER", command_len)) {
340 if (*optional_text == 0) {
341 msg_warn(
"missing FILTER command argument in %s map", map_class);
342 }
else if (strchr(optional_text,
':') == 0) {
343 msg_warn(
"bad FILTER command %s in %s -- "
344 "need transport:destination",
345 optional_text, map_class);
350 cleanup_act_log(state,
"filter", context, buf, optional_text);
354 if (
STREQUAL(value,
"PASS", command_len)) {
355 cleanup_act_log(state,
"pass", context, buf, optional_text);
359 if (
STREQUAL(value,
"DISCARD", command_len)) {
360 cleanup_act_log(state,
"discard", context, buf, optional_text);
365 if (
STREQUAL(value,
"HOLD", command_len)) {
367 cleanup_act_log(state,
"hold", context, buf, optional_text);
381 if (
STREQUAL(value,
"DELAY", command_len)) {
383 if (*optional_text == 0) {
384 msg_warn(
"missing DELAY argument in %s map", map_class);
385 }
else if (
conv_time(optional_text, &defer_delay,
's') == 0) {
386 msg_warn(
"ignoring bad DELAY argument %s in %s map",
387 optional_text, map_class);
389 cleanup_act_log(state,
"delay", context, buf, optional_text);
390 state->defer_delay = defer_delay;
396 if (
STREQUAL(value,
"PREPEND", command_len)) {
397 if (*optional_text == 0) {
398 msg_warn(
"PREPEND action without text in %s map", map_class);
401 msg_warn(
"bad PREPEND header text \"%s\" in %s map -- "
402 "need \"headername: headervalue\"",
403 optional_text, map_class);
413 cleanup_act_log(state,
"prepend", context, buf, optional_text);
420 cleanup_act_log(state,
"prepend", context, buf, optional_text);
425 if (
STREQUAL(value,
"REPLACE", command_len)) {
426 if (*optional_text == 0) {
427 msg_warn(
"REPLACE action without text in %s map", map_class);
431 msg_warn(
"bad REPLACE header text \"%s\" in %s map -- "
432 "need \"headername: headervalue\"",
433 optional_text, map_class);
436 cleanup_act_log(state,
"replace", context, buf, optional_text);
440 if (
STREQUAL(value,
"REDIRECT", command_len)) {
441 if (strchr(optional_text,
'@') == 0) {
442 msg_warn(
"bad REDIRECT target \"%s\" in %s map -- "
444 optional_text, map_class);
449 cleanup_act_log(state,
"redirect", context, buf, optional_text);
454 if (
STREQUAL(value,
"BCC", command_len)) {
455 if (strchr(optional_text,
'@') == 0) {
456 msg_warn(
"bad BCC address \"%s\" in %s map -- "
458 optional_text, map_class);
463 cleanup_act_log(state,
"bcc", context, buf, optional_text);
467 if (
STREQUAL(value,
"STRIP", command_len)) {
468 cleanup_act_log(state,
"strip", context, buf, optional_text);
473 if (
STREQUAL(value,
"IGNORE", command_len))
476 if (
STREQUAL(value,
"DUNNO", command_len))
479 if (
STREQUAL(value,
"OK", command_len))
482 msg_warn(
"unknown command in %s map: %s", map_class, value);
488 static void cleanup_header_callback(
void *context,
int header_class,
494 const char *myname =
"cleanup_header_callback";
498 const char *encoding;
500 static struct code_map code_map[] = {
508 struct code_map *cmp;
510 const char *map_class;
519 #define CHECK(class, maps, var_name) \
520 (header_class == class && (map_class = var_name, checks = maps) != 0)
536 if ((value =
maps_find(checks, header, 0)) != 0) {
540 header, value, map_class))
543 }
else if (result != header) {
548 }
else if (checks->
error) {
549 msg_warn(
"%s: %s map lookup problem -- "
550 "message not accepted, try again later",
576 for (cmp = code_map; cmp->name != 0; cmp++) {
631 msg_warn(
"%s: message rejected: hopcount exceeded",
641 state->
resent =
"Resent-";
644 cleanup_rewrite_sender(state, hdr_opts, header_buf);
647 cleanup_rewrite_recip(state, hdr_opts, header_buf);
657 static void cleanup_header_done_callback(
void *context)
659 const char *myname =
"cleanup_header_done_callback";
661 char time_stamp[1024];
684 msg_warn(
"%s: message rejected: no Received: header",
718 strftime(time_stamp,
sizeof(time_stamp),
"%Y%m%d%H%M%S", tp);
756 while ((cp = strchr(state->
fullname,
'\r')) != 0
757 || (cp = strchr(state->
fullname,
'\n')) != 0)
794 msg_panic(
"%s: unknown header format %d",
836 #define VISIBLE_RCPT ((1 << HDR_TO) | (1 << HDR_RESENT_TO) \
837 | (1 << HDR_CC) | (1 << HDR_RESENT_CC))
842 msg_warn(
"bad %s header text \"%s\" -- "
843 "need \"headername: headervalue\"",
867 static void cleanup_body_callback(
void *context,
int type,
868 const char *buf, ssize_t len,
901 }
else if (result != buf) {
907 msg_warn(
"%s: %s map lookup problem -- "
908 "message not accepted, try again later",
918 static void cleanup_message_headerbody(
CLEANUP_STATE *state,
int type,
919 const char *buf, ssize_t len)
921 const char *myname =
"cleanup_message_headerbody";
933 for (cp = buf; cp < buf + len; cp++) {
935 *(
const unsigned char *) cp,
938 buf,
"REJECT disallowed character",
959 for (cp = buf; cp < buf + len; cp++)
961 *(
const unsigned char *) cp,
1004 "unexpected record type %d in message content", myname, type);
1011 static void cleanup_mime_error_callback(
void *context,
int err_code,
1012 const char *text, ssize_t len)
1024 #define TEXT_LEN (len < 100 ? (int) len : 100)
1025 msg_info(
"%s: reject: mime-error %s: %.*s from %s; from=<%s> to=<%s>",
1035 const char *myname =
"cleanup_message";
1070 cleanup_header_callback,
1071 cleanup_header_done_callback,
1072 cleanup_body_callback,
1074 cleanup_mime_error_callback,
1081 #define KLUDGE_HEADER_LIMIT 60000
1089 state->
action = cleanup_message_headerbody;
1090 cleanup_message_headerbody(state, type, buf, len);
const CLEANUP_STAT_DETAIL * cleanup_stat_detail(unsigned status)
void cleanup_out_format(CLEANUP_STATE *state, int type, const char *fmt,...)
void cleanup_extracted(CLEANUP_STATE *, int, const char *, ssize_t)
int cleanup_rewrite_tree(const char *, TOK822 *)
char * mystrdup(const char *str)
#define MAIL_ATTR_ENCODING
#define VAR_MIMEHDR_CHECKS
char * var_nesthdr_checks
MIME_STATE * mime_state_alloc(int flags, MIME_STATE_HEAD_OUT head_out, MIME_STATE_ANY_END head_end, MIME_STATE_BODY_OUT body_out, MIME_STATE_ANY_END body_end, MIME_STATE_ERR_PRINT err_print, void *context)
#define CLEANUP_ACT_CTXT_ANY
const char * mail_date(time_t when)
#define CLEANUP_FLAG_MAP_OK
TOK822 ** tok822_grep(TOK822 *, int)
NORETURN msg_panic(const char *fmt,...)
MAPS * cleanup_body_checks
int var_auto_8bit_enc_hdr
NVTABLE_INFO * nvtable_update(NVTABLE *table, const char *key, const char *value)
off_t vstream_ftell(VSTREAM *stream)
#define CLEANUP_MASQ_FLAG_HDR_RCPT
MAPS * cleanup_rcpt_canon_maps
#define MIME_HDR_MULTIPART
int conv_time(const char *strval, int *timval, int def_unit)
#define MIME_OPT_REPORT_ENCODING_DOMAIN
#define CLEANUP_FLAG_FILTER
#define CHECK(class, maps, var_name)
int var_disable_mime_input
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
#define CLEANUP_OUT_BUF(s, t, b)
#define MAIL_ATTR_ORG_NONE
int cleanup_comm_canon_flags
#define CLEANUP_FLAG_DISCARD
void argv_add(ARGV *argvp,...)
#define MIME_OPT_REPORT_8BIT_IN_HEADER
struct timeval arrival_time
#define CLEANUP_STAT_HOPS
ARGV * cleanup_masq_domains
ARGV * argv_alloc(ssize_t len)
#define MAIL_ATTR_LOG_HELO_NAME
#define EXT_PROP_CANONICAL
#define CLEANUP_FLAG_HOLD
#define MAIL_ATTR_LOG_PROTO_NAME
#define MIME_OPT_DISABLE_MIME
#define CLEANUP_CANON_FLAG_HDR_RCPT
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
TOK822 * tok822_free_tree(TOK822 *)
#define CLEANUP_CANON_FLAG_HDR_FROM
int cleanup_ext_prop_mask
#define MIME_OPT_REPORT_8BIT_IN_7BIT_BODY
char * dsn_prepend(const char *def_dsn, const char *text)
MAPS * cleanup_nesthdr_checks
int cleanup_rcpt_canon_flags
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
#define MAIL_ATTR_LOG_ORIGIN
int mime_state_update(MIME_STATE *state, int rec_type, const char *text, ssize_t len)
#define HFROM_FORMAT_CODE_OBS
int cleanup_map11_tree(CLEANUP_STATE *, TOK822 *, MAPS *, int)
VSTRING * cleanup_reject_chars
#define VAR_NESTHDR_CHECKS
TOK822 * tok822_scan_limit(const char *, TOK822 **, int)
#define REC_TYPE_PTR_FORMAT
MIME_STATE * mime_state_free(MIME_STATE *state)
#define CLEANUP_ACT_CTXT_BODY
#define MIME_ERR_TRUNC_HEADER
void(* MIME_STATE_ANY_END)(void *)
void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t len)
off_t append_hdr_pt_offset
#define VSTRING_RESET(vp)
char * hdr_rewrite_context
#define MAIL_ADDR_MAIL_DAEMON
MAPS * cleanup_mimehdr_checks
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define HFROM_FORMAT_CODE_STD
VSTRING * tok822_externalize(VSTRING *, TOK822 *, int)
#define KLUDGE_HEADER_LIMIT
int cleanup_send_canon_flags
void(* action)(struct CLEANUP_STATE *, int, const char *, ssize_t)
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
const MIME_STATE_DETAIL * mime_state_detail(int error_code)
VSTRING * tok822_internalize(VSTRING *, TOK822 *, int)
MAPS * cleanup_comm_canon_maps
NORETURN msg_fatal(const char *fmt,...)
#define CLEANUP_MASQ_FLAG_HDR_FROM
#define CLEANUP_FLAG_FILTER_ALL
const char * mime_state_error(int error_code)
MAPS * cleanup_header_checks
#define CLEANUP_STAT_CONT
TOK822 * tok822_alloc(int, const char *)
#define CLEANUP_OUT_OK(s)
TOK822 * tok822_free(TOK822 *)
#define CLEANUP_ACT_CTXT_HEADER
TOK822 * tok822_parse_limit(const char *, int)
#define VSTRING_SPACE(vp, len)
#define quote_822_local(dst, src)
int strcasecmp(const char *s1, const char *s2)
void const char void cleanup_out_header(CLEANUP_STATE *, VSTRING *)
int cleanup_masquerade_tree(CLEANUP_STATE *, TOK822 *, ARGV *)
VSTRING * vstring_free(VSTRING *vp)
MAPS * cleanup_send_canon_maps
char * var_mimehdr_checks
#define CLEANUP_STAT_WRITE
#define nvtable_find(table, key)
void cleanup_out(CLEANUP_STATE *, int, const char *, ssize_t)
off_t append_hdr_pt_target
#define MIME_OPT_REPORT_NESTING
void cleanup_out_string(CLEANUP_STATE *, int, const char *)
#define CLEANUP_STAT_DEFER
MILTERS * cleanup_milters
#define MAIL_ATTR_ENC_8BIT
const char * maps_find(MAPS *maps, const char *name, int flags)
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
#define MAIL_ATTR_ENC_7BIT
#define VAR_HEADER_CHECKS
VSTRING * cleanup_strip_chars
#define STREQUAL(x, y, l)
void msg_info(const char *fmt,...)