Build: avoid compiling code for unused transports, routers, authenticators
[exim.git] / src / src / routers / redirect.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10
11 #include "../exim.h"
12
13 #ifdef ROUTER_REDIRECT  /* Remainder of file */
14 #include "rf_functions.h"
15 #include "redirect.h"
16
17
18
19 /* Options specific to the redirect router. */
20 #define LOFF(field) OPT_OFF(redirect_router_options_block, field)
21
22 optionlist redirect_router_options[] = {
23   { "allow_defer",        opt_bit | (RDON_DEFER << 16),
24       LOFF(bit_options) },
25   { "allow_fail",         opt_bit | (RDON_FAIL << 16),
26       LOFF(bit_options) },
27   { "allow_filter",       opt_bit | (RDON_FILTER << 16),
28       LOFF(bit_options) },
29   { "allow_freeze",       opt_bit | (RDON_FREEZE << 16),
30       LOFF(bit_options) },
31   { "check_ancestor",     opt_bool,             LOFF(check_ancestor) },
32   { "check_group",        opt_bool,             LOFF(check_group) },
33   { "check_owner",        opt_bool,             LOFF(check_owner) },
34   { "data",               opt_stringptr,        LOFF(data) },
35   { "directory_transport",opt_stringptr,        LOFF(directory_transport_name) },
36   { "file",               opt_stringptr,        LOFF(file) },
37   { "file_transport",     opt_stringptr,        LOFF(file_transport_name) },
38
39   { "filter_prepend_home",opt_bit | (RDON_PREPEND_HOME << 16),
40       LOFF(bit_options) },
41   { "forbid_blackhole",   opt_bit | (RDON_BLACKHOLE << 16),
42       LOFF(bit_options) },
43   { "forbid_exim_filter", opt_bit | (RDON_EXIM_FILTER << 16),
44       LOFF(bit_options) },
45   { "forbid_file",        opt_bool,
46       LOFF(forbid_file) },
47   { "forbid_filter_dlfunc", opt_bit | (RDON_DLFUNC << 16),
48       LOFF(bit_options) },
49   { "forbid_filter_existstest",  opt_bit | (RDON_EXISTS << 16),
50       LOFF(bit_options) },
51   { "forbid_filter_logwrite",opt_bit | (RDON_LOG << 16),
52       LOFF(bit_options) },
53   { "forbid_filter_lookup", opt_bit | (RDON_LOOKUP << 16),
54       LOFF(bit_options) },
55   { "forbid_filter_perl", opt_bit | (RDON_PERL << 16),
56       LOFF(bit_options) },
57   { "forbid_filter_readfile", opt_bit | (RDON_READFILE << 16),
58       LOFF(bit_options) },
59   { "forbid_filter_readsocket", opt_bit | (RDON_READSOCK << 16),
60       LOFF(bit_options) },
61   { "forbid_filter_reply",opt_bool,
62       LOFF(forbid_filter_reply) },
63   { "forbid_filter_run",  opt_bit | (RDON_RUN << 16),
64       LOFF(bit_options) },
65   { "forbid_include",     opt_bit | (RDON_INCLUDE << 16),
66       LOFF(bit_options) },
67   { "forbid_pipe",        opt_bool,
68       LOFF(forbid_pipe) },
69   { "forbid_sieve_filter",opt_bit | (RDON_SIEVE_FILTER << 16),
70       LOFF(bit_options) },
71   { "forbid_smtp_code",     opt_bool,
72       LOFF(forbid_smtp_code) },
73   { "hide_child_in_errmsg", opt_bool,
74       LOFF( hide_child_in_errmsg) },
75   { "ignore_eacces",      opt_bit | (RDON_EACCES << 16),
76       LOFF(bit_options) },
77   { "ignore_enotdir",     opt_bit | (RDON_ENOTDIR << 16),
78       LOFF(bit_options) },
79
80   { "include_directory",  opt_stringptr,        LOFF( include_directory) },
81   { "modemask",           opt_octint,           LOFF(modemask) },
82   { "one_time",           opt_bool,             LOFF(one_time) },
83   { "owners",             opt_uidlist,          LOFF(owners) },
84   { "owngroups",          opt_gidlist,          LOFF(owngroups) },
85   { "pipe_transport",     opt_stringptr,        LOFF(pipe_transport_name) },
86   { "qualify_domain",     opt_stringptr,        LOFF(qualify_domain) },
87   { "qualify_preserve_domain", opt_bool,        LOFF(qualify_preserve_domain) },
88   { "repeat_use",         opt_bool | opt_public, OPT_OFF(router_instance, repeat_use) },
89   { "reply_transport",    opt_stringptr,        LOFF(reply_transport_name) },
90
91   { "rewrite",            opt_bit | (RDON_REWRITE << 16),
92       LOFF(bit_options) },
93
94   { "sieve_enotify_mailto_owner", opt_stringptr, LOFF(sieve_enotify_mailto_owner) },
95   { "sieve_subaddress", opt_stringptr,          LOFF(sieve_subaddress) },
96   { "sieve_useraddress", opt_stringptr,         LOFF(sieve_useraddress) },
97   { "sieve_vacation_directory", opt_stringptr,  LOFF(sieve_vacation_directory) },
98   { "skip_syntax_errors", opt_bool,             LOFF(skip_syntax_errors) },
99   { "syntax_errors_text", opt_stringptr,        LOFF(syntax_errors_text) },
100   { "syntax_errors_to",   opt_stringptr,        LOFF(syntax_errors_to) }
101 };
102
103 /* Size of the options list. An extern variable has to be used so that its
104 address can appear in the tables drtables.c. */
105
106 int redirect_router_options_count =
107   sizeof(redirect_router_options)/sizeof(optionlist);
108
109
110 #ifdef MACRO_PREDEF
111
112 /* Dummy entries */
113 redirect_router_options_block redirect_router_option_defaults = {0};
114 void redirect_router_init(router_instance *rblock) {}
115 int redirect_router_entry(router_instance *rblock, address_item *addr,
116   struct passwd *pw, int verify, address_item **addr_local,
117   address_item **addr_remote, address_item **addr_new,
118   address_item **addr_succeed) {return 0;}
119
120 #else   /*!MACRO_PREDEF*/
121
122
123
124 /* Default private options block for the redirect router. */
125
126 redirect_router_options_block redirect_router_option_defaults = {
127   NULL,        /* directory_transport */
128   NULL,        /* file_transport */
129   NULL,        /* pipe_transport */
130   NULL,        /* reply_transport */
131   NULL,        /* data */
132   NULL,        /* directory_transport_name */
133   NULL,        /* file */
134   NULL,        /* file_dir */
135   NULL,        /* file_transport_name */
136   NULL,        /* include_directory */
137   NULL,        /* pipe_transport_name */
138   NULL,        /* reply_transport_name */
139   NULL,        /* sieve_subaddress */
140   NULL,        /* sieve_useraddress */
141   NULL,        /* sieve_vacation_directory */
142   NULL,        /* sieve_enotify_mailto_owner */
143   NULL,        /* syntax_errors_text */
144   NULL,        /* syntax_errors_to */
145   NULL,        /* qualify_domain */
146   NULL,        /* owners */
147   NULL,        /* owngroups */
148   022,         /* modemask */
149   RDO_REWRITE | RDO_PREPEND_HOME, /* bit_options */
150   FALSE,       /* check_ancestor */
151   TRUE_UNSET,  /* check_owner */
152   TRUE_UNSET,  /* check_group */
153   FALSE,       /* forbid_file */
154   FALSE,       /* forbid_filter_reply */
155   FALSE,       /* forbid_pipe */
156   FALSE,       /* forbid_smtp_code */
157   FALSE,       /* hide_child_in_errmsg */
158   FALSE,       /* one_time */
159   FALSE,       /* qualify_preserve_domain */
160   FALSE        /* skip_syntax_errors */
161 };
162
163
164
165 /*************************************************
166 *          Initialization entry point            *
167 *************************************************/
168
169 /* Called for each instance, after its options have been read, to enable
170 consistency checks to be done, or anything else that needs to be set up. */
171
172 void redirect_router_init(router_instance *rblock)
173 {
174 redirect_router_options_block *ob =
175   (redirect_router_options_block *)(rblock->options_block);
176
177 /* Either file or data must be set, but not both */
178
179 if ((ob->file == NULL) == (ob->data == NULL))
180   log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n  "
181     "%sone of \"file\" or \"data\" must be specified",
182     rblock->name, (ob->file == NULL)? "" : "only ");
183
184 /* Onetime aliases can only be real addresses. Headers can't be manipulated.
185 The combination of one_time and unseen is not allowed. We can't check the
186 expansion of "unseen" here, but we assume that if it is set to anything other
187 than false, there is likely to be a problem. */
188
189 if (ob->one_time)
190   {
191   ob->forbid_pipe = ob->forbid_file = ob->forbid_filter_reply = TRUE;
192   if (rblock->extra_headers || rblock->remove_headers)
193     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n  "
194       "\"headers_add\" and \"headers_remove\" are not permitted with "
195       "\"one_time\"", rblock->name);
196   if (rblock->unseen || rblock->expand_unseen)
197     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n  "
198       "\"unseen\" may not be used with \"one_time\"", rblock->name);
199   }
200
201 /* The defaults for check_owner and check_group depend on other settings. The
202 defaults are: Check the owner if check_local_user or owners is set; check the
203 group if check_local_user is set without a restriction on the group write bit,
204 or if owngroups is set. */
205
206 if (ob->check_owner == TRUE_UNSET)
207   ob->check_owner = rblock->check_local_user ||
208                     (ob->owners && ob->owners[0] != 0);
209
210 if (ob->check_group == TRUE_UNSET)
211   ob->check_group = (rblock->check_local_user && (ob->modemask & 020) == 0) ||
212                     (ob->owngroups != NULL && ob->owngroups[0] != 0);
213
214 /* If explicit qualify domain set, the preserve option is locked out */
215
216 if (ob->qualify_domain && ob->qualify_preserve_domain)
217   log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n  "
218     "only one of \"qualify_domain\" or \"qualify_preserve_domain\" must be set",
219     rblock->name);
220
221 /* If allow_filter is set, either user or check_local_user must be set. */
222
223 if (!rblock->check_local_user &&
224     !rblock->uid_set &&
225     rblock->expand_uid == NULL &&
226     (ob->bit_options & RDO_FILTER) != 0)
227   log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n  "
228     "\"user\" or \"check_local_user\" must be set with \"allow_filter\"",
229     rblock->name);
230 }
231
232
233
234 /*************************************************
235 *       Get errors address and header mods       *
236 *************************************************/
237
238 /* This function is called when new addresses are generated, in order to
239 sort out errors address and header modifications. We put the errors address
240 into the parent address (even though it is never used from there because that
241 address is never transported) so that it can be retrieved if any of the
242 children gets routed by an "unseen" router. The clone of the child that is
243 passed on must have the original errors_address value.
244
245 Arguments:
246   rblock               the router control block
247   addr                 the address being routed
248   verify               v_none/v_recipient/v_sender/v_expn
249   addr_prop            point to the propagated block, which is where the
250                          new values are to be placed
251
252 Returns:    the result of rf_get_errors_address() or rf_get_munge_headers(),
253             which is either OK or DEFER
254 */
255
256 static int
257 sort_errors_and_headers(router_instance *rblock, address_item *addr,
258   int verify, address_item_propagated *addr_prop)
259 {
260 int frc = rf_get_errors_address(addr, rblock, verify,
261   &addr_prop->errors_address);
262 if (frc != OK) return frc;
263 addr->prop.errors_address = addr_prop->errors_address;
264 return rf_get_munge_headers(addr, rblock, &addr_prop->extra_headers,
265   &addr_prop->remove_headers);
266 }
267
268
269
270 /*************************************************
271 *    Process a set of generated new addresses    *
272 *************************************************/
273
274 /* This function sets up a set of newly generated child addresses and puts them
275 on the new address chain. Copy in the uid, gid and permission flags for use by
276 pipes and files, set the parent, and "or" its af_ignore_error flag. Also record
277 the setting for any starting router.
278
279 If the generated address is the same as one of its ancestors, and the
280 check_ancestor flag is set, do not use this generated address, but replace it
281 with a copy of the input address. This is to cope with cases where A is aliased
282 to B and B has a .forward file pointing to A, though it is usually set on the
283 forwardfile rather than the aliasfile. We can't just pass on the old
284 address by returning FAIL, because it must act as a general parent for
285 generated addresses, and only get marked "done" when all its children are
286 delivered.
287
288 Arguments:
289   rblock                  router block
290   addr_new                new address chain
291   addr                    original address
292   generated               list of generated addresses
293   addr_prop               the propagated block, containing the errors_address,
294                             header modification stuff, and address_data
295   ugidptr                 points to uid/gid data for files, pipes, autoreplies
296   pw                      password entry, set if ob->check_local_user is TRUE
297
298 Returns:         nothing
299 */
300
301 static void
302 add_generated(router_instance *rblock, address_item **addr_new,
303   address_item *addr, address_item *generated,
304   address_item_propagated *addr_prop, ugid_block *ugidptr, struct passwd *pw)
305 {
306 redirect_router_options_block *ob =
307   (redirect_router_options_block *)(rblock->options_block);
308
309 while (generated)
310   {
311   address_item * next = generated, * parent;
312   const uschar * errors_address = next->prop.errors_address;
313
314   generated = next->next;
315   next->parent = addr;
316   next->start_router = rblock->redirect_router;
317   if (addr->child_count == USHRT_MAX)
318     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router generated more than %d "
319       "child addresses for <%s>", rblock->name, USHRT_MAX, addr->address);
320   addr->child_count++;
321
322   next->next = *addr_new;
323   *addr_new = next;
324
325   /* Don't do the "one_time" thing for the first pass of a 2-stage queue run. */
326
327   if (ob->one_time && !f.queue_2stage)
328     {
329     for (parent = addr; parent->parent; parent = parent->parent) ;
330     next->onetime_parent = parent->address;
331     }
332
333   if (ob->hide_child_in_errmsg) setflag(next, af_hide_child);
334
335   /* If check_ancestor is set, we want to know if any ancestor of this address
336   is the address we are about to generate. The check must be done caselessly
337   unless the ancestor was routed by a case-sensitive router. */
338
339   if (ob->check_ancestor)
340     for (parent = addr; parent; parent = parent->parent)
341       if ((parent->router && parent->router->caseful_local_part
342            ? Ustrcmp(next->address, parent->address)
343            : strcmpic(next->address, parent->address)
344           ) == 0)
345         {
346         DEBUG(D_route) debug_printf("generated parent replaced by child\n");
347         next->address = string_copy(addr->address);
348         break;
349         }
350
351   /* A user filter may, under some circumstances, set up an errors address.
352   If so, we must take care to re-instate it when we copy in the propagated
353   data so that it overrides any errors_to setting on the router. */
354
355     {
356     BOOL ignore_error = next->prop.ignore_error;
357     next->prop = *addr_prop;
358     next->prop.ignore_error = ignore_error || addr->prop.ignore_error;
359     }
360   if (errors_address) next->prop.errors_address = errors_address;
361
362   /* For pipes, files, and autoreplies, record this router as handling them,
363   because they don't go through the routing process again. Then set up uid,
364   gid, home and current directories for transporting. */
365
366   if (testflag(next, af_pfr))
367     {
368     next->router = rblock;
369     rf_set_ugid(next, ugidptr);   /* Will contain pw values if not overridden */
370
371     /* When getting the home directory out of the password information, wrap it
372     in \N...\N to avoid expansion later. In Cygwin, home directories can
373     contain $ characters. */
374
375     if (rblock->home_directory)
376       next->home_dir = rblock->home_directory;
377     else if (rblock->check_local_user)
378       next->home_dir = string_sprintf("\\N%s\\N", pw->pw_dir);
379     else if (rblock->router_home_directory && testflag(addr, af_home_expanded))
380       {
381       next->home_dir = deliver_home;
382       setflag(next, af_home_expanded);
383       }
384
385     next->current_dir = rblock->current_directory;
386
387     /* Permission options */
388
389     if (!ob->forbid_pipe) setflag(next, af_allow_pipe);
390     if (!ob->forbid_file) setflag(next, af_allow_file);
391     if (!ob->forbid_filter_reply) setflag(next, af_allow_reply);
392
393     /* If the transport setting fails, the error gets picked up at the outer
394     level from the setting of basic_errno in the address. */
395
396     if (next->address[0] == '|')
397       {
398       address_pipe = next->address;
399       GET_OPTION("pipe_transport");
400       if (rf_get_transport(ob->pipe_transport_name, &ob->pipe_transport,
401           next, rblock->name, US"pipe_transport"))
402         next->transport = ob->pipe_transport;
403       address_pipe = NULL;
404       }
405     else if (next->address[0] == '>')
406       {
407       GET_OPTION("reply_transport");
408       if (rf_get_transport(ob->reply_transport_name, &ob->reply_transport,
409           next, rblock->name, US"reply_transport"))
410         next->transport = ob->reply_transport;
411       }
412     else  /* must be file or directory */
413       {
414       int len = Ustrlen(next->address);
415       address_file = next->address;
416       if (next->address[len-1] == '/')
417         {
418         GET_OPTION("directory_transport");
419         if (rf_get_transport(ob->directory_transport_name,
420             &(ob->directory_transport), next, rblock->name,
421             US"directory_transport"))
422           next->transport = ob->directory_transport;
423         }
424       else
425         {
426         GET_OPTION("file_transport");
427         if (rf_get_transport(ob->file_transport_name, &ob->file_transport,
428             next, rblock->name, US"file_transport"))
429           next->transport = ob->file_transport;
430         }
431
432       address_file = NULL;
433       }
434     }
435
436 #ifdef SUPPORT_I18N
437     if (!next->prop.utf8_msg)
438       next->prop.utf8_msg = string_is_utf8(next->address)
439         || (sender_address && string_is_utf8(sender_address));
440 #endif
441
442   DEBUG(D_route)
443     {
444     debug_printf("%s router generated %s\n  %serrors_to=%s transport=%s\n",
445       rblock->name,
446       next->address,
447       testflag(next, af_pfr)? "pipe, file, or autoreply\n  " : "",
448       next->prop.errors_address,
449       (next->transport == NULL)? US"NULL" : next->transport->name);
450
451     if (testflag(next, af_uid_set))
452       debug_printf("  uid=%ld ", (long int)(next->uid));
453     else
454       debug_printf("  uid=unset ");
455
456     if (testflag(next, af_gid_set))
457       debug_printf("gid=%ld ", (long int)(next->gid));
458     else
459       debug_printf("gid=unset ");
460
461 #ifdef SUPPORT_I18N
462     if (next->prop.utf8_msg) debug_printf("utf8 ");
463 #endif
464
465     debug_printf("home=%s\n", next->home_dir);
466     }
467   }
468 }
469
470
471 /*************************************************
472 *              Main entry point                  *
473 *************************************************/
474
475 /* See local README for interface description. This router returns:
476
477 DECLINE
478   . empty address list, or filter did nothing significant
479
480 DEFER
481   . verifying the errors address caused a deferment or a big disaster such
482       as an expansion failure (rf_get_errors_address)
483   . expanding a headers_{add,remove} string caused a deferment or another
484       expansion error (rf_get_munge_headers)
485   . :defer: or "freeze" in a filter
486   . error in address list or filter
487   . skipped syntax errors, but failed to send the message
488
489 DISCARD
490   . address was :blackhole:d or "seen finish"ed
491
492 FAIL
493   . :fail:
494
495 OK
496   . new addresses added to addr_new
497 */
498
499 int redirect_router_entry(
500   router_instance *rblock,        /* data for this instantiation */
501   address_item *addr,             /* address we are working on */
502   struct passwd *pw,              /* passwd entry after check_local_user */
503   int verify,                     /* v_none/v_recipient/v_sender/v_expn */
504   address_item **addr_local,      /* add it to this if it's local */
505   address_item **addr_remote,     /* add it to this if it's remote */
506   address_item **addr_new,        /* put new addresses on here */
507   address_item **addr_succeed)    /* put old address here on success */
508 {
509 redirect_router_options_block *ob =
510   (redirect_router_options_block *)(rblock->options_block);
511 address_item *generated = NULL;
512 const uschar *save_qualify_domain_recipient = qualify_domain_recipient;
513 uschar *discarded = US"discarded";
514 address_item_propagated addr_prop;
515 error_block *eblock = NULL;
516 ugid_block ugid;
517 redirect_block redirect;
518 int filtertype = FILTER_UNSET;
519 int yield = OK;
520 int options = ob->bit_options;
521 int frc = 0;
522 int xrc = 0;
523
524 /* Initialize the data to be propagated to the children */
525
526 addr_prop.address_data = deliver_address_data;
527 addr_prop.domain_data = deliver_domain_data;
528 addr_prop.localpart_data = deliver_localpart_data;
529 addr_prop.errors_address = NULL;
530 addr_prop.extra_headers = NULL;
531 addr_prop.remove_headers = NULL;
532 addr_prop.variables = NULL;
533 tree_dup((tree_node **)&addr_prop.variables, addr->prop.variables);
534
535 #ifdef SUPPORT_I18N
536 addr_prop.utf8_msg = addr->prop.utf8_msg;
537 addr_prop.utf8_downcvt = addr->prop.utf8_downcvt;
538 addr_prop.utf8_downcvt_maybe = addr->prop.utf8_downcvt_maybe;
539 #endif
540
541
542 /* When verifying and testing addresses, the "logwrite" command in filters
543 must be bypassed. */
544
545 if (verify == v_none && !f.address_test_mode) options |= RDO_REALLOG;
546
547 /* Sort out the fixed or dynamic uid/gid. This uid is used (a) for reading the
548 file (and interpreting a filter) and (b) for running the transports for
549 generated file and pipe addresses. It is not (necessarily) the same as the uids
550 that may own the file. Exim panics if an expanded string is not a number and
551 can't be found in the password file. Other errors set the freezing bit. */
552
553 if (!rf_get_ugid(rblock, addr, &ugid)) return DEFER;
554
555 if (!ugid.uid_set && pw != NULL)
556   {
557   ugid.uid = pw->pw_uid;
558   ugid.uid_set = TRUE;
559   }
560
561 if (!ugid.gid_set && pw != NULL)
562   {
563   ugid.gid = pw->pw_gid;
564   ugid.gid_set = TRUE;
565   }
566
567 /* Call the function that interprets redirection data, either inline or from a
568 file. This is a separate function so that the system filter can use it. It will
569 run the function in a subprocess if necessary. If qualify_preserve_domain is
570 set, temporarily reset qualify_domain_recipient to the current domain so that
571 any unqualified addresses get qualified with the same domain as the incoming
572 address. Otherwise, if a local qualify_domain is provided, set that up. */
573
574 if (ob->qualify_preserve_domain)
575   qualify_domain_recipient = addr->domain;
576 else
577   {
578   GET_OPTION("qualify_domain");
579   if (ob->qualify_domain)
580     {
581     uschar *new_qdr = rf_expand_data(addr, ob->qualify_domain, &xrc);
582     if (!new_qdr) return xrc;
583     qualify_domain_recipient = new_qdr;
584     }
585   }
586
587 redirect.owners = ob->owners;
588 redirect.owngroups = ob->owngroups;
589 redirect.modemask = ob->modemask;
590 redirect.check_owner = ob->check_owner;
591 redirect.check_group = ob->check_group;
592 redirect.pw = pw;
593
594 redirect.string = (redirect.isfile = (ob->file != NULL))
595   ? ob->file : ob->data;
596
597 frc = rda_interpret(&redirect, options, ob->include_directory,
598   ob->sieve_vacation_directory, ob->sieve_enotify_mailto_owner,
599   ob->sieve_useraddress, ob->sieve_subaddress, &ugid, &generated,
600   &addr->message, ob->skip_syntax_errors? &eblock : NULL, &filtertype,
601   string_sprintf("%s router (recipient is %s)", rblock->name, addr->address));
602
603 qualify_domain_recipient = save_qualify_domain_recipient;
604
605 /* Handle exceptional returns from filtering or processing an address list.
606 For FAIL and FREEZE we honour any previously set up deliveries by a filter. */
607
608 switch (frc)
609   {
610   case FF_NONEXIST:
611     addr->message = addr->user_message = NULL;
612     return DECLINE;
613
614   case FF_BLACKHOLE:
615     DEBUG(D_route) debug_printf("address :blackhole:d\n");
616     generated = NULL;
617     discarded = US":blackhole:";
618     frc = FF_DELIVERED;
619     break;
620
621     /* FF_DEFER and FF_FAIL can arise only as a result of explicit commands
622     (:defer: or :fail: in an alias file or "fail" in a filter). If a configured
623     message was supplied, allow it to be included in an SMTP response after
624     verifying. Remove any SMTP code if it is not allowed. */
625
626   case FF_DEFER:
627     yield = DEFER;
628     goto SORT_MESSAGE;
629
630   case FF_FAIL:
631     if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK)
632       return xrc;
633     add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw);
634     yield = FAIL;
635
636     SORT_MESSAGE:
637     if (!addr->message)
638       addr->message = yield == FAIL ? US"forced rejection" : US"forced defer";
639     else
640       {
641       uschar * matched;
642       if (  ob->forbid_smtp_code
643          && regex_match(regex_smtp_code, addr->message, -1, &matched))
644         {
645         DEBUG(D_route) debug_printf("SMTP code at start of error message "
646           "is ignored because forbid_smtp_code is set\n");
647         addr->message += Ustrlen(matched);
648         }
649       addr->user_message = addr->message;
650       setflag(addr, af_pass_message);
651       }
652     return yield;
653
654     /* As in the case of a system filter, a freeze does not happen after a manual
655     thaw. In case deliveries were set up by the filter, we set the child count
656     high so that their completion does not mark the original address done. */
657
658   case FF_FREEZE:
659     if (!f.deliver_manual_thaw)
660       {
661       if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop))
662         != OK) return xrc;
663       add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw);
664       if (addr->message == NULL) addr->message = US"frozen by filter";
665       addr->special_action = SPECIAL_FREEZE;
666       addr->child_count = 9999;
667       return DEFER;
668       }
669     frc = FF_NOTDELIVERED;
670     break;
671
672     /* Handle syntax errors and :include: failures and lookup defers */
673
674   case FF_ERROR:
675   case FF_INCLUDEFAIL:
676
677     /* If filtertype is still FILTER_UNSET, it means that the redirection data
678     was never inspected, so the error was an expansion failure or failure to open
679     the file, or whatever. In these cases, the existing error message is probably
680     sufficient. */
681
682     if (filtertype == FILTER_UNSET) return DEFER;
683
684     /* If it was a filter and skip_syntax_errors is set, we want to set up
685     the error message so that it can be logged and mailed to somebody. */
686
687     if (filtertype != FILTER_FORWARD && ob->skip_syntax_errors)
688       {
689       eblock = store_get(sizeof(error_block), GET_UNTAINTED);
690       eblock->next = NULL;
691       eblock->text1 = addr->message;
692       eblock->text2 = NULL;
693       addr->message = addr->user_message = NULL;
694       }
695
696     /* Otherwise set up the error for the address and defer. */
697
698     else
699       {
700       addr->basic_errno = ERRNO_BADREDIRECT;
701       addr->message = string_sprintf("error in %s %s: %s",
702         filtertype == FILTER_FORWARD ? "redirect" : "filter",
703         ob->data ? "data" : "file",
704         addr->message);
705       return DEFER;
706       }
707   }
708
709
710 /* Yield is either FF_DELIVERED (significant action) or FF_NOTDELIVERED (no
711 significant action). Before dealing with these, however, we must handle the
712 effect of skip_syntax_errors.
713
714 If skip_syntax_errors was set and there were syntax errors in an address list,
715 error messages will be present in eblock. Log them and send a message if so
716 configured. We cannot do this earlier, because the error message must not be
717 sent as the local user. If there were no valid addresses, generated will be
718 NULL. In this case, the router declines.
719
720 For a filter file, the error message has been fudged into an eblock. After
721 dealing with it, the router declines. */
722
723 if (eblock != NULL)
724   {
725   if (!moan_skipped_syntax_errors(
726         rblock->name,                            /* For message content */
727         eblock,                                  /* Ditto */
728         (verify != v_none || f.address_test_mode)?
729           NULL : ob->syntax_errors_to,           /* Who to mail */
730         generated != NULL,                       /* True if not all failed */
731         ob->syntax_errors_text))                 /* Custom message */
732     return DEFER;
733
734   if (filtertype != FILTER_FORWARD || generated == NULL)
735     {
736     addr->message = US"syntax error in redirection data";
737     return DECLINE;
738     }
739   }
740
741 /* Sort out the errors address and any header modifications, and handle the
742 generated addresses, if any. If there are no generated addresses, we must avoid
743 calling sort_errors_and_headers() in case this router declines - that function
744 may modify the errors_address field in the current address, and we don't want
745 to do that for a decline. */
746
747 if (generated != NULL)
748   {
749   if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK)
750     return xrc;
751   add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw);
752   }
753
754 /* FF_DELIVERED with no generated addresses is what we get when an address list
755 contains :blackhole: or a filter contains "seen finish" without having
756 generated anything. Log what happened to this address, and return DISCARD. */
757
758 if (frc == FF_DELIVERED)
759   {
760   if (generated == NULL && verify == v_none && !f.address_test_mode)
761     {
762     log_write(0, LOG_MAIN, "=> %s <%s> R=%s", discarded, addr->address,
763       rblock->name);
764     yield = DISCARD;
765     }
766   }
767
768 /* For an address list, FF_NOTDELIVERED always means that no addresses were
769 generated. For a filter, addresses may or may not have been generated. If none
770 were, it's the same as an empty address list, and the router declines. However,
771 if addresses were generated, we can't just decline because successful delivery
772 of the base address gets it marked "done", so deferred generated addresses
773 never get tried again. We have to generate a new version of the base address,
774 as if there were a "deliver" command in the filter file, with the original
775 address as parent. */
776
777 else
778   {
779   address_item *next;
780
781   if (generated == NULL) return DECLINE;
782
783   next = deliver_make_addr(addr->address, FALSE);
784   next->parent = addr;
785   addr->child_count++;
786   next->next = *addr_new;
787   *addr_new = next;
788
789   /* Set the data that propagates. */
790
791   next->prop = addr_prop;
792
793   DEBUG(D_route) debug_printf("%s router autogenerated %s\n%s%s%s",
794     rblock->name,
795     next->address,
796     (addr_prop.errors_address != NULL)? "  errors to " : "",
797     (addr_prop.errors_address != NULL)? addr_prop.errors_address : US"",
798     (addr_prop.errors_address != NULL)? "\n" : "");
799   }
800
801 /* Control gets here only when the address has been completely handled. Put the
802 original address onto the succeed queue so that any retry items that get
803 attached to it get processed. */
804
805 addr->next = *addr_succeed;
806 *addr_succeed = addr;
807
808 return yield;
809 }
810
811 #endif   /*!MACRO_PREDEF*/
812 #endif  /*ROUTER_REDIRECT*/
813 /* End of routers/redirect.c */