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