diff options
Diffstat (limited to 'src/cleanup/cleanup_addr.c')
-rw-r--r-- | src/cleanup/cleanup_addr.c | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/src/cleanup/cleanup_addr.c b/src/cleanup/cleanup_addr.c new file mode 100644 index 0000000..fd8a511 --- /dev/null +++ b/src/cleanup/cleanup_addr.c @@ -0,0 +1,286 @@ +/*++ +/* NAME +/* cleanup_addr 3 +/* SUMMARY +/* process envelope addresses +/* SYNOPSIS +/* #include <cleanup.h> +/* +/* off_t cleanup_addr_sender(state, addr) +/* CLEANUP_STATE *state; +/* const char *addr; +/* +/* void cleanup_addr_recipient(state, addr) +/* CLEANUP_STATE *state; +/* const char *addr; +/* +/* void cleanup_addr_bcc_dsn(state, addr, dsn_orcpt, dsn_notify) +/* CLEANUP_STATE *state; +/* const char *addr; +/* const char *dsn_orcpt; +/* int dsn_notify; +/* +/* void cleanup_addr_bcc(state, addr) +/* CLEANUP_STATE *state; +/* const char *addr; +/* DESCRIPTION +/* This module processes envelope address records and writes the result +/* to the queue file. Processing includes address rewriting and +/* sender/recipient auto bcc address generation. +/* +/* cleanup_addr_sender() processes sender envelope information and updates +/* state->sender. The result value is the offset of the record that +/* follows the sender record if milters are enabled, otherwise zero. +/* +/* cleanup_addr_recipient() processes recipient envelope information +/* and updates state->recip. +/* +/* cleanup_addr_bcc_dsn() processes recipient envelope information. This +/* is a separate function to avoid invoking cleanup_addr_recipient() +/* recursively. +/* +/* cleanup_addr_bcc() is a backwards-compatibility wrapper for +/* cleanup_addr_bcc_dsn() that requests no delivery status +/* notification for the recipient. +/* +/* Arguments: +/* .IP state +/* Queue file and message processing state. This state is updated +/* as records are processed and as errors happen. +/* .IP buf +/* Record content. +/* .IP dsn_orcpt +/* The DSN original recipient (or NO_DSN_ORCPT to specify none). +/* .IP dsn_notify +/* DSN notification options. Specify NO_DSN_NOTIFY to disable +/* notification, and DEF_DSN_NOTIFY for default notification. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <string.h> +#include <stdlib.h> + +/* Utility library. */ + +#include <msg.h> +#include <vstring.h> +#include <vstream.h> +#include <mymalloc.h> +#include <stringops.h> + +/* Global library. */ + +#include <rec_type.h> +#include <record.h> +#include <cleanup_user.h> +#include <mail_params.h> +#include <ext_prop.h> +#include <mail_addr.h> +#include <canon_addr.h> +#include <mail_addr_find.h> +#include <mail_proto.h> +#include <dsn_mask.h> +#include <smtputf8.h> + +/* Application-specific. */ + +#include "cleanup.h" + +#define STR vstring_str +#define LEN VSTRING_LEN +#define IGNORE_EXTENSION (char **) 0 + +/* cleanup_addr_sender - process envelope sender record */ + +off_t cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) +{ + const char myname[] = "cleanup_addr_sender"; + VSTRING *clean_addr = vstring_alloc(100); + off_t after_sender_offs = 0; + const char *bcc; + size_t len; + + /* + * Note: an unqualified envelope address is for all practical purposes + * equivalent to a fully qualified local address, both for delivery and + * for replying. Having to support both forms is error prone, therefore + * an incomplete envelope address is rewritten to fully qualified form in + * the local domain context. + * + * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle + * bounced mail traffic more robustly. + */ + cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf); + if (strncasecmp_utf8(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@", + sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) { + canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON); + if (strcasecmp_utf8(STR(clean_addr), STR(state->temp1)) == 0) + vstring_strcpy(clean_addr, ""); + } + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_send_canon_maps + && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) + cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_comm_canon_maps + && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) + cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) + cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); + } + /* Fix 20140711: Auto-detect an UTF8 sender. */ + if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) + && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + state->smtputf8 |= SMTPUTF8_FLAG_SENDER; + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } + CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); + if (state->sender) /* XXX Can't happen */ + myfree(state->sender); + state->sender = mystrdup(STR(clean_addr)); /* Used by Milter client */ + /* Fix 20160310: Moved from cleanup_envelope.c. */ + if (state->milters || cleanup_milters) { + /* Make room to replace sender. */ + if ((len = LEN(clean_addr)) < REC_TYPE_PTR_PAYL_SIZE) + rec_pad(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_PAYL_SIZE - len); + /* Remember the after-sender record offset. */ + if ((after_sender_offs = vstream_ftell(state->dst)) < 0) + msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path); + } + if ((state->flags & CLEANUP_FLAG_BCC_OK) + && *STR(clean_addr) + && cleanup_send_bcc_maps) { + if ((bcc = mail_addr_find_to_internal(cleanup_send_bcc_maps, + STR(clean_addr), + IGNORE_EXTENSION)) != 0) { + cleanup_addr_bcc(state, bcc); + } else if (cleanup_send_bcc_maps->error) { + msg_warn("%s: %s map lookup problem -- " + "message not accepted, try again later", + state->queue_id, cleanup_send_bcc_maps->title); + state->errs |= CLEANUP_STAT_WRITE; + } + } + vstring_free(clean_addr); + return after_sender_offs; +} + +/* cleanup_addr_recipient - process envelope recipient */ + +void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) +{ + VSTRING *clean_addr = vstring_alloc(100); + const char *bcc; + + /* + * Note: an unqualified envelope address is for all practical purposes + * equivalent to a fully qualified local address, both for delivery and + * for replying. Having to support both forms is error prone, therefore + * an incomplete envelope address is rewritten to fully qualified form in + * the local domain context. + */ + cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, + clean_addr, *buf ? buf : var_empty_addr); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_rcpt_canon_maps + && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_comm_canon_maps + && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) + cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) + cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); + } + /* Fix 20140711: Auto-detect an UTF8 recipient. */ + if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) + && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } + /* Fix 20141024: Don't fake up a "bare" DSN original rcpt in smtp(8). */ + if (state->dsn_orcpt == 0 && *STR(clean_addr) != 0) + state->dsn_orcpt = concatenate((!allascii(STR(clean_addr)) + && (state->smtputf8 & SMTPUTF8_FLAG_REQUESTED)) ? + "utf-8" : "rfc822", ";", STR(clean_addr), (char *) 0); + cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify, + state->orig_rcpt, STR(clean_addr)); + if (state->recip) /* This can happen */ + myfree(state->recip); + state->recip = mystrdup(STR(clean_addr)); /* Used by Milter client */ + if ((state->flags & CLEANUP_FLAG_BCC_OK) + && *STR(clean_addr) + && cleanup_rcpt_bcc_maps) { + if ((bcc = mail_addr_find_to_internal(cleanup_rcpt_bcc_maps, + STR(clean_addr), + IGNORE_EXTENSION)) != 0) { + cleanup_addr_bcc(state, bcc); + } else if (cleanup_rcpt_bcc_maps->error) { + msg_warn("%s: %s map lookup problem -- " + "message not accepted, try again later", + state->queue_id, cleanup_rcpt_bcc_maps->title); + state->errs |= CLEANUP_STAT_WRITE; + } + } + vstring_free(clean_addr); +} + +/* cleanup_addr_bcc_dsn - process automatic BCC recipient */ + +void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc, + const char *dsn_orcpt, int dsn_notify) +{ + VSTRING *clean_addr = vstring_alloc(100); + + /* + * Note: BCC addresses are supplied locally, and must be rewritten in the + * local address rewriting context. + */ + cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, bcc); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_rcpt_canon_maps + && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_comm_canon_maps + && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) + cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) + cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); + } + /* Fix 20140711: Auto-detect an UTF8 recipient. */ + if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) + && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } + cleanup_out_recipient(state, dsn_orcpt, dsn_notify, + STR(clean_addr), STR(clean_addr)); + vstring_free(clean_addr); +} |