Don't go to next sibling on empty case. Fixes #1274
[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                         if (c->type == MOD_CASE) {
776                                 result = RLM_MODULE_NOOP;
777                                 goto calculate_result;
778                         }
779
780                         RDEBUG2("%s { ... } # empty sub-section is ignored", c->name);
781                         goto next_sibling;
782                 }
783
784                 MOD_LOG_OPEN_BRACE;
785                 modcall_child(request, component,
786                               depth + 1, entry, g->children,
787                               &result, true);
788                 MOD_LOG_CLOSE_BRACE;
789                 goto calculate_result;
790         } /* MOD_GROUP */
791
792 #ifdef WITH_UNLANG
793         if (c->type == MOD_SWITCH) {
794                 modcallable *this, *found, *null_case;
795                 modgroup *g, *h;
796                 fr_cond_t cond;
797                 value_data_t data;
798                 vp_map_t map;
799                 vp_tmpl_t vpt;
800
801                 MOD_LOG_OPEN_BRACE;
802
803                 g = mod_callabletogroup(c);
804
805                 memset(&cond, 0, sizeof(cond));
806                 memset(&map, 0, sizeof(map));
807
808                 cond.type = COND_TYPE_MAP;
809                 cond.data.map = &map;
810
811                 map.op = T_OP_CMP_EQ;
812                 map.ci = cf_section_to_item(g->cs);
813
814                 rad_assert(g->vpt != NULL);
815
816                 null_case = found = NULL;
817                 data.ptr = NULL;
818
819                 /*
820                  *      The attribute doesn't exist.  We can skip
821                  *      directly to the default 'case' statement.
822                  */
823                 if ((g->vpt->type == TMPL_TYPE_ATTR) && (tmpl_find_vp(NULL, request, g->vpt) < 0)) {
824                 find_null_case:
825                         for (this = g->children; this; this = this->next) {
826                                 rad_assert(this->type == MOD_CASE);
827
828                                 h = mod_callabletogroup(this);
829                                 if (h->vpt) continue;
830
831                                 found = this;
832                                 break;
833                         }
834
835                         goto do_null_case;
836                 }
837
838                 /*
839                  *      Expand the template if necessary, so that it
840                  *      is evaluated once instead of for each 'case'
841                  *      statement.
842                  */
843                 if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
844                     (g->vpt->type == TMPL_TYPE_XLAT) ||
845                     (g->vpt->type == TMPL_TYPE_EXEC)) {
846                         char *p;
847                         ssize_t len;
848
849                         len = tmpl_aexpand(request, &p, request, g->vpt, NULL, NULL);
850                         if (len < 0) goto find_null_case;
851                         data.strvalue = p;
852                         tmpl_init(&vpt, TMPL_TYPE_LITERAL, data.strvalue, len);
853                 }
854
855                 /*
856                  *      Find either the exact matching name, or the
857                  *      "case {...}" statement.
858                  */
859                 for (this = g->children; this; this = this->next) {
860                         rad_assert(this->type == MOD_CASE);
861
862                         h = mod_callabletogroup(this);
863
864                         /*
865                          *      Remember the default case
866                          */
867                         if (!h->vpt) {
868                                 if (!null_case) null_case = this;
869                                 continue;
870                         }
871
872                         /*
873                          *      If we're switching over an attribute
874                          *      AND we haven't pre-parsed the data for
875                          *      the case statement, then cast the data
876                          *      to the type of the attribute.
877                          */
878                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
879                             (h->vpt->type != TMPL_TYPE_DATA)) {
880                                 map.rhs = g->vpt;
881                                 map.lhs = h->vpt;
882                                 cond.cast = g->vpt->tmpl_da;
883
884                                 /*
885                                  *      Remove unnecessary casting.
886                                  */
887                                 if ((h->vpt->type == TMPL_TYPE_ATTR) &&
888                                     (g->vpt->tmpl_da->type == h->vpt->tmpl_da->type)) {
889                                         cond.cast = NULL;
890                                 }
891
892                                 /*
893                                  *      Use the pre-expanded string.
894                                  */
895                         } else if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
896                                    (g->vpt->type == TMPL_TYPE_XLAT) ||
897                                    (g->vpt->type == TMPL_TYPE_EXEC)) {
898                                 map.rhs = h->vpt;
899                                 map.lhs = &vpt;
900                                 cond.cast = NULL;
901
902                                 /*
903                                  *      Else evaluate the 'switch' statement.
904                                  */
905                         } else {
906                                 map.rhs = h->vpt;
907                                 map.lhs = g->vpt;
908                                 cond.cast = NULL;
909                         }
910
911                         if (radius_evaluate_map(request, RLM_MODULE_UNKNOWN, 0,
912                                                 &cond) == 1) {
913                                 found = this;
914                                 break;
915                         }
916                 }
917
918                 if (!found) found = null_case;
919
920         do_null_case:
921                 talloc_free(data.ptr);
922                 modcall_child(request, component, depth + 1, entry, found, &result, true);
923                 MOD_LOG_CLOSE_BRACE;
924                 goto calculate_result;
925         } /* MOD_SWITCH */
926 #endif
927
928         if ((c->type == MOD_LOAD_BALANCE) ||
929             (c->type == MOD_REDUNDANT_LOAD_BALANCE)) {
930                 uint32_t count = 0;
931                 modcallable *this, *found;
932                 modgroup *g;
933
934                 MOD_LOG_OPEN_BRACE;
935
936                 g = mod_callabletogroup(c);
937                 found = g->children;
938                 rad_assert(g->children != NULL);
939
940                 /*
941                  *      Choose a child at random.
942                  */
943                 for (this = g->children; this; this = this->next) {
944                         count++;
945
946                         if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
947                                 found = this;
948                         }
949                 }
950
951                 if (c->type == MOD_LOAD_BALANCE) {
952                         modcall_child(request, component,
953                                       depth + 1, entry, found,
954                                       &result, false);
955
956                 } else {
957                         this = found;
958
959                         do {
960                                 modcall_child(request, component,
961                                               depth + 1, entry, this,
962                                               &result, false);
963                                 if (this->actions[result] == MOD_ACTION_RETURN) {
964                                         priority = -1;
965                                         break;
966                                 }
967
968                                 this = this->next;
969                                 if (!this) this = g->children;
970                         } while (this != found);
971                 }
972                 MOD_LOG_CLOSE_BRACE;
973                 goto calculate_result;
974         } /* MOD_LOAD_BALANCE */
975
976         /*
977          *      Reference another virtual server.
978          *
979          *      This should really be deleted, and replaced with a
980          *      more abstracted / functional version.
981          */
982         if (c->type == MOD_REFERENCE) {
983                 modref *mr = mod_callabletoref(c);
984                 char const *server = request->server;
985
986                 if (server == mr->ref_name) {
987                         RWDEBUG("Suppressing recursive call to server %s", server);
988                         goto next_sibling;
989                 }
990
991                 request->server = mr->ref_name;
992                 RDEBUG("server %s { # nested call", mr->ref_name);
993                 result = indexed_modcall(component, 0, request);
994                 RDEBUG("} # server %s with nested call", mr->ref_name);
995                 request->server = server;
996                 goto calculate_result;
997         } /* MOD_REFERENCE */
998
999         /*
1000          *      xlat a string without doing anything else
1001          *
1002          *      This should really be deleted, and replaced with a
1003          *      more abstracted / functional version.
1004          */
1005         if (c->type == MOD_XLAT) {
1006                 modxlat *mx = mod_callabletoxlat(c);
1007                 char buffer[128];
1008
1009                 if (!mx->exec) {
1010                         radius_xlat(buffer, sizeof(buffer), request, mx->xlat_name, NULL, NULL);
1011                 } else {
1012                         RDEBUG("`%s`", mx->xlat_name);
1013                         radius_exec_program(request, NULL, 0, NULL, request, mx->xlat_name, request->packet->vps,
1014                                             false, true, EXEC_TIMEOUT);
1015                 }
1016
1017                 goto next_sibling;
1018         } /* MOD_XLAT */
1019
1020         /*
1021          *      Add new module types here.
1022          */
1023
1024 calculate_result:
1025 #if 0
1026         RDEBUG("(%s, %d) ? (%s, %d)",
1027                fr_int2str(mod_rcode_table, result, "<invalid>"),
1028                priority,
1029                fr_int2str(mod_rcode_table, entry->result, "<invalid>"),
1030                entry->priority);
1031 #endif
1032
1033
1034         rad_assert(result != RLM_MODULE_UNKNOWN);
1035
1036         /*
1037          *      The child's action says return.  Do so.
1038          */
1039         if ((c->actions[result] == MOD_ACTION_RETURN) &&
1040             (priority <= 0)) {
1041                 entry->result = result;
1042                 goto finish;
1043         }
1044
1045         /*
1046          *      If "reject", break out of the loop and return
1047          *      reject.
1048          */
1049         if (c->actions[result] == MOD_ACTION_REJECT) {
1050                 entry->result = RLM_MODULE_REJECT;
1051                 goto finish;
1052         }
1053
1054         /*
1055          *      The array holds a default priority for this return
1056          *      code.  Grab it in preference to any unset priority.
1057          */
1058         if (priority < 0) {
1059                 priority = c->actions[result];
1060         }
1061
1062         /*
1063          *      We're higher than any previous priority, remember this
1064          *      return code and priority.
1065          */
1066         if (priority > entry->priority) {
1067                 entry->result = result;
1068                 entry->priority = priority;
1069         }
1070
1071 #ifdef WITH_UNLANG
1072         /*
1073          *      If we're processing a "case" statement, we return once
1074          *      it's done, rather than going to the next "case" statement.
1075          */
1076         if (c->type == MOD_CASE) goto finish;
1077 #endif
1078
1079         /*
1080          *      If we've been told to stop processing
1081          *      it, do so.
1082          */
1083         if (entry->unwind == MOD_BREAK) {
1084                 RDEBUG2("# unwind to enclosing foreach");
1085                 goto finish;
1086         }
1087
1088         if (entry->unwind == MOD_RETURN) {
1089                 goto finish;
1090         }
1091
1092 next_sibling:
1093         if (do_next_sibling) {
1094                 entry->c = entry->c->next;
1095
1096                 if (entry->c) goto redo;
1097         }
1098
1099 finish:
1100         /*
1101          *      And we're done!
1102          */
1103         REXDENT();
1104         return true;
1105 }
1106
1107
1108 /** Call a module, iteratively, with a local stack, rather than recursively
1109  *
1110  * What did Paul Graham say about Lisp...?
1111  */
1112 int modcall(rlm_components_t component, modcallable *c, REQUEST *request)
1113 {
1114         modcall_stack_entry_t stack[MODCALL_STACK_MAX];
1115
1116 #ifndef NDEBUG
1117         memset(stack, 0, sizeof(stack));
1118 #endif
1119         /*
1120          *      Set up the initial stack frame.
1121          */
1122         stack[0].c = c;
1123         stack[0].result = default_component_results[component];
1124         stack[0].priority = 0;
1125         stack[0].unwind = 0;
1126
1127         /*
1128          *      Call the main handler.
1129          */
1130         if (!modcall_recurse(request, component, 0, &stack[0], true)) {
1131                 return RLM_MODULE_FAIL;
1132         }
1133
1134         /*
1135          *      Return the result.
1136          */
1137         return stack[0].result;
1138 }
1139
1140
1141 #if 0
1142 static char const *action2str(int action)
1143 {
1144         static char buf[32];
1145         if(action==MOD_ACTION_RETURN)
1146                 return "return";
1147         if(action==MOD_ACTION_REJECT)
1148                 return "reject";
1149         snprintf(buf, sizeof buf, "%d", action);
1150         return buf;
1151 }
1152
1153 /* If you suspect a bug in the parser, you'll want to use these dump
1154  * functions. dump_tree should reproduce a whole tree exactly as it was found
1155  * in radiusd.conf, but in long form (all actions explicitly defined) */
1156 static void dump_mc(modcallable *c, int indent)
1157 {
1158         int i;
1159
1160         if(c->type==MOD_SINGLE) {
1161                 modsingle *single = mod_callabletosingle(c);
1162                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1163                         single->modinst->name);
1164         } else if ((c->type > MOD_SINGLE) && (c->type <= MOD_POLICY)) {
1165                 modgroup *g = mod_callabletogroup(c);
1166                 modcallable *p;
1167                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1168                       unlang_keyword[c->type]);
1169                 for(p = g->children;p;p = p->next)
1170                         dump_mc(p, indent+1);
1171         } /* else ignore it for now */
1172
1173         for(i = 0; i<RLM_MODULE_NUMCODES; ++i) {
1174                 DEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t",
1175                       fr_int2str(mod_rcode_table, i, "<invalid>"),
1176                       action2str(c->actions[i]));
1177         }
1178
1179         DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");
1180 }
1181
1182 static void dump_tree(rlm_components_t comp, modcallable *c)
1183 {
1184         DEBUG("[%s]", comp2str[comp]);
1185         dump_mc(c, 0);
1186 }
1187 #else
1188 #define dump_tree(a, b)
1189 #endif
1190
1191 /* These are the default actions. For each component, the group{} block
1192  * behaves like the code from the old module_*() function. redundant{}
1193  * are based on my guesses of what they will be used for. --Pac. */
1194 static const int
1195 defaultactions[MOD_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
1196 {
1197         /* authenticate */
1198         {
1199                 /* group */
1200                 {
1201                         MOD_ACTION_RETURN,      /* reject   */
1202                         1,                      /* fail     */
1203                         MOD_ACTION_RETURN,      /* ok       */
1204                         MOD_ACTION_RETURN,      /* handled  */
1205                         1,                      /* invalid  */
1206                         MOD_ACTION_RETURN,      /* userlock */
1207                         MOD_ACTION_RETURN,      /* notfound */
1208                         1,                      /* noop     */
1209                         1                       /* updated  */
1210                 },
1211                 /* redundant */
1212                 {
1213                         MOD_ACTION_RETURN,      /* reject   */
1214                         1,                      /* fail     */
1215                         MOD_ACTION_RETURN,      /* ok       */
1216                         MOD_ACTION_RETURN,      /* handled  */
1217                         MOD_ACTION_RETURN,      /* invalid  */
1218                         MOD_ACTION_RETURN,      /* userlock */
1219                         MOD_ACTION_RETURN,      /* notfound */
1220                         MOD_ACTION_RETURN,      /* noop     */
1221                         MOD_ACTION_RETURN       /* updated  */
1222                 }
1223         },
1224         /* authorize */
1225         {
1226                 /* group */
1227                 {
1228                         MOD_ACTION_RETURN,      /* reject   */
1229                         MOD_ACTION_RETURN,      /* fail     */
1230                         3,                      /* ok       */
1231                         MOD_ACTION_RETURN,      /* handled  */
1232                         MOD_ACTION_RETURN,      /* invalid  */
1233                         MOD_ACTION_RETURN,      /* userlock */
1234                         1,                      /* notfound */
1235                         2,                      /* noop     */
1236                         4                       /* updated  */
1237                 },
1238                 /* redundant */
1239                 {
1240                         MOD_ACTION_RETURN,      /* reject   */
1241                         1,                      /* fail     */
1242                         MOD_ACTION_RETURN,      /* ok       */
1243                         MOD_ACTION_RETURN,      /* handled  */
1244                         MOD_ACTION_RETURN,      /* invalid  */
1245                         MOD_ACTION_RETURN,      /* userlock */
1246                         MOD_ACTION_RETURN,      /* notfound */
1247                         MOD_ACTION_RETURN,      /* noop     */
1248                         MOD_ACTION_RETURN       /* updated  */
1249                 }
1250         },
1251         /* preacct */
1252         {
1253                 /* group */
1254                 {
1255                         MOD_ACTION_RETURN,      /* reject   */
1256                         MOD_ACTION_RETURN,      /* fail     */
1257                         2,                      /* ok       */
1258                         MOD_ACTION_RETURN,      /* handled  */
1259                         MOD_ACTION_RETURN,      /* invalid  */
1260                         MOD_ACTION_RETURN,      /* userlock */
1261                         MOD_ACTION_RETURN,      /* notfound */
1262                         1,                      /* noop     */
1263                         3                       /* updated  */
1264                 },
1265                 /* redundant */
1266                 {
1267                         MOD_ACTION_RETURN,      /* reject   */
1268                         1,                      /* fail     */
1269                         MOD_ACTION_RETURN,      /* ok       */
1270                         MOD_ACTION_RETURN,      /* handled  */
1271                         MOD_ACTION_RETURN,      /* invalid  */
1272                         MOD_ACTION_RETURN,      /* userlock */
1273                         MOD_ACTION_RETURN,      /* notfound */
1274                         MOD_ACTION_RETURN,      /* noop     */
1275                         MOD_ACTION_RETURN       /* updated  */
1276                 }
1277         },
1278         /* accounting */
1279         {
1280                 /* group */
1281                 {
1282                         MOD_ACTION_RETURN,      /* reject   */
1283                         MOD_ACTION_RETURN,      /* fail     */
1284                         2,                      /* ok       */
1285                         MOD_ACTION_RETURN,      /* handled  */
1286                         MOD_ACTION_RETURN,      /* invalid  */
1287                         MOD_ACTION_RETURN,      /* userlock */
1288                         MOD_ACTION_RETURN,      /* notfound */
1289                         1,                      /* noop     */
1290                         3                       /* updated  */
1291                 },
1292                 /* redundant */
1293                 {
1294                         1,                      /* reject   */
1295                         1,                      /* fail     */
1296                         MOD_ACTION_RETURN,      /* ok       */
1297                         MOD_ACTION_RETURN,      /* handled  */
1298                         1,                      /* invalid  */
1299                         1,                      /* userlock */
1300                         1,                      /* notfound */
1301                         2,                      /* noop     */
1302                         4                       /* updated  */
1303                 }
1304         },
1305         /* checksimul */
1306         {
1307                 /* group */
1308                 {
1309                         MOD_ACTION_RETURN,      /* reject   */
1310                         1,                      /* fail     */
1311                         MOD_ACTION_RETURN,      /* ok       */
1312                         MOD_ACTION_RETURN,      /* handled  */
1313                         MOD_ACTION_RETURN,      /* invalid  */
1314                         MOD_ACTION_RETURN,      /* userlock */
1315                         MOD_ACTION_RETURN,      /* notfound */
1316                         MOD_ACTION_RETURN,      /* noop     */
1317                         MOD_ACTION_RETURN       /* updated  */
1318                 },
1319                 /* redundant */
1320                 {
1321                         MOD_ACTION_RETURN,      /* reject   */
1322                         1,                      /* fail     */
1323                         MOD_ACTION_RETURN,      /* ok       */
1324                         MOD_ACTION_RETURN,      /* handled  */
1325                         MOD_ACTION_RETURN,      /* invalid  */
1326                         MOD_ACTION_RETURN,      /* userlock */
1327                         MOD_ACTION_RETURN,      /* notfound */
1328                         MOD_ACTION_RETURN,      /* noop     */
1329                         MOD_ACTION_RETURN       /* updated  */
1330                 }
1331         },
1332         /* pre-proxy */
1333         {
1334                 /* group */
1335                 {
1336                         MOD_ACTION_RETURN,      /* reject   */
1337                         MOD_ACTION_RETURN,      /* fail     */
1338                         3,                      /* ok       */
1339                         MOD_ACTION_RETURN,      /* handled  */
1340                         MOD_ACTION_RETURN,      /* invalid  */
1341                         MOD_ACTION_RETURN,      /* userlock */
1342                         1,                      /* notfound */
1343                         2,                      /* noop     */
1344                         4                       /* updated  */
1345                 },
1346                 /* redundant */
1347                 {
1348                         MOD_ACTION_RETURN,      /* reject   */
1349                         1,                      /* fail     */
1350                         MOD_ACTION_RETURN,      /* ok       */
1351                         MOD_ACTION_RETURN,      /* handled  */
1352                         MOD_ACTION_RETURN,      /* invalid  */
1353                         MOD_ACTION_RETURN,      /* userlock */
1354                         MOD_ACTION_RETURN,      /* notfound */
1355                         MOD_ACTION_RETURN,      /* noop     */
1356                         MOD_ACTION_RETURN       /* updated  */
1357                 }
1358         },
1359         /* post-proxy */
1360         {
1361                 /* group */
1362                 {
1363                         MOD_ACTION_RETURN,      /* reject   */
1364                         MOD_ACTION_RETURN,      /* fail     */
1365                         3,                      /* ok       */
1366                         MOD_ACTION_RETURN,      /* handled  */
1367                         MOD_ACTION_RETURN,      /* invalid  */
1368                         MOD_ACTION_RETURN,      /* userlock */
1369                         1,                      /* notfound */
1370                         2,                      /* noop     */
1371                         4                       /* updated  */
1372                 },
1373                 /* redundant */
1374                 {
1375                         MOD_ACTION_RETURN,      /* reject   */
1376                         1,                      /* fail     */
1377                         MOD_ACTION_RETURN,      /* ok       */
1378                         MOD_ACTION_RETURN,      /* handled  */
1379                         MOD_ACTION_RETURN,      /* invalid  */
1380                         MOD_ACTION_RETURN,      /* userlock */
1381                         MOD_ACTION_RETURN,      /* notfound */
1382                         MOD_ACTION_RETURN,      /* noop     */
1383                         MOD_ACTION_RETURN       /* updated  */
1384                 }
1385         },
1386         /* post-auth */
1387         {
1388                 /* group */
1389                 {
1390                         MOD_ACTION_RETURN,      /* reject   */
1391                         MOD_ACTION_RETURN,      /* fail     */
1392                         3,                      /* ok       */
1393                         MOD_ACTION_RETURN,      /* handled  */
1394                         MOD_ACTION_RETURN,      /* invalid  */
1395                         MOD_ACTION_RETURN,      /* userlock */
1396                         1,                      /* notfound */
1397                         2,                      /* noop     */
1398                         4                       /* updated  */
1399                 },
1400                 /* redundant */
1401                 {
1402                         MOD_ACTION_RETURN,      /* reject   */
1403                         1,                      /* fail     */
1404                         MOD_ACTION_RETURN,      /* ok       */
1405                         MOD_ACTION_RETURN,      /* handled  */
1406                         MOD_ACTION_RETURN,      /* invalid  */
1407                         MOD_ACTION_RETURN,      /* userlock */
1408                         MOD_ACTION_RETURN,      /* notfound */
1409                         MOD_ACTION_RETURN,      /* noop     */
1410                         MOD_ACTION_RETURN       /* updated  */
1411                 }
1412         }
1413 #ifdef WITH_COA
1414         ,
1415         /* recv-coa */
1416         {
1417                 /* group */
1418                 {
1419                         MOD_ACTION_RETURN,      /* reject   */
1420                         MOD_ACTION_RETURN,      /* fail     */
1421                         3,                      /* ok       */
1422                         MOD_ACTION_RETURN,      /* handled  */
1423                         MOD_ACTION_RETURN,      /* invalid  */
1424                         MOD_ACTION_RETURN,      /* userlock */
1425                         1,                      /* notfound */
1426                         2,                      /* noop     */
1427                         4                       /* updated  */
1428                 },
1429                 /* redundant */
1430                 {
1431                         MOD_ACTION_RETURN,      /* reject   */
1432                         1,                      /* fail     */
1433                         MOD_ACTION_RETURN,      /* ok       */
1434                         MOD_ACTION_RETURN,      /* handled  */
1435                         MOD_ACTION_RETURN,      /* invalid  */
1436                         MOD_ACTION_RETURN,      /* userlock */
1437                         MOD_ACTION_RETURN,      /* notfound */
1438                         MOD_ACTION_RETURN,      /* noop     */
1439                         MOD_ACTION_RETURN       /* updated  */
1440                 }
1441         },
1442         /* send-coa */
1443         {
1444                 /* group */
1445                 {
1446                         MOD_ACTION_RETURN,      /* reject   */
1447                         MOD_ACTION_RETURN,      /* fail     */
1448                         3,                      /* ok       */
1449                         MOD_ACTION_RETURN,      /* handled  */
1450                         MOD_ACTION_RETURN,      /* invalid  */
1451                         MOD_ACTION_RETURN,      /* userlock */
1452                         1,                      /* notfound */
1453                         2,                      /* noop     */
1454                         4                       /* updated  */
1455                 },
1456                 /* redundant */
1457                 {
1458                         MOD_ACTION_RETURN,      /* reject   */
1459                         1,                      /* fail     */
1460                         MOD_ACTION_RETURN,      /* ok       */
1461                         MOD_ACTION_RETURN,      /* handled  */
1462                         MOD_ACTION_RETURN,      /* invalid  */
1463                         MOD_ACTION_RETURN,      /* userlock */
1464                         MOD_ACTION_RETURN,      /* notfound */
1465                         MOD_ACTION_RETURN,      /* noop     */
1466                         MOD_ACTION_RETURN       /* updated  */
1467                 }
1468         }
1469 #endif
1470 };
1471
1472 static const int authtype_actions[GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
1473 {
1474         /* group */
1475         {
1476                 MOD_ACTION_RETURN,      /* reject   */
1477                 MOD_ACTION_RETURN,      /* fail     */
1478                 4,                      /* ok       */
1479                 MOD_ACTION_RETURN,      /* handled  */
1480                 MOD_ACTION_RETURN,      /* invalid  */
1481                 MOD_ACTION_RETURN,      /* userlock */
1482                 1,                      /* notfound */
1483                 2,                      /* noop     */
1484                 3                       /* updated  */
1485         },
1486         /* redundant */
1487         {
1488                 MOD_ACTION_RETURN,      /* reject   */
1489                 1,                      /* fail     */
1490                 MOD_ACTION_RETURN,      /* ok       */
1491                 MOD_ACTION_RETURN,      /* handled  */
1492                 MOD_ACTION_RETURN,      /* invalid  */
1493                 MOD_ACTION_RETURN,      /* userlock */
1494                 MOD_ACTION_RETURN,      /* notfound */
1495                 MOD_ACTION_RETURN,      /* noop     */
1496                 MOD_ACTION_RETURN       /* updated  */
1497         }
1498 };
1499
1500 /** Validate and fixup a map that's part of an update section.
1501  *
1502  * @param map to validate.
1503  * @param ctx data to pass to fixup function (currently unused).
1504  * @return 0 if valid else -1.
1505  */
1506 int modcall_fixup_update(vp_map_t *map, UNUSED void *ctx)
1507 {
1508         CONF_PAIR *cp = cf_item_to_pair(map->ci);
1509
1510         /*
1511          *      Anal-retentive checks.
1512          */
1513         if (DEBUG_ENABLED3) {
1514                 if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->name[0] != '&')) {
1515                         WARN("%s[%d]: Please change attribute reference to '&%s %s ...'",
1516                              cf_pair_filename(cp), cf_pair_lineno(cp),
1517                              map->lhs->name, fr_int2str(fr_tokens, map->op, "<INVALID>"));
1518                 }
1519
1520                 if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->name[0] != '&')) {
1521                         WARN("%s[%d]: Please change attribute reference to '... %s &%s'",
1522                              cf_pair_filename(cp), cf_pair_lineno(cp),
1523                              fr_int2str(fr_tokens, map->op, "<INVALID>"), map->rhs->name);
1524                 }
1525         }
1526
1527         /*
1528          *      Values used by unary operators should be literal ANY
1529          *
1530          *      We then free the template and alloc a NULL one instead.
1531          */
1532         if (map->op == T_OP_CMP_FALSE) {
1533                 if ((map->rhs->type != TMPL_TYPE_LITERAL) || (strcmp(map->rhs->name, "ANY") != 0)) {
1534                         WARN("%s[%d] Wildcard deletion MUST use '!* ANY'",
1535                              cf_pair_filename(cp), cf_pair_lineno(cp));
1536                 }
1537
1538                 TALLOC_FREE(map->rhs);
1539
1540                 map->rhs = tmpl_alloc(map, TMPL_TYPE_NULL, NULL, 0);
1541         }
1542
1543         /*
1544          *      Lots of sanity checks for insane people...
1545          */
1546
1547         /*
1548          *      What exactly where you expecting to happen here?
1549          */
1550         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
1551             (map->rhs->type == TMPL_TYPE_LIST)) {
1552                 cf_log_err(map->ci, "Can't copy list into an attribute");
1553                 return -1;
1554         }
1555
1556         /*
1557          *      Depending on the attribute type, some operators are disallowed.
1558          */
1559         if ((map->lhs->type == TMPL_TYPE_ATTR) && (!fr_assignment_op[map->op] && !fr_equality_op[map->op])) {
1560                 cf_log_err(map->ci, "Invalid operator \"%s\" in update section.  "
1561                            "Only assignment or filter operators are allowed",
1562                            fr_int2str(fr_tokens, map->op, "<INVALID>"));
1563                 return -1;
1564         }
1565
1566         if (map->lhs->type == TMPL_TYPE_LIST) {
1567                 /*
1568                  *      Can't copy an xlat expansion or literal into a list,
1569                  *      we don't know what type of attribute we'd need
1570                  *      to create.
1571                  *
1572                  *      The only exception is where were using a unary
1573                  *      operator like !*.
1574                  */
1575                 if (map->op != T_OP_CMP_FALSE) switch (map->rhs->type) {
1576                 case TMPL_TYPE_XLAT:
1577                 case TMPL_TYPE_LITERAL:
1578                         cf_log_err(map->ci, "Can't copy value into list (we don't know which attribute to create)");
1579                         return -1;
1580
1581                 default:
1582                         break;
1583                 }
1584
1585                 /*
1586                  *      Only += and :=, and !* operators are supported
1587                  *      for lists.
1588                  */
1589                 switch (map->op) {
1590                 case T_OP_CMP_FALSE:
1591                         break;
1592
1593                 case T_OP_ADD:
1594                         if ((map->rhs->type != TMPL_TYPE_LIST) &&
1595                             (map->rhs->type != TMPL_TYPE_EXEC)) {
1596                                 cf_log_err(map->ci, "Invalid source for list assignment '%s += ...'", map->lhs->name);
1597                                 return -1;
1598                         }
1599                         break;
1600
1601                 case T_OP_SET:
1602                         if (map->rhs->type == TMPL_TYPE_EXEC) {
1603                                 WARN("%s[%d]: Please change ':=' to '=' for list assignment",
1604                                      cf_pair_filename(cp), cf_pair_lineno(cp));
1605                         }
1606
1607                         if (map->rhs->type != TMPL_TYPE_LIST) {
1608                                 cf_log_err(map->ci, "Invalid source for list assignment '%s := ...'", map->lhs->name);
1609                                 return -1;
1610                         }
1611                         break;
1612
1613                 case T_OP_EQ:
1614                         if (map->rhs->type != TMPL_TYPE_EXEC) {
1615                                 cf_log_err(map->ci, "Invalid source for list assignment '%s = ...'", map->lhs->name);
1616                                 return -1;
1617                         }
1618                         break;
1619
1620                 default:
1621                         cf_log_err(map->ci, "Operator \"%s\" not allowed for list assignment",
1622                                    fr_int2str(fr_tokens, map->op, "<INVALID>"));
1623                         return -1;
1624                 }
1625         }
1626
1627         /*
1628          *      If the map has a unary operator there's no further
1629          *      processing we need to, as RHS is unused.
1630          */
1631         if (map->op == T_OP_CMP_FALSE) return 0;
1632
1633         /*
1634          *      If LHS is an attribute, and RHS is a literal, we can
1635          *      preparse the information into a TMPL_TYPE_DATA.
1636          *
1637          *      Unless it's a unary operator in which case we
1638          *      ignore map->rhs.
1639          */
1640         if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->rhs->type == TMPL_TYPE_LITERAL)) {
1641                 /*
1642                  *      It's a literal string, just copy it.
1643                  *      Don't escape anything.
1644                  */
1645                 if (!cf_new_escape &&
1646                     (map->lhs->tmpl_da->type == PW_TYPE_STRING) &&
1647                     (cf_pair_value_type(cp) == T_SINGLE_QUOTED_STRING)) {
1648                         tmpl_cast_in_place_str(map->rhs);
1649
1650                 } else {
1651                         /*
1652                          *      RHS is hex, try to parse it as
1653                          *      type-specific data.
1654                          */
1655                         if (map->lhs->auto_converted &&
1656                             (map->rhs->name[0] == '0') && (map->rhs->name[1] == 'x') &&
1657                             (map->rhs->len > 2) && ((map->rhs->len & 0x01) == 0)) {
1658                                 vp_tmpl_t *vpt = map->rhs;
1659                                 map->rhs = NULL;
1660
1661                                 if (!map_cast_from_hex(map, T_BARE_WORD, vpt->name)) {
1662                                         map->rhs = vpt;
1663                                         cf_log_err(map->ci, "%s", fr_strerror());
1664                                         return -1;
1665                                 }
1666                                 talloc_free(vpt);
1667
1668                         } else if (tmpl_cast_in_place(map->rhs, map->lhs->tmpl_da->type, map->lhs->tmpl_da) < 0) {
1669                                 cf_log_err(map->ci, "%s", fr_strerror());
1670                                 return -1;
1671                         }
1672
1673                         /*
1674                          *      Fixup LHS da if it doesn't match the type
1675                          *      of the RHS.
1676                          */
1677                         if (map->lhs->tmpl_da->type != map->rhs->tmpl_data_type) {
1678                                 DICT_ATTR const *da;
1679
1680                                 da = dict_attrbytype(map->lhs->tmpl_da->attr, map->lhs->tmpl_da->vendor,
1681                                                      map->rhs->tmpl_data_type);
1682                                 if (!da) {
1683                                         fr_strerror_printf("Cannot find %s variant of attribute \"%s\"",
1684                                                            fr_int2str(dict_attr_types, map->rhs->tmpl_data_type,
1685                                                            "<INVALID>"), map->lhs->tmpl_da->name);
1686                                         return -1;
1687                                 }
1688                                 map->lhs->tmpl_da = da;
1689                         }
1690                 }
1691         } /* else we can't precompile the data */
1692
1693         return 0;
1694 }
1695
1696
1697 #ifdef WITH_UNLANG
1698 static modcallable *do_compile_modupdate(modcallable *parent, rlm_components_t component,
1699                                          CONF_SECTION *cs, char const *name2)
1700 {
1701         int rcode;
1702         modgroup *g;
1703         modcallable *csingle;
1704
1705         vp_map_t *head;
1706
1707         /*
1708          *      This looks at cs->name2 to determine which list to update
1709          */
1710         rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, modcall_fixup_update, NULL, 128);
1711         if (rcode < 0) return NULL; /* message already printed */
1712         if (!head) {
1713                 cf_log_err_cs(cs, "'update' sections cannot be empty");
1714                 return NULL;
1715         }
1716
1717         g = talloc_zero(parent, modgroup);
1718         csingle = mod_grouptocallable(g);
1719
1720         csingle->parent = parent;
1721         csingle->next = NULL;
1722
1723         if (name2) {
1724                 csingle->name = name2;
1725         } else {
1726                 csingle->name = "";
1727         }
1728         csingle->type = MOD_UPDATE;
1729         csingle->method = component;
1730
1731         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1732                sizeof(csingle->actions));
1733
1734         g->grouptype = GROUPTYPE_SIMPLE;
1735         g->children = NULL;
1736         g->cs = cs;
1737         g->map = talloc_steal(g, head);
1738
1739         return csingle;
1740 }
1741
1742
1743 static modcallable *do_compile_modswitch (modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
1744 {
1745         CONF_ITEM *ci;
1746         FR_TOKEN type;
1747         char const *name2;
1748         bool had_seen_default = false;
1749         modcallable *csingle;
1750         modgroup *g;
1751         ssize_t slen;
1752         vp_tmpl_t *vpt;
1753
1754         name2 = cf_section_name2(cs);
1755         if (!name2) {
1756                 cf_log_err_cs(cs, "You must specify a variable to switch over for 'switch'");
1757                 return NULL;
1758         }
1759
1760         if (!cf_item_find_next(cs, NULL)) {
1761                 cf_log_err_cs(cs, "'switch' statements cannot be empty");
1762                 return NULL;
1763         }
1764
1765         /*
1766          *      Create the template.  If we fail, AND it's a bare word
1767          *      with &Foo-Bar, it MAY be an attribute defined by a
1768          *      module.  Allow it for now.  The pass2 checks below
1769          *      will fix it up.
1770          */
1771         type = cf_section_name2_type(cs);
1772         slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
1773         if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
1774                 char *spaces, *text;
1775
1776                 fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
1777
1778                 cf_log_err_cs(cs, "Syntax error");
1779                 cf_log_err_cs(cs, "%s", name2);
1780                 cf_log_err_cs(cs, "%s^ %s", spaces, text);
1781
1782                 talloc_free(spaces);
1783                 talloc_free(text);
1784
1785                 return NULL;
1786         }
1787
1788         /*
1789          *      Otherwise a NULL vpt may refer to an attribute defined
1790          *      by a module.  That is checked in pass 2.
1791          */
1792
1793         if (vpt->type == TMPL_TYPE_LIST) {
1794                 cf_log_err_cs(cs, "Syntax error: Cannot switch over list '%s'", name2);
1795                 return NULL;
1796         }
1797
1798
1799         /*
1800          *      Walk through the children of the switch section,
1801          *      ensuring that they're all 'case' statements
1802          */
1803         for (ci = cf_item_find_next(cs, NULL);
1804              ci != NULL;
1805              ci = cf_item_find_next(cs, ci)) {
1806                 CONF_SECTION *subcs;
1807                 char const *name1;
1808
1809                 if (!cf_item_is_section(ci)) {
1810                         if (!cf_item_is_pair(ci)) continue;
1811
1812                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1813                         talloc_free(vpt);
1814                         return NULL;
1815                 }
1816
1817                 subcs = cf_item_to_section(ci); /* can't return NULL */
1818                 name1 = cf_section_name1(subcs);
1819
1820                 if (strcmp(name1, "case") != 0) {
1821                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1822                         talloc_free(vpt);
1823                         return NULL;
1824                 }
1825
1826                 name2 = cf_section_name2(subcs);
1827                 if (!name2) {
1828                         if (!had_seen_default) {
1829                                 had_seen_default = true;
1830                                 continue;
1831                         }
1832
1833                         cf_log_err(ci, "Cannot have two 'default' case statements");
1834                         talloc_free(vpt);
1835                         return NULL;
1836                 }
1837         }
1838
1839         csingle = do_compile_modgroup(parent, component, cs,
1840                                       GROUPTYPE_SIMPLE,
1841                                       GROUPTYPE_SIMPLE,
1842                                       MOD_SWITCH);
1843         if (!csingle) {
1844                 talloc_free(vpt);
1845                 return NULL;
1846         }
1847
1848         g = mod_callabletogroup(csingle);
1849         g->vpt = talloc_steal(g, vpt);
1850
1851         return csingle;
1852 }
1853
1854 static modcallable *do_compile_modcase(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
1855 {
1856         int i;
1857         char const *name2;
1858         modcallable *csingle;
1859         modgroup *g;
1860         vp_tmpl_t *vpt;
1861
1862         if (!parent || (parent->type != MOD_SWITCH)) {
1863                 cf_log_err_cs(cs, "\"case\" statements may only appear within a \"switch\" section");
1864                 return NULL;
1865         }
1866
1867         /*
1868          *      case THING means "match THING"
1869          *      case       means "match anything"
1870          */
1871         name2 = cf_section_name2(cs);
1872         if (name2) {
1873                 ssize_t slen;
1874                 FR_TOKEN type;
1875
1876                 type = cf_section_name2_type(cs);
1877
1878                 slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
1879                 if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
1880                         char *spaces, *text;
1881
1882                         fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
1883
1884                         cf_log_err_cs(cs, "Syntax error");
1885                         cf_log_err_cs(cs, "%s", name2);
1886                         cf_log_err_cs(cs, "%s^ %s", spaces, text);
1887
1888                         talloc_free(spaces);
1889                         talloc_free(text);
1890
1891                         return NULL;
1892                 }
1893
1894                 if (vpt->type == TMPL_TYPE_LIST) {
1895                         cf_log_err_cs(cs, "Syntax error: Cannot match list '%s'", name2);
1896                         return NULL;
1897                 }
1898
1899                 /*
1900                  *      Otherwise a NULL vpt may refer to an attribute defined
1901                  *      by a module.  That is checked in pass 2.
1902                  */
1903
1904         } else {
1905                 vpt = NULL;
1906         }
1907
1908         csingle = do_compile_modgroup(parent, component, cs,
1909                                       GROUPTYPE_SIMPLE,
1910                                       GROUPTYPE_SIMPLE,
1911                                       MOD_CASE);
1912         if (!csingle) {
1913                 talloc_free(vpt);
1914                 return NULL;
1915         }
1916
1917         /*
1918          *      The interpretor expects this to be NULL for the
1919          *      default case.  do_compile_modgroup sets it to name2,
1920          *      unless name2 is NULL, in which case it sets it to name1.
1921          */
1922         csingle->name = name2;
1923
1924         g = mod_callabletogroup(csingle);
1925         g->vpt = talloc_steal(g, vpt);
1926
1927         /*
1928          *      Set all of it's codes to return, so that
1929          *      when we pick a 'case' statement, we don't
1930          *      fall through to processing the next one.
1931          */
1932         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
1933                 csingle->actions[i] = MOD_ACTION_RETURN;
1934         }
1935
1936         return csingle;
1937 }
1938
1939 static modcallable *do_compile_modforeach(modcallable *parent,
1940                                           rlm_components_t component, CONF_SECTION *cs)
1941 {
1942         FR_TOKEN type;
1943         char const *name2;
1944         modcallable *csingle;
1945         modgroup *g;
1946         ssize_t slen;
1947         vp_tmpl_t *vpt;
1948
1949         name2 = cf_section_name2(cs);
1950         if (!name2) {
1951                 cf_log_err_cs(cs,
1952                            "You must specify an attribute to loop over in 'foreach'");
1953                 return NULL;
1954         }
1955
1956         if (!cf_item_find_next(cs, NULL)) {
1957                 cf_log_err_cs(cs, "'foreach' blocks cannot be empty");
1958                 return NULL;
1959         }
1960
1961         /*
1962          *      Create the template.  If we fail, AND it's a bare word
1963          *      with &Foo-Bar, it MAY be an attribute defined by a
1964          *      module.  Allow it for now.  The pass2 checks below
1965          *      will fix it up.
1966          */
1967         type = cf_section_name2_type(cs);
1968         slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
1969         if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
1970                 char *spaces, *text;
1971
1972                 fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
1973
1974                 cf_log_err_cs(cs, "Syntax error");
1975                 cf_log_err_cs(cs, "%s", name2);
1976                 cf_log_err_cs(cs, "%s^ %s", spaces, text);
1977
1978                 talloc_free(spaces);
1979                 talloc_free(text);
1980
1981                 return NULL;
1982         }
1983
1984         /*
1985          *      If we don't have a negative return code, we must have a vpt
1986          *      (mostly to quiet coverity).
1987          */
1988         rad_assert(vpt);
1989
1990         if ((vpt->type != TMPL_TYPE_ATTR) && (vpt->type != TMPL_TYPE_LIST)) {
1991                 cf_log_err_cs(cs, "MUST use attribute or list reference in 'foreach'");
1992                 return NULL;
1993         }
1994
1995         /*
1996          *      Fix up the template to iterate over all instances of
1997          *      the attribute. In a perfect consistent world, users would do
1998          *      foreach &attr[*], but that's taking the consistency thing a bit far.
1999          */
2000         vpt->tmpl_num = NUM_ALL;
2001
2002         csingle = do_compile_modgroup(parent, component, cs,
2003                                       GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2004                                       MOD_FOREACH);
2005
2006         if (!csingle) {
2007                 talloc_free(vpt);
2008                 return NULL;
2009         }
2010
2011         g = mod_callabletogroup(csingle);
2012         g->vpt = vpt;
2013
2014         return csingle;
2015 }
2016
2017 static modcallable *do_compile_modbreak(modcallable *parent,
2018                                         rlm_components_t component, CONF_ITEM const *ci)
2019 {
2020         CONF_SECTION const *cs = NULL;
2021
2022         for (cs = cf_item_parent(ci);
2023              cs != NULL;
2024              cs = cf_item_parent(cf_section_to_item(cs))) {
2025                 if (strcmp(cf_section_name1(cs), "foreach") == 0) {
2026                         break;
2027                 }
2028         }
2029
2030         if (!cs) {
2031                 cf_log_err(ci, "'break' can only be used in a 'foreach' section");
2032                 return NULL;
2033         }
2034
2035         return do_compile_modgroup(parent, component, NULL,
2036                                    GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2037                                    MOD_BREAK);
2038 }
2039 #endif
2040
2041 static modcallable *do_compile_modserver(modcallable *parent,
2042                                          rlm_components_t component, CONF_ITEM *ci,
2043                                          char const *name,
2044                                          CONF_SECTION *cs,
2045                                          char const *server)
2046 {
2047         modcallable *csingle;
2048         CONF_SECTION *subcs;
2049         modref *mr;
2050
2051         subcs = cf_section_sub_find_name2(cs, comp2str[component], NULL);
2052         if (!subcs) {
2053                 cf_log_err(ci, "Server %s has no %s section",
2054                            server, comp2str[component]);
2055                 return NULL;
2056         }
2057
2058         mr = talloc_zero(parent, modref);
2059
2060         csingle = mod_reftocallable(mr);
2061         csingle->parent = parent;
2062         csingle->next = NULL;
2063         csingle->name = name;
2064         csingle->type = MOD_REFERENCE;
2065         csingle->method = component;
2066
2067         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
2068                sizeof(csingle->actions));
2069
2070         mr->ref_name = strdup(server);
2071         mr->ref_cs = cs;
2072
2073         return csingle;
2074 }
2075
2076 static modcallable *do_compile_modxlat(modcallable *parent,
2077                                        rlm_components_t component, char const *fmt)
2078 {
2079         modcallable *csingle;
2080         modxlat *mx;
2081
2082         mx = talloc_zero(parent, modxlat);
2083
2084         csingle = mod_xlattocallable(mx);
2085         csingle->parent = parent;
2086         csingle->next = NULL;
2087         csingle->name = "expand";
2088         csingle->type = MOD_XLAT;
2089         csingle->method = component;
2090
2091         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
2092                sizeof(csingle->actions));
2093
2094         mx->xlat_name = strdup(fmt);
2095         if (fmt[0] != '%') {
2096                 char *p;
2097                 mx->exec = true;
2098
2099                 strcpy(mx->xlat_name, fmt + 1);
2100                 p = strrchr(mx->xlat_name, '`');
2101                 if (p) *p = '\0';
2102         }
2103
2104         return csingle;
2105 }
2106
2107 /*
2108  *      redundant, etc. can refer to modules or groups, but not much else.
2109  */
2110 static int all_children_are_modules(CONF_SECTION *cs, char const *name)
2111 {
2112         CONF_ITEM *ci;
2113
2114         for (ci=cf_item_find_next(cs, NULL);
2115              ci != NULL;
2116              ci=cf_item_find_next(cs, ci)) {
2117                 /*
2118                  *      If we're a redundant, etc. group, then the
2119                  *      intention is to call modules, rather than
2120                  *      processing logic.  These checks aren't
2121                  *      *strictly* necessary, but they keep the users
2122                  *      from doing crazy things.
2123                  */
2124                 if (cf_item_is_section(ci)) {
2125                         CONF_SECTION *subcs = cf_item_to_section(ci);
2126                         char const *name1 = cf_section_name1(subcs);
2127
2128                         if ((strcmp(name1, "if") == 0) ||
2129                             (strcmp(name1, "else") == 0) ||
2130                             (strcmp(name1, "elsif") == 0) ||
2131                             (strcmp(name1, "update") == 0) ||
2132                             (strcmp(name1, "switch") == 0) ||
2133                             (strcmp(name1, "case") == 0)) {
2134                                 cf_log_err(ci, "%s sections cannot contain a \"%s\" statement",
2135                                        name, name1);
2136                                 return 0;
2137                         }
2138                         continue;
2139                 }
2140
2141                 if (cf_item_is_pair(ci)) {
2142                         CONF_PAIR *cp = cf_item_to_pair(ci);
2143                         if (cf_pair_value(cp) != NULL) {
2144                                 cf_log_err(ci,
2145                                            "Entry with no value is invalid");
2146                                 return 0;
2147                         }
2148                 }
2149         }
2150
2151         return 1;
2152 }
2153
2154 /** Load a named module from "instantiate" or "policy".
2155  *
2156  * If it's "foo.method", look for "foo", and return "method" as the method
2157  * we wish to use, instead of the input component.
2158  *
2159  * @param[out] pcomponent Where to write the method we found, if any.  If no method is specified
2160  *      will be set to MOD_COUNT.
2161  * @param[in] real_name Complete name string e.g. foo.authorize.
2162  * @param[in] virtual_name Virtual module name e.g. foo.
2163  * @param[in] method_name Method override (may be NULL) or the method name e.g. authorize.
2164  * @return the CONF_SECTION specifying the virtual module.
2165  */
2166 static CONF_SECTION *virtual_module_find_cs(rlm_components_t *pcomponent,
2167                                             char const *real_name, char const *virtual_name, char const *method_name)
2168 {
2169         CONF_SECTION *cs, *subcs;
2170         rlm_components_t method = *pcomponent;
2171         char buffer[256];
2172
2173         /*
2174          *      Turn the method name into a method enum.
2175          */
2176         if (method_name) {
2177                 rlm_components_t i;
2178
2179                 for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) {
2180                         if (strcmp(comp2str[i], method_name) == 0) break;
2181                 }
2182
2183                 if (i != MOD_COUNT) {
2184                         method = i;
2185                 } else {
2186                         method_name = NULL;
2187                         virtual_name = real_name;
2188                 }
2189         }
2190
2191         /*
2192          *      Look for "foo" in the "instantiate" section.  If we
2193          *      find it, AND there's no method name, we've found the
2194          *      right thing.
2195          *
2196          *      Return it to the caller, with the updated method.
2197          */
2198         cs = cf_section_find("instantiate");
2199         if (cs) {
2200                 /*
2201                  *      Found "foo".  Load it as "foo", or "foo.method".
2202                  */
2203                 subcs = cf_section_sub_find_name2(cs, NULL, virtual_name);
2204                 if (subcs) {
2205                         *pcomponent = method;
2206                         return subcs;
2207                 }
2208         }
2209
2210         /*
2211          *      Look for it in "policy".
2212          *
2213          *      If there's no policy section, we can't do anything else.
2214          */
2215         cs = cf_section_find("policy");
2216         if (!cs) return NULL;
2217
2218         /*
2219          *      "foo.authorize" means "load policy "foo" as method "authorize".
2220          *
2221          *      And bail out if there's no policy "foo".
2222          */
2223         if (method_name) {
2224                 subcs = cf_section_sub_find_name2(cs, NULL, virtual_name);
2225                 if (subcs) *pcomponent = method;
2226
2227                 return subcs;
2228         }
2229
2230         /*
2231          *      "foo" means "look for foo.component" first, to allow
2232          *      method overrides.  If that's not found, just look for
2233          *      a policy "foo".
2234          *
2235          */
2236         snprintf(buffer, sizeof(buffer), "%s.%s",
2237                  virtual_name, comp2str[method]);
2238         subcs = cf_section_sub_find_name2(cs, NULL, buffer);
2239         if (subcs) return subcs;
2240
2241         return cf_section_sub_find_name2(cs, NULL, virtual_name);
2242 }
2243
2244
2245 /*
2246  *      Compile one entry of a module call.
2247  */
2248 static modcallable *do_compile_modsingle(modcallable *parent,
2249                                          rlm_components_t component, CONF_ITEM *ci,
2250                                          int grouptype,
2251                                          char const **modname)
2252 {
2253         char const *modrefname, *p;
2254         modsingle *single;
2255         modcallable *csingle;
2256         module_instance_t *this;
2257         CONF_SECTION *cs, *subcs, *modules;
2258         CONF_SECTION *loop;
2259         char const *realname;
2260         rlm_components_t method = component;
2261
2262         if (cf_item_is_section(ci)) {
2263                 char const *name2;
2264
2265                 cs = cf_item_to_section(ci);
2266                 modrefname = cf_section_name1(cs);
2267                 name2 = cf_section_name2(cs);
2268                 if (!name2) name2 = "";
2269
2270                 /*
2271                  *      group{}, redundant{}, or append{} may appear
2272                  *      where a single module instance was expected.
2273                  *      In that case, we hand it off to
2274                  *      compile_modgroup
2275                  */
2276                 if (strcmp(modrefname, "group") == 0) {
2277                         *modname = name2;
2278                         return do_compile_modgroup(parent, component, cs,
2279                                                    GROUPTYPE_SIMPLE,
2280                                                    grouptype, MOD_GROUP);
2281
2282                 } else if (strcmp(modrefname, "redundant") == 0) {
2283                         *modname = name2;
2284
2285                         if (!all_children_are_modules(cs, modrefname)) {
2286                                 return NULL;
2287                         }
2288
2289                         return do_compile_modgroup(parent, component, cs,
2290                                                    GROUPTYPE_REDUNDANT,
2291                                                    grouptype, MOD_GROUP);
2292
2293                 } else if (strcmp(modrefname, "load-balance") == 0) {
2294                         *modname = name2;
2295
2296                         if (!all_children_are_modules(cs, modrefname)) {
2297                                 return NULL;
2298                         }
2299
2300                         return do_compile_modgroup(parent, component, cs,
2301                                                    GROUPTYPE_SIMPLE,
2302                                                    grouptype, MOD_LOAD_BALANCE);
2303
2304                 } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
2305                         *modname = name2;
2306
2307                         if (!all_children_are_modules(cs, modrefname)) {
2308                                 return NULL;
2309                         }
2310
2311                         return do_compile_modgroup(parent, component, cs,
2312                                                    GROUPTYPE_REDUNDANT,
2313                                                    grouptype, MOD_REDUNDANT_LOAD_BALANCE);
2314
2315 #ifdef WITH_UNLANG
2316                 } else  if (strcmp(modrefname, "if") == 0) {
2317                         if (!cf_section_name2(cs)) {
2318                                 cf_log_err(ci, "'if' without condition");
2319                                 return NULL;
2320                         }
2321
2322                         *modname = name2;
2323                         csingle= do_compile_modgroup(parent, component, cs,
2324                                                      GROUPTYPE_SIMPLE,
2325                                                      grouptype, MOD_IF);
2326                         if (!csingle) return NULL;
2327                         *modname = name2;
2328
2329                         return csingle;
2330
2331                 } else  if (strcmp(modrefname, "elsif") == 0) {
2332                         if (parent &&
2333                             ((parent->type == MOD_LOAD_BALANCE) ||
2334                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2335                                 cf_log_err(ci, "'elsif' cannot be used in this section");
2336                                 return NULL;
2337                         }
2338
2339                         if (!cf_section_name2(cs)) {
2340                                 cf_log_err(ci, "'elsif' without condition");
2341                                 return NULL;
2342                         }
2343
2344                         *modname = name2;
2345                         return do_compile_modgroup(parent, component, cs,
2346                                                    GROUPTYPE_SIMPLE,
2347                                                    grouptype, MOD_ELSIF);
2348
2349                 } else  if (strcmp(modrefname, "else") == 0) {
2350                         if (parent &&
2351                             ((parent->type == MOD_LOAD_BALANCE) ||
2352                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2353                                 cf_log_err(ci, "'else' cannot be used in this section section");
2354                                 return NULL;
2355                         }
2356
2357                         if (cf_section_name2(cs)) {
2358                                 cf_log_err(ci, "Cannot have conditions on 'else'");
2359                                 return NULL;
2360                         }
2361
2362                         *modname = name2;
2363                         return  do_compile_modgroup(parent, component, cs,
2364                                                     GROUPTYPE_SIMPLE,
2365                                                     grouptype, MOD_ELSE);
2366
2367                 } else  if (strcmp(modrefname, "update") == 0) {
2368                         *modname = name2;
2369
2370                         return do_compile_modupdate(parent, component, cs,
2371                                                     name2);
2372
2373                 } else  if (strcmp(modrefname, "switch") == 0) {
2374                         *modname = name2;
2375
2376                         return do_compile_modswitch (parent, component, cs);
2377
2378                 } else  if (strcmp(modrefname, "case") == 0) {
2379                         *modname = name2;
2380
2381                         return do_compile_modcase(parent, component, cs);
2382
2383                 } else  if (strcmp(modrefname, "foreach") == 0) {
2384                         *modname = name2;
2385
2386                         return do_compile_modforeach(parent, component, cs);
2387
2388 #endif
2389                 } /* else it's something like sql { fail = 1 ...} */
2390
2391         } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */
2392                 return NULL;
2393
2394                 /*
2395                  *      Else it's a module reference, with updated return
2396                  *      codes.
2397                  */
2398         } else {
2399                 CONF_PAIR *cp = cf_item_to_pair(ci);
2400                 modrefname = cf_pair_attr(cp);
2401
2402                 /*
2403                  *      Actions (ok = 1), etc. are orthogonal to just
2404                  *      about everything else.
2405                  */
2406                 if (cf_pair_value(cp) != NULL) {
2407                         cf_log_err(ci, "Entry is not a reference to a module");
2408                         return NULL;
2409                 }
2410
2411                 /*
2412                  *      In-place xlat's via %{...}.
2413                  *
2414                  *      This should really be removed from the server.
2415                  */
2416                 if (((modrefname[0] == '%') && (modrefname[1] == '{')) ||
2417                     (modrefname[0] == '`')) {
2418                         return do_compile_modxlat(parent, component,
2419                                                   modrefname);
2420                 }
2421         }
2422
2423 #ifdef WITH_UNLANG
2424         /*
2425          *      These can't be over-ridden.
2426          */
2427         if (strcmp(modrefname, "break") == 0) {
2428                 if (!cf_item_is_pair(ci)) {
2429                         cf_log_err(ci, "Invalid use of 'break' as section name.");
2430                         return NULL;
2431                 }
2432
2433                 return do_compile_modbreak(parent, component, ci);
2434         }
2435
2436         if (strcmp(modrefname, "return") == 0) {
2437                 if (!cf_item_is_pair(ci)) {
2438                         cf_log_err(ci, "Invalid use of 'return' as section name.");
2439                         return NULL;
2440                 }
2441
2442                 return do_compile_modgroup(parent, component, NULL,
2443                                            GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2444                                            MOD_RETURN);
2445         }
2446 #endif
2447
2448         /*
2449          *      Run a virtual server.  This is really terrible and
2450          *      should be deleted.
2451          */
2452         if (strncmp(modrefname, "server[", 7) == 0) {
2453                 char buffer[256];
2454
2455                 if (!cf_item_is_pair(ci)) {
2456                         cf_log_err(ci, "Invalid syntax");
2457                         return NULL;
2458                 }
2459
2460                 strlcpy(buffer, modrefname + 7, sizeof(buffer));
2461                 p = strrchr(buffer, ']');
2462                 if (!p || p[1] != '\0' || (p == buffer)) {
2463                         cf_log_err(ci, "Invalid server reference in \"%s\".", modrefname);
2464                         return NULL;
2465                 }
2466
2467                 buffer[p - buffer] = '\0';
2468
2469                 cs = cf_section_sub_find_name2(NULL, "server", buffer);
2470                 if (!cs) {
2471                         cf_log_err(ci, "No such server \"%s\".", buffer);
2472                         return NULL;
2473                 }
2474
2475                 /*
2476                  *      Ignore stupid attempts to over-ride the return
2477                  *      code.
2478                  */
2479                 return do_compile_modserver(parent, component, ci,
2480                                             modrefname, cs, buffer);
2481         }
2482
2483         /*
2484          *      We now have a name.  It can be one of two forms.  A
2485          *      bare module name, or a section named for the module,
2486          *      with over-rides for the return codes.
2487          *
2488          *      The name can refer to a real module, in the "modules"
2489          *      section.  In that case, the name will be either the
2490          *      first or second name of the sub-section of "modules".
2491          *
2492          *      Or, the name can refer to a policy, in the "policy"
2493          *      section.  In that case, the name will be first name of
2494          *      the sub-section of "policy".  Unless it's a "redudant"
2495          *      block...
2496          *
2497          *      Or, the name can refer to a "module.method", in which
2498          *      case we're calling a different method than normal for
2499          *      this section.
2500          *
2501          *      Or, the name can refer to a virtual module, in the
2502          *      "instantiate" section.  In that case, the name will be
2503          *      the first of the sub-section of "instantiate".  Unless
2504          *      it's a "redudant" block...
2505          *
2506          *      We try these in sequence, from the bottom up.  This is
2507          *      so that things in "instantiate" and "policy" can
2508          *      over-ride calls to real modules.
2509          */
2510
2511
2512         /*
2513          *      Try:
2514          *
2515          *      instantiate { ... name { ...} ... }
2516          *      instantiate { ... name.method { ...} ... }
2517          *      policy { ... name { .. } .. }
2518          *      policy { ... name.method { .. } .. }
2519          *
2520          *      The only difference between things in "instantiate"
2521          *      and "policy" is that "instantiate" will cause modules
2522          *      to be instantiated in a particular order.
2523          */
2524         subcs = NULL;
2525         p = strrchr(modrefname, '.');
2526         if (!p) {
2527                 subcs = virtual_module_find_cs(&method, modrefname, modrefname, NULL);
2528         } else {
2529                 char buffer[256];
2530
2531                 strlcpy(buffer, modrefname, sizeof(buffer));
2532                 buffer[p - modrefname] = '\0';
2533
2534                 subcs = virtual_module_find_cs(&method, modrefname, buffer, buffer + (p - modrefname) + 1);
2535         }
2536
2537         /*
2538          *      Check that we're not creating a loop.  We may
2539          *      be compiling an "sql" module reference inside
2540          *      of an "sql" policy.  If so, we allow the
2541          *      second "sql" to refer to the module.
2542          */
2543         for (loop = cf_item_parent(ci);
2544              loop && subcs;
2545              loop = cf_item_parent(cf_section_to_item(loop))) {
2546                 if (loop == subcs) {
2547                         subcs = NULL;
2548                 }
2549         }
2550
2551         /*
2552          *      We've found the relevant entry.  It MUST be a
2553          *      sub-section.
2554          *
2555          *      However, it can be a "redundant" block, or just a
2556          *      section name.
2557          */
2558         if (subcs) {
2559                 /*
2560                  *      modules.c takes care of ensuring that this is:
2561                  *
2562                  *      group foo { ...
2563                  *      load-balance foo { ...
2564                  *      redundant foo { ...
2565                  *      redundant-load-balance foo { ...
2566                  *
2567                  *      We can just recurs to compile the section as
2568                  *      if it was found here.
2569                  */
2570                 if (cf_section_name2(subcs)) {
2571                         csingle = do_compile_modsingle(parent,
2572                                                        method,
2573                                                        cf_section_to_item(subcs),
2574                                                        grouptype,
2575                                                        modname);
2576                 } else {
2577                         /*
2578                          *      We have:
2579                          *
2580                          *      foo { ...
2581                          *
2582                          *      So we compile it like it was:
2583                          *
2584                          *      group foo { ...
2585                          */
2586                         csingle = do_compile_modgroup(parent,
2587                                                       method,
2588                                                       subcs,
2589                                                       GROUPTYPE_SIMPLE,
2590                                                       grouptype, MOD_GROUP);
2591                 }
2592
2593                 /*
2594                  *      Return the compiled thing if we can.
2595                  */
2596                 if (!csingle) return NULL;
2597                 if (cf_item_is_pair(ci)) return csingle;
2598
2599                 /*
2600                  *      Else we have a reference to a policy, and that reference
2601                  *      over-rides the return codes for the policy!
2602                  */
2603                 goto action_override;
2604         }
2605
2606         /*
2607          *      Not a virtual module.  It must be a real module.
2608          */
2609         modules = cf_section_find("modules");
2610         this = NULL;
2611         realname = modrefname;
2612
2613         if (modules) {
2614                 /*
2615                  *      Try to load the optional module.
2616                  */
2617                 if (realname[0] == '-') realname++;
2618
2619                 /*
2620                  *      As of v3, the "modules" section contains
2621                  *      modules we use.  Configuration for other
2622                  *      modules belongs in raddb/mods-available/,
2623                  *      which isn't loaded into the "modules" section.
2624                  */
2625                 this = module_instantiate_method(modules, realname, &method);
2626                 if (this) goto allocate_csingle;
2627
2628                 /*
2629                  *      We were asked to MAYBE load it and it
2630                  *      doesn't exist.  Return a soft error.
2631                  */
2632                 if (realname != modrefname) {
2633                         *modname = modrefname;
2634                         return NULL;
2635                 }
2636         }
2637
2638         /*
2639          *      Can't de-reference it to anything.  Ugh.
2640          */
2641         *modname = NULL;
2642         cf_log_err(ci, "Failed to find \"%s\" as a module or policy.", modrefname);
2643         cf_log_err(ci, "Please verify that the configuration exists in %s/mods-enabled/%s.", get_radius_dir(), modrefname);
2644         return NULL;
2645
2646         /*
2647          *      We know it's all OK, allocate the structures, and fill
2648          *      them in.
2649          */
2650 allocate_csingle:
2651         /*
2652          *      Check if the module in question has the necessary
2653          *      component.
2654          */
2655         if (!this->entry->module->methods[method]) {
2656                 cf_log_err(ci, "\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name,
2657                            comp2str[method]);
2658                 return NULL;
2659         }
2660
2661         single = talloc_zero(parent, modsingle);
2662         single->modinst = this;
2663         *modname = this->entry->module->name;
2664
2665         csingle = mod_singletocallable(single);
2666         csingle->parent = parent;
2667         csingle->next = NULL;
2668         if (!parent || (component != MOD_AUTHENTICATE)) {
2669                 memcpy(csingle->actions, defaultactions[component][grouptype],
2670                        sizeof csingle->actions);
2671         } else { /* inside Auth-Type has different rules */
2672                 memcpy(csingle->actions, authtype_actions[grouptype],
2673                        sizeof csingle->actions);
2674         }
2675         rad_assert(modrefname != NULL);
2676         csingle->name = realname;
2677         csingle->type = MOD_SINGLE;
2678         csingle->method = method;
2679
2680 action_override:
2681         /*
2682          *      Over-ride the default return codes of the module.
2683          */
2684         if (cf_item_is_section(ci)) {
2685                 CONF_ITEM *csi;
2686
2687                 cs = cf_item_to_section(ci);
2688                 for (csi=cf_item_find_next(cs, NULL);
2689                      csi != NULL;
2690                      csi=cf_item_find_next(cs, csi)) {
2691
2692                         if (cf_item_is_section(csi)) {
2693                                 cf_log_err(csi, "Subsection of module instance call not allowed");
2694                                 talloc_free(csingle);
2695                                 return NULL;
2696                         }
2697
2698                         if (!cf_item_is_pair(csi)) continue;
2699
2700                         if (!compile_action(csingle, cf_item_to_pair(csi))) {
2701                                 talloc_free(csingle);
2702                                 return NULL;
2703                         }
2704                 }
2705         }
2706
2707         return csingle;
2708 }
2709
2710 modcallable *compile_modsingle(TALLOC_CTX *ctx,
2711                                modcallable **parent,
2712                                rlm_components_t component, CONF_ITEM *ci,
2713                                char const **modname)
2714 {
2715         modcallable *ret;
2716
2717         if (!*parent) {
2718                 modcallable *c;
2719                 modgroup *g;
2720                 CONF_SECTION *parentcs;
2721
2722                 g = talloc_zero(ctx, modgroup);
2723                 memset(g, 0, sizeof(*g));
2724                 g->grouptype = GROUPTYPE_SIMPLE;
2725                 c = mod_grouptocallable(g);
2726                 c->next = NULL;
2727                 memcpy(c->actions,
2728                        defaultactions[component][GROUPTYPE_SIMPLE],
2729                        sizeof(c->actions));
2730
2731                 parentcs = cf_item_parent(ci);
2732                 c->name = cf_section_name2(parentcs);
2733                 if (!c->name) {
2734                         c->name = cf_section_name1(parentcs);
2735                 }
2736
2737                 c->type = MOD_GROUP;
2738                 c->method = component;
2739                 g->children = NULL;
2740
2741                 *parent = mod_grouptocallable(g);
2742         }
2743
2744         ret = do_compile_modsingle(*parent, component, ci,
2745                                    GROUPTYPE_SIMPLE,
2746                                    modname);
2747         dump_tree(component, ret);
2748         return ret;
2749 }
2750
2751
2752 /*
2753  *      Internal compile group code.
2754  */
2755 static modcallable *do_compile_modgroup(modcallable *parent,
2756                                         rlm_components_t component, CONF_SECTION *cs,
2757                                         int grouptype, int parentgrouptype, int mod_type)
2758 {
2759         int i;
2760         modgroup *g;
2761         modcallable *c;
2762         CONF_ITEM *ci;
2763
2764         g = talloc_zero(parent, modgroup);
2765         g->grouptype = grouptype;
2766         g->children = NULL;
2767         g->cs = cs;
2768
2769         c = mod_grouptocallable(g);
2770         c->parent = parent;
2771         c->type = mod_type;
2772         c->next = NULL;
2773         memset(c->actions, 0, sizeof(c->actions));
2774
2775         if (!cs) {              /* only for "break" and "return" */
2776                 c->name = "";
2777                 goto set_codes;
2778         }
2779
2780         /*
2781          *      Remember the name for printing, etc.
2782          *
2783          *      FIXME: We may also want to put the names into a
2784          *      rbtree, so that groups can reference each other...
2785          */
2786         c->name = cf_section_name2(cs);
2787         if (!c->name) {
2788                 c->name = cf_section_name1(cs);
2789                 if ((strcmp(c->name, "group") == 0) ||
2790                     (strcmp(c->name, "redundant") == 0)) {
2791                         c->name = "";
2792                 } else if (c->type == MOD_GROUP) {
2793                         c->type = MOD_POLICY;
2794                 }
2795         }
2796
2797 #ifdef WITH_UNLANG
2798         /*
2799          *      Do load-time optimizations
2800          */
2801         if ((c->type == MOD_IF) || (c->type == MOD_ELSIF) || (c->type == MOD_ELSE)) {
2802                 modgroup *f, *p;
2803
2804                 rad_assert(parent != NULL);
2805
2806                 if (c->type == MOD_IF) {
2807                         g->cond = cf_data_find(g->cs, "if");
2808                         rad_assert(g->cond != NULL);
2809
2810                 check_if:
2811                         if (g->cond->type == COND_TYPE_FALSE) {
2812                                 INFO(" # Skipping contents of '%s' as it is always 'false' -- %s:%d",
2813                                      unlang_keyword[g->mc.type],
2814                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2815                                 goto set_codes;
2816                         }
2817
2818                 } else if (c->type == MOD_ELSIF) {
2819
2820                         g->cond = cf_data_find(g->cs, "if");
2821                         rad_assert(g->cond != NULL);
2822
2823                         rad_assert(parent != NULL);
2824                         p = mod_callabletogroup(parent);
2825
2826                         rad_assert(p->tail != NULL);
2827
2828                         /*
2829                          *      We're in the process of compiling the
2830                          *      section, so the parent's tail is the
2831                          *      previous "if" statement.
2832                          */
2833                         f = mod_callabletogroup(p->tail);
2834                         if ((f->mc.type != MOD_IF) &&
2835                             (f->mc.type != MOD_ELSIF)) {
2836                                 cf_log_err_cs(g->cs, "Invalid location for 'elsif'.  There is no preceding 'if' statement");
2837                                 talloc_free(g);
2838                                 return NULL;
2839                         }
2840
2841                         /*
2842                          *      If we took the previous condition, we
2843                          *      don't need to take this one.
2844                          *
2845                          *      We reset our condition to 'true', so
2846                          *      that subsequent sections can check
2847                          *      that they don't need to be executed.
2848                          */
2849                         if (f->cond->type == COND_TYPE_TRUE) {
2850                         skip_true:
2851                                 INFO(" # Skipping contents of '%s' as previous '%s' is always  'true' -- %s:%d",
2852                                      unlang_keyword[g->mc.type],
2853                                      unlang_keyword[f->mc.type],
2854                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2855                                 g->cond = f->cond;
2856                                 goto set_codes;
2857                         }
2858                         goto check_if;
2859
2860                 } else {
2861                         rad_assert(c->type == MOD_ELSE);
2862
2863                         rad_assert(parent != NULL);
2864                         p = mod_callabletogroup(parent);
2865
2866                         rad_assert(p->tail != NULL);
2867
2868                         f = mod_callabletogroup(p->tail);
2869                         if ((f->mc.type != MOD_IF) &&
2870                             (f->mc.type != MOD_ELSIF)) {
2871                                 cf_log_err_cs(g->cs, "Invalid location for 'else'.  There is no preceding 'if' statement");
2872                                 talloc_free(g);
2873                                 return NULL;
2874                         }
2875
2876                         /*
2877                          *      If we took the previous condition, we
2878                          *      don't need to take this one.
2879                          */
2880                         if (f->cond->type == COND_TYPE_TRUE) goto skip_true;
2881                 }
2882
2883                 /*
2884                  *      Else we need to compile this section
2885                  */
2886         }
2887 #endif
2888
2889         /*
2890          *      Loop over the children of this group.
2891          */
2892         for (ci=cf_item_find_next(cs, NULL);
2893              ci != NULL;
2894              ci=cf_item_find_next(cs, ci)) {
2895
2896                 /*
2897                  *      Sections are references to other groups, or
2898                  *      to modules with updated return codes.
2899                  */
2900                 if (cf_item_is_section(ci)) {
2901                         char const *junk = NULL;
2902                         modcallable *single;
2903                         CONF_SECTION *subcs = cf_item_to_section(ci);
2904
2905                         single = do_compile_modsingle(c, component, ci,
2906                                                       grouptype, &junk);
2907                         if (!single) {
2908                                 cf_log_err(ci, "Failed to parse \"%s\" subsection.",
2909                                        cf_section_name1(subcs));
2910                                 talloc_free(c);
2911                                 return NULL;
2912                         }
2913                         add_child(g, single);
2914
2915                 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */
2916                         continue;
2917
2918                 } else {
2919                         char const *attr, *value;
2920                         CONF_PAIR *cp = cf_item_to_pair(ci);
2921
2922                         attr = cf_pair_attr(cp);
2923                         value = cf_pair_value(cp);
2924
2925                         /*
2926                          *      A CONF_PAIR is either a module
2927                          *      instance with no actions
2928                          *      specified ...
2929                          */
2930                         if (!value) {
2931                                 modcallable *single;
2932                                 char const *junk = NULL;
2933
2934                                 single = do_compile_modsingle(c,
2935                                                               component,
2936                                                               ci,
2937                                                               grouptype,
2938                                                               &junk);
2939                                 if (!single) {
2940                                         if (cf_item_is_pair(ci) &&
2941                                             cf_pair_attr(cf_item_to_pair(ci))[0] == '-') {
2942                                                 continue;
2943                                         }
2944
2945                                         cf_log_err(ci,
2946                                                    "Failed to parse \"%s\" entry.",
2947                                                    attr);
2948                                         talloc_free(c);
2949                                         return NULL;
2950                                 }
2951                                 add_child(g, single);
2952
2953                                 /*
2954                                  *      Or a module instance with action.
2955                                  */
2956                         } else if (!compile_action(c, cp)) {
2957                                 talloc_free(c);
2958                                 return NULL;
2959                         } /* else it worked */
2960                 }
2961         }
2962
2963 set_codes:
2964         /*
2965          *      Set the default actions, if they haven't already been
2966          *      set.
2967          */
2968         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
2969                 if (!c->actions[i]) {
2970                         if (!parent || (component != MOD_AUTHENTICATE)) {
2971                                 c->actions[i] = defaultactions[component][parentgrouptype][i];
2972                         } else { /* inside Auth-Type has different rules */
2973                                 c->actions[i] = authtype_actions[parentgrouptype][i];
2974                         }
2975                 }
2976         }
2977
2978         switch (c->type) {
2979         default:
2980                 break;
2981
2982         case MOD_GROUP:
2983                 if (grouptype != GROUPTYPE_REDUNDANT) break;
2984                 /* FALL-THROUGH */
2985
2986         case MOD_LOAD_BALANCE:
2987         case MOD_REDUNDANT_LOAD_BALANCE:
2988                 if (!g->children) {
2989                         cf_log_err_cs(g->cs, "%s sections cannot be empty",
2990                                       cf_section_name1(g->cs));
2991                         talloc_free(c);
2992                         return NULL;
2993                 }
2994         }
2995
2996         /*
2997          *      FIXME: If there are no children, return NULL?
2998          */
2999         return mod_grouptocallable(g);
3000 }
3001
3002 modcallable *compile_modgroup(modcallable *parent,
3003                               rlm_components_t component, CONF_SECTION *cs)
3004 {
3005         modcallable *ret = do_compile_modgroup(parent, component, cs,
3006                                                GROUPTYPE_SIMPLE,
3007                                                GROUPTYPE_SIMPLE, MOD_GROUP);
3008
3009         if (rad_debug_lvl > 3) {
3010                 modcall_debug(ret, 2);
3011         }
3012
3013         return ret;
3014 }
3015
3016 void add_to_modcallable(modcallable *parent, modcallable *this)
3017 {
3018         modgroup *g;
3019
3020         rad_assert(this != NULL);
3021         rad_assert(parent != NULL);
3022
3023         g = mod_callabletogroup(parent);
3024
3025         add_child(g, this);
3026 }
3027
3028
3029 #ifdef WITH_UNLANG
3030 static bool pass2_xlat_compile(CONF_ITEM const *ci, vp_tmpl_t **pvpt, bool convert,
3031                                DICT_ATTR const *da)
3032 {
3033         ssize_t slen;
3034         char *fmt;
3035         char const *error;
3036         xlat_exp_t *head;
3037         vp_tmpl_t *vpt;
3038
3039         vpt = *pvpt;
3040
3041         rad_assert(vpt->type == TMPL_TYPE_XLAT);
3042
3043         fmt = talloc_typed_strdup(vpt, vpt->name);
3044         slen = xlat_tokenize(vpt, fmt, &head, &error);
3045
3046         if (slen < 0) {
3047                 char *spaces, *text;
3048
3049                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3050
3051                 cf_log_err(ci, "Failed parsing expanded string:");
3052                 cf_log_err(ci, "%s", text);
3053                 cf_log_err(ci, "%s^ %s", spaces, error);
3054
3055                 talloc_free(spaces);
3056                 talloc_free(text);
3057                 return false;
3058         }
3059
3060         /*
3061          *      Convert %{Attribute-Name} to &Attribute-Name
3062          */
3063         if (convert) {
3064                 vp_tmpl_t *attr;
3065
3066                 attr = xlat_to_tmpl_attr(talloc_parent(vpt), head);
3067                 if (attr) {
3068                         /*
3069                          *      If it's a virtual attribute, leave it
3070                          *      alone.
3071                          */
3072                         if (attr->tmpl_da->flags.virtual) {
3073                                 talloc_free(attr);
3074                                 return true;
3075                         }
3076
3077                         /*
3078                          *      If the attribute is of incompatible
3079                          *      type, leave it alone.
3080                          */
3081                         if (da && (da->type != attr->tmpl_da->type)) {
3082                                 talloc_free(attr);
3083                                 return true;
3084                         }
3085
3086                         if (cf_item_is_pair(ci)) {
3087                                 CONF_PAIR *cp = cf_item_to_pair(ci);
3088
3089                                 WARN("%s[%d]: Please change \"%%{%s}\" to &%s",
3090                                        cf_pair_filename(cp), cf_pair_lineno(cp),
3091                                        attr->name, attr->name);
3092                         } else {
3093                                 CONF_SECTION *cs = cf_item_to_section(ci);
3094
3095                                 WARN("%s[%d]: Please change \"%%{%s}\" to &%s",
3096                                        cf_section_filename(cs), cf_section_lineno(cs),
3097                                        attr->name, attr->name);
3098                         }
3099                         TALLOC_FREE(*pvpt);
3100                         *pvpt = attr;
3101                         return true;
3102                 }
3103         }
3104
3105         /*
3106          *      Re-write it to be a pre-parsed XLAT structure.
3107          */
3108         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3109         vpt->tmpl_xlat = head;
3110
3111         return true;
3112 }
3113
3114
3115 #ifdef HAVE_REGEX
3116 static bool pass2_regex_compile(CONF_ITEM const *ci, vp_tmpl_t *vpt)
3117 {
3118         ssize_t slen;
3119         regex_t *preg;
3120
3121         rad_assert(vpt->type == TMPL_TYPE_REGEX);
3122
3123         /*
3124          *      It's a dynamic expansion.  We can't expand the string,
3125          *      but we can pre-parse it as an xlat struct.  In that
3126          *      case, we convert it to a pre-compiled XLAT.
3127          *
3128          *      This is a little more complicated than it needs to be
3129          *      because radius_evaluate_map() keys off of the src
3130          *      template type, instead of the operators.  And, the
3131          *      pass2_xlat_compile() function expects to get passed an
3132          *      XLAT instead of a REGEX.
3133          */
3134         if (strchr(vpt->name, '%')) {
3135                 vpt->type = TMPL_TYPE_XLAT;
3136                 return pass2_xlat_compile(ci, &vpt, false, NULL);
3137         }
3138
3139         slen = regex_compile(vpt, &preg, vpt->name, vpt->len,
3140                              vpt->tmpl_iflag, vpt->tmpl_mflag, true, false);
3141         if (slen <= 0) {
3142                 char *spaces, *text;
3143
3144                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3145
3146                 cf_log_err(ci, "Invalid regular expression:");
3147                 cf_log_err(ci, "%s", text);
3148                 cf_log_err(ci, "%s^ %s", spaces, fr_strerror());
3149
3150                 talloc_free(spaces);
3151                 talloc_free(text);
3152
3153                 return false;
3154         }
3155
3156         vpt->type = TMPL_TYPE_REGEX_STRUCT;
3157         vpt->tmpl_preg = preg;
3158
3159         return true;
3160 }
3161 #endif
3162
3163 static bool pass2_fixup_undefined(CONF_ITEM const *ci, vp_tmpl_t *vpt)
3164 {
3165         DICT_ATTR const *da;
3166
3167         rad_assert(vpt->type == TMPL_TYPE_ATTR_UNDEFINED);
3168
3169         da = dict_attrbyname(vpt->tmpl_unknown_name);
3170         if (!da) {
3171                 cf_log_err(ci, "Unknown attribute '%s'", vpt->tmpl_unknown_name);
3172                 return false;
3173         }
3174
3175         vpt->tmpl_da = da;
3176         vpt->type = TMPL_TYPE_ATTR;
3177         return true;
3178 }
3179
3180 static bool pass2_callback(void *ctx, fr_cond_t *c)
3181 {
3182         vp_map_t *map;
3183         vp_tmpl_t *vpt;
3184
3185         /*
3186          *      These don't get optimized.
3187          */
3188         if ((c->type == COND_TYPE_TRUE) ||
3189             (c->type == COND_TYPE_FALSE)) {
3190                 return true;
3191         }
3192
3193         /*
3194          *      Call children.
3195          */
3196         if (c->type == COND_TYPE_CHILD) return pass2_callback(ctx, c->data.child);
3197
3198         /*
3199          *      A few simple checks here.
3200          */
3201         if (c->type == COND_TYPE_EXISTS) {
3202                 if (c->data.vpt->type == TMPL_TYPE_XLAT) {
3203                         return pass2_xlat_compile(c->ci, &c->data.vpt, true, NULL);
3204                 }
3205
3206                 rad_assert(c->data.vpt->type != TMPL_TYPE_REGEX);
3207
3208                 /*
3209                  *      The existence check might have been &Foo-Bar,
3210                  *      where Foo-Bar is defined by a module.
3211                  */
3212                 if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3213                         if (!pass2_fixup_undefined(c->ci, c->data.vpt)) return false;
3214                         c->pass2_fixup = PASS2_FIXUP_NONE;
3215                 }
3216
3217                 /*
3218                  *      Convert virtual &Attr-Foo to "%{Attr-Foo}"
3219                  */
3220                 vpt = c->data.vpt;
3221                 if ((vpt->type == TMPL_TYPE_ATTR) && vpt->tmpl_da->flags.virtual) {
3222                         vpt->tmpl_xlat = xlat_from_tmpl_attr(vpt, vpt);
3223                         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3224                 }
3225
3226                 return true;
3227         }
3228
3229         /*
3230          *      And tons of complicated checks.
3231          */
3232         rad_assert(c->type == COND_TYPE_MAP);
3233
3234         map = c->data.map;      /* shorter */
3235
3236         /*
3237          *      Auth-Type := foo
3238          *
3239          *      Where "foo" is dynamically defined.
3240          */
3241         if (c->pass2_fixup == PASS2_FIXUP_TYPE) {
3242                 if (!dict_valbyname(map->lhs->tmpl_da->attr,
3243                                     map->lhs->tmpl_da->vendor,
3244                                     map->rhs->name)) {
3245                         cf_log_err(map->ci, "Invalid reference to non-existent %s %s { ... }",
3246                                    map->lhs->tmpl_da->name,
3247                                    map->rhs->name);
3248                         return false;
3249                 }
3250
3251                 /*
3252                  *      These guys can't have a paircompare fixup applied.
3253                  */
3254                 c->pass2_fixup = PASS2_FIXUP_NONE;
3255                 return true;
3256         }
3257
3258         if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3259                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3260                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3261                 }
3262
3263                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3264                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3265                 }
3266
3267                 c->pass2_fixup = PASS2_FIXUP_NONE;
3268         }
3269
3270         /*
3271          *      Just in case someone adds a new fixup later.
3272          */
3273         rad_assert((c->pass2_fixup == PASS2_FIXUP_NONE) ||
3274                    (c->pass2_fixup == PASS2_PAIRCOMPARE));
3275
3276         /*
3277          *      Precompile xlat's
3278          */
3279         if (map->lhs->type == TMPL_TYPE_XLAT) {
3280                 /*
3281                  *      Compile the LHS to an attribute reference only
3282                  *      if the RHS is a literal.
3283                  *
3284                  *      @todo v3.1: allow anything anywhere.
3285                  */
3286                 if (map->rhs->type != TMPL_TYPE_LITERAL) {
3287                         if (!pass2_xlat_compile(map->ci, &map->lhs, false, NULL)) {
3288                                 return false;
3289                         }
3290                 } else {
3291                         if (!pass2_xlat_compile(map->ci, &map->lhs, true, NULL)) {
3292                                 return false;
3293                         }
3294
3295                         /*
3296                          *      Attribute compared to a literal gets
3297                          *      the literal cast to the data type of
3298                          *      the attribute.
3299                          *
3300                          *      The code in parser.c did this for
3301                          *
3302                          *              &Attr == data
3303                          *
3304                          *      But now we've just converted "%{Attr}"
3305                          *      to &Attr, so we've got to do it again.
3306                          */
3307                         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
3308                             (map->rhs->type == TMPL_TYPE_LITERAL)) {
3309                                 /*
3310                                  *      RHS is hex, try to parse it as
3311                                  *      type-specific data.
3312                                  */
3313                                 if (map->lhs->auto_converted &&
3314                                     (map->rhs->name[0] == '0') && (map->rhs->name[1] == 'x') &&
3315                                     (map->rhs->len > 2) && ((map->rhs->len & 0x01) == 0)) {
3316                                         vpt = map->rhs;
3317                                         map->rhs = NULL;
3318
3319                                         if (!map_cast_from_hex(map, T_BARE_WORD, vpt->name)) {
3320                                                 map->rhs = vpt;
3321                                                 cf_log_err(map->ci, "%s", fr_strerror());
3322                                                 return -1;
3323                                         }
3324                                         talloc_free(vpt);
3325
3326                                 } else if ((map->rhs->len > 0) ||
3327                                            (map->op != T_OP_CMP_EQ) ||
3328                                            (map->lhs->tmpl_da->type == PW_TYPE_STRING) ||
3329                                            (map->lhs->tmpl_da->type == PW_TYPE_OCTETS)) {
3330
3331                                         if (tmpl_cast_in_place(map->rhs, map->lhs->tmpl_da->type, map->lhs->tmpl_da) < 0) {
3332                                                 cf_log_err(map->ci, "Failed to parse data type %s from string: %s",
3333                                                            fr_int2str(dict_attr_types, map->lhs->tmpl_da->type, "<UNKNOWN>"),
3334                                                            map->rhs->name);
3335                                                 return false;
3336                                         } /* else the cast was successful */
3337
3338                                 } else {        /* RHS is empty, it's just a check for empty / non-empty string */
3339                                         vpt = talloc_steal(c, map->lhs);
3340                                         map->lhs = NULL;
3341                                         talloc_free(c->data.map);
3342
3343                                         /*
3344                                          *      "%{Foo}" == '' ---> !Foo
3345                                          *      "%{Foo}" != '' ---> Foo
3346                                          */
3347                                         c->type = COND_TYPE_EXISTS;
3348                                         c->data.vpt = vpt;
3349                                         c->negate = !c->negate;
3350
3351                                         WARN("%s[%d]: Please change (\"%%{%s}\" %s '') to %c&%s",
3352                                              cf_section_filename(cf_item_to_section(c->ci)),
3353                                              cf_section_lineno(cf_item_to_section(c->ci)),
3354                                              vpt->name, c->negate ? "==" : "!=",
3355                                              c->negate ? '!' : ' ', vpt->name);
3356
3357                                         /*
3358                                          *      No more RHS, so we can't do more optimizations
3359                                          */
3360                                         return true;
3361                                 }
3362                         }
3363                 }
3364         }
3365
3366         if (map->rhs->type == TMPL_TYPE_XLAT) {
3367                 /*
3368                  *      Convert the RHS to an attribute reference only
3369                  *      if the LHS is an attribute reference, AND is
3370                  *      of the same type as the RHS.
3371                  *
3372                  *      We can fix this when the code in evaluate.c
3373                  *      can handle strings on the LHS, and attributes
3374                  *      on the RHS.  For now, the code in parser.c
3375                  *      forbids this.
3376                  */
3377                 if (map->lhs->type == TMPL_TYPE_ATTR) {
3378                         DICT_ATTR const *da = c->cast;
3379
3380                         if (!c->cast) da = map->lhs->tmpl_da;
3381
3382                         if (!pass2_xlat_compile(map->ci, &map->rhs, true, da)) {
3383                                 return false;
3384                         }
3385
3386                 } else {
3387                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3388                                 return false;
3389                         }
3390                 }
3391         }
3392
3393         /*
3394          *      Convert bare refs to %{Foreach-Variable-N}
3395          */
3396         if ((map->lhs->type == TMPL_TYPE_LITERAL) &&
3397             (strncmp(map->lhs->name, "Foreach-Variable-", 17) == 0)) {
3398                 char *fmt;
3399                 ssize_t slen;
3400
3401                 fmt = talloc_asprintf(map->lhs, "%%{%s}", map->lhs->name);
3402                 slen = tmpl_afrom_str(map, &vpt, fmt, talloc_array_length(fmt) - 1,
3403                                       T_DOUBLE_QUOTED_STRING, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3404                 if (slen < 0) {
3405                         char *spaces, *text;
3406
3407                         fr_canonicalize_error(map->ci, &spaces, &text, slen, fr_strerror());
3408
3409                         cf_log_err(map->ci, "Failed converting %s to xlat", map->lhs->name);
3410                         cf_log_err(map->ci, "%s", fmt);
3411                         cf_log_err(map->ci, "%s^ %s", spaces, text);
3412
3413                         talloc_free(spaces);
3414                         talloc_free(text);
3415                         talloc_free(fmt);
3416
3417                         return false;
3418                 }
3419                 talloc_free(map->lhs);
3420                 map->lhs = vpt;
3421         }
3422
3423 #ifdef HAVE_REGEX
3424         if (map->rhs->type == TMPL_TYPE_REGEX) {
3425                 if (!pass2_regex_compile(map->ci, map->rhs)) {
3426                         return false;
3427                 }
3428         }
3429         rad_assert(map->lhs->type != TMPL_TYPE_REGEX);
3430 #endif
3431
3432         /*
3433          *      Convert &Packet-Type to "%{Packet-Type}", because
3434          *      these attributes don't really exist.  The code to
3435          *      find an attribute reference doesn't work, but the
3436          *      xlat code does.
3437          */
3438         vpt = c->data.map->lhs;
3439         if ((vpt->type == TMPL_TYPE_ATTR) && vpt->tmpl_da->flags.virtual) {
3440                 if (!c->cast) c->cast = vpt->tmpl_da;
3441                 vpt->tmpl_xlat = xlat_from_tmpl_attr(vpt, vpt);
3442                 vpt->type = TMPL_TYPE_XLAT_STRUCT;
3443         }
3444
3445         /*
3446          *      Convert RHS to expansions, too.
3447          */
3448         vpt = c->data.map->rhs;
3449         if ((vpt->type == TMPL_TYPE_ATTR) && vpt->tmpl_da->flags.virtual) {
3450                 vpt->tmpl_xlat = xlat_from_tmpl_attr(vpt, vpt);
3451                 vpt->type = TMPL_TYPE_XLAT_STRUCT;
3452         }
3453
3454         /*
3455          *      @todo v3.1: do the same thing for the RHS...
3456          */
3457
3458         /*
3459          *      Only attributes can have a paircompare registered, and
3460          *      they can only be with the current REQUEST, and only
3461          *      with the request pairs.
3462          */
3463         if ((map->lhs->type != TMPL_TYPE_ATTR) ||
3464             (map->lhs->tmpl_request != REQUEST_CURRENT) ||
3465             (map->lhs->tmpl_list != PAIR_LIST_REQUEST)) {
3466                 return true;
3467         }
3468
3469         if (!radius_find_compare(map->lhs->tmpl_da)) return true;
3470
3471         if (map->rhs->type == TMPL_TYPE_ATTR) {
3472                 cf_log_err(map->ci, "Cannot compare virtual attribute %s to another attribute",
3473                            map->lhs->name);
3474                 return false;
3475         }
3476
3477         if (map->rhs->type == TMPL_TYPE_REGEX) {
3478                 cf_log_err(map->ci, "Cannot compare virtual attribute %s via a regex",
3479                            map->lhs->name);
3480                 return false;
3481         }
3482
3483         if (c->cast) {
3484                 cf_log_err(map->ci, "Cannot cast virtual attribute %s",
3485                            map->lhs->name);
3486                 return false;
3487         }
3488
3489         if (map->op != T_OP_CMP_EQ) {
3490                 cf_log_err(map->ci, "Must use '==' for comparisons with virtual attribute %s",
3491                            map->lhs->name);
3492                 return false;
3493         }
3494
3495         /*
3496          *      Mark it as requiring a paircompare() call, instead of
3497          *      fr_pair_cmp().
3498          */
3499         c->pass2_fixup = PASS2_PAIRCOMPARE;
3500
3501         return true;
3502 }
3503
3504
3505 /*
3506  *      Compile the RHS of update sections to xlat_exp_t
3507  */
3508 static bool modcall_pass2_update(modgroup *g)
3509 {
3510         vp_map_t *map;
3511
3512         for (map = g->map; map != NULL; map = map->next) {
3513                 if (map->rhs->type == TMPL_TYPE_XLAT) {
3514                         rad_assert(map->rhs->tmpl_xlat == NULL);
3515
3516                         /*
3517                          *      FIXME: compile to attribute && handle
3518                          *      the conversion in map_to_vp().
3519                          */
3520                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3521                                 return false;
3522                         }
3523                 }
3524
3525                 rad_assert(map->rhs->type != TMPL_TYPE_REGEX);
3526
3527                 /*
3528                  *      Deal with undefined attributes now.
3529                  */
3530                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3531                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3532                 }
3533
3534                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3535                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3536                 }
3537         }
3538
3539         return true;
3540 }
3541 #endif
3542
3543 /*
3544  *      Do a second-stage pass on compiling the modules.
3545  */
3546 bool modcall_pass2(modcallable *mc)
3547 {
3548         ssize_t slen;
3549         char const *name2;
3550         modcallable *c;
3551         modgroup *g;
3552
3553         for (c = mc; c != NULL; c = c->next) {
3554                 switch (c->type) {
3555                 default:
3556                         rad_assert(0 == 1);
3557                         break;
3558
3559 #ifdef WITH_UNLANG
3560                 case MOD_UPDATE:
3561                         g = mod_callabletogroup(c);
3562                         if (g->done_pass2) goto do_next;
3563
3564                         name2 = cf_section_name2(g->cs);
3565                         if (!name2) {
3566                                 c->debug_name = unlang_keyword[c->type];
3567                         } else {
3568                                 c->debug_name = talloc_asprintf(c, "update %s", name2);
3569                         }
3570
3571                         if (!modcall_pass2_update(g)) {
3572                                 return false;
3573                         }
3574                         g->done_pass2 = true;
3575                         break;
3576
3577                 case MOD_XLAT:   /* @todo: pre-parse xlat's */
3578                 case MOD_REFERENCE:
3579                 case MOD_BREAK:
3580                 case MOD_RETURN:
3581 #endif
3582
3583                 case MOD_SINGLE:
3584                         c->debug_name = c->name;
3585                         break;  /* do nothing */
3586
3587 #ifdef WITH_UNLANG
3588                 case MOD_IF:
3589                 case MOD_ELSIF:
3590                         g = mod_callabletogroup(c);
3591                         if (g->done_pass2) goto do_next;
3592
3593                         name2 = cf_section_name2(g->cs);
3594                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3595
3596                         /*
3597                          *      The compilation code takes care of
3598                          *      simplifying 'true' and 'false'
3599                          *      conditions.  For others, we have to do
3600                          *      a second pass to parse && compile
3601                          *      xlats.
3602                          */
3603                         if (!((g->cond->type == COND_TYPE_TRUE) ||
3604                               (g->cond->type == COND_TYPE_FALSE))) {
3605                                 if (!fr_condition_walk(g->cond, pass2_callback, NULL)) {
3606                                         return false;
3607                                 }
3608                         }
3609
3610                         if (!modcall_pass2(g->children)) return false;
3611                         g->done_pass2 = true;
3612                         break;
3613 #endif
3614
3615 #ifdef WITH_UNLANG
3616                 case MOD_SWITCH:
3617                         g = mod_callabletogroup(c);
3618                         if (g->done_pass2) goto do_next;
3619
3620                         name2 = cf_section_name2(g->cs);
3621                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3622
3623                         /*
3624                          *      We had &Foo-Bar, where Foo-Bar is
3625                          *      defined by a module.
3626                          */
3627                         if (!g->vpt) {
3628                                 rad_assert(c->name != NULL);
3629                                 rad_assert(c->name[0] == '&');
3630                                 rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3631
3632                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3633                                                       cf_section_name2_type(g->cs),
3634                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3635                                 if (slen < 0) {
3636                                         char *spaces, *text;
3637
3638                                 parse_error:
3639                                         fr_canonicalize_error(g->cs, &spaces, &text, slen, fr_strerror());
3640
3641                                         cf_log_err_cs(g->cs, "Syntax error");
3642                                         cf_log_err_cs(g->cs, "%s", c->name);
3643                                         cf_log_err_cs(g->cs, "%s^ %s", spaces, text);
3644
3645                                         talloc_free(spaces);
3646                                         talloc_free(text);
3647
3648                                         return false;
3649                                 }
3650
3651                                 goto do_children;
3652                         }
3653
3654                         /*
3655                          *      Statically compile xlats
3656                          */
3657                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3658                                 if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3659                                                         &g->vpt, true, NULL)) {
3660                                         return false;
3661                                 }
3662
3663                                 goto do_children;
3664                         }
3665
3666                         /*
3667                          *      Convert virtual &Attr-Foo to "%{Attr-Foo}"
3668                          */
3669                         if ((g->vpt->type == TMPL_TYPE_ATTR) && g->vpt->tmpl_da->flags.virtual) {
3670                                 g->vpt->tmpl_xlat = xlat_from_tmpl_attr(g->vpt, g->vpt);
3671                                 g->vpt->type = TMPL_TYPE_XLAT_STRUCT;
3672                         }
3673
3674                         /*
3675                          *      We may have: switch Foo-Bar {
3676                          *
3677                          *      where Foo-Bar is an attribute defined
3678                          *      by a module.  Since there's no leading
3679                          *      &, it's parsed as a literal.  But if
3680                          *      we can parse it as an attribute,
3681                          *      switch to using that.
3682                          */
3683                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3684                                 vp_tmpl_t *vpt;
3685
3686                                 slen = tmpl_afrom_str(g->cs, &vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3687                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3688                                 if (slen < 0) goto parse_error;
3689                                 if (vpt->type == TMPL_TYPE_ATTR) {
3690                                         talloc_free(g->vpt);
3691                                         g->vpt = vpt;
3692                                 }
3693
3694                                 goto do_children;
3695                         }
3696
3697                         /*
3698                          *      Warn about old-style configuration.
3699                          *
3700                          *      DEPRECATED: switch User-Name { ...
3701                          *      ALLOWED   : switch &User-Name { ...
3702                          */
3703                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
3704                             (c->name[0] != '&')) {
3705                                 WARN("%s[%d]: Please change %s to &%s",
3706                                      cf_section_filename(g->cs),
3707                                      cf_section_lineno(g->cs),
3708                                      c->name, c->name);
3709                         }
3710
3711                 do_children:
3712                         if (!modcall_pass2(g->children)) return false;
3713                         g->done_pass2 = true;
3714                         break;
3715
3716                 case MOD_CASE:
3717                         g = mod_callabletogroup(c);
3718                         if (g->done_pass2) goto do_next;
3719
3720                         name2 = cf_section_name2(g->cs);
3721                         if (!name2) {
3722                                 c->debug_name = unlang_keyword[c->type];
3723                         } else {
3724                                 c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3725                         }
3726
3727                         rad_assert(c->parent != NULL);
3728                         rad_assert(c->parent->type == MOD_SWITCH);
3729
3730                         /*
3731                          *      The statement may refer to an
3732                          *      attribute which doesn't exist until
3733                          *      all of the modules have been loaded.
3734                          *      Check for that now.
3735                          */
3736                         if (!g->vpt && c->name &&
3737                             (c->name[0] == '&') &&
3738                             (cf_section_name2_type(g->cs) == T_BARE_WORD)) {
3739                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3740                                                       cf_section_name2_type(g->cs),
3741                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3742                                 if (slen < 0) goto parse_error;
3743                         }
3744
3745                         /*
3746                          *      We have "case {...}".  There's no
3747                          *      argument, so we don't need to check
3748                          *      it.
3749                          */
3750                         if (!g->vpt) goto do_children;
3751
3752                         /*
3753                          *      Do type-specific checks on the case statement
3754                          */
3755                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3756                                 modgroup *f;
3757
3758                                 f = mod_callabletogroup(mc->parent);
3759                                 rad_assert(f->vpt != NULL);
3760
3761                                 /*
3762                                  *      We're switching over an
3763                                  *      attribute.  Check that the
3764                                  *      values match.
3765                                  */
3766                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3767                                         rad_assert(f->vpt->tmpl_da != NULL);
3768
3769                                         if (tmpl_cast_in_place(g->vpt, f->vpt->tmpl_da->type, f->vpt->tmpl_da) < 0) {
3770                                                 cf_log_err_cs(g->cs, "Invalid argument for case statement: %s",
3771                                                               fr_strerror());
3772                                                 return false;
3773                                         }
3774                                 }
3775
3776                                 goto do_children;
3777                         }
3778
3779                         /*
3780                          *      Compile and sanity check xlat
3781                          *      expansions.
3782                          */
3783                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3784                                 modgroup *f;
3785
3786                                 f = mod_callabletogroup(mc->parent);
3787                                 rad_assert(f->vpt != NULL);
3788
3789                                 /*
3790                                  *      Don't expand xlat's into an
3791                                  *      attribute of a different type.
3792                                  */
3793                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3794                                         if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3795                                                                 &g->vpt, true, f->vpt->tmpl_da)) {
3796                                                 return false;
3797                                         }
3798                                 } else {
3799                                         if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3800                                                                 &g->vpt, true, NULL)) {
3801                                                 return false;
3802                                         }
3803                                 }
3804                         }
3805
3806                         /*
3807                          *      Virtual attribute fixes for "case" statements, too.
3808                          */
3809                         if ((g->vpt->type == TMPL_TYPE_ATTR) && g->vpt->tmpl_da->flags.virtual) {
3810                                 g->vpt->tmpl_xlat = xlat_from_tmpl_attr(g->vpt, g->vpt);
3811                                 g->vpt->type = TMPL_TYPE_XLAT_STRUCT;
3812                         }
3813
3814                         if (!modcall_pass2(g->children)) return false;
3815                         g->done_pass2 = true;
3816                         break;
3817
3818                 case MOD_FOREACH:
3819                         g = mod_callabletogroup(c);
3820                         if (g->done_pass2) goto do_next;
3821
3822                         name2 = cf_section_name2(g->cs);
3823                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3824
3825                         /*
3826                          *      Already parsed, handle the children.
3827                          */
3828                         if (g->vpt) goto check_children;
3829
3830                         /*
3831                          *      We had &Foo-Bar, where Foo-Bar is
3832                          *      defined by a module.
3833                          */
3834                         rad_assert(c->name != NULL);
3835                         rad_assert(c->name[0] == '&');
3836                         rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3837
3838                         /*
3839                          *      The statement may refer to an
3840                          *      attribute which doesn't exist until
3841                          *      all of the modules have been loaded.
3842                          *      Check for that now.
3843                          */
3844                         slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3845                                               REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3846                         if (slen < 0) goto parse_error;
3847
3848                 check_children:
3849                         rad_assert((g->vpt->type == TMPL_TYPE_ATTR) || (g->vpt->type == TMPL_TYPE_LIST));
3850                         if (g->vpt->tmpl_num != NUM_ALL) {
3851                                 cf_log_err_cs(g->cs, "MUST NOT use instance selectors in 'foreach'");
3852                                 return false;
3853                         }
3854                         if (!modcall_pass2(g->children)) return false;
3855                         g->done_pass2 = true;
3856                         break;
3857
3858                 case MOD_ELSE:
3859                         c->debug_name = unlang_keyword[c->type];
3860                         goto do_recurse;
3861
3862                 case MOD_POLICY:
3863                         g = mod_callabletogroup(c);
3864                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], cf_section_name1(g->cs));
3865                         goto do_recurse;
3866 #endif
3867
3868                 case MOD_GROUP:
3869                 case MOD_LOAD_BALANCE:
3870                 case MOD_REDUNDANT_LOAD_BALANCE:
3871                         c->debug_name = unlang_keyword[c->type];
3872
3873 #ifdef WITH_UNLANG
3874                 do_recurse:
3875 #endif
3876                         g = mod_callabletogroup(c);
3877                         if (!g->cs) {
3878                                 c->debug_name = mc->name; /* for authorize, etc. */
3879
3880                         } else if (c->type == MOD_GROUP) { /* for Auth-Type, etc. */
3881                                 char const *name1 = cf_section_name1(g->cs);
3882
3883                                 if (strcmp(name1, unlang_keyword[c->type]) != 0) {
3884                                         c->debug_name = talloc_asprintf(c, "%s %s", name1, cf_section_name2(g->cs));
3885                                 }
3886                         }
3887
3888                         if (g->done_pass2) goto do_next;
3889                         if (!modcall_pass2(g->children)) return false;
3890                         g->done_pass2 = true;
3891                         break;
3892                 }
3893
3894         do_next:
3895                 rad_assert(c->debug_name != NULL);
3896         }
3897
3898         return true;
3899 }
3900
3901 void modcall_debug(modcallable *mc, int depth)
3902 {
3903         modcallable *this;
3904         modgroup *g;
3905         vp_map_t *map;
3906         char buffer[1024];
3907
3908         for (this = mc; this != NULL; this = this->next) {
3909                 switch (this->type) {
3910                 default:
3911                         break;
3912
3913                 case MOD_SINGLE: {
3914                         modsingle *single = mod_callabletosingle(this);
3915
3916                         DEBUG("%.*s%s", depth, modcall_spaces,
3917                                 single->modinst->name);
3918                         }
3919                         break;
3920
3921 #ifdef WITH_UNLANG
3922                 case MOD_UPDATE:
3923                         g = mod_callabletogroup(this);
3924                         DEBUG("%.*s%s {", depth, modcall_spaces,
3925                                 unlang_keyword[this->type]);
3926
3927                         for (map = g->map; map != NULL; map = map->next) {
3928                                 map_prints(buffer, sizeof(buffer), map);
3929                                 DEBUG("%.*s%s", depth + 1, modcall_spaces, buffer);
3930                         }
3931
3932                         DEBUG("%.*s}", depth, modcall_spaces);
3933                         break;
3934
3935                 case MOD_ELSE:
3936                         g = mod_callabletogroup(this);
3937                         DEBUG("%.*s%s {", depth, modcall_spaces,
3938                                 unlang_keyword[this->type]);
3939                         modcall_debug(g->children, depth + 1);
3940                         DEBUG("%.*s}", depth, modcall_spaces);
3941                         break;
3942
3943                 case MOD_IF:
3944                 case MOD_ELSIF:
3945                         g = mod_callabletogroup(this);
3946                         fr_cond_sprint(buffer, sizeof(buffer), g->cond);
3947                         DEBUG("%.*s%s (%s) {", depth, modcall_spaces,
3948                                 unlang_keyword[this->type], buffer);
3949                         modcall_debug(g->children, depth + 1);
3950                         DEBUG("%.*s}", depth, modcall_spaces);
3951                         break;
3952
3953                 case MOD_SWITCH:
3954                 case MOD_CASE:
3955                         g = mod_callabletogroup(this);
3956                         tmpl_prints(buffer, sizeof(buffer), g->vpt, NULL);
3957                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3958                                 unlang_keyword[this->type], buffer);
3959                         modcall_debug(g->children, depth + 1);
3960                         DEBUG("%.*s}", depth, modcall_spaces);
3961                         break;
3962
3963                 case MOD_POLICY:
3964                 case MOD_FOREACH:
3965                         g = mod_callabletogroup(this);
3966                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3967                                 unlang_keyword[this->type], this->name);
3968                         modcall_debug(g->children, depth + 1);
3969                         DEBUG("%.*s}", depth, modcall_spaces);
3970                         break;
3971
3972                 case MOD_BREAK:
3973                         DEBUG("%.*sbreak", depth, modcall_spaces);
3974                         break;
3975
3976 #endif
3977                 case MOD_GROUP:
3978                         g = mod_callabletogroup(this);
3979                         DEBUG("%.*s%s {", depth, modcall_spaces,
3980                               unlang_keyword[this->type]);
3981                         modcall_debug(g->children, depth + 1);
3982                         DEBUG("%.*s}", depth, modcall_spaces);
3983                         break;
3984
3985
3986                 case MOD_LOAD_BALANCE:
3987                 case MOD_REDUNDANT_LOAD_BALANCE:
3988                         g = mod_callabletogroup(this);
3989                         DEBUG("%.*s%s {", depth, modcall_spaces,
3990                                 unlang_keyword[this->type]);
3991                         modcall_debug(g->children, depth + 1);
3992                         DEBUG("%.*s}", depth, modcall_spaces);
3993                         break;
3994                 }
3995         }
3996 }