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