|
1 diff -urN README_FILES/SRS_README.orig README_FILES/SRS_README |
|
2 --- README_FILES/SRS_README.orig 1970-01-01 01:00:00.000000000 +0100 |
|
3 +++ README_FILES/SRS_README 2012-02-21 14:22:05.000000000 +0100 |
|
4 @@ -0,0 +1,56 @@ |
|
5 + |
|
6 +CREDITS: |
|
7 + |
|
8 +- originally written by Shevek <srs@anarres.org> |
|
9 +- fixes and porting to postfix 2.1 by Branko F. Gracnar <bfg@frost.ath.cx> |
|
10 +- redesigned and ported to debian postfix 2.7.0 by Chris <chris@codefrickler.de> |
|
11 + |
|
12 +SYNOPSIS: |
|
13 +Works with all address classes (not limited to local domain). |
|
14 +Doesn't depend on .forward-files or alias_maps. |
|
15 +SMTPD accepts valid srs addresses without further configuration. |
|
16 +Sender gets rewritten only when necessary: |
|
17 +- rewrite after queuing (after separation to on- and off-site destinations) |
|
18 +- rewrite only if sender and recipient are off-site and host is not a relay for recipient |
|
19 +Alias domain can be chosen automatically from original on-site-recipient. |
|
20 + |
|
21 + |
|
22 +USAGE: |
|
23 + |
|
24 +1) Apply the patch. |
|
25 + |
|
26 +2) Create makefiles with |
|
27 + |
|
28 +make makefiles CCARGS="-DHAS_SRS -I<directory-containing--srs2.h>" AUXLIBS="-L<directory-containing--libsrs2.so> -lsrs2" |
|
29 + |
|
30 + |
|
31 +3) Build. |
|
32 + |
|
33 +4) Add the following global configuration variables to main.cf: |
|
34 +All variables are optional, except where stated: |
|
35 + |
|
36 + srs_domain (string) |
|
37 + A domain to use in rewritten addresses. This must point only |
|
38 + to machines which know the encoding secret used by this |
|
39 + system. It defaults to $myorigin. If set to the emtpy |
|
40 + string, use domain from original recipient if host is final |
|
41 + destination, otherwise use $myorigin. |
|
42 + srs_hashlength (int) |
|
43 + The hash length to generate in a rewritten address. |
|
44 + srs_hashmin (int) |
|
45 + The hash length to require when checking an address. |
|
46 + srs_maxage (int) |
|
47 + The maximum permitted age of a rewritten address. |
|
48 + srs_secrets (string) |
|
49 + [required] A list of secrets with which to generate |
|
50 + and check addresses. |
|
51 + srs_separator (string) |
|
52 + The separator to appear immediately after SRS[01] in |
|
53 + rewritten addresses. |
|
54 + |
|
55 + |
|
56 +See http://www.libsrs2.org/ for more information about the meaning |
|
57 +of these variables. They are standard across MTAs. |
|
58 + |
|
59 +5) Fire up and enjoy. |
|
60 + |
|
61 diff -urN src/cleanup/cleanup_addr.c.orig src/cleanup/cleanup_addr.c |
|
62 --- src/cleanup/cleanup_addr.c.orig 2012-02-21 14:21:34.000000000 +0100 |
|
63 +++ src/cleanup/cleanup_addr.c 2012-02-21 14:22:05.000000000 +0100 |
|
64 @@ -163,6 +163,10 @@ |
|
65 { |
|
66 VSTRING *clean_addr = vstring_alloc(100); |
|
67 const char *bcc; |
|
68 +#ifdef HAS_SRS |
|
69 + int srs_state; |
|
70 + VSTRING *srs_rcpt; |
|
71 +#endif |
|
72 |
|
73 /* |
|
74 * Note: an unqualified envelope address is for all practical purposes |
|
75 @@ -174,6 +178,14 @@ |
|
76 cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, |
|
77 clean_addr, *buf ? buf : var_empty_addr); |
|
78 if (state->flags & CLEANUP_FLAG_MAP_OK) { |
|
79 +#ifdef HAS_SRS |
|
80 + if ((srs_state = postfix_srs_reverse(STR(clean_addr), &srs_rcpt)) < 0) { |
|
81 + /* XXX errors */ |
|
82 + } else if (srs_state == 1) { |
|
83 + vstring_free(clean_addr); |
|
84 + clean_addr = srs_rcpt; |
|
85 + } |
|
86 +#endif |
|
87 if (cleanup_rcpt_canon_maps |
|
88 && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) |
|
89 cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, |
|
90 diff -urN src/global/mail_params.c.orig src/global/mail_params.c |
|
91 --- src/global/mail_params.c.orig 2012-02-21 14:21:34.000000000 +0100 |
|
92 +++ src/global/mail_params.c 2012-02-21 14:22:05.000000000 +0100 |
|
93 @@ -308,6 +308,15 @@ |
|
94 bool var_long_queue_ids; |
|
95 bool var_daemon_open_fatal; |
|
96 |
|
97 +#ifdef HAS_SRS |
|
98 +int var_srs_hashlength; |
|
99 +int var_srs_hashmin; |
|
100 +int var_srs_maxage; |
|
101 +char *var_srs_secrets; |
|
102 +char *var_srs_separator; |
|
103 +char *var_srs_domain; |
|
104 +#endif |
|
105 + |
|
106 const char null_format_string[1] = ""; |
|
107 |
|
108 /* check_myhostname - lookup hostname and validate */ |
|
109 @@ -579,6 +588,11 @@ |
|
110 VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0, |
|
111 /* multi_instance_wrapper may have dependencies but not dependents. */ |
|
112 VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0, |
|
113 +#ifdef HAS_SRS |
|
114 + VAR_SRS_SECRETS, DEF_SRS_SECRETS, &var_srs_secrets, 0, 0, |
|
115 + VAR_SRS_SEPARATOR, DEF_SRS_SEPARATOR, &var_srs_separator, 1, 1, |
|
116 + VAR_SRS_DOMAIN, DEF_SRS_DOMAIN, &var_srs_domain, 0, 0, |
|
117 +#endif |
|
118 0, |
|
119 }; |
|
120 static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = { |
|
121 @@ -602,6 +616,11 @@ |
|
122 VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0, |
|
123 VAR_DELAY_MAX_RES, DEF_DELAY_MAX_RES, &var_delay_max_res, MIN_DELAY_MAX_RES, MAX_DELAY_MAX_RES, |
|
124 VAR_INET_WINDOW, DEF_INET_WINDOW, &var_inet_windowsize, 0, 0, |
|
125 +#ifdef HAS_SRS |
|
126 + VAR_SRS_HASHLENGTH, DEF_SRS_HASHLENGTH, &var_srs_hashlength, 1, 20, |
|
127 + VAR_SRS_HASHMIN, DEF_SRS_HASHMIN, &var_srs_hashmin, 1, 20, |
|
128 + VAR_SRS_MAXAGE, DEF_SRS_MAXAGE, &var_srs_maxage, 1, 0, |
|
129 +#endif |
|
130 0, |
|
131 }; |
|
132 static const CONFIG_LONG_TABLE long_defaults[] = { |
|
133 diff -urN src/global/mail_params.h.orig src/global/mail_params.h |
|
134 --- src/global/mail_params.h.orig 2012-02-21 14:21:34.000000000 +0100 |
|
135 +++ src/global/mail_params.h 2012-02-21 14:22:41.000000000 +0100 |
|
136 @@ -1981,6 +1981,35 @@ |
|
137 #define DEF_ALLOW_UNTRUST_ROUTE 0 |
|
138 extern bool var_allow_untrust_route; |
|
139 |
|
140 +/** |
|
141 + * SRS. Shevek <srs@anarres.org>, updated by Chris <chris@codefrickler.de> |
|
142 + */ |
|
143 +#ifdef HAS_SRS |
|
144 +#define VAR_SRS_HASHLENGTH "srs_hashlength" |
|
145 +#define DEF_SRS_HASHLENGTH 4 |
|
146 +extern int var_srs_hashlength; |
|
147 + |
|
148 +#define VAR_SRS_HASHMIN "srs_hashmin" |
|
149 +#define DEF_SRS_HASHMIN 4 |
|
150 +extern int var_srs_hashmin; |
|
151 + |
|
152 +#define VAR_SRS_MAXAGE "srs_maxage" |
|
153 +#define DEF_SRS_MAXAGE 21 |
|
154 +extern int var_srs_maxage; |
|
155 + |
|
156 +#define VAR_SRS_SECRETS "srs_secrets" |
|
157 +#define DEF_SRS_SECRETS "" |
|
158 +extern char *var_srs_secrets; |
|
159 + |
|
160 +#define VAR_SRS_DOMAIN "srs_domain" |
|
161 +#define DEF_SRS_DOMAIN "$myorigin" |
|
162 +extern char *var_srs_domain; |
|
163 + |
|
164 +#define VAR_SRS_SEPARATOR "srs_separator" |
|
165 +#define DEF_SRS_SEPARATOR "=" |
|
166 +extern char *var_srs_separator; |
|
167 +#endif |
|
168 + |
|
169 /* |
|
170 * Names of specific restrictions, and the corresponding configuration |
|
171 * parameters that control the status codes sent in response to rejected |
|
172 diff -urN src/global/Makefile.in.orig src/global/Makefile.in |
|
173 --- src/global/Makefile.in.orig 2012-02-21 14:21:34.000000000 +0100 |
|
174 +++ src/global/Makefile.in 2012-02-21 14:22:05.000000000 +0100 |
|
175 @@ -29,7 +29,7 @@ |
|
176 user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \ |
|
177 verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \ |
|
178 fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \ |
|
179 - match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \ |
|
180 + match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c srs.c \ |
|
181 smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \ |
|
182 dict_memcache.c mail_version.c memcache_proto.c server_acl.c \ |
|
183 mkmap_fail.c |
|
184 @@ -63,7 +63,7 @@ |
|
185 user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \ |
|
186 verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \ |
|
187 fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \ |
|
188 - match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \ |
|
189 + match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o srs.o \ |
|
190 smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \ |
|
191 dict_memcache.o mail_version.o memcache_proto.o server_acl.o \ |
|
192 mkmap_fail.o |
|
193 diff -urN src/global/srs.c.orig src/global/srs.c |
|
194 --- src/global/srs.c.orig 1970-01-01 01:00:00.000000000 +0100 |
|
195 +++ src/global/srs.c 2012-02-21 14:22:27.000000000 +0100 |
|
196 @@ -0,0 +1,144 @@ |
|
197 +/*++ |
|
198 +/* NAME |
|
199 +/* srs 3 |
|
200 +/* SUMMARY |
|
201 +/* Sender Rewriting Scheme |
|
202 +/* SYNOPSIS |
|
203 +/* void postfix_srs_reverse(rcpt, decoded) |
|
204 +/* const char *rcpt |
|
205 +/* VSTRING **decoded |
|
206 +/* |
|
207 +/* int postfix_srs_forward(sender, alias, encoded) |
|
208 +/* const char *sender |
|
209 +/* const char *alias |
|
210 +/* VSTRING **decoded |
|
211 +/* DESCRIPTION |
|
212 +/* This module rewrites addresses according to the Sender Rewriting |
|
213 +/* Scheme, documented at http://www.libsrs2.org/. |
|
214 +/* |
|
215 +/* srs_reverse() reverse-rewrites the rewritten form of an address |
|
216 +/* |
|
217 +/* srs_forward() rewrites the envelope sender using alias domain |
|
218 +/* |
|
219 +/* DIAGNOSTICS |
|
220 +/* LICENSE |
|
221 +/* .ad |
|
222 +/* .fi |
|
223 +/* The Secure Mailer license must be distributed with this software. |
|
224 +/* AUTHOR(S) |
|
225 +/* Shevek <srs@anarres.org> |
|
226 +/* Chris <chris@codefrickler.de> |
|
227 +/*--*/ |
|
228 + |
|
229 +#ifdef HAS_SRS |
|
230 + |
|
231 +/* System library. */ |
|
232 + |
|
233 +#include <stdlib.h> |
|
234 +#include <sys_defs.h> |
|
235 +#include <string.h> |
|
236 + |
|
237 +#include <srs2.h> |
|
238 + |
|
239 +/* Utility library. */ |
|
240 + |
|
241 +#include <msg.h> |
|
242 +#include <vstring.h> |
|
243 +#include <mymalloc.h> |
|
244 +#include <stringops.h> |
|
245 + |
|
246 +/* Global library. */ |
|
247 + |
|
248 +#include <mail_params.h> |
|
249 + |
|
250 +#define SRS_FAIL_UNLESS(x) do { int __ret = (x); if (__ret != SRS_SUCCESS) msg_fatal("SRS configuration error: %s", srs_strerror(__ret)); } while(0) |
|
251 + |
|
252 +/* my function declarations */ |
|
253 +int postfix_srs_forward (const char *sender, const char *alias, VSTRING **encoded); |
|
254 +int postfix_srs_reverse (const char *rcpt, VSTRING **decoded); |
|
255 + |
|
256 +static srs_t *srs; |
|
257 + |
|
258 +static void postfix_srs_init (void) { |
|
259 + char *saved_secrets; |
|
260 + char *secret; |
|
261 + char *ptr; |
|
262 + |
|
263 + if (srs == NULL) { |
|
264 + /* XXX Can't use memory functions from postfix because of inconsistensies in libsrs2 |
|
265 + srs_set_malloc((srs_malloc_t)mymalloc, (srs_realloc_t)myrealloc, (srs_free_t)myfree); |
|
266 + */ |
|
267 + |
|
268 + srs = srs_new(); |
|
269 + /* avoid sender-domain-check, since we have already done this ourselves */ |
|
270 + SRS_FAIL_UNLESS(srs_set_alwaysrewrite(srs, 1)); |
|
271 + SRS_FAIL_UNLESS(srs_set_hashlength(srs, var_srs_hashlength)); |
|
272 + SRS_FAIL_UNLESS(srs_set_hashmin(srs, var_srs_hashmin)); |
|
273 + SRS_FAIL_UNLESS(srs_set_maxage(srs, var_srs_maxage)); |
|
274 + SRS_FAIL_UNLESS(srs_set_separator(srs, var_srs_separator[0])); |
|
275 + |
|
276 + ptr = saved_secrets = mystrdup(var_srs_secrets); |
|
277 + while ((secret = mystrtok(&ptr, ", \t\r\n")) != 0) { |
|
278 + SRS_FAIL_UNLESS(srs_add_secret(srs, secret)); |
|
279 + } |
|
280 + myfree(saved_secrets); |
|
281 + } |
|
282 +} |
|
283 + |
|
284 +int postfix_srs_reverse(const char *rcpt, VSTRING **decoded) { |
|
285 + char *out; |
|
286 + int ret; |
|
287 + |
|
288 + if (!SRS_IS_SRS_ADDRESS(rcpt)) |
|
289 + return (0); |
|
290 + |
|
291 + postfix_srs_init(); |
|
292 + |
|
293 + ret = srs_reverse_alloc(srs, &out, rcpt); |
|
294 + |
|
295 + if (ret != SRS_SUCCESS) { |
|
296 + switch (SRS_ERROR_TYPE(ret)) { |
|
297 + case SRS_ERRTYPE_CONFIG: |
|
298 + msg_fatal("SRS configuration error: %s", srs_strerror(ret)); |
|
299 + return (-1); |
|
300 + case SRS_ERRTYPE_INPUT: |
|
301 + msg_fatal("SRS reverse failed for <%s>: %s", rcpt, srs_strerror(ret)); |
|
302 + return (-1); |
|
303 + case SRS_ERRTYPE_SYNTAX: |
|
304 + case SRS_ERRTYPE_SRS: |
|
305 + msg_warn("SRS reverse failed for <%s>: %s", rcpt, srs_strerror(ret)); |
|
306 + break; |
|
307 + } |
|
308 + return (0); |
|
309 + } |
|
310 + |
|
311 + if (decoded) { |
|
312 + *decoded = vstring_alloc(100); |
|
313 + vstring_strcpy(*decoded, out); |
|
314 + } |
|
315 + free(out); |
|
316 + |
|
317 + return (1); |
|
318 +} |
|
319 + |
|
320 +int postfix_srs_forward(const char *sender, const char *alias, VSTRING **encoded) { |
|
321 + char *out; |
|
322 + int ret; |
|
323 + |
|
324 + postfix_srs_init(); |
|
325 + |
|
326 + ret = srs_forward_alloc(srs, &out, sender, alias); |
|
327 + |
|
328 + if (ret != SRS_SUCCESS) { |
|
329 + msg_warn("SRS forward failed for <%s>: %s", sender, srs_strerror(ret)); |
|
330 + return (0); |
|
331 + } |
|
332 + |
|
333 + *encoded = vstring_alloc(100); |
|
334 + vstring_strcpy(*encoded, out); |
|
335 + free(out); |
|
336 + |
|
337 + return (1); |
|
338 +} |
|
339 + |
|
340 +#endif |
|
341 diff -urN src/qmgr/qmgr_deliver.c.orig src/qmgr/qmgr_deliver.c |
|
342 --- src/qmgr/qmgr_deliver.c.orig 2012-02-21 14:21:34.000000000 +0100 |
|
343 +++ src/qmgr/qmgr_deliver.c 2012-02-21 14:22:05.000000000 +0100 |
|
344 @@ -76,6 +76,7 @@ |
|
345 #include <dsn_buf.h> |
|
346 #include <dsb_scan.h> |
|
347 #include <rcpt_print.h> |
|
348 +#include <resolve_clnt.h> |
|
349 |
|
350 /* Application-specific. */ |
|
351 |
|
352 @@ -129,6 +130,73 @@ |
|
353 } |
|
354 } |
|
355 |
|
356 +#ifdef HAS_SRS |
|
357 +/* qmgr_deliver_check_srs - check whether sender should be rewritten */ |
|
358 + |
|
359 +static int qmgr_deliver_check_srs(QMGR_MESSAGE *message, RECIPIENT_LIST list, char **alias, RESOLVE_REPLY *reply) |
|
360 +{ |
|
361 + char *pos; |
|
362 + |
|
363 + /* |
|
364 + * Rewrite if we are not final destination nor relay host for recipient and sender address |
|
365 + * it should be enough to look at the first recipient, since transport/nexthop are the same for all recipients |
|
366 + */ |
|
367 + resolve_clnt_query(list.info->address, reply); |
|
368 + if (reply->flags & RESOLVE_FLAG_FAIL) |
|
369 + return (-1); |
|
370 + else if (!(reply->flags & RESOLVE_CLASS_DEFAULT)) |
|
371 + return (0); |
|
372 + |
|
373 + resolve_clnt_query(message->sender, reply); |
|
374 + if (reply->flags & RESOLVE_FLAG_FAIL) |
|
375 + return (-1); |
|
376 + else if (!(reply->flags & RESOLVE_CLASS_DEFAULT)) |
|
377 + return (0); |
|
378 + |
|
379 + if (var_srs_domain[0]) { |
|
380 + *alias = var_srs_domain; |
|
381 + } else { |
|
382 + /* retrieve alias domain from original recipient if we are final destination ... */ |
|
383 + resolve_clnt_query(list.info->orig_addr, reply); |
|
384 + if (reply->flags & RESOLVE_FLAG_FAIL) |
|
385 + return (-1); |
|
386 + if ((reply->flags & RESOLVE_CLASS_FINAL) && (pos = strrchr(list.info->orig_addr, '@'))) { |
|
387 + *alias = pos + 1; |
|
388 + } else { |
|
389 + /* ... or use myorigin as fallback */ |
|
390 + *alias = var_myorigin; |
|
391 + } |
|
392 + } |
|
393 + |
|
394 + return (1); |
|
395 +} |
|
396 + |
|
397 +/* qmgr_deliver_do_srs - compute srs address if necessary */ |
|
398 + |
|
399 +static int qmgr_deliver_do_srs(QMGR_MESSAGE *message, RECIPIENT_LIST list, VSTRING **encoded) |
|
400 +{ |
|
401 + RESOLVE_REPLY reply; |
|
402 + char *alias; |
|
403 + int state; |
|
404 + |
|
405 + resolve_clnt_init(&reply); |
|
406 + state = qmgr_deliver_check_srs(message, list, &alias, &reply); |
|
407 + resolve_clnt_free(&reply); |
|
408 + if (state < 0) { |
|
409 + msg_warn("srs lookup problem"); |
|
410 + return (-1); |
|
411 + } else if (state == 0) { |
|
412 + return (0); |
|
413 + } |
|
414 + |
|
415 + state = postfix_srs_forward(message->sender, alias, encoded); |
|
416 + if (state < 0) |
|
417 + return (-1); |
|
418 + |
|
419 + return (1); |
|
420 +} |
|
421 +#endif |
|
422 + |
|
423 /* qmgr_deliver_send_request - send delivery request to delivery process */ |
|
424 |
|
425 static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) |
|
426 @@ -140,6 +208,9 @@ |
|
427 MSG_STATS stats; |
|
428 char *sender; |
|
429 int flags; |
|
430 +#ifdef HAS_SRS |
|
431 + int srs_state; |
|
432 +#endif |
|
433 |
|
434 /* |
|
435 * If variable envelope return path is requested, change prefix+@origin |
|
436 @@ -147,7 +218,19 @@ |
|
437 * recipient per delivery. |
|
438 */ |
|
439 if (message->verp_delims == 0) { |
|
440 - sender = message->sender; |
|
441 +#ifdef HAS_SRS |
|
442 + srs_state = qmgr_deliver_do_srs(message, list, &sender_buf); |
|
443 + if (srs_state < 0) { |
|
444 + return (-1); |
|
445 + } else if (srs_state == 1) { |
|
446 + sender = vstring_str(sender_buf); |
|
447 + msg_info("%s: srs_from=<%s>", message->queue_id, sender); |
|
448 + } else { |
|
449 + sender = message->sender; |
|
450 + } |
|
451 +#else |
|
452 + sender = message->sender; |
|
453 +#endif |
|
454 } else { |
|
455 sender_buf = vstring_alloc(100); |
|
456 verp_sender(sender_buf, message->verp_delims, |
|
457 diff -urN src/smtpd/smtpd_check.c.orig src/smtpd/smtpd_check.c |
|
458 --- src/smtpd/smtpd_check.c.orig 2012-02-21 14:21:34.000000000 +0100 |
|
459 +++ src/smtpd/smtpd_check.c 2012-02-21 14:22:05.000000000 +0100 |
|
460 @@ -929,6 +929,19 @@ |
|
461 reject_server_error(state); |
|
462 } |
|
463 |
|
464 +#ifdef HAS_SRS |
|
465 +/* check_mail_addr_srs - check if address is a valid srs address */ |
|
466 + |
|
467 +static int check_mail_addr_srs(SMTPD_STATE *state, const char *reply_name, const char *addr) |
|
468 +{ |
|
469 + int result; |
|
470 + |
|
471 + if ((result = postfix_srs_reverse(addr, 0)) < 0) |
|
472 + reject_dict_retry(state, reply_name); |
|
473 + return (result); |
|
474 +} |
|
475 +#endif |
|
476 + |
|
477 /* reject_unknown_reverse_name - fail if reverse client hostname is unknown */ |
|
478 |
|
479 static int reject_unknown_reverse_name(SMTPD_STATE *state) |
|
480 @@ -4552,6 +4565,13 @@ |
|
481 || MATCH(canonical_maps, CONST_STR(reply->recipient)) |
|
482 || MATCH(virt_alias_maps, CONST_STR(reply->recipient))) |
|
483 return (0); |
|
484 + |
|
485 +#ifdef HAS_SRS |
|
486 + /* allow valid srs address */ |
|
487 + if ((reply->flags & RESOLVE_CLASS_FINAL) |
|
488 + && check_mail_addr_srs(state, recipient, CONST_STR(reply->recipient)) == 1) |
|
489 + return (0); |
|
490 +#endif |
|
491 |
|
492 /* |
|
493 * At this point, anything that resolves to the error mailer is known to |