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