1/*++
2/* NAME
3/*	cleanup_addr 3
4/* SUMMARY
5/*	process envelope addresses
6/* SYNOPSIS
7/*	#include <cleanup.h>
8/*
9/*	void	cleanup_addr_sender(state, addr)
10/*	CLEANUP_STATE *state;
11/*	const char *addr;
12/*
13/*	void	cleanup_addr_recipient(state, addr)
14/*	CLEANUP_STATE *state;
15/*	const char *addr;
16/*
17/*	void	cleanup_addr_bcc_dsn(state, addr, dsn_orcpt, dsn_notify)
18/*	CLEANUP_STATE *state;
19/*	const char *addr;
20/*	const char *dsn_orcpt;
21/*	int	dsn_notify;
22/*
23/*	void	cleanup_addr_bcc(state, addr)
24/*	CLEANUP_STATE *state;
25/*	const char *addr;
26/* DESCRIPTION
27/*	This module processes envelope address records and writes the result
28/*	to the queue file. Processing includes address rewriting and
29/*	sender/recipient auto bcc address generation.
30/*
31/*	cleanup_addr_sender() processes sender envelope information and updates
32/*	state->sender.
33/*
34/*	cleanup_addr_recipient() processes recipient envelope information
35/*	and updates state->recip.
36/*
37/*	cleanup_addr_bcc_dsn() processes recipient envelope information. This
38/*	is a separate function to avoid invoking cleanup_addr_recipient()
39/*	recursively.
40/*
41/*	cleanup_addr_bcc() is a backwards-compatibility wrapper for
42/*	cleanup_addr_bcc_dsn() that requests no delivery status
43/*	notification for the recipient.
44/*
45/*	Arguments:
46/* .IP state
47/*	Queue file and message processing state. This state is updated
48/*	as records are processed and as errors happen.
49/* .IP buf
50/*	Record content.
51/* .IP dsn_orcpt
52/*	The DSN original recipient (or NO_DSN_ORCPT to specify none).
53/* .IP dsn_notify
54/*	DSN notification options. Specify NO_DSN_NOTIFY to disable
55/*	notification, and DEF_DSN_NOTIFY for default notification.
56/* LICENSE
57/* .ad
58/* .fi
59/*	The Secure Mailer license must be distributed with this software.
60/* AUTHOR(S)
61/*	Wietse Venema
62/*	IBM T.J. Watson Research
63/*	P.O. Box 704
64/*	Yorktown Heights, NY 10598, USA
65/*--*/
66
67/* System library. */
68
69#include <sys_defs.h>
70#include <string.h>
71#include <stdlib.h>
72
73#ifdef STRCASECMP_IN_STRINGS_H
74#include <strings.h>
75#endif
76
77/* Utility library. */
78
79#include <msg.h>
80#include <vstring.h>
81#include <vstream.h>
82#include <mymalloc.h>
83#include <stringops.h>
84
85/* Global library. */
86
87#include <rec_type.h>
88#include <cleanup_user.h>
89#include <mail_params.h>
90#include <ext_prop.h>
91#include <mail_addr.h>
92#include <canon_addr.h>
93#include <mail_addr_find.h>
94#include <mail_proto.h>
95#include <dsn_mask.h>
96
97/* Application-specific. */
98
99#include "cleanup.h"
100
101#define STR			vstring_str
102#define IGNORE_EXTENSION	(char **) 0
103
104/* cleanup_addr_sender - process envelope sender record */
105
106void    cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
107{
108    VSTRING *clean_addr = vstring_alloc(100);
109    const char *bcc;
110
111    /*
112     * Note: an unqualified envelope address is for all practical purposes
113     * equivalent to a fully qualified local address, both for delivery and
114     * for replying. Having to support both forms is error prone, therefore
115     * an incomplete envelope address is rewritten to fully qualified form in
116     * the local domain context.
117     *
118     * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle
119     * bounced mail traffic more robustly.
120     */
121    cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf);
122    if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
123		    sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
124	canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
125	if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0)
126	    vstring_strcpy(clean_addr, "");
127    }
128    if (state->flags & CLEANUP_FLAG_MAP_OK) {
129	if (cleanup_send_canon_maps
130	    && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
131	    cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps,
132				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
133	if (cleanup_comm_canon_maps
134	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
135	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
136				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
137	if (cleanup_masq_domains
138	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
139	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
140    }
141    CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr);
142    if (state->sender)				/* XXX Can't happen */
143	myfree(state->sender);
144    state->sender = mystrdup(STR(clean_addr));	/* Used by Milter client */
145    if ((state->flags & CLEANUP_FLAG_BCC_OK)
146	&& *STR(clean_addr)
147	&& cleanup_send_bcc_maps) {
148	if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr),
149				  IGNORE_EXTENSION)) != 0) {
150	    cleanup_addr_bcc(state, bcc);
151	} else if (cleanup_send_bcc_maps->error) {
152	    msg_warn("%s: %s lookup problem",
153		     state->queue_id, cleanup_send_bcc_maps->title);
154	    state->errs |= CLEANUP_STAT_WRITE;
155	}
156    }
157    vstring_free(clean_addr);
158}
159
160/* cleanup_addr_recipient - process envelope recipient */
161
162void    cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
163{
164    VSTRING *clean_addr = vstring_alloc(100);
165    const char *bcc;
166
167    /*
168     * Note: an unqualified envelope address is for all practical purposes
169     * equivalent to a fully qualified local address, both for delivery and
170     * for replying. Having to support both forms is error prone, therefore
171     * an incomplete envelope address is rewritten to fully qualified form in
172     * the local domain context.
173     */
174    cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL,
175			     clean_addr, *buf ? buf : var_empty_addr);
176    if (state->flags & CLEANUP_FLAG_MAP_OK) {
177	if (cleanup_rcpt_canon_maps
178	    && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
179	    cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
180				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
181	if (cleanup_comm_canon_maps
182	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
183	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
184				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
185	if (cleanup_masq_domains
186	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
187	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
188    }
189    cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
190			  state->orig_rcpt, STR(clean_addr));
191    if (state->recip)				/* This can happen */
192	myfree(state->recip);
193    state->recip = mystrdup(STR(clean_addr));	/* Used by Milter client */
194    if ((state->flags & CLEANUP_FLAG_BCC_OK)
195	&& *STR(clean_addr)
196	&& cleanup_rcpt_bcc_maps) {
197	if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr),
198				  IGNORE_EXTENSION)) != 0) {
199	    cleanup_addr_bcc(state, bcc);
200	} else if (cleanup_rcpt_bcc_maps->error) {
201	    msg_warn("%s: %s lookup problem",
202		     state->queue_id, cleanup_rcpt_bcc_maps->title);
203	    state->errs |= CLEANUP_STAT_WRITE;
204	}
205    }
206    vstring_free(clean_addr);
207}
208
209/* cleanup_addr_bcc_dsn - process automatic BCC recipient */
210
211void    cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc,
212			             const char *dsn_orcpt, int dsn_notify)
213{
214    VSTRING *clean_addr = vstring_alloc(100);
215
216    /*
217     * Note: BCC addresses are supplied locally, and must be rewritten in the
218     * local address rewriting context.
219     */
220    cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, bcc);
221    if (state->flags & CLEANUP_FLAG_MAP_OK) {
222	if (cleanup_rcpt_canon_maps
223	    && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
224	    cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
225				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
226	if (cleanup_comm_canon_maps
227	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
228	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
229				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
230	if (cleanup_masq_domains
231	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
232	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
233    }
234    cleanup_out_recipient(state, dsn_orcpt, dsn_notify,
235			  STR(clean_addr), STR(clean_addr));
236    vstring_free(clean_addr);
237}
238