xref: /netbsd-src/external/ibm-public/postfix/dist/src/cleanup/cleanup_addr.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1 /*	$NetBSD: cleanup_addr.c,v 1.3 2020/03/18 19:05:15 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	cleanup_addr 3
6 /* SUMMARY
7 /*	process envelope addresses
8 /* SYNOPSIS
9 /*	#include <cleanup.h>
10 /*
11 /*	off_t	cleanup_addr_sender(state, addr)
12 /*	CLEANUP_STATE *state;
13 /*	const char *addr;
14 /*
15 /*	void	cleanup_addr_recipient(state, addr)
16 /*	CLEANUP_STATE *state;
17 /*	const char *addr;
18 /*
19 /*	void	cleanup_addr_bcc_dsn(state, addr, dsn_orcpt, dsn_notify)
20 /*	CLEANUP_STATE *state;
21 /*	const char *addr;
22 /*	const char *dsn_orcpt;
23 /*	int	dsn_notify;
24 /*
25 /*	void	cleanup_addr_bcc(state, addr)
26 /*	CLEANUP_STATE *state;
27 /*	const char *addr;
28 /* DESCRIPTION
29 /*	This module processes envelope address records and writes the result
30 /*	to the queue file. Processing includes address rewriting and
31 /*	sender/recipient auto bcc address generation.
32 /*
33 /*	cleanup_addr_sender() processes sender envelope information and updates
34 /*	state->sender. The result value is the offset of the record that
35 /*	follows the sender record if milters are enabled, otherwise zero.
36 /*
37 /*	cleanup_addr_recipient() processes recipient envelope information
38 /*	and updates state->recip.
39 /*
40 /*	cleanup_addr_bcc_dsn() processes recipient envelope information. This
41 /*	is a separate function to avoid invoking cleanup_addr_recipient()
42 /*	recursively.
43 /*
44 /*	cleanup_addr_bcc() is a backwards-compatibility wrapper for
45 /*	cleanup_addr_bcc_dsn() that requests no delivery status
46 /*	notification for the recipient.
47 /*
48 /*	Arguments:
49 /* .IP state
50 /*	Queue file and message processing state. This state is updated
51 /*	as records are processed and as errors happen.
52 /* .IP buf
53 /*	Record content.
54 /* .IP dsn_orcpt
55 /*	The DSN original recipient (or NO_DSN_ORCPT to specify none).
56 /* .IP dsn_notify
57 /*	DSN notification options. Specify NO_DSN_NOTIFY to disable
58 /*	notification, and DEF_DSN_NOTIFY for default notification.
59 /* LICENSE
60 /* .ad
61 /* .fi
62 /*	The Secure Mailer license must be distributed with this software.
63 /* AUTHOR(S)
64 /*	Wietse Venema
65 /*	IBM T.J. Watson Research
66 /*	P.O. Box 704
67 /*	Yorktown Heights, NY 10598, USA
68 /*
69 /*	Wietse Venema
70 /*	Google, Inc.
71 /*	111 8th Avenue
72 /*	New York, NY 10011, USA
73 /*--*/
74 
75 /* System library. */
76 
77 #include <sys_defs.h>
78 #include <string.h>
79 #include <stdlib.h>
80 
81 /* Utility library. */
82 
83 #include <msg.h>
84 #include <vstring.h>
85 #include <vstream.h>
86 #include <mymalloc.h>
87 #include <stringops.h>
88 
89 /* Global library. */
90 
91 #include <rec_type.h>
92 #include <record.h>
93 #include <cleanup_user.h>
94 #include <mail_params.h>
95 #include <ext_prop.h>
96 #include <mail_addr.h>
97 #include <canon_addr.h>
98 #include <mail_addr_find.h>
99 #include <mail_proto.h>
100 #include <dsn_mask.h>
101 #include <smtputf8.h>
102 
103 /* Application-specific. */
104 
105 #include "cleanup.h"
106 
107 #define STR			vstring_str
108 #define LEN			VSTRING_LEN
109 #define IGNORE_EXTENSION	(char **) 0
110 
111 /* cleanup_addr_sender - process envelope sender record */
112 
cleanup_addr_sender(CLEANUP_STATE * state,const char * buf)113 off_t   cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
114 {
115     const char myname[] = "cleanup_addr_sender";
116     VSTRING *clean_addr = vstring_alloc(100);
117     off_t   after_sender_offs = 0;
118     const char *bcc;
119     size_t  len;
120 
121     /*
122      * Note: an unqualified envelope address is for all practical purposes
123      * equivalent to a fully qualified local address, both for delivery and
124      * for replying. Having to support both forms is error prone, therefore
125      * an incomplete envelope address is rewritten to fully qualified form in
126      * the local domain context.
127      *
128      * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle
129      * bounced mail traffic more robustly.
130      */
131     cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf);
132     if (strncasecmp_utf8(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
133 			 sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
134 	canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
135 	if (strcasecmp_utf8(STR(clean_addr), STR(state->temp1)) == 0)
136 	    vstring_strcpy(clean_addr, "");
137     }
138     if (state->flags & CLEANUP_FLAG_MAP_OK) {
139 	if (cleanup_send_canon_maps
140 	    && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
141 	    cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps,
142 				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
143 	if (cleanup_comm_canon_maps
144 	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
145 	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
146 				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
147 	if (cleanup_masq_domains
148 	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
149 	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
150     }
151     /* Fix 20140711: Auto-detect an UTF8 sender. */
152     if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
153 	&& valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
154 	state->smtputf8 |= SMTPUTF8_FLAG_SENDER;
155 	/* Fix 20140713: request SMTPUTF8 support selectively. */
156 	if (state->flags & CLEANUP_FLAG_AUTOUTF8)
157 	    state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
158     }
159     CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr);
160     if (state->sender)				/* XXX Can't happen */
161 	myfree(state->sender);
162     state->sender = mystrdup(STR(clean_addr));	/* Used by Milter client */
163     /* Fix 20160310: Moved from cleanup_envelope.c. */
164     if (state->milters || cleanup_milters) {
165 	/* Make room to replace sender. */
166 	if ((len = LEN(clean_addr)) < REC_TYPE_PTR_PAYL_SIZE)
167 	    rec_pad(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_PAYL_SIZE - len);
168 	/* Remember the after-sender record offset. */
169 	if ((after_sender_offs = vstream_ftell(state->dst)) < 0)
170 	    msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
171     }
172     if ((state->flags & CLEANUP_FLAG_BCC_OK)
173 	&& *STR(clean_addr)
174 	&& cleanup_send_bcc_maps) {
175 	if ((bcc = mail_addr_find_to_internal(cleanup_send_bcc_maps,
176 					      STR(clean_addr),
177 					      IGNORE_EXTENSION)) != 0) {
178 	    cleanup_addr_bcc(state, bcc);
179 	} else if (cleanup_send_bcc_maps->error) {
180 	    msg_warn("%s: %s map lookup problem -- "
181 		     "message not accepted, try again later",
182 		     state->queue_id, cleanup_send_bcc_maps->title);
183 	    state->errs |= CLEANUP_STAT_WRITE;
184 	}
185     }
186     vstring_free(clean_addr);
187     return after_sender_offs;
188 }
189 
190 /* cleanup_addr_recipient - process envelope recipient */
191 
cleanup_addr_recipient(CLEANUP_STATE * state,const char * buf)192 void    cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
193 {
194     VSTRING *clean_addr = vstring_alloc(100);
195     const char *bcc;
196 
197     /*
198      * Note: an unqualified envelope address is for all practical purposes
199      * equivalent to a fully qualified local address, both for delivery and
200      * for replying. Having to support both forms is error prone, therefore
201      * an incomplete envelope address is rewritten to fully qualified form in
202      * the local domain context.
203      */
204     cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL,
205 			     clean_addr, *buf ? buf : var_empty_addr);
206     if (state->flags & CLEANUP_FLAG_MAP_OK) {
207 	if (cleanup_rcpt_canon_maps
208 	    && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
209 	    cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
210 				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
211 	if (cleanup_comm_canon_maps
212 	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
213 	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
214 				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
215 	if (cleanup_masq_domains
216 	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
217 	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
218     }
219     /* Fix 20140711: Auto-detect an UTF8 recipient. */
220     if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
221 	&& valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
222 	/* Fix 20140713: request SMTPUTF8 support selectively. */
223 	if (state->flags & CLEANUP_FLAG_AUTOUTF8)
224 	    state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
225     }
226     /* Fix 20141024: Don't fake up a "bare" DSN original rcpt in smtp(8). */
227     if (state->dsn_orcpt == 0 && *STR(clean_addr) != 0)
228 	state->dsn_orcpt = concatenate((!allascii(STR(clean_addr))
229 			   && (state->smtputf8 & SMTPUTF8_FLAG_REQUESTED)) ?
230 		      "utf-8" : "rfc822", ";", STR(clean_addr), (char *) 0);
231     cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
232 			  state->orig_rcpt, STR(clean_addr));
233     if (state->recip)				/* This can happen */
234 	myfree(state->recip);
235     state->recip = mystrdup(STR(clean_addr));	/* Used by Milter client */
236     if ((state->flags & CLEANUP_FLAG_BCC_OK)
237 	&& *STR(clean_addr)
238 	&& cleanup_rcpt_bcc_maps) {
239 	if ((bcc = mail_addr_find_to_internal(cleanup_rcpt_bcc_maps,
240 					      STR(clean_addr),
241 					      IGNORE_EXTENSION)) != 0) {
242 	    cleanup_addr_bcc(state, bcc);
243 	} else if (cleanup_rcpt_bcc_maps->error) {
244 	    msg_warn("%s: %s map lookup problem -- "
245 		     "message not accepted, try again later",
246 		     state->queue_id, cleanup_rcpt_bcc_maps->title);
247 	    state->errs |= CLEANUP_STAT_WRITE;
248 	}
249     }
250     vstring_free(clean_addr);
251 }
252 
253 /* cleanup_addr_bcc_dsn - process automatic BCC recipient */
254 
cleanup_addr_bcc_dsn(CLEANUP_STATE * state,const char * bcc,const char * dsn_orcpt,int dsn_notify)255 void    cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc,
256 			             const char *dsn_orcpt, int dsn_notify)
257 {
258     VSTRING *clean_addr = vstring_alloc(100);
259 
260     /*
261      * Note: BCC addresses are supplied locally, and must be rewritten in the
262      * local address rewriting context.
263      */
264     cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, bcc);
265     if (state->flags & CLEANUP_FLAG_MAP_OK) {
266 	if (cleanup_rcpt_canon_maps
267 	    && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
268 	    cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
269 				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
270 	if (cleanup_comm_canon_maps
271 	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
272 	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
273 				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
274 	if (cleanup_masq_domains
275 	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
276 	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
277     }
278     /* Fix 20140711: Auto-detect an UTF8 recipient. */
279     if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
280 	&& valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
281 	/* Fix 20140713: request SMTPUTF8 support selectively. */
282 	if (state->flags & CLEANUP_FLAG_AUTOUTF8)
283 	    state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
284     }
285     cleanup_out_recipient(state, dsn_orcpt, dsn_notify,
286 			  STR(clean_addr), STR(clean_addr));
287     vstring_free(clean_addr);
288 }
289