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