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