Don't free thing until we're done
[freeradius.git] / src / main / modcall.c
1 /*
2  * @name modcall.c
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 RCSID("$Id$")
24
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/modpriv.h>
27 #include <freeradius-devel/modcall.h>
28 #include <freeradius-devel/parser.h>
29 #include <freeradius-devel/rad_assert.h>
30
31
32 /* mutually-recursive static functions need a prototype up front */
33 static modcallable *do_compile_modgroup(modcallable *,
34                                         rlm_components_t, CONF_SECTION *,
35                                         int, int, int);
36
37 /* Actions may be a positive integer (the highest one returned in the group
38  * will be returned), or the keyword "return", represented here by
39  * MOD_ACTION_RETURN, to cause an immediate return.
40  * There's also the keyword "reject", represented here by MOD_ACTION_REJECT
41  * to cause an immediate reject. */
42 #define MOD_ACTION_RETURN  (-1)
43 #define MOD_ACTION_REJECT  (-2)
44
45 /* Here are our basic types: modcallable, modgroup, and modsingle. For an
46  * explanation of what they are all about, see doc/configurable_failover.rst */
47 struct modcallable {
48         modcallable *parent;
49         struct modcallable *next;
50         char const *name;
51         char const *debug_name;
52         enum { MOD_SINGLE = 1, MOD_GROUP, MOD_LOAD_BALANCE, MOD_REDUNDANT_LOAD_BALANCE,
53 #ifdef WITH_UNLANG
54                MOD_IF, MOD_ELSE, MOD_ELSIF, MOD_UPDATE, MOD_SWITCH, MOD_CASE,
55                MOD_FOREACH, MOD_BREAK, MOD_RETURN,
56 #endif
57                MOD_POLICY, MOD_REFERENCE, MOD_XLAT } type;
58         rlm_components_t method;
59         int actions[RLM_MODULE_NUMCODES];
60 };
61
62 #define MOD_LOG_OPEN_BRACE RDEBUG2("%s {", c->debug_name)
63
64 #define MOD_LOG_CLOSE_BRACE RDEBUG2("} # %s = %s", c->debug_name, fr_int2str(mod_rcode_table, result, "<invalid>"))
65
66 typedef struct {
67         modcallable             mc;             /* self */
68         enum {
69                 GROUPTYPE_SIMPLE = 0,
70                 GROUPTYPE_REDUNDANT,
71                 GROUPTYPE_APPEND,
72                 GROUPTYPE_COUNT
73         } grouptype;                            /* after mc */
74         modcallable             *children;
75         modcallable             *tail;          /* of the children list */
76         CONF_SECTION            *cs;
77         value_pair_map_t        *map;           /* update */
78         value_pair_tmpl_t       *vpt;           /* switch */
79         fr_cond_t               *cond;          /* if/elsif */
80         bool                    done_pass2;
81 } modgroup;
82
83 typedef struct {
84         modcallable mc;
85         module_instance_t *modinst;
86 } modsingle;
87
88 typedef struct {
89         modcallable mc;
90         char const *ref_name;
91         CONF_SECTION *ref_cs;
92 } modref;
93
94 typedef struct {
95         modcallable mc;
96         int exec;
97         char *xlat_name;
98 } modxlat;
99
100 /* Simple conversions: modsingle and modgroup are subclasses of modcallable,
101  * so we often want to go back and forth between them. */
102 static modsingle *mod_callabletosingle(modcallable *p)
103 {
104         rad_assert(p->type==MOD_SINGLE);
105         return (modsingle *)p;
106 }
107 static modgroup *mod_callabletogroup(modcallable *p)
108 {
109         rad_assert((p->type > MOD_SINGLE) && (p->type <= MOD_POLICY));
110
111         return (modgroup *)p;
112 }
113 static modcallable *mod_singletocallable(modsingle *p)
114 {
115         return (modcallable *)p;
116 }
117 static modcallable *mod_grouptocallable(modgroup *p)
118 {
119         return (modcallable *)p;
120 }
121
122 static modref *mod_callabletoref(modcallable *p)
123 {
124         rad_assert(p->type==MOD_REFERENCE);
125         return (modref *)p;
126 }
127 static modcallable *mod_reftocallable(modref *p)
128 {
129         return (modcallable *)p;
130 }
131
132 static modxlat *mod_callabletoxlat(modcallable *p)
133 {
134         rad_assert(p->type==MOD_XLAT);
135         return (modxlat *)p;
136 }
137 static modcallable *mod_xlattocallable(modxlat *p)
138 {
139         return (modcallable *)p;
140 }
141
142 /* modgroups are grown by adding a modcallable to the end */
143 static void add_child(modgroup *g, modcallable *c)
144 {
145         if (!c) return;
146
147         (void) talloc_steal(g, c);
148
149         if (!g->children) {
150                 g->children = g->tail = c;
151         } else {
152                 rad_assert(g->tail->next == NULL);
153                 g->tail->next = c;
154                 g->tail = c;
155         }
156
157         c->parent = mod_grouptocallable(g);
158 }
159
160 /* Here's where we recognize all of our keywords: first the rcodes, then the
161  * actions */
162 const FR_NAME_NUMBER mod_rcode_table[] = {
163         { "reject",     RLM_MODULE_REJECT       },
164         { "fail",       RLM_MODULE_FAIL  },
165         { "ok",         RLM_MODULE_OK      },
166         { "handled",    RLM_MODULE_HANDLED      },
167         { "invalid",    RLM_MODULE_INVALID      },
168         { "userlock",   RLM_MODULE_USERLOCK     },
169         { "notfound",   RLM_MODULE_NOTFOUND     },
170         { "noop",       RLM_MODULE_NOOP  },
171         { "updated",    RLM_MODULE_UPDATED      },
172         { NULL, 0 }
173 };
174
175
176 static char const *group_name[];
177
178 /*
179  *      Compile action && rcode for later use.
180  */
181 static int compile_action(modcallable *c, CONF_PAIR *cp)
182 {
183         int action;
184         char const *attr, *value;
185
186         attr = cf_pair_attr(cp);
187         value = cf_pair_value(cp);
188         if (!value) return 0;
189
190         if (c->type != MOD_SINGLE) {
191                 ERROR("%s[%d] Invalid return code assigment inside of a %s section",
192                       cf_pair_filename(cp), cf_pair_lineno(cp), group_name[c->type]);
193                 return 0;
194         }
195
196         if (!strcasecmp(value, "return"))
197                 action = MOD_ACTION_RETURN;
198
199         else if (!strcasecmp(value, "break"))
200                 action = MOD_ACTION_RETURN;
201
202         else if (!strcasecmp(value, "reject"))
203                 action = MOD_ACTION_REJECT;
204
205         else if (strspn(value, "0123456789")==strlen(value)) {
206                 action = atoi(value);
207
208                 /*
209                  *      Don't allow priority zero, for future use.
210                  */
211                 if (action == 0) return 0;
212         } else {
213                 cf_log_err_cp(cp, "Unknown action '%s'.\n",
214                            value);
215                 return 0;
216         }
217
218         if (strcasecmp(attr, "default") != 0) {
219                 int rcode;
220
221                 rcode = fr_str2int(mod_rcode_table, attr, -1);
222                 if (rcode < 0) {
223                         cf_log_err_cp(cp,
224                                    "Unknown module rcode '%s'.\n",
225                                    attr);
226                         return 0;
227                 }
228                 c->actions[rcode] = action;
229
230         } else {                /* set all unset values to the default */
231                 int i;
232
233                 for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
234                         if (!c->actions[i]) c->actions[i] = action;
235                 }
236         }
237
238         return 1;
239 }
240
241 /* Some short names for debugging output */
242 static char const * const comp2str[] = {
243         "authenticate",
244         "authorize",
245         "preacct",
246         "accounting",
247         "session",
248         "pre-proxy",
249         "post-proxy",
250         "post-auth"
251 #ifdef WITH_COA
252         ,
253         "recv-coa",
254         "send-coa"
255 #endif
256 };
257
258 #ifdef HAVE_PTHREAD_H
259 /*
260  *      Lock the mutex for the module
261  */
262 static void safe_lock(module_instance_t *instance)
263 {
264         if (instance->mutex)
265                 pthread_mutex_lock(instance->mutex);
266 }
267
268 /*
269  *      Unlock the mutex for the module
270  */
271 static void safe_unlock(module_instance_t *instance)
272 {
273         if (instance->mutex)
274                 pthread_mutex_unlock(instance->mutex);
275 }
276 #else
277 /*
278  *      No threads: these functions become NULL's.
279  */
280 #define safe_lock(foo)
281 #define safe_unlock(foo)
282 #endif
283
284 static rlm_rcode_t CC_HINT(nonnull) call_modsingle(rlm_components_t component, modsingle *sp, REQUEST *request)
285 {
286         int blocked;
287         int indent = request->log.indent;
288
289         /*
290          *      If the request should stop, refuse to do anything.
291          */
292         blocked = (request->master_state == REQUEST_STOP_PROCESSING);
293         if (blocked) return RLM_MODULE_NOOP;
294
295         RDEBUG3("modsingle[%s]: calling %s (%s) for request %d",
296                 comp2str[component], sp->modinst->name,
297                 sp->modinst->entry->name, request->number);
298         request->log.indent = 0;
299
300         if (sp->modinst->force) {
301                 request->rcode = sp->modinst->code;
302                 goto fail;
303         }
304
305         /*
306          *      For logging unresponsive children.
307          */
308         request->module = sp->modinst->name;
309
310         safe_lock(sp->modinst);
311         request->rcode = sp->modinst->entry->module->methods[component](sp->modinst->insthandle, request);
312         safe_unlock(sp->modinst);
313
314         request->module = "";
315
316         /*
317          *      Wasn't blocked, and now is.  Complain!
318          */
319         blocked = (request->master_state == REQUEST_STOP_PROCESSING);
320         if (blocked) {
321                 RWARN("Module %s became unblocked for request %u", sp->modinst->entry->name, request->number);
322         }
323
324  fail:
325         request->log.indent = indent;
326         RDEBUG3("modsingle[%s]: returned from %s (%s) for request %d",
327                comp2str[component], sp->modinst->name,
328                sp->modinst->entry->name, request->number);
329
330         return request->rcode;
331 }
332
333 static int default_component_results[RLM_COMPONENT_COUNT] = {
334         RLM_MODULE_REJECT,      /* AUTH */
335         RLM_MODULE_NOTFOUND,    /* AUTZ */
336         RLM_MODULE_NOOP,        /* PREACCT */
337         RLM_MODULE_NOOP,        /* ACCT */
338         RLM_MODULE_FAIL,        /* SESS */
339         RLM_MODULE_NOOP,        /* PRE_PROXY */
340         RLM_MODULE_NOOP,        /* POST_PROXY */
341         RLM_MODULE_NOOP         /* POST_AUTH */
342 #ifdef WITH_COA
343         ,
344         RLM_MODULE_NOOP,        /* RECV_COA_TYPE */
345         RLM_MODULE_NOOP         /* SEND_COA_TYPE */
346 #endif
347 };
348
349
350 static char const *group_name[] = {
351         "",
352         "single",
353         "group",
354         "load-balance group",
355         "redundant-load-balance group",
356 #ifdef WITH_UNLANG
357         "if",
358         "else",
359         "elsif",
360         "update",
361         "switch",
362         "case",
363         "foreach",
364         "break",
365         "return",
366 #endif
367         "policy",
368         "reference",
369         "xlat"
370 };
371
372 static char const modcall_spaces[] = "                                                                ";
373
374 #define MODCALL_STACK_MAX (32)
375
376 /*
377  *      Don't call the modules recursively.  Instead, do them
378  *      iteratively, and manage the call stack ourselves.
379  */
380 typedef struct modcall_stack_entry_t {
381         rlm_rcode_t result;
382         int priority;
383         int unwind;             /* unwind to this one if it exists */
384         modcallable *c;
385 } modcall_stack_entry_t;
386
387
388 static bool modcall_recurse(REQUEST *request, rlm_components_t component, int depth,
389                             modcall_stack_entry_t *entry);
390
391 /*
392  *      Call a child of a block.
393  */
394 static void modcall_child(REQUEST *request, rlm_components_t component, int depth,
395                           modcall_stack_entry_t *entry, modcallable *c,
396                           rlm_rcode_t *result)
397 {
398         modcall_stack_entry_t *next;
399
400         if (depth >= MODCALL_STACK_MAX) {
401                 ERROR("Internal sanity check failed: module stack is too deep");
402                 fr_exit(1);
403         }
404
405         /*
406          *      Initialize the childs stack frame.
407          */
408         next = entry + 1;
409         next->c = c;
410         next->result = entry->result;
411         next->priority = 0;
412         next->unwind = 0;
413
414         if (!modcall_recurse(request, component,
415                              depth, next)) {
416                 *result = RLM_MODULE_FAIL;
417                  return;
418         }
419
420         /*
421          *      Unwind back up the stack
422          */
423         if (next->unwind != 0) {
424                 entry->unwind = next->unwind;
425         }
426
427         *result = next->result;
428
429         return;
430 }
431
432
433 /*
434  *      Interpret the various types of blocks.
435  */
436 static bool modcall_recurse(REQUEST *request, rlm_components_t component, int depth,
437                             modcall_stack_entry_t *entry)
438 {
439         bool if_taken, was_if;
440         modcallable *c;
441         int priority;
442         rlm_rcode_t result;
443
444         was_if = if_taken = false;
445         result = RLM_MODULE_UNKNOWN;
446         RINDENT();
447
448 redo:
449         priority = -1;
450         c = entry->c;
451
452         /*
453          *      Nothing more to do.  Return the code and priority
454          *      which was set by the caller.
455          */
456         if (!c) goto finish;
457
458         /*
459          *      We've been asked to stop.  Do so.
460          */
461         if ((request->master_state == REQUEST_STOP_PROCESSING) ||
462             (request->parent &&
463              (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
464                 entry->result = RLM_MODULE_FAIL;
465                 entry->priority = 9999;
466                 goto finish;
467         }
468
469 #ifdef WITH_UNLANG
470         /*
471          *      Handle "if" conditions.
472          */
473         if (c->type == MOD_IF) {
474                 int condition;
475                 modgroup *g;
476
477         mod_if:
478                 g = mod_callabletogroup(c);
479                 rad_assert(g->cond != NULL);
480
481                 RDEBUG2("%s %s{", group_name[c->type], c->name);
482
483                 condition = radius_evaluate_cond(request, result, 0, g->cond);
484                 if (condition < 0) {
485                         condition = false;
486                         REDEBUG("Failed retrieving values required to evaluate condition");
487                 } else {
488                         RDEBUG2("%s %s -> %s",
489                                 group_name[c->type],
490                                 c->name, condition ? "TRUE" : "FALSE");
491                 }
492
493                 /*
494                  *      Didn't pass.  Remember that.
495                  */
496                 if (!condition) {
497                         was_if = true;
498                         if_taken = false;
499                         goto next_sibling;
500                 }
501
502                 /*
503                  *      We took the "if".  Go recurse into its' children.
504                  */
505                 was_if = true;
506                 if_taken = true;
507                 goto do_children;
508         } /* MOD_IF */
509
510         /*
511          *      "else" if the previous "if" was taken.
512          *      "if" if the previous if wasn't taken.
513          */
514         if (c->type == MOD_ELSIF) {
515                 if (!was_if) goto elsif_error;
516
517                 /*
518                  *      Like MOD_ELSE, but allow for a later "else"
519                  */
520                 if (if_taken) {
521                         RDEBUG2("... skipping %s for request %d: Preceding \"if\" was taken",
522                                 group_name[c->type], request->number);
523                         was_if = true;
524                         if_taken = true;
525                         goto next_sibling;
526                 }
527
528                 /*
529                  *      Check the "if" condition.
530                  */
531                 goto mod_if;
532         } /* MOD_ELSIF */
533
534         /*
535          *      "else" for a preceding "if".
536          */
537         if (c->type == MOD_ELSE) {
538                 if (!was_if) { /* error */
539                 elsif_error:
540                         RDEBUG2("... skipping %s for request %d: No preceding \"if\"",
541                                 group_name[c->type], request->number);
542                         goto next_sibling;
543                 }
544
545                 if (if_taken) {
546                         RDEBUG2("... skipping %s for request %d: Preceding \"if\" was taken",
547                                 group_name[c->type], request->number);
548                         was_if = false;
549                         if_taken = false;
550                         goto next_sibling;
551                 }
552
553                 /*
554                  *      We need to process it.  Go do that.
555                  */
556                 was_if = false;
557                 if_taken = false;
558                 goto do_children;
559         } /* MOD_ELSE */
560
561         /*
562          *      We're no longer processing if/else/elsif.  Reset the
563          *      trackers for those conditions.
564          */
565         was_if = false;
566         if_taken = false;
567 #endif  /* WITH_UNLANG */
568
569         if (c->type == MOD_SINGLE) {
570                 modsingle *sp;
571
572                 /*
573                  *      Process a stand-alone child, and fall through
574                  *      to dealing with it's parent.
575                  */
576                 sp = mod_callabletosingle(c);
577
578                 result = call_modsingle(c->method, sp, request);
579                 RDEBUG2("[%s] = %s", c->name ? c->name : "",
580                         fr_int2str(mod_rcode_table, result, "<invalid>"));
581                 goto calculate_result;
582         } /* MOD_SINGLE */
583
584 #ifdef WITH_UNLANG
585         /*
586          *      Update attribute(s)
587          */
588         if (c->type == MOD_UPDATE) {
589                 int rcode;
590                 modgroup *g = mod_callabletogroup(c);
591                 value_pair_map_t *map;
592
593                 MOD_LOG_OPEN_BRACE;
594                 RINDENT();
595                 for (map = g->map; map != NULL; map = map->next) {
596                         rcode = map_to_request(request, map, map_to_vp, NULL);
597                         if (rcode < 0) {
598                                 result = (rcode == -2) ? RLM_MODULE_INVALID : RLM_MODULE_FAIL;
599                                 REXDENT();
600                                 MOD_LOG_CLOSE_BRACE;
601                                 goto calculate_result;
602                         }
603                 }
604                 REXDENT();
605                 result = RLM_MODULE_NOOP;
606                 MOD_LOG_CLOSE_BRACE;
607                 goto calculate_result;
608         } /* MOD_IF */
609
610         /*
611          *      Loop over a set of attributes.
612          */
613         if (c->type == MOD_FOREACH) {
614                 int i, foreach_depth = -1;
615                 VALUE_PAIR *vps, *vp;
616                 modcall_stack_entry_t *next = NULL;
617                 vp_cursor_t copy;
618                 modgroup *g = mod_callabletogroup(c);
619
620                 if (depth >= MODCALL_STACK_MAX) {
621                         ERROR("Internal sanity check failed: module stack is too deep");
622                         fr_exit(1);
623                 }
624
625                 /*
626                  *      Figure out how deep we are in nesting by looking at request_data
627                  *      stored previously.
628                  */
629                 for (i = 0; i < 8; i++) {
630                         if (!request_data_reference(request,
631                                                     radius_get_vp, i)) {
632                                 foreach_depth = i;
633                                 break;
634                         }
635                 }
636
637                 if (foreach_depth < 0) {
638                         REDEBUG("foreach Nesting too deep!");
639                         result = RLM_MODULE_FAIL;
640                         goto calculate_result;
641                 }
642
643                 /*
644                  *      Copy the VPs from the original request, this ensures deterministic
645                  *      behaviour if someone decides to add or remove VPs in the set were
646                  *      iterating over.
647                  */
648                 if (tmpl_copy_vps(request, &vps, request, g->vpt) < 0) {        /* nothing to loop over */
649                         MOD_LOG_OPEN_BRACE;
650                         result = RLM_MODULE_NOOP;
651                         MOD_LOG_CLOSE_BRACE;
652                         goto calculate_result;
653                 }
654
655                 rad_assert(vps != NULL);
656                 fr_cursor_init(&copy, &vps);
657
658                 RDEBUG2("foreach %s ", c->name);
659
660                 /*
661                  *      This is the actual body of the foreach loop
662                  */
663                 for (vp = fr_cursor_first(&copy);
664                      vp != NULL;
665                      vp = fr_cursor_next(&copy)) {
666 #ifndef NDEBUG
667                         if (fr_debug_flag >= 2) {
668                                 char buffer[1024];
669
670                                 vp_prints_value(buffer, sizeof(buffer), vp, '"');
671                                 RDEBUG2("# Foreach-Variable-%d = %s", foreach_depth, buffer);
672                         }
673 #endif
674
675                         /*
676                          *      Add the vp to the request, so that
677                          *      xlat.c, xlat_foreach() can find it.
678                          */
679                         request_data_add(request, radius_get_vp, foreach_depth, &vp, false);
680
681                         /*
682                          *      Initialize the childs stack frame.
683                          */
684                         next = entry + 1;
685                         next->c = g->children;
686                         next->result = entry->result;
687                         next->priority = 0;
688                         next->unwind = 0;
689
690                         if (!modcall_recurse(request, component, depth + 1, next)) {
691                                 break;
692                         }
693
694                         /*
695                          *      We've unwound to the enclosing
696                          *      "foreach".  Stop the unwinding.
697                          */
698                         if (next->unwind == MOD_FOREACH) {
699                                 break;
700                         }
701
702                         /*
703                          *      Unwind all the way.
704                          */
705                         if (next->unwind == MOD_RETURN) {
706                                 entry->unwind = MOD_RETURN;
707                                 break;
708                         }
709                 } /* loop over VPs */
710
711                 /*
712                  *      Free the copied vps and the request data
713                  *      If we don't remove the request data, something could call
714                  *      the xlat outside of a foreach loop and trigger a segv.
715                  */
716                 pairfree(&vps);
717                 request_data_get(request, radius_get_vp, foreach_depth);
718
719                 rad_assert(next != NULL);
720                 result = next->result;
721                 priority = next->priority;
722                 MOD_LOG_CLOSE_BRACE;
723                 goto calculate_result;
724         } /* MOD_FOREACH */
725
726         /*
727          *      Break out of a "foreach" loop, or return from a nested
728          *      group.
729          */
730         if ((c->type == MOD_BREAK) || (c->type == MOD_RETURN)) {
731                 int i;
732                 VALUE_PAIR **copy_p;
733
734                 RDEBUG2("%s", group_name[c->type]);
735
736                 for (i = 8; i >= 0; i--) {
737                         copy_p = request_data_get(request, radius_get_vp, i);
738                         if (copy_p) {
739                                 if (c->type == MOD_BREAK) {
740                                         RDEBUG2("# break Foreach-Variable-%d", i);
741                                         break;
742                                 }
743                         }
744                 }
745
746                 /*
747                  *      Leave result / priority on the stack, and stop processing the section.
748                  */
749                 entry->unwind = c->type;
750                 goto finish;
751         } /* MOD_BREAK */
752
753 #endif    /* WITH_UNLANG */
754
755         /*
756          *      Child is a group that has children of it's own.
757          */
758         if ((c->type == MOD_GROUP) || (c->type == MOD_POLICY)
759 #ifdef WITH_UNLANG
760             || (c->type == MOD_CASE)
761 #endif
762                 ) {
763                 modgroup *g;
764
765 #ifdef WITH_UNLANG
766         do_children:
767 #endif
768                 g = mod_callabletogroup(c);
769
770                 /*
771                  *      This should really have been caught in the
772                  *      compiler, and the node never generated.  But
773                  *      doing that requires changing it's API so that
774                  *      it returns a flag instead of the compiled
775                  *      MOD_GROUP.
776                  */
777                 if (!g->children) {
778                         RDEBUG2("%s { ... } # empty sub-section is ignored", c->name);
779                         goto next_sibling;
780                 }
781
782                 MOD_LOG_OPEN_BRACE;
783                 modcall_child(request, component,
784                               depth + 1, entry, g->children,
785                               &result);
786                 MOD_LOG_CLOSE_BRACE;
787                 goto calculate_result;
788         } /* MOD_GROUP */
789
790 #ifdef WITH_UNLANG
791         if (c->type == MOD_SWITCH) {
792                 modcallable *this, *found, *null_case;
793                 modgroup *g, *h;
794                 fr_cond_t cond;
795                 value_data_t data;
796                 value_pair_map_t map;
797                 value_pair_tmpl_t vpt;
798
799                 MOD_LOG_OPEN_BRACE;
800
801                 g = mod_callabletogroup(c);
802
803                 memset(&cond, 0, sizeof(cond));
804                 memset(&map, 0, sizeof(map));
805
806                 cond.type = COND_TYPE_MAP;
807                 cond.data.map = &map;
808
809                 map.op = T_OP_CMP_EQ;
810                 map.ci = cf_sectiontoitem(g->cs);
811
812                 rad_assert(g->vpt != NULL);
813
814                 null_case = found = NULL;
815
816                 /*
817                  *      The attribute doesn't exist.  We can skip
818                  *      directly to the default 'case' statement.
819                  */
820                 if ((g->vpt->type == TMPL_TYPE_ATTR) && (tmpl_find_vp(NULL, request, g->vpt) < 0)) {
821                 find_null_case:
822                         for (this = g->children; this; this = this->next) {
823                                 rad_assert(this->type == MOD_CASE);
824
825                                 h = mod_callabletogroup(this);
826                                 if (h->vpt) continue;
827
828                                 found = this;
829                                 break;
830                         }
831
832                         goto do_null_case;
833                 }
834
835                 /*
836                  *      Expand the template if necessary, so that it
837                  *      is evaluated once instead of for each 'case'
838                  *      statement.
839                  */
840                 if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
841                     (g->vpt->type == TMPL_TYPE_XLAT) ||
842                     (g->vpt->type == TMPL_TYPE_EXEC)) {
843                         if (radius_expand_tmpl(&data, request, g->vpt) < 0) goto find_null_case;
844                         tmpl_init(&vpt, TMPL_TYPE_LITERAL, data.strvalue, talloc_array_length(data.strvalue) - 1);
845                 } else {
846                         data.ptr = NULL;
847                 }
848
849                 /*
850                  *      Find either the exact matching name, or the
851                  *      "case {...}" statement.
852                  */
853                 for (this = g->children; this; this = this->next) {
854                         rad_assert(this->type == MOD_CASE);
855
856                         h = mod_callabletogroup(this);
857
858                         /*
859                          *      Remember the default case
860                          */
861                         if (!h->vpt) {
862                                 if (!null_case) null_case = this;
863                                 continue;
864                         }
865
866                         /*
867                          *      If we're switching over an attribute
868                          *      AND we haven't pre-parsed the data for
869                          *      the case statement, then cast the data
870                          *      to the type of the attribute.
871                          */
872                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
873                             (h->vpt->type != TMPL_TYPE_DATA)) {
874                                 map.rhs = g->vpt;
875                                 map.lhs = h->vpt;
876                                 cond.cast = g->vpt->tmpl_da;
877
878                                 /*
879                                  *      Remove unnecessary casting.
880                                  */
881                                 if ((h->vpt->type == TMPL_TYPE_ATTR) &&
882                                     (g->vpt->tmpl_da->type == h->vpt->tmpl_da->type)) {
883                                         cond.cast = NULL;
884                                 }
885
886                                 /*
887                                  *      Use the pre-expanded string.
888                                  */
889                         } else if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
890                                    (g->vpt->type == TMPL_TYPE_XLAT) ||
891                                    (g->vpt->type == TMPL_TYPE_EXEC)) {
892                                 map.rhs = h->vpt;
893                                 map.lhs = &vpt;
894                                 cond.cast = NULL;
895
896                                 /*
897                                  *      Else evaluate the 'switch' statement.
898                                  */
899                         } else {
900                                 map.rhs = h->vpt;
901                                 map.lhs = g->vpt;
902                                 cond.cast = NULL;
903                         }
904
905                         if (radius_evaluate_map(request, RLM_MODULE_UNKNOWN, 0,
906                                                 &cond) == 1) {
907                                 found = this;
908                                 break;
909                         }
910                 }
911
912                 if (!found) found = null_case;
913
914         do_null_case:
915                 talloc_free(data.ptr);
916                 modcall_child(request, component, depth + 1, entry, found, &result);
917                 MOD_LOG_CLOSE_BRACE;
918                 goto calculate_result;
919         } /* MOD_SWITCH */
920 #endif
921
922         if ((c->type == MOD_LOAD_BALANCE) ||
923             (c->type == MOD_REDUNDANT_LOAD_BALANCE)) {
924                 uint32_t count = 0;
925                 modcallable *this, *found;
926                 modgroup *g;
927
928                 MOD_LOG_OPEN_BRACE;
929
930                 g = mod_callabletogroup(c);
931                 found = g->children;
932                 rad_assert(g->children != NULL);
933
934                 /*
935                  *      Choose a child at random.
936                  */
937                 for (this = g->children; this; this = this->next) {
938                         count++;
939
940                         if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
941                                 found = this;
942                         }
943                 }
944
945                 MOD_LOG_OPEN_BRACE;
946
947                 if (c->type == MOD_LOAD_BALANCE) {
948                         modcall_child(request, component,
949                                       depth + 1, entry, found,
950                                       &result);
951
952                 } else {
953                         this = found;
954
955                         do {
956                                 modcall_child(request, component,
957                                               depth + 1, entry, this,
958                                               &result);
959                                 if (this->actions[result] == MOD_ACTION_RETURN) {
960                                         priority = -1;
961                                         break;
962                                 }
963
964                                 this = this->next;
965                                 if (!this) this = g->children;
966                         } while (this != found);
967                 }
968                 MOD_LOG_CLOSE_BRACE;
969                 goto calculate_result;
970         } /* MOD_LOAD_BALANCE */
971
972         /*
973          *      Reference another virtual server.
974          *
975          *      This should really be deleted, and replaced with a
976          *      more abstracted / functional version.
977          */
978         if (c->type == MOD_REFERENCE) {
979                 modref *mr = mod_callabletoref(c);
980                 char const *server = request->server;
981
982                 if (server == mr->ref_name) {
983                         RWDEBUG("Suppressing recursive call to server %s", server);
984                         goto next_sibling;
985                 }
986
987                 request->server = mr->ref_name;
988                 RDEBUG("server %s { # nested call", mr->ref_name);
989                 result = indexed_modcall(component, 0, request);
990                 RDEBUG("} # server %s with nested call", mr->ref_name);
991                 request->server = server;
992                 goto calculate_result;
993         } /* MOD_REFERENCE */
994
995         /*
996          *      xlat a string without doing anything else
997          *
998          *      This should really be deleted, and replaced with a
999          *      more abstracted / functional version.
1000          */
1001         if (c->type == MOD_XLAT) {
1002                 modxlat *mx = mod_callabletoxlat(c);
1003                 char buffer[128];
1004
1005                 if (!mx->exec) {
1006                         radius_xlat(buffer, sizeof(buffer), request, mx->xlat_name, NULL, NULL);
1007                 } else {
1008                         RDEBUG("`%s`", mx->xlat_name);
1009                         radius_exec_program(NULL, 0, NULL, request, mx->xlat_name, request->packet->vps,
1010                                             false, true, EXEC_TIMEOUT);
1011                 }
1012
1013                 goto next_sibling;
1014         } /* MOD_XLAT */
1015
1016         /*
1017          *      Add new module types here.
1018          */
1019
1020 calculate_result:
1021 #if 0
1022         RDEBUG("(%s, %d) ? (%s, %d)",
1023                fr_int2str(mod_rcode_table, result, "<invalid>"),
1024                priority,
1025                fr_int2str(mod_rcode_table, entry->result, "<invalid>"),
1026                entry->priority);
1027 #endif
1028
1029
1030         rad_assert(result != RLM_MODULE_UNKNOWN);
1031
1032         /*
1033          *      The child's action says return.  Do so.
1034          */
1035         if ((c->actions[result] == MOD_ACTION_RETURN) &&
1036             (priority <= 0)) {
1037                 entry->result = result;
1038                 goto finish;
1039         }
1040
1041         /*
1042          *      If "reject", break out of the loop and return
1043          *      reject.
1044          */
1045         if (c->actions[result] == MOD_ACTION_REJECT) {
1046                 entry->result = RLM_MODULE_REJECT;
1047                 goto finish;
1048         }
1049
1050         /*
1051          *      The array holds a default priority for this return
1052          *      code.  Grab it in preference to any unset priority.
1053          */
1054         if (priority < 0) {
1055                 priority = c->actions[result];
1056         }
1057
1058         /*
1059          *      We're higher than any previous priority, remember this
1060          *      return code and priority.
1061          */
1062         if (priority > entry->priority) {
1063                 entry->result = result;
1064                 entry->priority = priority;
1065         }
1066
1067 #ifdef WITH_UNLANG
1068         /*
1069          *      If we're processing a "case" statement, we return once
1070          *      it's done, rather than going to the next "case" statement.
1071          */
1072         if (c->type == MOD_CASE) goto finish;
1073 #endif
1074
1075         /*
1076          *      If we've been told to stop processing
1077          *      it, do so.
1078          */
1079         if (entry->unwind == MOD_BREAK) {
1080                 RDEBUG2("# unwind to enclosing foreach");
1081                 entry->unwind = 0;
1082                 goto finish;
1083         }
1084
1085         if (entry->unwind == MOD_RETURN) {
1086                 goto finish;
1087         }
1088
1089 next_sibling:
1090         entry->c = entry->c->next;
1091
1092         if (entry->c) goto redo;
1093
1094 finish:
1095         /*
1096          *      And we're done!
1097          */
1098         REXDENT();
1099         return true;
1100 }
1101
1102
1103 /** Call a module, iteratively, with a local stack, rather than recursively
1104  *
1105  * What did Paul Graham say about Lisp...?
1106  */
1107 int modcall(rlm_components_t component, modcallable *c, REQUEST *request)
1108 {
1109         modcall_stack_entry_t stack[MODCALL_STACK_MAX];
1110
1111 #ifndef NDEBUG
1112         memset(stack, 0, sizeof(stack));
1113 #endif
1114         /*
1115          *      Set up the initial stack frame.
1116          */
1117         stack[0].c = c;
1118         stack[0].result = default_component_results[component];
1119         stack[0].priority = 0;
1120         stack[0].unwind = 0;
1121
1122         /*
1123          *      Call the main handler.
1124          */
1125         if (!modcall_recurse(request, component, 0, &stack[0])) {
1126                 return RLM_MODULE_FAIL;
1127         }
1128
1129         /*
1130          *      Return the result.
1131          */
1132         return stack[0].result;
1133 }
1134
1135
1136 #if 0
1137 static char const *action2str(int action)
1138 {
1139         static char buf[32];
1140         if(action==MOD_ACTION_RETURN)
1141                 return "return";
1142         if(action==MOD_ACTION_REJECT)
1143                 return "reject";
1144         snprintf(buf, sizeof buf, "%d", action);
1145         return buf;
1146 }
1147
1148 /* If you suspect a bug in the parser, you'll want to use these dump
1149  * functions. dump_tree should reproduce a whole tree exactly as it was found
1150  * in radiusd.conf, but in long form (all actions explicitly defined) */
1151 static void dump_mc(modcallable *c, int indent)
1152 {
1153         int i;
1154
1155         if(c->type==MOD_SINGLE) {
1156                 modsingle *single = mod_callabletosingle(c);
1157                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1158                         single->modinst->name);
1159         } else if ((c->type > MOD_SINGLE) && (c->type <= MOD_POLICY)) {
1160                 modgroup *g = mod_callabletogroup(c);
1161                 modcallable *p;
1162                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1163                       group_name[c->type]);
1164                 for(p = g->children;p;p = p->next)
1165                         dump_mc(p, indent+1);
1166         } /* else ignore it for now */
1167
1168         for(i = 0; i<RLM_MODULE_NUMCODES; ++i) {
1169                 DEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t",
1170                       fr_int2str(mod_rcode_table, i, "<invalid>"),
1171                       action2str(c->actions[i]));
1172         }
1173
1174         DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");
1175 }
1176
1177 static void dump_tree(rlm_components_t comp, modcallable *c)
1178 {
1179         DEBUG("[%s]", comp2str[comp]);
1180         dump_mc(c, 0);
1181 }
1182 #else
1183 #define dump_tree(a, b)
1184 #endif
1185
1186 /* These are the default actions. For each component, the group{} block
1187  * behaves like the code from the old module_*() function. redundant{} and
1188  * append{} are based on my guesses of what they will be used for. --Pac. */
1189 static const int
1190 defaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
1191 {
1192         /* authenticate */
1193         {
1194                 /* group */
1195                 {
1196                         MOD_ACTION_RETURN,      /* reject   */
1197                         1,                      /* fail     */
1198                         MOD_ACTION_RETURN,      /* ok       */
1199                         MOD_ACTION_RETURN,      /* handled  */
1200                         1,                      /* invalid  */
1201                         MOD_ACTION_RETURN,      /* userlock */
1202                         MOD_ACTION_RETURN,      /* notfound */
1203                         1,                      /* noop     */
1204                         1                       /* updated  */
1205                 },
1206                 /* redundant */
1207                 {
1208                         MOD_ACTION_RETURN,      /* reject   */
1209                         1,                      /* fail     */
1210                         MOD_ACTION_RETURN,      /* ok       */
1211                         MOD_ACTION_RETURN,      /* handled  */
1212                         MOD_ACTION_RETURN,      /* invalid  */
1213                         MOD_ACTION_RETURN,      /* userlock */
1214                         MOD_ACTION_RETURN,      /* notfound */
1215                         MOD_ACTION_RETURN,      /* noop     */
1216                         MOD_ACTION_RETURN       /* updated  */
1217                 },
1218                 /* append */
1219                 {
1220                         MOD_ACTION_RETURN,      /* reject   */
1221                         1,                      /* fail     */
1222                         MOD_ACTION_RETURN,      /* ok       */
1223                         MOD_ACTION_RETURN,      /* handled  */
1224                         MOD_ACTION_RETURN,      /* invalid  */
1225                         MOD_ACTION_RETURN,      /* userlock */
1226                         2,                      /* notfound */
1227                         MOD_ACTION_RETURN,      /* noop     */
1228                         MOD_ACTION_RETURN       /* updated  */
1229                 }
1230         },
1231         /* authorize */
1232         {
1233                 /* group */
1234                 {
1235                         MOD_ACTION_RETURN,      /* reject   */
1236                         MOD_ACTION_RETURN,      /* fail     */
1237                         3,                      /* ok       */
1238                         MOD_ACTION_RETURN,      /* handled  */
1239                         MOD_ACTION_RETURN,      /* invalid  */
1240                         MOD_ACTION_RETURN,      /* userlock */
1241                         1,                      /* notfound */
1242                         2,                      /* noop     */
1243                         4                       /* updated  */
1244                 },
1245                 /* redundant */
1246                 {
1247                         MOD_ACTION_RETURN,      /* reject   */
1248                         1,                      /* fail     */
1249                         MOD_ACTION_RETURN,      /* ok       */
1250                         MOD_ACTION_RETURN,      /* handled  */
1251                         MOD_ACTION_RETURN,      /* invalid  */
1252                         MOD_ACTION_RETURN,      /* userlock */
1253                         MOD_ACTION_RETURN,      /* notfound */
1254                         MOD_ACTION_RETURN,      /* noop     */
1255                         MOD_ACTION_RETURN       /* updated  */
1256                 },
1257                 /* append */
1258                 {
1259                         MOD_ACTION_RETURN,      /* reject   */
1260                         1,                      /* fail     */
1261                         MOD_ACTION_RETURN,      /* ok       */
1262                         MOD_ACTION_RETURN,      /* handled  */
1263                         MOD_ACTION_RETURN,      /* invalid  */
1264                         MOD_ACTION_RETURN,      /* userlock */
1265                         2,                      /* notfound */
1266                         MOD_ACTION_RETURN,      /* noop     */
1267                         MOD_ACTION_RETURN       /* updated  */
1268                 }
1269         },
1270         /* preacct */
1271         {
1272                 /* group */
1273                 {
1274                         MOD_ACTION_RETURN,      /* reject   */
1275                         MOD_ACTION_RETURN,      /* fail     */
1276                         2,                      /* ok       */
1277                         MOD_ACTION_RETURN,      /* handled  */
1278                         MOD_ACTION_RETURN,      /* invalid  */
1279                         MOD_ACTION_RETURN,      /* userlock */
1280                         MOD_ACTION_RETURN,      /* notfound */
1281                         1,                      /* noop     */
1282                         3                       /* updated  */
1283                 },
1284                 /* redundant */
1285                 {
1286                         MOD_ACTION_RETURN,      /* reject   */
1287                         1,                      /* fail     */
1288                         MOD_ACTION_RETURN,      /* ok       */
1289                         MOD_ACTION_RETURN,      /* handled  */
1290                         MOD_ACTION_RETURN,      /* invalid  */
1291                         MOD_ACTION_RETURN,      /* userlock */
1292                         MOD_ACTION_RETURN,      /* notfound */
1293                         MOD_ACTION_RETURN,      /* noop     */
1294                         MOD_ACTION_RETURN       /* updated  */
1295                 },
1296                 /* append */
1297                 {
1298                         MOD_ACTION_RETURN,      /* reject   */
1299                         1,                      /* fail     */
1300                         MOD_ACTION_RETURN,      /* ok       */
1301                         MOD_ACTION_RETURN,      /* handled  */
1302                         MOD_ACTION_RETURN,      /* invalid  */
1303                         MOD_ACTION_RETURN,      /* userlock */
1304                         2,                      /* notfound */
1305                         MOD_ACTION_RETURN,      /* noop     */
1306                         MOD_ACTION_RETURN       /* updated  */
1307                 }
1308         },
1309         /* accounting */
1310         {
1311                 /* group */
1312                 {
1313                         MOD_ACTION_RETURN,      /* reject   */
1314                         MOD_ACTION_RETURN,      /* fail     */
1315                         2,                      /* ok       */
1316                         MOD_ACTION_RETURN,      /* handled  */
1317                         MOD_ACTION_RETURN,      /* invalid  */
1318                         MOD_ACTION_RETURN,      /* userlock */
1319                         MOD_ACTION_RETURN,      /* notfound */
1320                         1,                      /* noop     */
1321                         3                       /* updated  */
1322                 },
1323                 /* redundant */
1324                 {
1325                         1,                      /* reject   */
1326                         1,                      /* fail     */
1327                         MOD_ACTION_RETURN,      /* ok       */
1328                         MOD_ACTION_RETURN,      /* handled  */
1329                         1,                      /* invalid  */
1330                         1,                      /* userlock */
1331                         1,                      /* notfound */
1332                         2,                      /* noop     */
1333                         4                       /* updated  */
1334                 },
1335                 /* append */
1336                 {
1337                         MOD_ACTION_RETURN,      /* reject   */
1338                         1,                      /* fail     */
1339                         MOD_ACTION_RETURN,      /* ok       */
1340                         MOD_ACTION_RETURN,      /* handled  */
1341                         MOD_ACTION_RETURN,      /* invalid  */
1342                         MOD_ACTION_RETURN,      /* userlock */
1343                         2,                      /* notfound */
1344                         MOD_ACTION_RETURN,      /* noop     */
1345                         MOD_ACTION_RETURN       /* updated  */
1346                 }
1347         },
1348         /* checksimul */
1349         {
1350                 /* group */
1351                 {
1352                         MOD_ACTION_RETURN,      /* reject   */
1353                         1,                      /* fail     */
1354                         MOD_ACTION_RETURN,      /* ok       */
1355                         MOD_ACTION_RETURN,      /* handled  */
1356                         MOD_ACTION_RETURN,      /* invalid  */
1357                         MOD_ACTION_RETURN,      /* userlock */
1358                         MOD_ACTION_RETURN,      /* notfound */
1359                         MOD_ACTION_RETURN,      /* noop     */
1360                         MOD_ACTION_RETURN       /* updated  */
1361                 },
1362                 /* redundant */
1363                 {
1364                         MOD_ACTION_RETURN,      /* reject   */
1365                         1,                      /* fail     */
1366                         MOD_ACTION_RETURN,      /* ok       */
1367                         MOD_ACTION_RETURN,      /* handled  */
1368                         MOD_ACTION_RETURN,      /* invalid  */
1369                         MOD_ACTION_RETURN,      /* userlock */
1370                         MOD_ACTION_RETURN,      /* notfound */
1371                         MOD_ACTION_RETURN,      /* noop     */
1372                         MOD_ACTION_RETURN       /* updated  */
1373                 },
1374                 /* append */
1375                 {
1376                         MOD_ACTION_RETURN,      /* reject   */
1377                         1,                      /* fail     */
1378                         MOD_ACTION_RETURN,      /* ok       */
1379                         MOD_ACTION_RETURN,      /* handled  */
1380                         MOD_ACTION_RETURN,      /* invalid  */
1381                         MOD_ACTION_RETURN,      /* userlock */
1382                         MOD_ACTION_RETURN,      /* notfound */
1383                         MOD_ACTION_RETURN,      /* noop     */
1384                         MOD_ACTION_RETURN       /* updated  */
1385                 }
1386         },
1387         /* pre-proxy */
1388         {
1389                 /* group */
1390                 {
1391                         MOD_ACTION_RETURN,      /* reject   */
1392                         MOD_ACTION_RETURN,      /* fail     */
1393                         3,                      /* ok       */
1394                         MOD_ACTION_RETURN,      /* handled  */
1395                         MOD_ACTION_RETURN,      /* invalid  */
1396                         MOD_ACTION_RETURN,      /* userlock */
1397                         1,                      /* notfound */
1398                         2,                      /* noop     */
1399                         4                       /* updated  */
1400                 },
1401                 /* redundant */
1402                 {
1403                         MOD_ACTION_RETURN,      /* reject   */
1404                         1,                      /* fail     */
1405                         MOD_ACTION_RETURN,      /* ok       */
1406                         MOD_ACTION_RETURN,      /* handled  */
1407                         MOD_ACTION_RETURN,      /* invalid  */
1408                         MOD_ACTION_RETURN,      /* userlock */
1409                         MOD_ACTION_RETURN,      /* notfound */
1410                         MOD_ACTION_RETURN,      /* noop     */
1411                         MOD_ACTION_RETURN       /* updated  */
1412                 },
1413                 /* append */
1414                 {
1415                         MOD_ACTION_RETURN,      /* reject   */
1416                         1,                      /* fail     */
1417                         MOD_ACTION_RETURN,      /* ok       */
1418                         MOD_ACTION_RETURN,      /* handled  */
1419                         MOD_ACTION_RETURN,      /* invalid  */
1420                         MOD_ACTION_RETURN,      /* userlock */
1421                         2,                      /* notfound */
1422                         MOD_ACTION_RETURN,      /* noop     */
1423                         MOD_ACTION_RETURN       /* updated  */
1424                 }
1425         },
1426         /* post-proxy */
1427         {
1428                 /* group */
1429                 {
1430                         MOD_ACTION_RETURN,      /* reject   */
1431                         MOD_ACTION_RETURN,      /* fail     */
1432                         3,                      /* ok       */
1433                         MOD_ACTION_RETURN,      /* handled  */
1434                         MOD_ACTION_RETURN,      /* invalid  */
1435                         MOD_ACTION_RETURN,      /* userlock */
1436                         1,                      /* notfound */
1437                         2,                      /* noop     */
1438                         4                       /* updated  */
1439                 },
1440                 /* redundant */
1441                 {
1442                         MOD_ACTION_RETURN,      /* reject   */
1443                         1,                      /* fail     */
1444                         MOD_ACTION_RETURN,      /* ok       */
1445                         MOD_ACTION_RETURN,      /* handled  */
1446                         MOD_ACTION_RETURN,      /* invalid  */
1447                         MOD_ACTION_RETURN,      /* userlock */
1448                         MOD_ACTION_RETURN,      /* notfound */
1449                         MOD_ACTION_RETURN,      /* noop     */
1450                         MOD_ACTION_RETURN       /* updated  */
1451                 },
1452                 /* append */
1453                 {
1454                         MOD_ACTION_RETURN,      /* reject   */
1455                         1,                      /* fail     */
1456                         MOD_ACTION_RETURN,      /* ok       */
1457                         MOD_ACTION_RETURN,      /* handled  */
1458                         MOD_ACTION_RETURN,      /* invalid  */
1459                         MOD_ACTION_RETURN,      /* userlock */
1460                         2,                      /* notfound */
1461                         MOD_ACTION_RETURN,      /* noop     */
1462                         MOD_ACTION_RETURN       /* updated  */
1463                 }
1464         },
1465         /* post-auth */
1466         {
1467                 /* group */
1468                 {
1469                         MOD_ACTION_RETURN,      /* reject   */
1470                         MOD_ACTION_RETURN,      /* fail     */
1471                         3,                      /* ok       */
1472                         MOD_ACTION_RETURN,      /* handled  */
1473                         MOD_ACTION_RETURN,      /* invalid  */
1474                         MOD_ACTION_RETURN,      /* userlock */
1475                         1,                      /* notfound */
1476                         2,                      /* noop     */
1477                         4                       /* updated  */
1478                 },
1479                 /* redundant */
1480                 {
1481                         MOD_ACTION_RETURN,      /* reject   */
1482                         1,                      /* fail     */
1483                         MOD_ACTION_RETURN,      /* ok       */
1484                         MOD_ACTION_RETURN,      /* handled  */
1485                         MOD_ACTION_RETURN,      /* invalid  */
1486                         MOD_ACTION_RETURN,      /* userlock */
1487                         MOD_ACTION_RETURN,      /* notfound */
1488                         MOD_ACTION_RETURN,      /* noop     */
1489                         MOD_ACTION_RETURN       /* updated  */
1490                 },
1491                 /* append */
1492                 {
1493                         MOD_ACTION_RETURN,      /* reject   */
1494                         1,                      /* fail     */
1495                         MOD_ACTION_RETURN,      /* ok       */
1496                         MOD_ACTION_RETURN,      /* handled  */
1497                         MOD_ACTION_RETURN,      /* invalid  */
1498                         MOD_ACTION_RETURN,      /* userlock */
1499                         2,                      /* notfound */
1500                         MOD_ACTION_RETURN,      /* noop     */
1501                         MOD_ACTION_RETURN       /* updated  */
1502                 }
1503         }
1504 #ifdef WITH_COA
1505         ,
1506         /* recv-coa */
1507         {
1508                 /* group */
1509                 {
1510                         MOD_ACTION_RETURN,      /* reject   */
1511                         MOD_ACTION_RETURN,      /* fail     */
1512                         3,                      /* ok       */
1513                         MOD_ACTION_RETURN,      /* handled  */
1514                         MOD_ACTION_RETURN,      /* invalid  */
1515                         MOD_ACTION_RETURN,      /* userlock */
1516                         1,                      /* notfound */
1517                         2,                      /* noop     */
1518                         4                       /* updated  */
1519                 },
1520                 /* redundant */
1521                 {
1522                         MOD_ACTION_RETURN,      /* reject   */
1523                         1,                      /* fail     */
1524                         MOD_ACTION_RETURN,      /* ok       */
1525                         MOD_ACTION_RETURN,      /* handled  */
1526                         MOD_ACTION_RETURN,      /* invalid  */
1527                         MOD_ACTION_RETURN,      /* userlock */
1528                         MOD_ACTION_RETURN,      /* notfound */
1529                         MOD_ACTION_RETURN,      /* noop     */
1530                         MOD_ACTION_RETURN       /* updated  */
1531                 },
1532                 /* append */
1533                 {
1534                         MOD_ACTION_RETURN,      /* reject   */
1535                         1,                      /* fail     */
1536                         MOD_ACTION_RETURN,      /* ok       */
1537                         MOD_ACTION_RETURN,      /* handled  */
1538                         MOD_ACTION_RETURN,      /* invalid  */
1539                         MOD_ACTION_RETURN,      /* userlock */
1540                         2,                      /* notfound */
1541                         MOD_ACTION_RETURN,      /* noop     */
1542                         MOD_ACTION_RETURN       /* updated  */
1543                 }
1544         },
1545         /* send-coa */
1546         {
1547                 /* group */
1548                 {
1549                         MOD_ACTION_RETURN,      /* reject   */
1550                         MOD_ACTION_RETURN,      /* fail     */
1551                         3,                      /* ok       */
1552                         MOD_ACTION_RETURN,      /* handled  */
1553                         MOD_ACTION_RETURN,      /* invalid  */
1554                         MOD_ACTION_RETURN,      /* userlock */
1555                         1,                      /* notfound */
1556                         2,                      /* noop     */
1557                         4                       /* updated  */
1558                 },
1559                 /* redundant */
1560                 {
1561                         MOD_ACTION_RETURN,      /* reject   */
1562                         1,                      /* fail     */
1563                         MOD_ACTION_RETURN,      /* ok       */
1564                         MOD_ACTION_RETURN,      /* handled  */
1565                         MOD_ACTION_RETURN,      /* invalid  */
1566                         MOD_ACTION_RETURN,      /* userlock */
1567                         MOD_ACTION_RETURN,      /* notfound */
1568                         MOD_ACTION_RETURN,      /* noop     */
1569                         MOD_ACTION_RETURN       /* updated  */
1570                 },
1571                 /* append */
1572                 {
1573                         MOD_ACTION_RETURN,      /* reject   */
1574                         1,                      /* fail     */
1575                         MOD_ACTION_RETURN,      /* ok       */
1576                         MOD_ACTION_RETURN,      /* handled  */
1577                         MOD_ACTION_RETURN,      /* invalid  */
1578                         MOD_ACTION_RETURN,      /* userlock */
1579                         2,                      /* notfound */
1580                         MOD_ACTION_RETURN,      /* noop     */
1581                         MOD_ACTION_RETURN       /* updated  */
1582                 }
1583         }
1584 #endif
1585 };
1586
1587 /** Validate and fixup a map that's part of an update section.
1588  *
1589  * @param map to validate.
1590  * @param ctx data to pass to fixup function (currently unused).
1591  * @return 0 if valid else -1.
1592  */
1593 int modcall_fixup_update(value_pair_map_t *map, UNUSED void *ctx)
1594 {
1595         CONF_PAIR *cp = cf_itemtopair(map->ci);
1596
1597         /*
1598          *      Anal-retentive checks.
1599          */
1600         if (DEBUG_ENABLED2) {
1601                 if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->name[0] != '&')) {
1602                         WARN("%s[%d]: Please change attribute reference to '&%s %s ...'",
1603                              cf_pair_filename(cp), cf_pair_lineno(cp),
1604                              map->lhs->name, fr_int2str(fr_tokens, map->op, "<INVALID>"));
1605                 }
1606
1607                 if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->name[0] != '&')) {
1608                         WARN("%s[%d]: Please change attribute reference to '... %s &%s'",
1609                              cf_pair_filename(cp), cf_pair_lineno(cp),
1610                              fr_int2str(fr_tokens, map->op, "<INVALID>"), map->rhs->name);
1611                 }
1612         }
1613
1614         /*
1615          *      Values used by unary operators should be literal ANY
1616          *
1617          *      We then free the template and alloc a NULL one instead.
1618          */
1619         if (map->op == T_OP_CMP_FALSE) {
1620                 if ((map->rhs->type != TMPL_TYPE_LITERAL) || (strcmp(map->rhs->name, "ANY") != 0)) {
1621                         WARN("%s[%d] Wildcard deletion MUST use '!* ANY'",
1622                              cf_pair_filename(cp), cf_pair_lineno(cp));
1623                 }
1624
1625                 tmpl_free(&map->rhs);
1626
1627                 map->rhs = tmpl_alloc(map, TMPL_TYPE_NULL, NULL, 0);
1628         }
1629
1630         /*
1631          *      Lots of sanity checks for insane people...
1632          */
1633
1634         /*
1635          *      We don't support implicit type conversion,
1636          *      except for "octets"
1637          */
1638         if (((map->lhs->type == TMPL_TYPE_ATTR) || (map->lhs->type == TMPL_TYPE_DATA)) &&
1639             ((map->rhs->type == TMPL_TYPE_ATTR) || (map->rhs->type == TMPL_TYPE_DATA))) {
1640                 PW_TYPE rhs_type;
1641                 PW_TYPE lhs_type;
1642
1643                 switch (map->lhs->type) {
1644                 case TMPL_TYPE_ATTR:
1645                         lhs_type = map->lhs->tmpl_da->type;
1646                         break;
1647
1648                 case TMPL_TYPE_DATA:
1649                         lhs_type = map->lhs->tmpl_data_type;
1650                         break;
1651
1652                 default:
1653                         rad_assert(0);
1654                         return -1;
1655                 }
1656
1657                 switch (map->rhs->type) {
1658                 case TMPL_TYPE_ATTR:
1659                         rhs_type = map->rhs->tmpl_da->type;
1660                         break;
1661
1662                 case TMPL_TYPE_DATA:
1663                         rhs_type = map->rhs->tmpl_data_type;
1664                         break;
1665
1666                 default:
1667                         rad_assert(0);
1668                         return -1;
1669                 }
1670
1671
1672                 if ((lhs_type != rhs_type) &&
1673                     (lhs_type != PW_TYPE_OCTETS) &&
1674                     (rhs_type != PW_TYPE_OCTETS)) {
1675                         cf_log_err(map->ci, "Attribute type mismatch");
1676                         return -1;
1677                 }
1678         }
1679
1680         /*
1681          *      What exactly where you expecting to happen here?
1682          */
1683         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
1684             (map->rhs->type == TMPL_TYPE_LIST)) {
1685                 cf_log_err(map->ci, "Can't copy list into an attribute");
1686                 return -1;
1687         }
1688
1689         /*
1690          *      Depending on the attribute type, some operators are disallowed.
1691          */
1692         if (map->lhs->type == TMPL_TYPE_ATTR) {
1693                 switch (map->op) {
1694                 default:
1695                         cf_log_err(map->ci, "Invalid operator for attribute");
1696                         return -1;
1697
1698                 case T_OP_EQ:
1699                 case T_OP_CMP_EQ:
1700                 case T_OP_ADD:
1701                 case T_OP_SUB:
1702                 case T_OP_LE:
1703                 case T_OP_GE:
1704                 case T_OP_CMP_FALSE:
1705                 case T_OP_SET:
1706                         break;
1707                 }
1708         }
1709
1710         if (map->lhs->type == TMPL_TYPE_LIST) {
1711                 /*
1712                  *      Can't copy an xlat expansion or literal into a list,
1713                  *      we don't know what type of attribute we'd need
1714                  *      to create.
1715                  *
1716                  *      The only exception is where were using a unary
1717                  *      operator like !*.
1718                  */
1719                 if (map->op != T_OP_CMP_FALSE) switch (map->rhs->type) {
1720                 case TMPL_TYPE_XLAT:
1721                 case TMPL_TYPE_LITERAL:
1722                         cf_log_err(map->ci, "Can't copy value into list (we don't know which attribute to create)");
1723                         return -1;
1724
1725                 default:
1726                         break;
1727                 }
1728
1729                 /*
1730                  *      Only += and :=, and !* operators are supported
1731                  *      for lists.
1732                  */
1733                 switch (map->op) {
1734                 case T_OP_CMP_FALSE:
1735                         break;
1736
1737                 case T_OP_ADD:
1738                         if ((map->rhs->type != TMPL_TYPE_LIST) &&
1739                             (map->rhs->type != TMPL_TYPE_EXEC)) {
1740                                 cf_log_err(map->ci, "Invalid source for list assignment '%s += ...'", map->lhs->name);
1741                                 return -1;
1742                         }
1743                         break;
1744
1745                 case T_OP_SET:
1746                         if (map->rhs->type == TMPL_TYPE_EXEC) {
1747                                 WARN("%s[%d] Please change ':=' to '=' for list assignment",
1748                                      cf_pair_filename(cp), cf_pair_lineno(cp));
1749                         }
1750
1751                         if (map->rhs->type != TMPL_TYPE_LIST) {
1752                                 cf_log_err(map->ci, "Invalid source for list assignment '%s := ...'", map->lhs->name);
1753                                 return -1;
1754                         }
1755                         break;
1756
1757                 case T_OP_EQ:
1758                         if (map->rhs->type != TMPL_TYPE_EXEC) {
1759                                 cf_log_err(map->ci, "Invalid source for list assignment '%s = ...'", map->lhs->name);
1760                                 return -1;
1761                         }
1762                         break;
1763
1764                 default:
1765                         cf_log_err(map->ci, "Operator \"%s\" not allowed for list assignment",
1766                                    fr_int2str(fr_tokens, map->op, "<INVALID>"));
1767                         return -1;
1768                 }
1769         }
1770
1771         /*
1772          *      If the map has a unary operator there's no further
1773          *      processing we need to, as RHS is unused.
1774          */
1775         if (map->op == T_OP_CMP_FALSE) return 0;
1776
1777         /*
1778          *      If LHS is an attribute, and RHS is a literal, we can
1779          *      preparse the information into a TMPL_TYPE_DATA.
1780          *
1781          *      Unless it's a unary operator in which case we
1782          *      ignore map->rhs.
1783          */
1784         if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->rhs->type == TMPL_TYPE_LITERAL)) {
1785                 /*
1786                  *      It's a literal string, just copy it.
1787                  *      Don't escape anything.
1788                  */
1789                 if (!cf_new_escape &&
1790                     (map->lhs->tmpl_da->type == PW_TYPE_STRING) &&
1791                     (cf_pair_value_type(cp) == T_SINGLE_QUOTED_STRING)) {
1792                         tmpl_cast_in_place_str(map->rhs);
1793                 } else {
1794                         if (!tmpl_cast_in_place(map->rhs, map->lhs->tmpl_da->type, map->lhs->tmpl_da)) {
1795                                 cf_log_err(map->ci, "%s", fr_strerror());
1796                                 return -1;
1797                         }
1798
1799                         /*
1800                          *      Fixup LHS da if it doesn't match the type
1801                          *      of the RHS.
1802                          */
1803                         if (map->lhs->tmpl_da->type != map->rhs->tmpl_data_type) {
1804                                 DICT_ATTR const *da;
1805
1806                                 da = dict_attrbytype(map->lhs->tmpl_da->attr, map->lhs->tmpl_da->vendor,
1807                                                      map->rhs->tmpl_data_type);
1808                                 if (!da) {
1809                                         fr_strerror_printf("Cannot find %s variant of attribute \"%s\"",
1810                                                            fr_int2str(dict_attr_types, map->rhs->tmpl_data_type,
1811                                                            "<INVALID>"), map->lhs->tmpl_da->name);
1812                                         return -1;
1813                                 }
1814                                 map->lhs->tmpl_da = da;
1815                         }
1816                 }
1817         } /* else we can't precompile the data */
1818
1819         return 0;
1820 }
1821
1822
1823 #ifdef WITH_UNLANG
1824 static modcallable *do_compile_modupdate(modcallable *parent, UNUSED rlm_components_t component,
1825                                          CONF_SECTION *cs, char const *name2)
1826 {
1827         int rcode;
1828         modgroup *g;
1829         modcallable *csingle;
1830
1831         value_pair_map_t *head;
1832
1833         /*
1834          *      This looks at cs->name2 to determine which list to update
1835          */
1836         rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, modcall_fixup_update, NULL, 128);
1837         if (rcode < 0) return NULL; /* message already printed */
1838         if (!head) {
1839                 cf_log_err_cs(cs, "'update' sections cannot be empty");
1840                 return NULL;
1841         }
1842
1843         g = talloc_zero(parent, modgroup);
1844         csingle = mod_grouptocallable(g);
1845
1846         csingle->parent = parent;
1847         csingle->next = NULL;
1848
1849         if (name2) {
1850                 csingle->name = name2;
1851         } else {
1852                 csingle->name = "";
1853         }
1854         csingle->type = MOD_UPDATE;
1855         csingle->method = component;
1856
1857         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1858                sizeof(csingle->actions));
1859
1860         g->grouptype = GROUPTYPE_SIMPLE;
1861         g->children = NULL;
1862         g->cs = cs;
1863         g->map = talloc_steal(g, head);
1864
1865         return csingle;
1866 }
1867
1868
1869 static modcallable *do_compile_modswitch (modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
1870 {
1871         CONF_ITEM *ci;
1872         FR_TOKEN type;
1873         char const *name2;
1874         bool had_seen_default = false;
1875         modcallable *csingle;
1876         modgroup *g;
1877         ssize_t slen;
1878         value_pair_tmpl_t *vpt;
1879
1880         name2 = cf_section_name2(cs);
1881         if (!name2) {
1882                 cf_log_err_cs(cs, "You must specify a variable to switch over for 'switch'");
1883                 return NULL;
1884         }
1885
1886         if (!cf_item_find_next(cs, NULL)) {
1887                 cf_log_err_cs(cs, "'switch' statements cannot be empty");
1888                 return NULL;
1889         }
1890
1891         /*
1892          *      Create the template.  If we fail, AND it's a bare word
1893          *      with &Foo-Bar, it MAY be an attribute defined by a
1894          *      module.  Allow it for now.  The pass2 checks below
1895          *      will fix it up.
1896          */
1897         type = cf_section_name2_type(cs);
1898         slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
1899         if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
1900                 char *spaces, *text;
1901
1902                 fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
1903
1904                 cf_log_err_cs(cs, "Syntax error");
1905                 cf_log_err_cs(cs, "%s", name2);
1906                 cf_log_err_cs(cs, "%s^ %s", spaces, text);
1907
1908                 talloc_free(spaces);
1909                 talloc_free(text);
1910
1911                 return NULL;
1912         }
1913
1914         /*
1915          *      Otherwise a NULL vpt may refer to an attribute defined
1916          *      by a module.  That is checked in pass 2.
1917          */
1918
1919         /*
1920          *      Walk through the children of the switch section,
1921          *      ensuring that they're all 'case' statements
1922          */
1923         for (ci = cf_item_find_next(cs, NULL);
1924              ci != NULL;
1925              ci = cf_item_find_next(cs, ci)) {
1926                 CONF_SECTION *subcs;
1927                 char const *name1;
1928
1929                 if (!cf_item_is_section(ci)) {
1930                         if (!cf_item_is_pair(ci)) continue;
1931
1932                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1933                         talloc_free(vpt);
1934                         return NULL;
1935                 }
1936
1937                 subcs = cf_itemtosection(ci);   /* can't return NULL */
1938                 name1 = cf_section_name1(subcs);
1939
1940                 if (strcmp(name1, "case") != 0) {
1941                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1942                         talloc_free(vpt);
1943                         return NULL;
1944                 }
1945
1946                 name2 = cf_section_name2(subcs);
1947                 if (!name2) {
1948                         if (!had_seen_default) {
1949                                 had_seen_default = true;
1950                                 continue;
1951                         }
1952
1953                         cf_log_err(ci, "Cannot have two 'default' case statements");
1954                         talloc_free(vpt);
1955                         return NULL;
1956                 }
1957         }
1958
1959         csingle = do_compile_modgroup(parent, component, cs,
1960                                       GROUPTYPE_SIMPLE,
1961                                       GROUPTYPE_SIMPLE,
1962                                       MOD_SWITCH);
1963         if (!csingle) {
1964                 talloc_free(vpt);
1965                 return NULL;
1966         }
1967
1968         g = mod_callabletogroup(csingle);
1969         g->vpt = talloc_steal(g, vpt);
1970
1971         return csingle;
1972 }
1973
1974 static modcallable *do_compile_modcase(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
1975 {
1976         int i;
1977         char const *name2;
1978         modcallable *csingle;
1979         modgroup *g;
1980         value_pair_tmpl_t *vpt;
1981
1982         if (!parent || (parent->type != MOD_SWITCH)) {
1983                 cf_log_err_cs(cs, "\"case\" statements may only appear within a \"switch\" section");
1984                 return NULL;
1985         }
1986
1987         /*
1988          *      case THING means "match THING"
1989          *      case       means "match anything"
1990          */
1991         name2 = cf_section_name2(cs);
1992         if (name2) {
1993                 ssize_t slen;
1994                 FR_TOKEN type;
1995
1996                 type = cf_section_name2_type(cs);
1997
1998                 slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
1999                 if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
2000                         char *spaces, *text;
2001
2002                         fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
2003
2004                         cf_log_err_cs(cs, "Syntax error");
2005                         cf_log_err_cs(cs, "%s", name2);
2006                         cf_log_err_cs(cs, "%s^ %s", spaces, text);
2007
2008                         talloc_free(spaces);
2009                         talloc_free(text);
2010
2011                         return NULL;
2012                 }
2013
2014                 /*
2015                  *      Otherwise a NULL vpt may refer to an attribute defined
2016                  *      by a module.  That is checked in pass 2.
2017                  */
2018
2019         } else {
2020                 vpt = NULL;
2021         }
2022
2023         csingle = do_compile_modgroup(parent, component, cs,
2024                                       GROUPTYPE_SIMPLE,
2025                                       GROUPTYPE_SIMPLE,
2026                                       MOD_CASE);
2027         if (!csingle) {
2028                 talloc_free(vpt);
2029                 return NULL;
2030         }
2031
2032         /*
2033          *      The interpretor expects this to be NULL for the
2034          *      default case.  do_compile_modgroup sets it to name2,
2035          *      unless name2 is NULL, in which case it sets it to name1.
2036          */
2037         csingle->name = name2;
2038
2039         g = mod_callabletogroup(csingle);
2040         g->vpt = talloc_steal(g, vpt);
2041
2042         /*
2043          *      Set all of it's codes to return, so that
2044          *      when we pick a 'case' statement, we don't
2045          *      fall through to processing the next one.
2046          */
2047         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
2048                 csingle->actions[i] = MOD_ACTION_RETURN;
2049         }
2050
2051         return csingle;
2052 }
2053
2054 static modcallable *do_compile_modforeach(modcallable *parent,
2055                                           UNUSED rlm_components_t component, CONF_SECTION *cs)
2056 {
2057         FR_TOKEN type;
2058         char const *name2;
2059         modcallable *csingle;
2060         modgroup *g;
2061         ssize_t slen;
2062         value_pair_tmpl_t *vpt;
2063
2064         name2 = cf_section_name2(cs);
2065         if (!name2) {
2066                 cf_log_err_cs(cs,
2067                            "You must specify an attribute to loop over in 'foreach'");
2068                 return NULL;
2069         }
2070
2071         if (!cf_item_find_next(cs, NULL)) {
2072                 cf_log_err_cs(cs, "'foreach' blocks cannot be empty");
2073                 return NULL;
2074         }
2075
2076         /*
2077          *      Create the template.  If we fail, AND it's a bare word
2078          *      with &Foo-Bar, it MAY be an attribute defined by a
2079          *      module.  Allow it for now.  The pass2 checks below
2080          *      will fix it up.
2081          */
2082         type = cf_section_name2_type(cs);
2083         slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
2084         if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
2085                 char *spaces, *text;
2086
2087                 fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
2088
2089                 cf_log_err_cs(cs, "Syntax error");
2090                 cf_log_err_cs(cs, "%s", name2);
2091                 cf_log_err_cs(cs, "%s^ %s", spaces, text);
2092
2093                 talloc_free(spaces);
2094                 talloc_free(text);
2095
2096                 return NULL;
2097         }
2098
2099         if (vpt && (vpt->type != TMPL_TYPE_ATTR)) {
2100                 cf_log_err_cs(cs, "MUST use attribute reference in 'foreach'");
2101                 return NULL;
2102         }
2103
2104         /*
2105          *      Fix up the template to iterate over all instances of
2106          *      the attribute. In a perfect consistent world, users would do
2107          *      foreach &attr[*], but that's taking the consistency thing a bit far.
2108          */
2109         if (vpt && (vpt->type == TMPL_TYPE_ATTR)) {
2110                 vpt->tmpl_num = NUM_ALL;
2111         }
2112
2113         csingle = do_compile_modgroup(parent, component, cs,
2114                                       GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2115                                       MOD_FOREACH);
2116
2117         if (!csingle) {
2118                 talloc_free(vpt);
2119                 return NULL;
2120         }
2121
2122         g = mod_callabletogroup(csingle);
2123         g->vpt = vpt;
2124
2125         return csingle;
2126 }
2127
2128 static modcallable *do_compile_modbreak(modcallable *parent,
2129                                         rlm_components_t component, CONF_ITEM const *ci)
2130 {
2131         CONF_SECTION const *cs = NULL;
2132
2133         for (cs = cf_item_parent(ci);
2134              cs != NULL;
2135              cs = cf_item_parent(cf_sectiontoitem(cs))) {
2136                 if (strcmp(cf_section_name1(cs), "foreach") == 0) {
2137                         break;
2138                 }
2139         }
2140
2141         if (!cs) {
2142                 cf_log_err(ci, "'break' can only be used in a 'foreach' section");
2143                 return NULL;
2144         }
2145
2146         return do_compile_modgroup(parent, component, NULL,
2147                                    GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2148                                    MOD_BREAK);
2149 }
2150 #endif
2151
2152 static modcallable *do_compile_modserver(modcallable *parent,
2153                                          rlm_components_t component, CONF_ITEM *ci,
2154                                          char const *name,
2155                                          CONF_SECTION *cs,
2156                                          char const *server)
2157 {
2158         modcallable *csingle;
2159         CONF_SECTION *subcs;
2160         modref *mr;
2161
2162         subcs = cf_section_sub_find_name2(cs, comp2str[component], NULL);
2163         if (!subcs) {
2164                 cf_log_err(ci, "Server %s has no %s section",
2165                            server, comp2str[component]);
2166                 return NULL;
2167         }
2168
2169         mr = talloc_zero(parent, modref);
2170
2171         csingle = mod_reftocallable(mr);
2172         csingle->parent = parent;
2173         csingle->next = NULL;
2174         csingle->name = name;
2175         csingle->type = MOD_REFERENCE;
2176         csingle->method = component;
2177
2178         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
2179                sizeof(csingle->actions));
2180
2181         mr->ref_name = strdup(server);
2182         mr->ref_cs = cs;
2183
2184         return csingle;
2185 }
2186
2187 static modcallable *do_compile_modxlat(modcallable *parent,
2188                                        rlm_components_t component, char const *fmt)
2189 {
2190         modcallable *csingle;
2191         modxlat *mx;
2192
2193         mx = talloc_zero(parent, modxlat);
2194
2195         csingle = mod_xlattocallable(mx);
2196         csingle->parent = parent;
2197         csingle->next = NULL;
2198         csingle->name = "expand";
2199         csingle->type = MOD_XLAT;
2200         csingle->method = component;
2201
2202         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
2203                sizeof(csingle->actions));
2204
2205         mx->xlat_name = strdup(fmt);
2206         if (fmt[0] != '%') {
2207                 char *p;
2208                 mx->exec = true;
2209
2210                 strcpy(mx->xlat_name, fmt + 1);
2211                 p = strrchr(mx->xlat_name, '`');
2212                 if (p) *p = '\0';
2213         }
2214
2215         return csingle;
2216 }
2217
2218 /*
2219  *      redundant, etc. can refer to modules or groups, but not much else.
2220  */
2221 static int all_children_are_modules(CONF_SECTION *cs, char const *name)
2222 {
2223         CONF_ITEM *ci;
2224
2225         for (ci=cf_item_find_next(cs, NULL);
2226              ci != NULL;
2227              ci=cf_item_find_next(cs, ci)) {
2228                 /*
2229                  *      If we're a redundant, etc. group, then the
2230                  *      intention is to call modules, rather than
2231                  *      processing logic.  These checks aren't
2232                  *      *strictly* necessary, but they keep the users
2233                  *      from doing crazy things.
2234                  */
2235                 if (cf_item_is_section(ci)) {
2236                         CONF_SECTION *subcs = cf_itemtosection(ci);
2237                         char const *name1 = cf_section_name1(subcs);
2238
2239                         if ((strcmp(name1, "if") == 0) ||
2240                             (strcmp(name1, "else") == 0) ||
2241                             (strcmp(name1, "elsif") == 0) ||
2242                             (strcmp(name1, "update") == 0) ||
2243                             (strcmp(name1, "switch") == 0) ||
2244                             (strcmp(name1, "case") == 0)) {
2245                                 cf_log_err(ci, "%s sections cannot contain a \"%s\" statement",
2246                                        name, name1);
2247                                 return 0;
2248                         }
2249                         continue;
2250                 }
2251
2252                 if (cf_item_is_pair(ci)) {
2253                         CONF_PAIR *cp = cf_itemtopair(ci);
2254                         if (cf_pair_value(cp) != NULL) {
2255                                 cf_log_err(ci,
2256                                            "Entry with no value is invalid");
2257                                 return 0;
2258                         }
2259                 }
2260         }
2261
2262         return 1;
2263 }
2264
2265
2266 /*
2267  *      Compile one entry of a module call.
2268  */
2269 static modcallable *do_compile_modsingle(modcallable *parent,
2270                                          rlm_components_t component, CONF_ITEM *ci,
2271                                          int grouptype,
2272                                          char const **modname)
2273 {
2274         char const *modrefname;
2275         modsingle *single;
2276         modcallable *csingle;
2277         module_instance_t *this;
2278         CONF_SECTION *cs, *subcs, *modules;
2279         char const *realname;
2280
2281         if (cf_item_is_section(ci)) {
2282                 char const *name2;
2283
2284                 cs = cf_itemtosection(ci);
2285                 modrefname = cf_section_name1(cs);
2286                 name2 = cf_section_name2(cs);
2287                 if (!name2) name2 = "";
2288
2289                 /*
2290                  *      group{}, redundant{}, or append{} may appear
2291                  *      where a single module instance was expected.
2292                  *      In that case, we hand it off to
2293                  *      compile_modgroup
2294                  */
2295                 if (strcmp(modrefname, "group") == 0) {
2296                         *modname = name2;
2297                         return do_compile_modgroup(parent, component, cs,
2298                                                    GROUPTYPE_SIMPLE,
2299                                                    grouptype, MOD_GROUP);
2300
2301                 } else if (strcmp(modrefname, "redundant") == 0) {
2302                         *modname = name2;
2303
2304                         if (!all_children_are_modules(cs, modrefname)) {
2305                                 return NULL;
2306                         }
2307
2308                         return do_compile_modgroup(parent, component, cs,
2309                                                    GROUPTYPE_REDUNDANT,
2310                                                    grouptype, MOD_GROUP);
2311
2312                 } else if (strcmp(modrefname, "append") == 0) {
2313                         *modname = name2;
2314                         return do_compile_modgroup(parent, component, cs,
2315                                                    GROUPTYPE_APPEND,
2316                                                    grouptype, MOD_GROUP);
2317
2318                 } else if (strcmp(modrefname, "load-balance") == 0) {
2319                         *modname = name2;
2320
2321                         if (!all_children_are_modules(cs, modrefname)) {
2322                                 return NULL;
2323                         }
2324
2325                         return do_compile_modgroup(parent, component, cs,
2326                                                    GROUPTYPE_SIMPLE,
2327                                                    grouptype, MOD_LOAD_BALANCE);
2328
2329                 } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
2330                         *modname = name2;
2331
2332                         if (!all_children_are_modules(cs, modrefname)) {
2333                                 return NULL;
2334                         }
2335
2336                         return do_compile_modgroup(parent, component, cs,
2337                                                    GROUPTYPE_REDUNDANT,
2338                                                    grouptype, MOD_REDUNDANT_LOAD_BALANCE);
2339
2340 #ifdef WITH_UNLANG
2341                 } else  if (strcmp(modrefname, "if") == 0) {
2342                         if (!cf_section_name2(cs)) {
2343                                 cf_log_err(ci, "'if' without condition");
2344                                 return NULL;
2345                         }
2346
2347                         *modname = name2;
2348                         csingle= do_compile_modgroup(parent, component, cs,
2349                                                      GROUPTYPE_SIMPLE,
2350                                                      grouptype, MOD_IF);
2351                         if (!csingle) return NULL;
2352                         *modname = name2;
2353
2354                         return csingle;
2355
2356                 } else  if (strcmp(modrefname, "elsif") == 0) {
2357                         if (parent &&
2358                             ((parent->type == MOD_LOAD_BALANCE) ||
2359                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2360                                 cf_log_err(ci, "'elsif' cannot be used in this section");
2361                                 return NULL;
2362                         }
2363
2364                         if (!cf_section_name2(cs)) {
2365                                 cf_log_err(ci, "'elsif' without condition");
2366                                 return NULL;
2367                         }
2368
2369                         *modname = name2;
2370                         return do_compile_modgroup(parent, component, cs,
2371                                                    GROUPTYPE_SIMPLE,
2372                                                    grouptype, MOD_ELSIF);
2373
2374                 } else  if (strcmp(modrefname, "else") == 0) {
2375                         if (parent &&
2376                             ((parent->type == MOD_LOAD_BALANCE) ||
2377                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2378                                 cf_log_err(ci, "'else' cannot be used in this section section");
2379                                 return NULL;
2380                         }
2381
2382                         if (cf_section_name2(cs)) {
2383                                 cf_log_err(ci, "Cannot have conditions on 'else'");
2384                                 return NULL;
2385                         }
2386
2387                         *modname = name2;
2388                         return  do_compile_modgroup(parent, component, cs,
2389                                                     GROUPTYPE_SIMPLE,
2390                                                     grouptype, MOD_ELSE);
2391
2392                 } else  if (strcmp(modrefname, "update") == 0) {
2393                         *modname = name2;
2394
2395                         return do_compile_modupdate(parent, component, cs,
2396                                                     name2);
2397
2398                 } else  if (strcmp(modrefname, "switch") == 0) {
2399                         *modname = name2;
2400
2401                         return do_compile_modswitch (parent, component, cs);
2402
2403                 } else  if (strcmp(modrefname, "case") == 0) {
2404                         *modname = name2;
2405
2406                         return do_compile_modcase(parent, component, cs);
2407
2408                 } else  if (strcmp(modrefname, "foreach") == 0) {
2409                         *modname = name2;
2410
2411                         return do_compile_modforeach(parent, component, cs);
2412
2413 #endif
2414                 } /* else it's something like sql { fail = 1 ...} */
2415
2416         } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */
2417                 return NULL;
2418
2419                 /*
2420                  *      Else it's a module reference, with updated return
2421                  *      codes.
2422                  */
2423         } else {
2424                 CONF_SECTION *loop;
2425                 CONF_PAIR *cp = cf_itemtopair(ci);
2426                 modrefname = cf_pair_attr(cp);
2427
2428                 /*
2429                  *      Actions (ok = 1), etc. are orthogonal to just
2430                  *      about everything else.
2431                  */
2432                 if (cf_pair_value(cp) != NULL) {
2433                         cf_log_err(ci, "Entry is not a reference to a module");
2434                         return NULL;
2435                 }
2436
2437                 if (((modrefname[0] == '%') && (modrefname[1] == '{')) ||
2438                     (modrefname[0] == '`')) {
2439                         return do_compile_modxlat(parent, component,
2440                                                   modrefname);
2441                 }
2442
2443                 /*
2444                  *      See if the module is a virtual one.  If so,
2445                  *      return that, rather than doing anything here.
2446                  */
2447                 subcs = NULL;
2448                 cs = cf_section_find("instantiate");
2449                 if (cs) subcs = cf_section_sub_find_name2(cs, NULL,
2450                                                           modrefname);
2451                 if (!subcs &&
2452                     (cs = cf_section_find("policy")) != NULL) {
2453                         char buffer[256];
2454
2455                         snprintf(buffer, sizeof(buffer), "%s.%s",
2456                                  modrefname, comp2str[component]);
2457
2458                         /*
2459                          *      Prefer name.section, then name.
2460                          */
2461                         subcs = cf_section_sub_find_name2(cs, NULL,
2462                                                           buffer);
2463                         if (!subcs) {
2464                                 subcs = cf_section_sub_find_name2(cs, NULL,
2465                                                                   modrefname);
2466                         }
2467                 }
2468
2469                 /*
2470                  *      Allow policies to over-ride module names.
2471                  *      i.e. the "sql" policy can do some extra things,
2472                  *      and then call the "sql" module.
2473                  */
2474                 for (loop = cf_item_parent(ci);
2475                      loop && subcs;
2476                      loop = cf_item_parent(cf_sectiontoitem(loop))) {
2477                         if (loop == subcs) {
2478                                 subcs = NULL;
2479                         }
2480                 }
2481
2482                 if (subcs) {
2483                         /*
2484                          *      redundant foo {} is a single.
2485                          */
2486                         if (cf_section_name2(subcs)) {
2487                                 return do_compile_modsingle(parent,
2488                                                             component,
2489                                                             cf_sectiontoitem(subcs),
2490                                                             grouptype,
2491                                                             modname);
2492                         } else {
2493                                 /*
2494                                  *      foo {} is a group.
2495                                  */
2496                                 return do_compile_modgroup(parent,
2497                                                            component,
2498                                                            subcs,
2499                                                            GROUPTYPE_SIMPLE,
2500                                                            grouptype, MOD_GROUP);
2501                         }
2502                 }
2503         }
2504
2505 #ifdef WITH_UNLANG
2506         if (strcmp(modrefname, "break") == 0) {
2507                 return do_compile_modbreak(parent, component, ci);
2508         }
2509
2510         if (strcmp(modrefname, "return") == 0) {
2511                 return do_compile_modgroup(parent, component, NULL,
2512                                            GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2513                                            MOD_RETURN);
2514         }
2515 #endif
2516
2517         /*
2518          *      Not a virtual module.  It must be a real module.
2519          */
2520         modules = cf_section_find("modules");
2521         this = NULL;
2522         realname = modrefname;
2523
2524         if (modules) {
2525                 /*
2526                  *      Try to load the optional module.
2527                  */
2528                 if (realname[0] == '-') realname++;
2529
2530                 /*
2531                  *      As of v3, only known modules are in the
2532                  *      "modules" section.
2533                  */
2534                 if (cf_section_sub_find_name2(modules, NULL, realname)) {
2535                         this = find_module_instance(modules, realname, true);
2536                         if (!this && (realname != modrefname)) {
2537                                 return NULL;
2538                         }
2539
2540                 } else {
2541                         /*
2542                          *      We were asked to MAYBE load it and it
2543                          *      doesn't exist.  Return a soft error.
2544                          */
2545                         if (realname != modrefname) {
2546                                 *modname = modrefname;
2547                                 return NULL;
2548                         }
2549                 }
2550         }
2551
2552         if (!this) do {
2553                 int i;
2554                 char *p;
2555
2556                 /*
2557                  *      Maybe it's module.method
2558                  */
2559                 p = strrchr(modrefname, '.');
2560                 if (p) for (i = RLM_COMPONENT_AUTH;
2561                             i < RLM_COMPONENT_COUNT;
2562                             i++) {
2563                         if (strcmp(p + 1, comp2str[i]) == 0) {
2564                                 char buffer[256];
2565
2566                                 strlcpy(buffer, modrefname, sizeof(buffer));
2567                                 buffer[p - modrefname] = '\0';
2568                                 component = i;
2569
2570                                 this = find_module_instance(modules, buffer, true);
2571                                 if (this && !this->entry->module->methods[i]) {
2572                                         *modname = NULL;
2573                                         cf_log_err(ci, "Module %s has no such method %s", buffer, comp2str[i]);
2574                                         return NULL;
2575                                 }
2576                                 break;
2577                         }
2578                 }
2579                 if (this) break;
2580
2581                 /*
2582                  *      Call a server.  This should really be deleted...
2583                  */
2584                 if (strncmp(modrefname, "server[", 7) == 0) {
2585                         char buffer[256];
2586
2587                         strlcpy(buffer, modrefname + 7, sizeof(buffer));
2588                         p = strrchr(buffer, ']');
2589                         if (!p || p[1] != '\0' || (p == buffer)) {
2590                                 cf_log_err(ci, "Invalid server reference in \"%s\".", modrefname);
2591                                 return NULL;
2592                         }
2593                         *p = '\0';
2594
2595                         cs = cf_section_sub_find_name2(NULL, "server", buffer);
2596                         if (!cs) {
2597                                 cf_log_err(ci, "No such server \"%s\".", buffer);
2598                                 return NULL;
2599                         }
2600
2601                         return do_compile_modserver(parent, component, ci,
2602                                                     modrefname, cs, buffer);
2603                 }
2604
2605                 *modname = NULL;
2606                 cf_log_err(ci, "Failed to find \"%s\" in the \"modules\" section.", modrefname);
2607                 cf_log_err(ci, "Please verify that the configuration exists in the file %s/mods-enabled/%s.", get_radius_dir(), modrefname);
2608                 return NULL;
2609         } while (0);
2610
2611         /*
2612          *      We know it's all OK, allocate the structures, and fill
2613          *      them in.
2614          */
2615         single = talloc_zero(parent, modsingle);
2616         csingle = mod_singletocallable(single);
2617         csingle->parent = parent;
2618         csingle->next = NULL;
2619         if (!parent || (component != RLM_COMPONENT_AUTH)) {
2620                 memcpy(csingle->actions, defaultactions[component][grouptype],
2621                        sizeof csingle->actions);
2622         } else { /* inside Auth-Type has different rules */
2623                 memcpy(csingle->actions, defaultactions[RLM_COMPONENT_AUTZ][grouptype],
2624                        sizeof csingle->actions);
2625         }
2626         rad_assert(modrefname != NULL);
2627         csingle->name = realname;
2628         csingle->type = MOD_SINGLE;
2629         csingle->method = component;
2630
2631         /*
2632          *      Singles can override the actions, virtual modules cannot.
2633          *
2634          *      FIXME: We may want to re-visit how to do this...
2635          *      maybe a csingle as a ref?
2636          */
2637         if (cf_item_is_section(ci)) {
2638                 CONF_ITEM *csi;
2639
2640                 cs = cf_itemtosection(ci);
2641                 for (csi=cf_item_find_next(cs, NULL);
2642                      csi != NULL;
2643                      csi=cf_item_find_next(cs, csi)) {
2644
2645                         if (cf_item_is_section(csi)) {
2646                                 cf_log_err(csi, "Subsection of module instance call not allowed");
2647                                 talloc_free(csingle);
2648                                 return NULL;
2649                         }
2650
2651                         if (!cf_item_is_pair(csi)) continue;
2652
2653                         if (!compile_action(csingle, cf_itemtopair(csi))) {
2654                                 talloc_free(csingle);
2655                                 return NULL;
2656                         }
2657                 }
2658         }
2659
2660         /*
2661          *      Bail out if the module in question does not supply the
2662          *      wanted component
2663          */
2664         if (!this->entry->module->methods[component]) {
2665                 cf_log_err(ci, "\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name,
2666                        comp2str[component]);
2667                 talloc_free(csingle);
2668                 return NULL;
2669         }
2670
2671         single->modinst = this;
2672         *modname = this->entry->module->name;
2673         return csingle;
2674 }
2675
2676 modcallable *compile_modsingle(TALLOC_CTX *ctx,
2677                                modcallable **parent,
2678                                rlm_components_t component, CONF_ITEM *ci,
2679                                char const **modname)
2680 {
2681         modcallable *ret;
2682
2683         if (!*parent) {
2684                 modcallable *c;
2685                 modgroup *g;
2686                 CONF_SECTION *parentcs;
2687
2688                 g = talloc_zero(ctx, modgroup);
2689                 memset(g, 0, sizeof(*g));
2690                 g->grouptype = GROUPTYPE_SIMPLE;
2691                 c = mod_grouptocallable(g);
2692                 c->next = NULL;
2693                 memcpy(c->actions,
2694                        defaultactions[component][GROUPTYPE_SIMPLE],
2695                        sizeof(c->actions));
2696
2697                 parentcs = cf_item_parent(ci);
2698                 c->name = cf_section_name2(parentcs);
2699                 if (!c->name) {
2700                         c->name = cf_section_name1(parentcs);
2701                 }
2702
2703                 c->type = MOD_GROUP;
2704                 c->method = component;
2705                 g->children = NULL;
2706
2707                 *parent = mod_grouptocallable(g);
2708         }
2709
2710         ret = do_compile_modsingle(*parent, component, ci,
2711                                    GROUPTYPE_SIMPLE,
2712                                    modname);
2713         dump_tree(component, ret);
2714         return ret;
2715 }
2716
2717
2718 /*
2719  *      Internal compile group code.
2720  */
2721 static modcallable *do_compile_modgroup(modcallable *parent,
2722                                         rlm_components_t component, CONF_SECTION *cs,
2723                                         int grouptype, int parentgrouptype, int mod_type)
2724 {
2725         int i;
2726         modgroup *g;
2727         modcallable *c;
2728         CONF_ITEM *ci;
2729
2730         g = talloc_zero(parent, modgroup);
2731         g->grouptype = grouptype;
2732         g->children = NULL;
2733         g->cs = cs;
2734
2735         c = mod_grouptocallable(g);
2736         c->parent = parent;
2737         c->type = mod_type;
2738         c->next = NULL;
2739         memset(c->actions, 0, sizeof(c->actions));
2740
2741         if (!cs) {              /* only for "break" and "return" */
2742                 c->name = "";
2743                 goto set_codes;
2744         }
2745
2746         /*
2747          *      Remember the name for printing, etc.
2748          *
2749          *      FIXME: We may also want to put the names into a
2750          *      rbtree, so that groups can reference each other...
2751          */
2752         c->name = cf_section_name2(cs);
2753         if (!c->name) {
2754                 c->name = cf_section_name1(cs);
2755                 if ((strcmp(c->name, "group") == 0) ||
2756                     (strcmp(c->name, "redundant") == 0)) {
2757                         c->name = "";
2758                 } else if (c->type == MOD_GROUP) {
2759                         c->type = MOD_POLICY;
2760                 }
2761         }
2762
2763 #ifdef WITH_UNLANG
2764         /*
2765          *      Do load-time optimizations
2766          */
2767         if ((c->type == MOD_IF) || (c->type == MOD_ELSIF) || (c->type == MOD_ELSE)) {
2768                 modgroup *f, *p;
2769
2770                 rad_assert(parent != NULL);
2771
2772                 if (c->type == MOD_IF) {
2773                         g->cond = cf_data_find(g->cs, "if");
2774                         rad_assert(g->cond != NULL);
2775
2776                 check_if:
2777                         if (g->cond->type == COND_TYPE_FALSE) {
2778                                 INFO(" # Skipping contents of '%s' as it is always 'false' -- %s:%d",
2779                                      group_name[g->mc.type],
2780                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2781                                 goto set_codes;
2782                         }
2783
2784                 } else if (c->type == MOD_ELSIF) {
2785
2786                         g->cond = cf_data_find(g->cs, "if");
2787                         rad_assert(g->cond != NULL);
2788
2789                         rad_assert(parent != NULL);
2790                         p = mod_callabletogroup(parent);
2791
2792                         rad_assert(p->tail != NULL);
2793
2794                         f = mod_callabletogroup(p->tail);
2795                         rad_assert((f->mc.type == MOD_IF) ||
2796                                    (f->mc.type == MOD_ELSIF));
2797
2798                         /*
2799                          *      If we took the previous condition, we
2800                          *      don't need to take this one.
2801                          *
2802                          *      We reset our condition to 'true', so
2803                          *      that subsequent sections can check
2804                          *      that they don't need to be executed.
2805                          */
2806                         if (f->cond->type == COND_TYPE_TRUE) {
2807                         skip_true:
2808                                 INFO(" # Skipping contents of '%s' as previous '%s' is always  'true' -- %s:%d",
2809                                      group_name[g->mc.type],
2810                                      group_name[f->mc.type],
2811                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2812                                 g->cond = f->cond;
2813                                 goto set_codes;
2814                         }
2815                         goto check_if;
2816
2817                 } else {
2818                         rad_assert(c->type == MOD_ELSE);
2819
2820                         rad_assert(parent != NULL);
2821                         p = mod_callabletogroup(parent);
2822
2823                         rad_assert(p->tail != NULL);
2824
2825                         f = mod_callabletogroup(p->tail);
2826                         rad_assert((f->mc.type == MOD_IF) ||
2827                                    (f->mc.type == MOD_ELSIF));
2828
2829                         /*
2830                          *      If we took the previous condition, we
2831                          *      don't need to take this one.
2832                          */
2833                         if (f->cond->type == COND_TYPE_TRUE) goto skip_true;
2834                 }
2835
2836                 /*
2837                  *      Else we need to compile this section
2838                  */
2839         }
2840 #endif
2841
2842         /*
2843          *      Loop over the children of this group.
2844          */
2845         for (ci=cf_item_find_next(cs, NULL);
2846              ci != NULL;
2847              ci=cf_item_find_next(cs, ci)) {
2848
2849                 /*
2850                  *      Sections are references to other groups, or
2851                  *      to modules with updated return codes.
2852                  */
2853                 if (cf_item_is_section(ci)) {
2854                         char const *junk = NULL;
2855                         modcallable *single;
2856                         CONF_SECTION *subcs = cf_itemtosection(ci);
2857
2858                         single = do_compile_modsingle(c, component, ci,
2859                                                       grouptype, &junk);
2860                         if (!single) {
2861                                 cf_log_err(ci, "Failed to parse \"%s\" subsection.",
2862                                        cf_section_name1(subcs));
2863                                 talloc_free(c);
2864                                 return NULL;
2865                         }
2866                         add_child(g, single);
2867
2868                 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */
2869                         continue;
2870
2871                 } else {
2872                         char const *attr, *value;
2873                         CONF_PAIR *cp = cf_itemtopair(ci);
2874
2875                         attr = cf_pair_attr(cp);
2876                         value = cf_pair_value(cp);
2877
2878                         /*
2879                          *      A CONF_PAIR is either a module
2880                          *      instance with no actions
2881                          *      specified ...
2882                          */
2883                         if (!value) {
2884                                 modcallable *single;
2885                                 char const *junk = NULL;
2886
2887                                 single = do_compile_modsingle(c,
2888                                                               component,
2889                                                               ci,
2890                                                               grouptype,
2891                                                               &junk);
2892                                 if (!single) {
2893                                         if (cf_item_is_pair(ci) &&
2894                                             cf_pair_attr(cf_itemtopair(ci))[0] == '-') {
2895                                                 continue;
2896                                         }
2897
2898                                         cf_log_err(ci,
2899                                                    "Failed to parse \"%s\" entry.",
2900                                                    attr);
2901                                         talloc_free(c);
2902                                         return NULL;
2903                                 }
2904                                 add_child(g, single);
2905
2906                                 /*
2907                                  *      Or a module instance with action.
2908                                  */
2909                         } else if (!compile_action(c, cp)) {
2910                                 talloc_free(c);
2911                                 return NULL;
2912                         } /* else it worked */
2913                 }
2914         }
2915
2916 set_codes:
2917         /*
2918          *      Set the default actions, if they haven't already been
2919          *      set.
2920          */
2921         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
2922                 if (!c->actions[i]) {
2923                         if (!parent || (component != RLM_COMPONENT_AUTH)) {
2924                                 c->actions[i] = defaultactions[component][parentgrouptype][i];
2925                         } else { /* inside Auth-Type has different rules */
2926                                 c->actions[i] = defaultactions[RLM_COMPONENT_AUTZ][parentgrouptype][i];
2927                         }
2928                 }
2929         }
2930
2931         switch (c->type) {
2932         default:
2933                 break;
2934
2935         case MOD_GROUP:
2936                 if (grouptype != GROUPTYPE_REDUNDANT) break;
2937                 /* FALL-THROUGH */
2938
2939         case MOD_LOAD_BALANCE:
2940         case MOD_REDUNDANT_LOAD_BALANCE:
2941                 if (!g->children) {
2942                         cf_log_err_cs(g->cs, "%s sections cannot be empty",
2943                                       cf_section_name1(g->cs));
2944                         talloc_free(c);
2945                         return NULL;
2946                 }
2947         }
2948
2949         /*
2950          *      FIXME: If there are no children, return NULL?
2951          */
2952         return mod_grouptocallable(g);
2953 }
2954
2955 modcallable *compile_modgroup(modcallable *parent,
2956                               rlm_components_t component, CONF_SECTION *cs)
2957 {
2958         modcallable *ret = do_compile_modgroup(parent, component, cs,
2959                                                GROUPTYPE_SIMPLE,
2960                                                GROUPTYPE_SIMPLE, MOD_GROUP);
2961
2962         if (debug_flag > 3) {
2963                 modcall_debug(ret, 2);
2964         }
2965
2966         return ret;
2967 }
2968
2969 void add_to_modcallable(modcallable *parent, modcallable *this)
2970 {
2971         modgroup *g;
2972
2973         rad_assert(this != NULL);
2974         rad_assert(parent != NULL);
2975
2976         g = mod_callabletogroup(parent);
2977
2978         add_child(g, this);
2979 }
2980
2981
2982 #ifdef WITH_UNLANG
2983 static bool pass2_xlat_compile(CONF_ITEM const *ci, value_pair_tmpl_t **pvpt, bool convert,
2984                                DICT_ATTR const *da)
2985 {
2986         ssize_t slen;
2987         char *fmt;
2988         char const *error;
2989         xlat_exp_t *head;
2990         value_pair_tmpl_t *vpt;
2991
2992         vpt = *pvpt;
2993
2994         rad_assert(vpt->type == TMPL_TYPE_XLAT);
2995
2996         fmt = talloc_typed_strdup(vpt, vpt->name);
2997         slen = xlat_tokenize(vpt, fmt, &head, &error);
2998
2999         if (slen < 0) {
3000                 char *spaces, *text;
3001
3002                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3003
3004                 cf_log_err(ci, "Failed parsing expanded string:");
3005                 cf_log_err(ci, "%s", text);
3006                 cf_log_err(ci, "%s^ %s", spaces, error);
3007
3008                 talloc_free(spaces);
3009                 talloc_free(text);
3010                 return false;
3011         }
3012
3013         /*
3014          *      Convert %{Attribute-Name} to &Attribute-Name
3015          */
3016         if (convert) {
3017                 value_pair_tmpl_t *attr;
3018
3019                 attr = xlat_to_tmpl_attr(talloc_parent(vpt), head);
3020                 if (attr) {
3021                         /*
3022                          *      If it's a virtual attribute, leave it
3023                          *      alone.
3024                          */
3025                         if (attr->tmpl_da->flags.virtual) {
3026                                 talloc_free(attr);
3027                                 return true;
3028                         }
3029
3030                         /*
3031                          *      If the attribute is of incompatible
3032                          *      type, leave it alone.
3033                          */
3034                         if (da && (da->type != attr->tmpl_da->type)) {
3035                                 talloc_free(attr);
3036                                 return true;
3037                         }
3038
3039                         if (cf_item_is_pair(ci)) {
3040                                 CONF_PAIR *cp = cf_itemtopair(ci);
3041
3042                                 WARN("%s[%d] Please change %%{%s} to &%s",
3043                                        cf_pair_filename(cp), cf_pair_lineno(cp),
3044                                        attr->name, attr->name);
3045                         } else {
3046                                 CONF_SECTION *cs = cf_itemtosection(ci);
3047
3048                                 WARN("%s[%d] Please change %%{%s} to &%s",
3049                                        cf_section_filename(cs), cf_section_lineno(cs),
3050                                        attr->name, attr->name);
3051                         }
3052                         TALLOC_FREE(*pvpt);
3053                         *pvpt = attr;
3054                         return true;
3055                 }
3056         }
3057
3058         /*
3059          *      Re-write it to be a pre-parsed XLAT structure.
3060          */
3061         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3062         vpt->tmpl_xlat = head;
3063
3064         return true;
3065 }
3066
3067
3068 #ifdef HAVE_REGEX
3069 static int _free_compiled_regex(regex_t *preg)
3070 {
3071         regfree(preg);
3072         return 0;
3073 }
3074
3075 static bool pass2_regex_compile(CONF_ITEM const *ci, value_pair_tmpl_t *vpt)
3076 {
3077         int rcode;
3078         regex_t *preg;
3079
3080         rad_assert(vpt->type == TMPL_TYPE_REGEX);
3081
3082         /*
3083          *      It's a dynamic expansion.  We can't expand the string,
3084          *      but we can pre-parse it as an xlat struct.  In that
3085          *      case, we convert it to a pre-compiled XLAT.
3086          *
3087          *      This is a little more complicated than it needs to be
3088          *      because radius_evaluate_map() keys off of the src
3089          *      template type, instead of the operators.  And, the
3090          *      pass2_xlat_compile() function expects to get passed an
3091          *      XLAT instead of a REGEX.
3092          */
3093         if (strchr(vpt->name, '%')) {
3094                 vpt->type = TMPL_TYPE_XLAT;
3095                 return pass2_xlat_compile(ci, &vpt, false, NULL);
3096         }
3097
3098         preg = talloc_zero(vpt, regex_t);
3099         talloc_set_destructor(preg, _free_compiled_regex);
3100         if (!preg) return false;
3101
3102         rcode = regcomp(preg, vpt->name, REG_EXTENDED | (vpt->tmpl_iflag ? REG_ICASE : 0));
3103         if (rcode != 0) {
3104                 char buffer[256];
3105                 regerror(rcode, preg, buffer, sizeof(buffer));
3106
3107                 cf_log_err(ci, "Invalid regular expression %s: %s",
3108                            vpt->name, buffer);
3109                 return false;
3110         }
3111
3112         vpt->type = TMPL_TYPE_REGEX_STRUCT;
3113         vpt->tmpl_preg = preg;
3114
3115         return true;
3116 }
3117 #endif
3118
3119 static bool pass2_fixup_undefined(CONF_ITEM const *ci, value_pair_tmpl_t *vpt)
3120 {
3121         DICT_ATTR const *da;
3122
3123         rad_assert(vpt->type == TMPL_TYPE_ATTR_UNDEFINED);
3124
3125         da = dict_attrbyname(vpt->tmpl_unknown_name);
3126         if (!da) {
3127                 cf_log_err(ci, "Unknown attribute '%s'", vpt->tmpl_unknown_name);
3128                 return false;
3129         }
3130
3131         vpt->tmpl_da = da;
3132         vpt->type = TMPL_TYPE_ATTR;
3133         return true;
3134 }
3135
3136 /** Convert an &attr[*] reference to an XLAT
3137  *
3138  * @param vpt to convert
3139  * @return true if conversion was successful, else false.
3140  */
3141 static bool pass2_fixup_attr_count(value_pair_tmpl_t *vpt)
3142 {
3143         xlat_exp_t *node;
3144
3145         rad_assert(vpt->type == TMPL_TYPE_ATTR);
3146         rad_assert(vpt->tmpl_num == NUM_COUNT);
3147
3148         node = xlat_from_tmpl_attr(vpt, vpt);
3149         if (!node) return false;
3150
3151         memset(&vpt->data, 0, sizeof(vpt->data));
3152         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3153         vpt->data.xlat = node;
3154
3155         return true;
3156 }
3157
3158 static bool pass2_callback(UNUSED void *ctx, fr_cond_t *c)
3159 {
3160         value_pair_map_t *map;
3161
3162         if (c->type == COND_TYPE_EXISTS) {
3163                 if (c->data.vpt->type == TMPL_TYPE_XLAT) {
3164                         return pass2_xlat_compile(c->ci, &c->data.vpt, true, NULL);
3165                 }
3166
3167                 rad_assert(c->data.vpt->type != TMPL_TYPE_REGEX);
3168
3169                 /*
3170                  *      The existence check might have been &Foo-Bar,
3171                  *      where Foo-Bar is defined by a module.
3172                  */
3173                 if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3174                         if (!pass2_fixup_undefined(c->ci, c->data.vpt)) return false;
3175                         c->pass2_fixup = PASS2_FIXUP_NONE;
3176                 }
3177
3178                 if ((c->data.vpt->type == TMPL_TYPE_ATTR) && (c->data.vpt->tmpl_num == NUM_COUNT)) {
3179                         return pass2_fixup_attr_count(c->data.vpt);
3180                 }
3181                 return true;
3182         }
3183
3184         /*
3185          *      Maps have a paircompare fixup applied to them.
3186          *      Others get ignored.
3187          */
3188         if (c->pass2_fixup == PASS2_FIXUP_NONE) {
3189                 if (c->type == COND_TYPE_MAP) {
3190                         map = c->data.map;
3191                         goto check_paircmp;
3192                 }
3193
3194                 return true;
3195         }
3196
3197         map = c->data.map;      /* shorter */
3198
3199         /*
3200          *      Auth-Type := foo
3201          *
3202          *      Where "foo" is dynamically defined.
3203          */
3204         if (c->pass2_fixup == PASS2_FIXUP_TYPE) {
3205                 if (!dict_valbyname(map->lhs->tmpl_da->attr,
3206                                     map->lhs->tmpl_da->vendor,
3207                                     map->rhs->name)) {
3208                         cf_log_err(map->ci, "Invalid reference to non-existent %s %s { ... }",
3209                                    map->lhs->tmpl_da->name,
3210                                    map->rhs->name);
3211                         return false;
3212                 }
3213
3214                 /*
3215                  *      These guys can't have a paircompare fixup applied.
3216                  */
3217                 c->pass2_fixup = PASS2_FIXUP_NONE;
3218                 return true;
3219         }
3220
3221         if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3222                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3223                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3224                 }
3225
3226                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3227                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3228                 }
3229
3230                 c->pass2_fixup = PASS2_FIXUP_NONE;
3231         }
3232
3233 check_paircmp:
3234         /*
3235          *      Just in case someone adds a new fixup later.
3236          */
3237         rad_assert((c->pass2_fixup == PASS2_FIXUP_NONE) ||
3238                    (c->pass2_fixup == PASS2_PAIRCOMPARE));
3239
3240         if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->tmpl_num == NUM_COUNT)) {
3241                 if (!pass2_fixup_attr_count(map->lhs)) return false;
3242         }
3243         if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->tmpl_num == NUM_COUNT)) {
3244                 if (!pass2_fixup_attr_count(map->rhs)) return false;
3245         }
3246
3247         /*
3248          *      Precompile xlat's
3249          */
3250         if (map->lhs->type == TMPL_TYPE_XLAT) {
3251                 /*
3252                  *      Don't compile the LHS to an attribute
3253                  *      reference for now.  When we do that, we've got
3254                  *      to check the RHS for type-specific data, and
3255                  *      parse it to a TMPL_TYPE_DATA.
3256                  */
3257                 if (!pass2_xlat_compile(map->ci, &map->lhs, false, NULL)) {
3258                         return false;
3259                 }
3260         }
3261
3262         if (map->rhs->type == TMPL_TYPE_XLAT) {
3263                 /*
3264                  *      Convert the RHS to an attribute reference only
3265                  *      if the LHS is an attribute reference, AND is
3266                  *      of the same type as the RHS.
3267                  *
3268                  *      We can fix this when the code in evaluate.c
3269                  *      can handle strings on the LHS, and attributes
3270                  *      on the RHS.  For now, the code in parser.c
3271                  *      forbids this.
3272                  */
3273                 if (map->lhs->type == TMPL_TYPE_ATTR) {
3274                         DICT_ATTR const *da = c->cast;
3275
3276                         if (!c->cast) da = map->lhs->tmpl_da;
3277
3278                         if (!pass2_xlat_compile(map->ci, &map->rhs, true, da)) {
3279                                 return false;
3280                         }
3281
3282                 } else {
3283                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3284                                 return false;
3285                         }
3286                 }
3287         }
3288
3289         /*
3290          *      Convert bare refs to %{Foreach-Variable-N}
3291          */
3292         if ((map->lhs->type == TMPL_TYPE_LITERAL) &&
3293             (strncmp(map->lhs->name, "Foreach-Variable-", 17) == 0)) {
3294                 char *fmt;
3295                 ssize_t slen;
3296                 value_pair_tmpl_t *vpt;
3297
3298                 fmt = talloc_asprintf(map->lhs, "%%{%s}", map->lhs->name);
3299                 slen = tmpl_afrom_str(map, &vpt, fmt, talloc_array_length(fmt) - 1,
3300                                       T_DOUBLE_QUOTED_STRING, REQUEST_CURRENT, PAIR_LIST_REQUEST);
3301                 if (slen < 0) {
3302                         char *spaces, *text;
3303
3304                         fr_canonicalize_error(map->ci, &spaces, &text, slen, fr_strerror());
3305
3306                         cf_log_err(map->ci, "Failed converting %s to xlat", map->lhs->name);
3307                         cf_log_err(map->ci, "%s", fmt);
3308                         cf_log_err(map->ci, "%s^ %s", spaces, text);
3309
3310                         talloc_free(spaces);
3311                         talloc_free(text);
3312                         talloc_free(fmt);
3313
3314                         return false;
3315                 }
3316                 talloc_free(map->lhs);
3317                 map->lhs = vpt;
3318         }
3319
3320 #ifdef HAVE_REGEX
3321         if (map->rhs->type == TMPL_TYPE_REGEX) {
3322                 if (!pass2_regex_compile(map->ci, map->rhs)) {
3323                         return false;
3324                 }
3325         }
3326         rad_assert(map->lhs->type != TMPL_TYPE_REGEX);
3327 #endif
3328
3329         /*
3330          *      Only attributes can have a paircompare registered, and
3331          *      they can only be with the current REQUEST, and only
3332          *      with the request pairs.
3333          */
3334         if ((map->lhs->type != TMPL_TYPE_ATTR) ||
3335             (map->lhs->tmpl_request != REQUEST_CURRENT) ||
3336             (map->lhs->tmpl_list != PAIR_LIST_REQUEST)) {
3337                 return true;
3338         }
3339
3340         if (!radius_find_compare(map->lhs->tmpl_da)) return true;
3341
3342         if (map->rhs->type == TMPL_TYPE_ATTR) {
3343                 cf_log_err(map->ci, "Cannot compare virtual attribute %s to another attribute",
3344                            map->lhs->name);
3345                 return false;
3346         }
3347
3348         if (map->rhs->type == TMPL_TYPE_REGEX) {
3349                 cf_log_err(map->ci, "Cannot compare virtual attribute %s via a regex",
3350                            map->lhs->name);
3351                 return false;
3352         }
3353
3354         if (c->cast) {
3355                 cf_log_err(map->ci, "Cannot cast virtual attribute %s",
3356                            map->lhs->name);
3357                 return false;
3358         }
3359
3360         if (map->op != T_OP_CMP_EQ) {
3361                 cf_log_err(map->ci, "Must use '==' for comparisons with virtual attribute %s",
3362                            map->lhs->name);
3363                 return false;
3364         }
3365
3366         /*
3367          *      Mark it as requiring a paircompare() call, instead of
3368          *      paircmp().
3369          */
3370         c->pass2_fixup = PASS2_PAIRCOMPARE;
3371
3372         return true;
3373 }
3374
3375
3376 /*
3377  *      Compile the RHS of update sections to xlat_exp_t
3378  */
3379 static bool modcall_pass2_update(modgroup *g)
3380 {
3381         value_pair_map_t *map;
3382
3383         for (map = g->map; map != NULL; map = map->next) {
3384                 if (map->rhs->type == TMPL_TYPE_XLAT) {
3385                         rad_assert(map->rhs->tmpl_xlat == NULL);
3386
3387                         /*
3388                          *      FIXME: compile to attribute && handle
3389                          *      the conversion in map_to_vp().
3390                          */
3391                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3392                                 return false;
3393                         }
3394                 }
3395
3396                 rad_assert(map->rhs->type != TMPL_TYPE_REGEX);
3397         }
3398
3399         return true;
3400 }
3401 #endif
3402
3403 /*
3404  *      Do a second-stage pass on compiling the modules.
3405  */
3406 bool modcall_pass2(modcallable *mc)
3407 {
3408         ssize_t slen;
3409         char const *name2;
3410         modcallable *c;
3411         modgroup *g;
3412
3413         for (c = mc; c != NULL; c = c->next) {
3414                 switch (c->type) {
3415                 default:
3416                         rad_assert(0 == 1);
3417                         break;
3418
3419 #ifdef WITH_UNLANG
3420                 case MOD_UPDATE:
3421                         g = mod_callabletogroup(c);
3422                         if (g->done_pass2) return true;
3423
3424                         name2 = cf_section_name2(g->cs);
3425                         if (!name2) {
3426                                 c->debug_name = group_name[c->type];
3427                         } else {
3428                                 c->debug_name = talloc_asprintf(c, "update %s", name2);
3429                         }
3430
3431                         if (!modcall_pass2_update(g)) {
3432                                 return false;
3433                         }
3434                         g->done_pass2 = true;
3435                         break;
3436
3437                 case MOD_XLAT:   /* @todo: pre-parse xlat's */
3438                 case MOD_REFERENCE:
3439                 case MOD_BREAK:
3440                 case MOD_RETURN:
3441 #endif
3442
3443                 case MOD_SINGLE:
3444                         c->debug_name = c->name;
3445                         break;  /* do nothing */
3446
3447 #ifdef WITH_UNLANG
3448                 case MOD_IF:
3449                 case MOD_ELSIF:
3450                         g = mod_callabletogroup(c);
3451                         if (g->done_pass2) return true;
3452
3453                         name2 = cf_section_name2(g->cs);
3454                         c->debug_name = talloc_asprintf(c, "%s %s", group_name[c->type], name2);
3455
3456                         /*
3457                          *      Don't walk over these.
3458                          */
3459                         if ((g->cond->type == COND_TYPE_TRUE) ||
3460                             (g->cond->type == COND_TYPE_FALSE)) {
3461                                 break;
3462                         }
3463
3464                         /*
3465                          *      The compilation code takes care of
3466                          *      simplifying 'true' and 'false'
3467                          *      conditions.  For others, we have to do
3468                          *      a second pass to parse && compile xlats.
3469                          */
3470                         if (!fr_condition_walk(g->cond, pass2_callback, NULL)) {
3471                                 return false;
3472                         }
3473
3474                         if (!modcall_pass2(g->children)) return false;
3475                         g->done_pass2 = true;
3476                         break;
3477 #endif
3478
3479 #ifdef WITH_UNLANG
3480                 case MOD_SWITCH:
3481                         g = mod_callabletogroup(c);
3482                         if (g->done_pass2) return true;
3483
3484                         name2 = cf_section_name2(g->cs);
3485                         c->debug_name = talloc_asprintf(c, "%s %s", group_name[c->type], name2);
3486
3487                         /*
3488                          *      We had &Foo-Bar, where Foo-Bar is
3489                          *      defined by a module.
3490                          */
3491                         if (!g->vpt) {
3492                                 rad_assert(c->name != NULL);
3493                                 rad_assert(c->name[0] == '&');
3494                                 rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3495
3496                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3497                                                       cf_section_name2_type(g->cs),
3498                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST);
3499                                 if (slen < 0) {
3500                                         char *spaces, *text;
3501
3502                                 parse_error:
3503                                         fr_canonicalize_error(g->cs, &spaces, &text, slen, fr_strerror());
3504
3505                                         cf_log_err_cs(g->cs, "Syntax error");
3506                                         cf_log_err_cs(g->cs, "%s", c->name);
3507                                         cf_log_err_cs(g->cs, "%s^ %s", spaces, text);
3508
3509                                         talloc_free(spaces);
3510                                         talloc_free(text);
3511
3512                                         return false;
3513                                 }
3514
3515                                 goto do_children;
3516                         }
3517
3518                         /*
3519                          *      Statically compile xlats
3520                          */
3521                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3522                                 if (!pass2_xlat_compile(cf_sectiontoitem(g->cs),
3523                                                         &g->vpt, true, NULL)) {
3524                                         return false;
3525                                 }
3526
3527                                 goto do_children;
3528                         }
3529
3530                         /*
3531                          *      We may have: switch Foo-Bar {
3532                          *
3533                          *      where Foo-Bar is an attribute defined
3534                          *      by a module.  Since there's no leading
3535                          *      &, it's parsed as a literal.  But if
3536                          *      we can parse it as an attribute,
3537                          *      switch to using that.
3538                          */
3539                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3540                                 value_pair_tmpl_t *vpt;
3541
3542                                 slen = tmpl_afrom_str(g->cs, &vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3543                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST);
3544                                 if (slen < 0) goto parse_error;
3545                                 if (vpt->type == TMPL_TYPE_ATTR) {
3546                                         talloc_free(g->vpt);
3547                                         g->vpt = vpt;
3548                                 }
3549
3550                                 goto do_children;
3551                         }
3552
3553                         /*
3554                          *      Warn about old-style configuration.
3555                          *
3556                          *      DEPRECATED: switch User-Name { ...
3557                          *      ALLOWED   : switch &User-Name { ...
3558                          */
3559                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
3560                             (c->name[0] != '&')) {
3561                                 WARN("%s[%d]: Please change %s to &%s",
3562                                        cf_section_filename(g->cs),
3563                                        cf_section_lineno(g->cs),
3564                                        c->name, c->name);
3565                         }
3566
3567                 do_children:
3568                         if (!modcall_pass2(g->children)) return false;
3569                         g->done_pass2 = true;
3570                         break;
3571
3572                 case MOD_CASE:
3573                         g = mod_callabletogroup(c);
3574                         if (g->done_pass2) return true;
3575
3576                         name2 = cf_section_name2(g->cs);
3577                         if (!name2) {
3578                                 c->debug_name = group_name[c->type];
3579                         } else {
3580                                 c->debug_name = talloc_asprintf(c, "%s %s", group_name[c->type], name2);
3581                         }
3582
3583                         rad_assert(c->parent != NULL);
3584                         rad_assert(c->parent->type == MOD_SWITCH);
3585
3586                         /*
3587                          *      The statement may refer to an
3588                          *      attribute which doesn't exist until
3589                          *      all of the modules have been loaded.
3590                          *      Check for that now.
3591                          */
3592                         if (!g->vpt && c->name &&
3593                             (c->name[0] == '&') &&
3594                             (cf_section_name2_type(g->cs) == T_BARE_WORD)) {
3595                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3596                                                       cf_section_name2_type(g->cs),
3597                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST);
3598                                 if (slen < 0) goto parse_error;
3599                         }
3600
3601                         /*
3602                          *      We have "case {...}".  There's no
3603                          *      argument, so we don't need to check
3604                          *      it.
3605                          */
3606                         if (!g->vpt) goto do_children;
3607
3608                         /*
3609                          *      Do type-specific checks on the case statement
3610                          */
3611                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3612                                 modgroup *f;
3613
3614                                 f = mod_callabletogroup(mc->parent);
3615                                 rad_assert(f->vpt != NULL);
3616
3617                                 /*
3618                                  *      We're switching over an
3619                                  *      attribute.  Check that the
3620                                  *      values match.
3621                                  */
3622                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3623                                         rad_assert(f->vpt->tmpl_da != NULL);
3624
3625                                         if (!tmpl_cast_in_place(g->vpt, f->vpt->tmpl_da->type, f->vpt->tmpl_da)) {
3626                                                 cf_log_err_cs(g->cs, "Invalid argument for case statement: %s",
3627                                                               fr_strerror());
3628                                                 return false;
3629                                         }
3630                                 }
3631
3632                                 goto do_children;
3633                         }
3634
3635                         /*
3636                          *      Compile and sanity check xlat
3637                          *      expansions.
3638                          */
3639                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3640                                 modgroup *f;
3641
3642                                 f = mod_callabletogroup(mc->parent);
3643                                 rad_assert(f->vpt != NULL);
3644
3645                                 /*
3646                                  *      Don't expand xlat's into an
3647                                  *      attribute of a different type.
3648                                  */
3649                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3650                                         if (!pass2_xlat_compile(cf_sectiontoitem(g->cs),
3651                                                                 &g->vpt, true, f->vpt->tmpl_da)) {
3652                                                 return false;
3653                                         }
3654                                 } else {
3655                                         if (!pass2_xlat_compile(cf_sectiontoitem(g->cs),
3656                                                                 &g->vpt, true, NULL)) {
3657                                                 return false;
3658                                         }
3659                                 }
3660                         }
3661
3662                         if (!modcall_pass2(g->children)) return false;
3663                         g->done_pass2 = true;
3664                         break;
3665
3666                 case MOD_FOREACH:
3667                         g = mod_callabletogroup(c);
3668                         if (g->done_pass2) return true;
3669
3670                         name2 = cf_section_name2(g->cs);
3671                         c->debug_name = talloc_asprintf(c, "%s %s", group_name[c->type], name2);
3672
3673                         /*
3674                          *      Already parsed, handle the children.
3675                          */
3676                         if (g->vpt) goto check_children;
3677
3678                         /*
3679                          *      We had &Foo-Bar, where Foo-Bar is
3680                          *      defined by a module.
3681                          */
3682                         rad_assert(c->name != NULL);
3683                         rad_assert(c->name[0] == '&');
3684                         rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3685
3686                         /*
3687                          *      The statement may refer to an
3688                          *      attribute which doesn't exist until
3689                          *      all of the modules have been loaded.
3690                          *      Check for that now.
3691                          */
3692                         slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3693                                               REQUEST_CURRENT, PAIR_LIST_REQUEST);
3694                         if (slen < 0) goto parse_error;
3695
3696                 check_children:
3697                         rad_assert(g->vpt->type == TMPL_TYPE_ATTR);
3698                         if (g->vpt->tmpl_num != NUM_ALL) {
3699                                 cf_log_err_cs(g->cs, "MUST NOT use instance selectors in 'foreach'");
3700                                 return false;
3701                         }
3702                         if (!modcall_pass2(g->children)) return false;
3703                         g->done_pass2 = true;
3704                         break;
3705
3706                 case MOD_ELSE:
3707                         c->debug_name = group_name[c->type];
3708                         goto do_recurse;
3709
3710                 case MOD_POLICY:
3711                         g = mod_callabletogroup(c);
3712                         c->debug_name = talloc_asprintf(c, "%s %s", group_name[c->type], cf_section_name1(g->cs));
3713                         goto do_recurse;
3714 #endif
3715
3716                 case MOD_GROUP:
3717                 case MOD_LOAD_BALANCE:
3718                 case MOD_REDUNDANT_LOAD_BALANCE:
3719                         c->debug_name = group_name[c->type];
3720
3721 #ifdef WITH_UNLANG
3722                 do_recurse:
3723 #endif
3724                         g = mod_callabletogroup(c);
3725                         if (!g->cs) {
3726                                 c->debug_name = mc->name; /* for authorize, etc. */
3727
3728                         } else if (c->type == MOD_GROUP) { /* for Auth-Type, etc. */
3729                                 char const *name1 = cf_section_name1(g->cs);
3730
3731                                 if (strcmp(name1, group_name[c->type]) != 0) {
3732                                         c->debug_name = talloc_asprintf(c, "%s %s", name1, cf_section_name2(g->cs));
3733                                 }
3734                         }
3735
3736                         if (g->done_pass2) return true;
3737                         if (!modcall_pass2(g->children)) return false;
3738                         g->done_pass2 = true;
3739                         break;
3740                 }
3741         }
3742
3743         return true;
3744 }
3745
3746 void modcall_debug(modcallable *mc, int depth)
3747 {
3748         modcallable *this;
3749         modgroup *g;
3750         value_pair_map_t *map;
3751         char buffer[1024];
3752
3753         for (this = mc; this != NULL; this = this->next) {
3754                 switch (this->type) {
3755                 default:
3756                         break;
3757
3758                 case MOD_SINGLE: {
3759                         modsingle *single = mod_callabletosingle(this);
3760
3761                         DEBUG("%.*s%s", depth, modcall_spaces,
3762                                 single->modinst->name);
3763                         }
3764                         break;
3765
3766 #ifdef WITH_UNLANG
3767                 case MOD_UPDATE:
3768                         g = mod_callabletogroup(this);
3769                         DEBUG("%.*s%s {", depth, modcall_spaces,
3770                                 group_name[this->type]);
3771
3772                         for (map = g->map; map != NULL; map = map->next) {
3773                                 map_prints(buffer, sizeof(buffer), map);
3774                                 DEBUG("%.*s%s", depth + 1, modcall_spaces, buffer);
3775                         }
3776
3777                         DEBUG("%.*s}", depth, modcall_spaces);
3778                         break;
3779
3780                 case MOD_ELSE:
3781                         g = mod_callabletogroup(this);
3782                         DEBUG("%.*s%s {", depth, modcall_spaces,
3783                                 group_name[this->type]);
3784                         modcall_debug(g->children, depth + 1);
3785                         DEBUG("%.*s}", depth, modcall_spaces);
3786                         break;
3787
3788                 case MOD_IF:
3789                 case MOD_ELSIF:
3790                         g = mod_callabletogroup(this);
3791                         fr_cond_sprint(buffer, sizeof(buffer), g->cond);
3792                         DEBUG("%.*s%s (%s) {", depth, modcall_spaces,
3793                                 group_name[this->type], buffer);
3794                         modcall_debug(g->children, depth + 1);
3795                         DEBUG("%.*s}", depth, modcall_spaces);
3796                         break;
3797
3798                 case MOD_SWITCH:
3799                 case MOD_CASE:
3800                         g = mod_callabletogroup(this);
3801                         tmpl_prints(buffer, sizeof(buffer), g->vpt, NULL);
3802                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3803                                 group_name[this->type], buffer);
3804                         modcall_debug(g->children, depth + 1);
3805                         DEBUG("%.*s}", depth, modcall_spaces);
3806                         break;
3807
3808                 case MOD_POLICY:
3809                 case MOD_FOREACH:
3810                         g = mod_callabletogroup(this);
3811                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3812                                 group_name[this->type], this->name);
3813                         modcall_debug(g->children, depth + 1);
3814                         DEBUG("%.*s}", depth, modcall_spaces);
3815                         break;
3816
3817                 case MOD_BREAK:
3818                         DEBUG("%.*sbreak", depth, modcall_spaces);
3819                         break;
3820
3821 #endif
3822                 case MOD_GROUP:
3823                         g = mod_callabletogroup(this);
3824                         DEBUG("%.*s%s {", depth, modcall_spaces,
3825                               group_name[this->type]);
3826                         modcall_debug(g->children, depth + 1);
3827                         DEBUG("%.*s}", depth, modcall_spaces);
3828                         break;
3829
3830
3831                 case MOD_LOAD_BALANCE:
3832                 case MOD_REDUNDANT_LOAD_BALANCE:
3833                         g = mod_callabletogroup(this);
3834                         DEBUG("%.*s%s {", depth, modcall_spaces,
3835                                 group_name[this->type]);
3836                         modcall_debug(g->children, depth + 1);
3837                         DEBUG("%.*s}", depth, modcall_spaces);
3838                         break;
3839                 }
3840         }
3841 }