1 /*
2  * modules.c	Radius module support.
3  *
4  * Version:	$Id: 9919482c8605d89c907ab37f6479f7c651b0f1a6 $
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 2003,2006  The FreeRADIUS server project
21  * Copyright 2000  Alan DeKok <aland@ox.org>
22  * Copyright 2000  Alan Curry <pacman@world.std.com>
23  */
24 
25 RCSID("$Id: 9919482c8605d89c907ab37f6479f7c651b0f1a6 $")
26 
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modpriv.h>
29 #include <freeradius-devel/modcall.h>
30 #include <freeradius-devel/parser.h>
31 #include <freeradius-devel/rad_assert.h>
32 
33 /** Path to search for modules in
34  *
35  */
36 char const *radlib_dir = NULL;
37 
38 typedef struct indexed_modcallable {
39 	rlm_components_t	comp;
40 	int			idx;
41 	modcallable		*modulelist;
42 } indexed_modcallable;
43 
44 typedef struct virtual_server_t {
45 	char const	*name;
46 	time_t		created;
47 	int		can_free;
48 	CONF_SECTION	*cs;
49 	rbtree_t	*components;
50 	modcallable	*mc[MOD_COUNT];
51 	CONF_SECTION	*subcs[MOD_COUNT];
52 	struct virtual_server_t *next;
53 } virtual_server_t;
54 
55 /*
56  *	Keep a hash of virtual servers, so that we can reload them.
57  */
58 #define VIRTUAL_SERVER_HASH_SIZE (256)
59 static virtual_server_t *virtual_servers[VIRTUAL_SERVER_HASH_SIZE];
60 
61 static rbtree_t *module_tree = NULL;
62 
63 static rbtree_t *instance_tree = NULL;
64 
65 struct fr_module_hup_t {
66 	module_instance_t	*mi;
67 	time_t			when;
68 	void			*insthandle;
69 	fr_module_hup_t		*next;
70 };
71 
72 /*
73  *	Ordered by component
74  */
75 const section_type_value_t section_type_value[MOD_COUNT] = {
76 	{ "authenticate", "Auth-Type",       PW_AUTH_TYPE },
77 	{ "authorize",    "Autz-Type",       PW_AUTZ_TYPE },
78 	{ "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },
79 	{ "accounting",   "Acct-Type",       PW_ACCT_TYPE },
80 	{ "session",      "Session-Type",    PW_SESSION_TYPE },
81 	{ "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
82 	{ "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
83 	{ "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE }
84 #ifdef WITH_COA
85 	,
86 	{ "recv-coa",     "Recv-CoA-Type",   PW_RECV_COA_TYPE },
87 	{ "send-coa",     "Send-CoA-Type",   PW_SEND_COA_TYPE }
88 #endif
89 };
90 
91 #ifndef RTLD_NOW
92 #define RTLD_NOW (0)
93 #endif
94 #ifndef RTLD_LOCAL
95 #define RTLD_LOCAL (0)
96 #endif
97 
98 /** Check if the magic number in the module matches the one in the library
99  *
100  * This is used to detect potential ABI issues caused by running with modules which
101  * were built for a different version of the server.
102  *
103  * @param cs being parsed.
104  * @param module being loaded.
105  * @returns 0 on success, -1 if prefix mismatch, -2 if version mismatch, -3 if commit mismatch.
106  */
check_module_magic(CONF_SECTION * cs,module_t const * module)107 static int check_module_magic(CONF_SECTION *cs, module_t const *module)
108 {
109 #ifdef HAVE_DLADDR
110 	Dl_info dl_info;
111 	dladdr(module, &dl_info);
112 #endif
113 
114 	if (MAGIC_PREFIX(module->magic) != MAGIC_PREFIX(RADIUSD_MAGIC_NUMBER)) {
115 #ifdef HAVE_DLADDR
116 		cf_log_err_cs(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
117 #endif
118 		cf_log_err_cs(cs, "Application and rlm_%s magic number (prefix) mismatch."
119 			      "  application: %x module: %x", module->name,
120 			      MAGIC_PREFIX(RADIUSD_MAGIC_NUMBER),
121 			      MAGIC_PREFIX(module->magic));
122 		return -1;
123 	}
124 
125 	if (MAGIC_VERSION(module->magic) != MAGIC_VERSION(RADIUSD_MAGIC_NUMBER)) {
126 #ifdef HAVE_DLADDR
127 		cf_log_err_cs(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
128 #endif
129 		cf_log_err_cs(cs, "Application and rlm_%s magic number (version) mismatch."
130 			      "  application: %lx module: %lx", module->name,
131 			      (unsigned long) MAGIC_VERSION(RADIUSD_MAGIC_NUMBER),
132 			      (unsigned long) MAGIC_VERSION(module->magic));
133 		return -2;
134 	}
135 
136 	if (MAGIC_COMMIT(module->magic) != MAGIC_COMMIT(RADIUSD_MAGIC_NUMBER)) {
137 #ifdef HAVE_DLADDR
138 		cf_log_err_cs(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
139 #endif
140 		cf_log_err_cs(cs, "Application and rlm_%s magic number (commit) mismatch."
141 			      "  application: %lx module: %lx", module->name,
142 			      (unsigned long) MAGIC_COMMIT(RADIUSD_MAGIC_NUMBER),
143 			      (unsigned long) MAGIC_COMMIT(module->magic));
144 		return -3;
145 	}
146 
147 	return 0;
148 }
149 
fr_dlopenext(char const * name)150 fr_dlhandle fr_dlopenext(char const *name)
151 {
152 	int		flags = RTLD_NOW;
153 	void		*handle;
154 	char		buffer[2048];
155 	char		*env;
156 	char const	*search_path;
157 #ifdef RTLD_GLOBAL
158 	if (strcmp(name, "rlm_perl") == 0) {
159 		flags |= RTLD_GLOBAL;
160 	} else
161 #endif
162 		flags |= RTLD_LOCAL;
163 #if defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__)
164 		flags |= RTLD_DEEPBIND;
165 #endif
166 
167 #ifndef NDEBUG
168 	/*
169 	 *	Bind all the symbols *NOW* so we don't hit errors later
170 	 */
171 	flags |= RTLD_NOW;
172 #endif
173 
174 	/*
175 	 *	Apple removed support for DYLD_LIBRARY_PATH in rootless mode.
176 	 */
177 	env = getenv("FR_LIBRARY_PATH");
178 	if (env) {
179 		DEBUG3("Ignoring libdir as FR_LIBRARY_PATH set.  Module search path will be: %s", env);
180 		search_path = env;
181 	} else {
182 		search_path = radlib_dir;
183 	}
184 
185 	/*
186 	 *	Prefer loading our libraries by absolute path.
187 	 */
188 	if (search_path) {
189 		char *error;
190 		char *ctx, *paths, *path;
191 		char *p;
192 
193 		fr_strerror();
194 
195 		ctx = paths = talloc_strdup(NULL, search_path);
196 		while ((path = strsep(&paths, ":")) != NULL) {
197 			/*
198 			 *	Trim the trailing slash
199 			 */
200 			p = strrchr(path, '/');
201 			if (p && ((p[1] == '\0') || (p[1] == ':'))) *p = '\0';
202 
203 			path = talloc_asprintf(ctx, "%s/%s%s", path, name, LT_SHREXT);
204 
205 			DEBUG4("Loading %s with path: %s", name, path);
206 
207 			handle = dlopen(path, flags);
208 			if (handle) {
209 				talloc_free(ctx);
210 				return handle;
211 			}
212 			error = dlerror();
213 
214 			fr_strerror_printf("%s%s\n", fr_strerror(), error);
215 			DEBUG4("Loading %s failed: %s - %s", name, error,
216 			       (access(path, R_OK) < 0) ? fr_syserror(errno) : "No access errors");
217 			talloc_free(path);
218 		}
219 		talloc_free(ctx);
220 	}
221 
222 	DEBUG4("Loading library using linker search path(s)");
223 	if (DEBUG_ENABLED4) {
224 #ifdef __APPLE__
225 		env = getenv("LD_LIBRARY_PATH");
226 		if (env) {
227 			DEBUG4("LD_LIBRARY_PATH            : %s", env);
228 		}
229 		env = getenv("DYLD_LIBRARY_PATH");
230 		if (env) {
231 			DEBUG4("DYLB_LIBRARY_PATH          : %s", env);
232 		}
233 		env = getenv("DYLD_FALLBACK_LIBRARY_PATH");
234 		if (env) {
235 			DEBUG4("DYLD_FALLBACK_LIBRARY_PATH : %s", env);
236 		}
237 		env = getcwd(buffer, sizeof(buffer));
238 		if (env) {
239 			DEBUG4("Current directory          : %s", env);
240 		}
241 #else
242 		env = getenv("LD_LIBRARY_PATH");
243 		if (env) {
244 			DEBUG4("LD_LIBRARY_PATH  : %s", env);
245 		}
246 		DEBUG4("Defaults         : /lib:/usr/lib");
247 #endif
248 	}
249 
250 	strlcpy(buffer, name, sizeof(buffer));
251 	/*
252 	 *	FIXME: Make this configurable...
253 	 */
254 	strlcat(buffer, LT_SHREXT, sizeof(buffer));
255 
256 	handle = dlopen(buffer, flags);
257 	if (!handle) {
258 		char *error = dlerror();
259 
260 		DEBUG4("Failed with error: %s", error);
261 		/*
262 		 *	Don't overwrite the previous message
263 		 *	It's likely to contain a better error.
264 		 */
265 		if (!radlib_dir) fr_strerror_printf("%s", dlerror());
266 		return NULL;
267 	}
268 	return handle;
269 }
270 
fr_dlsym(fr_dlhandle handle,char const * symbol)271 void *fr_dlsym(fr_dlhandle handle, char const *symbol)
272 {
273 	return dlsym(handle, symbol);
274 }
275 
fr_dlclose(fr_dlhandle handle)276 int fr_dlclose(fr_dlhandle handle)
277 {
278 	if (!handle) return 0;
279 
280 	return dlclose(handle);
281 }
282 
fr_dlerror(void)283 char const *fr_dlerror(void)
284 {
285 	return dlerror();
286 }
287 
virtual_server_idx(char const * name)288 static int virtual_server_idx(char const *name)
289 {
290 	uint32_t hash;
291 
292 	if (!name) return 0;
293 
294 	hash = fr_hash_string(name);
295 
296 	return hash & (VIRTUAL_SERVER_HASH_SIZE - 1);
297 }
298 
virtual_server_find(char const * name)299 static virtual_server_t *virtual_server_find(char const *name)
300 {
301 	rlm_rcode_t rcode;
302 	virtual_server_t *server;
303 
304 	rcode = virtual_server_idx(name);
305 	for (server = virtual_servers[rcode];
306 	     server != NULL;
307 	     server = server->next) {
308 		if (!name && !server->name) break;
309 
310 		if ((name && server->name) &&
311 		    (strcmp(name, server->name) == 0)) break;
312 	}
313 
314 	return server;
315 }
316 
_virtual_server_free(virtual_server_t * server)317 static int _virtual_server_free(virtual_server_t *server)
318 {
319 	if (server->components) rbtree_free(server->components);
320 	return 0;
321 }
322 
virtual_servers_free(time_t when)323 void virtual_servers_free(time_t when)
324 {
325 	int i;
326 	virtual_server_t **last;
327 
328 	for (i = 0; i < VIRTUAL_SERVER_HASH_SIZE; i++) {
329 		virtual_server_t *server, *next;
330 
331 		last = &virtual_servers[i];
332 		for (server = virtual_servers[i];
333 		     server != NULL;
334 		     server = next) {
335 			next = server->next;
336 
337 			/*
338 			 *	If we delete it, fix the links so that
339 			 *	we don't orphan anything.  Also,
340 			 *	delete it if it's old, AND a newer one
341 			 *	was defined.
342 			 *
343 			 *	Otherwise, the last pointer gets set to
344 			 *	the one we didn't delete.
345 			 */
346 			if ((when == 0) ||
347 			    ((server->created < when) && server->can_free)) {
348 				*last = server->next;
349 				talloc_free(server);
350 			} else {
351 				last = &(server->next);
352 			}
353 		}
354 	}
355 }
356 
indexed_modcallable_cmp(void const * one,void const * two)357 static int indexed_modcallable_cmp(void const *one, void const *two)
358 {
359 	indexed_modcallable const *a = one;
360 	indexed_modcallable const *b = two;
361 
362 	if (a->comp < b->comp) return -1;
363 	if (a->comp >  b->comp) return +1;
364 
365 	return a->idx - b->idx;
366 }
367 
368 
369 /*
370  *	Compare two module entries
371  */
module_instance_cmp(void const * one,void const * two)372 static int module_instance_cmp(void const *one, void const *two)
373 {
374 	module_instance_t const *a = one;
375 	module_instance_t const *b = two;
376 
377 	return strcmp(a->name, b->name);
378 }
379 
380 
module_instance_free_old(UNUSED CONF_SECTION * cs,module_instance_t * node,time_t when)381 static void module_instance_free_old(UNUSED CONF_SECTION *cs, module_instance_t *node, time_t when)
382 {
383 	fr_module_hup_t *mh, **last;
384 
385 	/*
386 	 *	Walk the list, freeing up old instances.
387 	 */
388 	last = &(node->mh);
389 	while (*last) {
390 		mh = *last;
391 
392 		/*
393 		 *	Free only every 60 seconds.
394 		 */
395 		if ((when - mh->when) < 60) {
396 			last = &(mh->next);
397 			continue;
398 		}
399 
400 		talloc_free(mh->insthandle);
401 
402 		*last = mh->next;
403 		talloc_free(mh);
404 	}
405 }
406 
407 
408 /*
409  *	Free a module instance.
410  */
module_instance_free(void * data)411 static void module_instance_free(void *data)
412 {
413 	module_instance_t *module = talloc_get_type_abort(data, module_instance_t);
414 
415 	module_instance_free_old(module->cs, module, time(NULL) + 100);
416 
417 #ifdef HAVE_PTHREAD_H
418 	if (module->mutex) {
419 		/*
420 		 *	FIXME
421 		 *	The mutex MIGHT be locked...
422 		 *	we'll check for that later, I guess.
423 		 */
424 		pthread_mutex_destroy(module->mutex);
425 		talloc_free(module->mutex);
426 	}
427 #endif
428 
429 	xlat_unregister(module->name, NULL, module->insthandle);
430 
431 	/*
432 	 *	Remove all xlat's registered to module instance.
433 	 */
434 	if (module->insthandle) {
435 		/*
436 		 *	Remove any registered paircompares.
437 		 */
438 		paircompare_unregister_instance(module->insthandle);
439 
440 		xlat_unregister_module(module->insthandle);
441 	}
442 	talloc_free(module);
443 }
444 
445 
446 /*
447  *	Compare two module entries
448  */
module_entry_cmp(void const * one,void const * two)449 static int module_entry_cmp(void const *one, void const *two)
450 {
451 	module_entry_t const *a = one;
452 	module_entry_t const *b = two;
453 
454 	return strcmp(a->name, b->name);
455 }
456 
457 /*
458  *	Free a module entry.
459  */
_module_entry_free(module_entry_t * this)460 static int _module_entry_free(module_entry_t *this)
461 {
462 #ifndef NDEBUG
463 	/*
464 	 *	Don't dlclose() modules if we're doing memory
465 	 *	debugging.  This removes the symbols needed by
466 	 *	valgrind.
467 	 */
468 	if (!main_config.debug_memory)
469 #endif
470 		dlclose(this->handle);	/* ignore any errors */
471 	return 0;
472 }
473 
474 
475 /*
476  *	Remove the module lists.
477  */
modules_free(void)478 int modules_free(void)
479 {
480 	rbtree_free(instance_tree);
481 	rbtree_free(module_tree);
482 
483 	return 0;
484 }
485 
486 
487 /*
488  *	dlopen() a module.
489  */
module_dlopen(CONF_SECTION * cs,char const * module_name)490 static module_entry_t *module_dlopen(CONF_SECTION *cs, char const *module_name)
491 {
492 	module_entry_t myentry;
493 	module_entry_t *node;
494 	void *handle = NULL;
495 	module_t const *module;
496 
497 	strlcpy(myentry.name, module_name, sizeof(myentry.name));
498 	node = rbtree_finddata(module_tree, &myentry);
499 	if (node) return node;
500 
501 	/*
502 	 *	Link to the module's rlm_FOO{} structure, the same as
503 	 *	the module name.
504 	 */
505 
506 #if !defined(WITH_LIBLTDL) && defined(HAVE_DLFCN_H) && defined(RTLD_SELF)
507 	module = dlsym(RTLD_SELF, module_name);
508 	if (module) goto open_self;
509 #endif
510 
511 	/*
512 	 *	Keep the handle around so we can dlclose() it.
513 	 */
514 	handle = fr_dlopenext(module_name);
515 	if (!handle) {
516 		cf_log_err_cs(cs, "Failed to link to module '%s': %s", module_name, fr_strerror());
517 		return NULL;
518 	}
519 
520 	DEBUG3("Loaded %s, checking if it's valid", module_name);
521 
522 	module = dlsym(handle, module_name);
523 	if (!module) {
524 		cf_log_err_cs(cs, "Failed linking to %s structure: %s", module_name, dlerror());
525 		dlclose(handle);
526 		return NULL;
527 	}
528 
529 #if !defined(WITH_LIBLTDL) && defined (HAVE_DLFCN_H) && defined(RTLD_SELF)
530  open_self:
531 #endif
532 	/*
533 	 *	Before doing anything else, check if it's sane.
534 	 */
535 	if (check_module_magic(cs, module) < 0) {
536 		dlclose(handle);
537 		return NULL;
538 	}
539 
540 	/* make room for the module type */
541 	node = talloc_zero(cs, module_entry_t);
542 	talloc_set_destructor(node, _module_entry_free);
543 	strlcpy(node->name, module_name, sizeof(node->name));
544 	node->module = module;
545 	node->handle = handle;
546 
547 	cf_log_module(cs, "Loaded module %s", module_name);
548 
549 	/*
550 	 *	Add the module as "rlm_foo-version" to the configuration
551 	 *	section.
552 	 */
553 	if (!rbtree_insert(module_tree, node)) {
554 		ERROR("Failed to cache module %s", module_name);
555 		dlclose(handle);
556 		talloc_free(node);
557 		return NULL;
558 	}
559 
560 	return node;
561 }
562 
563 /** Parse module's configuration section and setup destructors
564  *
565  */
module_conf_parse(module_instance_t * node,void ** handle)566 static int module_conf_parse(module_instance_t *node, void **handle)
567 {
568 	*handle = NULL;
569 
570 	/*
571 	 *	If there is supposed to be instance data, allocate it now.
572 	 *	Also parse the configuration data, if required.
573 	 */
574 	if (node->entry->module->inst_size) {
575 		*handle = talloc_zero_array(node, uint8_t, node->entry->module->inst_size);
576 		rad_assert(*handle);
577 
578 		talloc_set_name(*handle, "rlm_%s_t",
579 				node->entry->module->name ? node->entry->module->name : "config");
580 
581 		if (node->entry->module->config &&
582 		    (cf_section_parse(node->cs, *handle, node->entry->module->config) < 0)) {
583 			cf_log_err_cs(node->cs,"Invalid configuration for module \"%s\"", node->name);
584 			talloc_free(*handle);
585 
586 			return -1;
587 		}
588 
589 		/*
590 		 *	Set the destructor.
591 		 */
592 		if (node->entry->module->detach) {
593 			talloc_set_destructor(*handle, node->entry->module->detach);
594 		}
595 	}
596 
597 	return 0;
598 }
599 
600 /** Bootstrap a module.
601  *
602  *  Load the module shared library, allocate instance memory for it,
603  *  parse the module configuration, and call the modules "bootstrap" method.
604  */
module_bootstrap(CONF_SECTION * cs)605 static module_instance_t *module_bootstrap(CONF_SECTION *cs)
606 {
607 	char const *name1, *name2, *askedname;
608 	module_instance_t *node, myNode;
609 	char module_name[256];
610 
611 	/*
612 	 *	Figure out which module we want to load.
613 	 */
614 	name1 = cf_section_name1(cs);
615 	askedname = name2 = cf_section_name2(cs);
616 	if (!askedname) {
617 		askedname = name1;
618 		name2 = "";
619 	}
620 
621 	strlcpy(myNode.name, askedname, sizeof(myNode.name));
622 
623 	/*
624 	 *	See if the module already exists.
625 	 */
626 	node = rbtree_finddata(instance_tree, &myNode);
627 	if (node) {
628 		ERROR("Duplicate module \"%s %s { ... }\", in file %s:%d and file %s:%d",
629 		      name1, name2,
630 		      cf_section_filename(cs),
631 		      cf_section_lineno(cs),
632 		      cf_section_filename(node->cs),
633 		      cf_section_lineno(node->cs));
634 		return NULL;
635 	}
636 
637 	/*
638 	 *	Hang the node struct off of the configuration
639 	 *	section. If the CS is free'd the instance will be
640 	 *	free'd, too.
641 	 */
642 	node = talloc_zero(instance_tree, module_instance_t);
643 	node->cs = cs;
644 	strlcpy(node->name, askedname, sizeof(node->name));
645 
646 	/*
647 	 *	Names in the "modules" section aren't prefixed
648 	 *	with "rlm_", so we add it here.
649 	 */
650 	snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
651 
652 	/*
653 	 *	Load the module shared library.
654 	 */
655 	node->entry = module_dlopen(cs, module_name);
656 	if (!node->entry) {
657 		talloc_free(node);
658 		return NULL;
659 	}
660 
661 	cf_log_module(cs, "Loading module \"%s\" from file %s", node->name,
662 		      cf_section_filename(cs));
663 
664 	/*
665 	 *	Parse the modules configuration.
666 	 */
667 	if (module_conf_parse(node, &node->insthandle) < 0) {
668 		talloc_free(node);
669 		return NULL;
670 	}
671 
672 	/*
673 	 *	Bootstrap the module.
674 	 */
675 	if (node->entry->module->bootstrap &&
676 	    ((node->entry->module->bootstrap)(cs, node->insthandle) < 0)) {
677 		cf_log_err_cs(cs, "Instantiation failed for module \"%s\"", node->name);
678 		talloc_free(node);
679 		return NULL;
680 	}
681 
682 	/*
683 	 *	Remember the module for later.
684 	 */
685 	rbtree_insert(instance_tree, node);
686 
687 	return node;
688 }
689 
690 
691 /** Find an existing module instance.
692  *
693  */
module_find(CONF_SECTION * modules,char const * askedname)694 module_instance_t *module_find(CONF_SECTION *modules, char const *askedname)
695 {
696 	char const *instname;
697 	module_instance_t myNode;
698 
699 	if (!modules) return NULL;
700 
701 	/*
702 	 *	Look for the real name.  Ignore the first character,
703 	 *	which tells the server "it's OK for this module to not
704 	 *	exist."
705 	 */
706 	instname = askedname;
707 	if (instname[0] == '-') instname++;
708 
709 	strlcpy(myNode.name, instname, sizeof(myNode.name));
710 
711 	return rbtree_finddata(instance_tree, &myNode);
712 }
713 
714 
715 /** Load a module, and instantiate it.
716  *
717  */
module_instantiate(CONF_SECTION * modules,char const * askedname)718 module_instance_t *module_instantiate(CONF_SECTION *modules, char const *askedname)
719 {
720 	module_instance_t *node;
721 
722 	/*
723 	 *	Find the module.  If it's not there, do nothing.
724 	 */
725 	node = module_find(modules, askedname);
726 	if (!node) {
727 		ERROR("Cannot find module \"%s\"", askedname);
728 		return NULL;
729 	}
730 
731 	/*
732 	 *	The module is already instantiated.  Return it.
733 	 */
734 	if (node->instantiated) return node;
735 
736 	/*
737 	 *	Now that ALL modules are instantiated, and ALL xlats
738 	 *	are defined, go compile the config items marked as XLAT.
739 	 */
740 	if (node->entry->module->config &&
741 	    (cf_section_parse_pass2(node->cs, node->insthandle,
742 				    node->entry->module->config) < 0)) {
743 		return NULL;
744 	}
745 
746 	/*
747 	 *	Call the instantiate method, if any.
748 	 */
749 	if (node->entry->module->instantiate) {
750 		cf_log_module(node->cs, "Instantiating module \"%s\" from file %s", node->name,
751 			      cf_section_filename(node->cs));
752 
753 		/*
754 		 *	Call the module's instantiation routine.
755 		 */
756 		if ((node->entry->module->instantiate)(node->cs, node->insthandle) < 0) {
757 			cf_log_err_cs(node->cs, "Instantiation failed for module \"%s\"", node->name);
758 
759 			return NULL;
760 		}
761 	}
762 
763 #ifdef HAVE_PTHREAD_H
764 	/*
765 	 *	If we're threaded, check if the module is thread-safe.
766 	 *
767 	 *	If it isn't, we create a mutex.
768 	 */
769 	if ((node->entry->module->type & RLM_TYPE_THREAD_UNSAFE) != 0) {
770 		node->mutex = talloc_zero(node, pthread_mutex_t);
771 
772 		/*
773 		 *	Initialize the mutex.
774 		 */
775 		pthread_mutex_init(node->mutex, NULL);
776 	}
777 #endif
778 
779 	node->instantiated = true;
780 	node->last_hup = time(NULL); /* don't let us load it, then immediately hup it */
781 
782 	return node;
783 }
784 
785 
module_instantiate_method(CONF_SECTION * modules,char const * name,rlm_components_t * method)786 module_instance_t *module_instantiate_method(CONF_SECTION *modules, char const *name, rlm_components_t *method)
787 {
788 	char *p;
789 	rlm_components_t i;
790 	module_instance_t *mi;
791 
792 	/*
793 	 *	If the module exists, ensure it's instantiated.
794 	 *
795 	 *	Doing it this way avoids complaints from
796 	 *	module_instantiate()
797 	 */
798 	mi = module_find(modules, name);
799 	if (mi) return module_instantiate(modules, name);
800 
801 	/*
802 	 *	Find out which method is being used.
803 	 */
804 	p = strrchr(name, '.');
805 	if (!p) return NULL;
806 
807 	p++;
808 
809 	/*
810 	 *	Find the component.
811 	 */
812 	for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) {
813 		if (strcmp(p, section_type_value[i].section) == 0) {
814 			char buffer[256];
815 
816 			strlcpy(buffer, name, sizeof(buffer));
817 			buffer[p - name - 1] = '\0';
818 
819 			mi = module_find(modules, buffer);
820 			if (mi) {
821 				if (method) *method = i;
822 				return module_instantiate(modules, buffer);
823 			}
824 		}
825 	}
826 
827 	/*
828 	 *	Not found.
829 	 */
830 	return NULL;
831 }
832 
833 
834 /** Resolve polymorphic item's from a module's CONF_SECTION to a subsection in another module
835  *
836  * This allows certain module sections to reference module sections in other instances
837  * of the same module and share CONF_DATA associated with them.
838  *
839  * @verbatim
840 example {
841 	data {
842 		...
843 	}
844 }
845 
846 example inst {
847 	data = example
848 }
849  * @endverbatim
850  *
851  * @param out where to write the pointer to a module's config section.  May be NULL on success, indicating the config
852  *	  item was not found within the module CONF_SECTION, or the chain of module references was followed and the
853  *	  module at the end of the chain did not a subsection.
854  * @param module CONF_SECTION.
855  * @param name of the polymorphic sub-section.
856  * @return 0 on success with referenced section, 1 on success with local section, or -1 on failure.
857  */
find_module_sibling_section(CONF_SECTION ** out,CONF_SECTION * module,char const * name)858 int find_module_sibling_section(CONF_SECTION **out, CONF_SECTION *module, char const *name)
859 {
860 	static bool loop = true;	/* not used, we just need a valid pointer to quiet static analysis */
861 
862 	CONF_PAIR *cp;
863 	CONF_SECTION *cs;
864 
865 	module_instance_t *inst;
866 	char const *inst_name;
867 
868 #define FIND_SIBLING_CF_KEY "find_sibling"
869 
870 	*out = NULL;
871 
872 	/*
873 	 *	Is a real section (not referencing sibling module).
874 	 */
875 	cs = cf_section_sub_find(module, name);
876 	if (cs) {
877 		*out = cs;
878 
879 		return 0;
880 	}
881 
882 	/*
883 	 *	Item omitted completely from module config.
884 	 */
885 	cp = cf_pair_find(module, name);
886 	if (!cp) return 0;
887 
888 	if (cf_data_find(module, FIND_SIBLING_CF_KEY)) {
889 		cf_log_err_cp(cp, "Module reference loop found");
890 
891 		return -1;
892 	}
893 	cf_data_add(module, FIND_SIBLING_CF_KEY, &loop, NULL);
894 
895 	/*
896 	 *	Item found, resolve it to a module instance.
897 	 *	This triggers module loading, so we don't have
898 	 *	instantiation order issues.
899 	 */
900 	inst_name = cf_pair_value(cp);
901 	inst = module_instantiate(cf_item_parent(cf_section_to_item(module)), inst_name);
902 
903 	/*
904 	 *	Remove the config data we added for loop
905 	 *	detection.
906 	 */
907 	cf_data_remove(module, FIND_SIBLING_CF_KEY);
908 	if (!inst) {
909 		cf_log_err_cp(cp, "Unknown module instance \"%s\"", inst_name);
910 
911 		return -1;
912 	}
913 
914 	/*
915 	 *	Check the module instances are of the same type.
916 	 */
917 	if (strcmp(cf_section_name1(inst->cs), cf_section_name1(module)) != 0) {
918 		cf_log_err_cp(cp, "Referenced module is a rlm_%s instance, must be a rlm_%s instance",
919 			      cf_section_name1(inst->cs), cf_section_name1(module));
920 
921 		return -1;
922 	}
923 
924 	*out = cf_section_sub_find(inst->cs, name);
925 
926 	return 1;
927 }
928 
lookup_by_index(rbtree_t * components,rlm_components_t comp,int idx)929 static indexed_modcallable *lookup_by_index(rbtree_t *components,
930 					    rlm_components_t comp, int idx)
931 {
932 	indexed_modcallable myc;
933 
934 	myc.comp = comp;
935 	myc.idx = idx;
936 
937 	return rbtree_finddata(components, &myc);
938 }
939 
940 /*
941  *	Create a new sublist.
942  */
new_sublist(CONF_SECTION * cs,rbtree_t * components,rlm_components_t comp,int idx)943 static indexed_modcallable *new_sublist(CONF_SECTION *cs,
944 					rbtree_t *components, rlm_components_t comp, int idx)
945 {
946 	indexed_modcallable *c;
947 
948 	c = lookup_by_index(components, comp, idx);
949 
950 	/* It is an error to try to create a sublist that already
951 	 * exists. It would almost certainly be caused by accidental
952 	 * duplication in the config file.
953 	 *
954 	 * index 0 is the exception, because it is used when we want
955 	 * to collect _all_ listed modules under a single index by
956 	 * default, which is currently the case in all components
957 	 * except authenticate. */
958 	if (c) {
959 		if (idx == 0) {
960 			return c;
961 		}
962 		return NULL;
963 	}
964 
965 	c = talloc_zero(cs, indexed_modcallable);
966 	c->modulelist = NULL;
967 	c->comp = comp;
968 	c->idx = idx;
969 
970 	if (!rbtree_insert(components, c)) {
971 		talloc_free(c);
972 		return NULL;
973 	}
974 
975 	return c;
976 }
977 
indexed_modcall(rlm_components_t comp,int idx,REQUEST * request)978 rlm_rcode_t indexed_modcall(rlm_components_t comp, int idx, REQUEST *request)
979 {
980 	rlm_rcode_t rcode;
981 	modcallable *list = NULL;
982 	virtual_server_t *server;
983 
984 	/*
985 	 *	Hack to find the correct virtual server.
986 	 */
987 	server = virtual_server_find(request->server);
988 	if (!server) {
989 		RDEBUG("No such virtual server \"%s\"", request->server);
990 		return RLM_MODULE_FAIL;
991 	}
992 
993 	if (idx == 0) {
994 		list = server->mc[comp];
995 		if (!list) {
996 			if (server->name) {
997 				RDEBUG3("Empty %s section in virtual server \"%s\".  Using default return values.",
998 					section_type_value[comp].section, server->name);
999 			} else {
1000 				RDEBUG3("Empty %s section.  Using default return values.", section_type_value[comp].section);
1001 			}
1002 		}
1003 	} else {
1004 		indexed_modcallable *this;
1005 
1006 		this = lookup_by_index(server->components, comp, idx);
1007 		if (this) {
1008 			list = this->modulelist;
1009 		} else {
1010 			RDEBUG2("%s sub-section not found.  Ignoring.", section_type_value[comp].typename);
1011 		}
1012 	}
1013 
1014 	if (server->subcs[comp]) {
1015 		if (idx == 0) {
1016 			RDEBUG("# Executing section %s from file %s",
1017 			       section_type_value[comp].section,
1018 			       cf_section_filename(server->subcs[comp]));
1019 		} else {
1020 			RDEBUG("# Executing group from file %s",
1021 			       cf_section_filename(server->subcs[comp]));
1022 		}
1023 	}
1024 	request->component = section_type_value[comp].section;
1025 	rcode = modcall(comp, list, request);
1026 	request->component = "<core>";
1027 
1028 	return rcode;
1029 }
1030 
1031 /*
1032  *	Load a sub-module list, as found inside an Auth-Type foo {}
1033  *	block
1034  */
load_subcomponent_section(CONF_SECTION * cs,rbtree_t * components,DICT_ATTR const * da,rlm_components_t comp)1035 static int load_subcomponent_section(CONF_SECTION *cs,
1036 				     rbtree_t *components,
1037 				     DICT_ATTR const *da, rlm_components_t comp)
1038 {
1039 	indexed_modcallable *subcomp;
1040 	modcallable *ml;
1041 	DICT_VALUE *dval;
1042 	char const *name2 = cf_section_name2(cs);
1043 
1044 	/*
1045 	 *	Sanity check.
1046 	 */
1047 	if (!name2) {
1048 		return 1;
1049 	}
1050 
1051 	DEBUG("Compiling %s %s for attr %s", cf_section_name1(cs), name2, da->name);
1052 
1053 	/*
1054 	 *	Compile the group.
1055 	 */
1056 	ml = compile_modgroup(NULL, comp, cs);
1057 	if (!ml) {
1058 		return 0;
1059 	}
1060 
1061 	/*
1062 	 *	We must assign a numeric index to this subcomponent.
1063 	 *	It is generated and placed in the dictionary
1064 	 *	automatically.  If it isn't found, it's a serious
1065 	 *	error.
1066 	 */
1067 	dval = dict_valbyname(da->attr, da->vendor, name2);
1068 	if (!dval) {
1069 		talloc_free(ml);
1070 		cf_log_err_cs(cs,
1071 			   "The %s attribute has no VALUE defined for %s",
1072 			      section_type_value[comp].typename, name2);
1073 		return 0;
1074 	}
1075 
1076 	subcomp = new_sublist(cs, components, comp, dval->value);
1077 	if (!subcomp) {
1078 		talloc_free(ml);
1079 		return 1;
1080 	}
1081 
1082 	/*
1083 	 *	Link it into the talloc hierarchy.
1084 	 */
1085 	subcomp->modulelist = talloc_steal(subcomp, ml);
1086 	return 1;		/* OK */
1087 }
1088 
1089 /*
1090  *	Don't complain too often.
1091  */
1092 #define MAX_IGNORED (32)
1093 static int last_ignored = -1;
1094 static char const *ignored[MAX_IGNORED];
1095 
load_component_section(CONF_SECTION * cs,rbtree_t * components,rlm_components_t comp)1096 static int load_component_section(CONF_SECTION *cs,
1097 				  rbtree_t *components, rlm_components_t comp)
1098 {
1099 	modcallable *this;
1100 	CONF_ITEM *modref;
1101 	int idx;
1102 	indexed_modcallable *subcomp;
1103 	char const *modname;
1104 	DICT_ATTR const *da;
1105 
1106 	/*
1107 	 *	Find the attribute used to store VALUEs for this section.
1108 	 */
1109 	da = dict_attrbyvalue(section_type_value[comp].attr, 0);
1110 	if (!da) {
1111 		cf_log_err_cs(cs,
1112 			   "No such attribute %s",
1113 			   section_type_value[comp].typename);
1114 		return -1;
1115 	}
1116 
1117 	/*
1118 	 *	Loop over the entries in the named section, loading
1119 	 *	the sections this time.
1120 	 */
1121 	for (modref = cf_item_find_next(cs, NULL);
1122 	     modref != NULL;
1123 	     modref = cf_item_find_next(cs, modref)) {
1124 		char const *name1;
1125 		CONF_PAIR *cp = NULL;
1126 		CONF_SECTION *scs = NULL;
1127 
1128 		if (cf_item_is_section(modref)) {
1129 			scs = cf_item_to_section(modref);
1130 
1131 			name1 = cf_section_name1(scs);
1132 
1133 			if (strcmp(name1,
1134 				   section_type_value[comp].typename) == 0) {
1135 				if (!load_subcomponent_section(scs,
1136 							       components,
1137 							       da,
1138 							       comp)) {
1139 
1140 					return -1; /* FIXME: memleak? */
1141 				}
1142 				continue;
1143 			}
1144 
1145 			cp = NULL;
1146 
1147 		} else if (cf_item_is_pair(modref)) {
1148 			cp = cf_item_to_pair(modref);
1149 
1150 		} else {
1151 			continue; /* ignore it */
1152 		}
1153 
1154 		/*
1155 		 *	Look for Auth-Type foo {}, which are special
1156 		 *	cases of named sections, and allowable ONLY
1157 		 *	at the top-level.
1158 		 *
1159 		 *	i.e. They're not allowed in a "group" or "redundant"
1160 		 *	subsection.
1161 		 */
1162 		if (comp == MOD_AUTHENTICATE) {
1163 			DICT_VALUE *dval;
1164 			char const *modrefname = NULL;
1165 
1166 			if (cp) {
1167 				modrefname = cf_pair_attr(cp);
1168 			} else {
1169 				modrefname = cf_section_name2(scs);
1170 				if (!modrefname) {
1171 					cf_log_err_cs(cs,
1172 						   "Errors parsing %s sub-section.\n",
1173 						   cf_section_name1(scs));
1174 					return -1;
1175 				}
1176 			}
1177 			if (*modrefname == '-') modrefname++;
1178 
1179 			dval = dict_valbyname(PW_AUTH_TYPE, 0, modrefname);
1180 			if (!dval) {
1181 				/*
1182 				 *	It's a section, but nothing we
1183 				 *	recognize.  Die!
1184 				 */
1185 				cf_log_err_cs(cs,
1186 					   "Unknown Auth-Type \"%s\" in %s sub-section.",
1187 					   modrefname, section_type_value[comp].section);
1188 				return -1;
1189 			}
1190 			idx = dval->value;
1191 		} else {
1192 			/* See the comment in new_sublist() for explanation
1193 			 * of the special index 0 */
1194 			idx = 0;
1195 		}
1196 
1197 		subcomp = new_sublist(cs, components, comp, idx);
1198 		if (!subcomp) continue;
1199 
1200 		/*
1201 		 *	Try to compile one entry.
1202 		 */
1203 		this = compile_modsingle(subcomp, &subcomp->modulelist, comp, modref, &modname);
1204 
1205 		/*
1206 		 *	It's OK for the module to not exist.
1207 		 */
1208 		if (!this && modname && (modname[0] == '-')) {
1209 			int i;
1210 
1211 			if (last_ignored < 0) {
1212 			save_complain:
1213 				last_ignored++;
1214 				ignored[last_ignored] = modname;
1215 
1216 			complain:
1217 				WARN("Ignoring \"%s\" (see raddb/mods-available/README.rst)", modname + 1);
1218 				continue;
1219 			}
1220 
1221 			if (last_ignored >= MAX_IGNORED) goto complain;
1222 
1223 			for (i = 0; i <= last_ignored; i++) {
1224 				if (strcmp(ignored[i], modname) == 0) {
1225 					break;
1226 				}
1227 			}
1228 
1229 			if (i > last_ignored) goto save_complain;
1230 			continue;
1231 		}
1232 
1233 		if (!this) {
1234 			cf_log_err_cs(cs,
1235 				   "Errors parsing %s section.\n",
1236 				   cf_section_name1(cs));
1237 			return -1;
1238 		}
1239 
1240 		if (rad_debug_lvl > 2) modcall_debug(this, 2);
1241 
1242 		add_to_modcallable(subcomp->modulelist, this);
1243 	}
1244 
1245 
1246 	return 0;
1247 }
1248 
load_byserver(CONF_SECTION * cs)1249 static int load_byserver(CONF_SECTION *cs)
1250 {
1251 	rlm_components_t comp;
1252 	bool found;
1253 	char const *name = cf_section_name2(cs);
1254 	rbtree_t *components;
1255 	virtual_server_t *server = NULL;
1256 	indexed_modcallable *c;
1257 	bool is_bare;
1258 
1259 	if (name) {
1260 		cf_log_info(cs, "server %s { # from file %s",
1261 			    name, cf_section_filename(cs));
1262 	} else {
1263 		cf_log_info(cs, "server { # from file %s",
1264 			    cf_section_filename(cs));
1265 	}
1266 
1267 	is_bare = (cf_item_parent(cf_section_to_item(cs)) == NULL);
1268 
1269 	server = talloc_zero(cs, virtual_server_t);
1270 	server->name = name;
1271 	server->created = time(NULL);
1272 	server->cs = cs;
1273 	server->components = components = rbtree_create(server, indexed_modcallable_cmp, NULL, 0);
1274 	if (!components) {
1275 		ERROR("Failed to initialize components");
1276 
1277 	error:
1278 		if (rad_debug_lvl == 0) {
1279 			ERROR("Failed to load virtual server %s",
1280 			      (name != NULL) ? name : "<default>");
1281 		}
1282 		return -1;
1283 	}
1284 	talloc_set_destructor(server, _virtual_server_free);
1285 
1286 	/*
1287 	 *	Loop over all of the known components, finding their
1288 	 *	configuration section, and loading it.
1289 	 */
1290 	found = false;
1291 	for (comp = 0; comp < MOD_COUNT; ++comp) {
1292 		CONF_SECTION *subcs;
1293 
1294 		subcs = cf_section_sub_find(cs,
1295 					    section_type_value[comp].section);
1296 		if (!subcs) continue;
1297 
1298 		if (is_bare) {
1299 			cf_log_err_cs(subcs, "The %s section should be inside of a 'server { ... }' block!",
1300 				      section_type_value[comp].section);
1301 		}
1302 
1303 		if (cf_item_find_next(subcs, NULL) == NULL) continue;
1304 
1305 		/*
1306 		 *	Skip pre/post-proxy sections if we're not
1307 		 *	proxying.
1308 		 */
1309 		if (
1310 #ifdef WITH_PROXY
1311 		    !main_config.proxy_requests &&
1312 #endif
1313 		    ((comp == MOD_PRE_PROXY) ||
1314 		     (comp == MOD_POST_PROXY))) {
1315 			continue;
1316 		}
1317 
1318 #ifndef WITH_ACCOUNTING
1319 		if (comp == MOD_ACCOUNTING) continue;
1320 #endif
1321 
1322 #ifndef WITH_SESSION_MGMT
1323 		if (comp == MOD_SESSION) continue;
1324 #endif
1325 
1326 		if (rad_debug_lvl <= 3) {
1327 			cf_log_module(cs, "Loading %s {...}",
1328 				      section_type_value[comp].section);
1329 		} else {
1330 			DEBUG(" %s {", section_type_value[comp].section);
1331 		}
1332 
1333 		if (load_component_section(subcs, components, comp) < 0) {
1334 			goto error;
1335 		}
1336 
1337 		if (rad_debug_lvl > 3) {
1338 			DEBUG(" } # %s", section_type_value[comp].section);
1339 		}
1340 
1341 		/*
1342 		 *	Cache a default, if it exists.  Some people
1343 		 *	put empty sections for some reason...
1344 		 */
1345 		c = lookup_by_index(components, comp, 0);
1346 		if (c) server->mc[comp] = c->modulelist;
1347 
1348 		server->subcs[comp] = subcs;
1349 
1350 		found = true;
1351 	} /* loop over components */
1352 
1353 	/*
1354 	 *	We haven't loaded any of the normal sections.  Maybe we're
1355 	 *	supposed to load the vmps section.
1356 	 *
1357 	 *	This is a bit of a hack...
1358 	 */
1359 	if (!found) do {
1360 #if defined(WITH_VMPS) || defined(WITH_DHCP)
1361 		CONF_SECTION *subcs;
1362 #endif
1363 #if defined(WITH_DHCP) || defined(WITH_TLS)
1364 		DICT_ATTR const *da;
1365 #endif
1366 
1367 #ifdef WITH_VMPS
1368 		subcs = cf_section_sub_find(cs, "vmps");
1369 		if (subcs) {
1370 			cf_log_module(cs, "Loading vmps {...}");
1371 			if (load_component_section(subcs, components,
1372 						   MOD_POST_AUTH) < 0) {
1373 				goto error;
1374 			}
1375 			c = lookup_by_index(components,
1376 					    MOD_POST_AUTH, 0);
1377 			if (c) server->mc[MOD_POST_AUTH] = c->modulelist;
1378 			break;
1379 		}
1380 #endif
1381 
1382 #ifdef WITH_TLS
1383 		/*
1384 		 *	It's OK to not have TLS cache sections.
1385 		 */
1386 		da = dict_attrbyname("TLS-Cache-Method");
1387 		subcs = cf_section_sub_find_name2(cs, "cache", "load");
1388 		if (subcs && !load_subcomponent_section(subcs,
1389 							components,
1390 							da,
1391 							MOD_POST_AUTH)) {
1392 			goto error; /* FIXME: memleak? */
1393 		}
1394 
1395 		subcs = cf_section_sub_find_name2(cs, "cache", "save");
1396 		if (subcs && !load_subcomponent_section(subcs,
1397 							components,
1398 							da,
1399 							MOD_POST_AUTH)) {
1400 			goto error; /* FIXME: memleak? */
1401 		}
1402 
1403 		subcs = cf_section_sub_find_name2(cs, "cache", "clear");
1404 		if (subcs && !load_subcomponent_section(subcs,
1405 							components,
1406 							da,
1407 							MOD_POST_AUTH)) {
1408 			goto error; /* FIXME: memleak? */
1409 		}
1410 
1411 		subcs = cf_section_sub_find_name2(cs, "cache", "refresh");
1412 		if (subcs && !load_subcomponent_section(subcs,
1413 							components,
1414 							da,
1415 							MOD_POST_AUTH)) {
1416 			goto error; /* FIXME: memleak? */
1417 		}
1418 #endif
1419 
1420 #ifdef WITH_DHCP
1421 		/*
1422 		 *	It's OK to not have DHCP.
1423 		 */
1424 		subcs = cf_subsection_find_next(cs, NULL, "dhcp");
1425 		if (!subcs) break;
1426 
1427 		da = dict_attrbyname("DHCP-Message-Type");
1428 
1429 		/*
1430 		 *	Handle each DHCP Message type separately.
1431 		 */
1432 		while (subcs) {
1433 			char const *name2 = cf_section_name2(subcs);
1434 
1435 			if (name2) {
1436 				cf_log_module(cs, "Loading dhcp %s {...}", name2);
1437 			} else {
1438 				cf_log_module(cs, "Loading dhcp {...}");
1439 			}
1440 			if (!load_subcomponent_section(subcs,
1441 						       components,
1442 						       da,
1443 						       MOD_POST_AUTH)) {
1444 				goto error; /* FIXME: memleak? */
1445 			}
1446 			c = lookup_by_index(components,
1447 					    MOD_POST_AUTH, 0);
1448 			if (c) server->mc[MOD_POST_AUTH] = c->modulelist;
1449 
1450 			subcs = cf_subsection_find_next(cs, subcs, "dhcp");
1451 		}
1452 #endif
1453 
1454 
1455 	} while (0);
1456 
1457 	if (name) {
1458 		cf_log_info(cs, "} # server %s", name);
1459 	} else {
1460 		cf_log_info(cs, "} # server");
1461 	}
1462 
1463 	if (rad_debug_lvl == 0) {
1464 		INFO("Loaded virtual server %s",
1465 		       (name != NULL) ? name : "<default>");
1466 	}
1467 
1468 	/*
1469 	 *	Now that it is OK, insert it into the list.
1470 	 *
1471 	 *	This is thread-safe...
1472 	 */
1473 	comp = virtual_server_idx(name);
1474 	server->next = virtual_servers[comp];
1475 	virtual_servers[comp] = server;
1476 
1477 	/*
1478 	 *	Mark OLDER ones of the same name as being unused.
1479 	 */
1480 	server = server->next;
1481 	while (server) {
1482 		if ((!name && !server->name) ||
1483 		    (name && server->name &&
1484 		     (strcmp(server->name, name) == 0))) {
1485 			server->can_free = true;
1486 			break;
1487 		}
1488 		server = server->next;
1489 	}
1490 
1491 	return 0;
1492 }
1493 
1494 
pass2_cb(UNUSED void * ctx,void * data)1495 static int pass2_cb(UNUSED void *ctx, void *data)
1496 {
1497 	indexed_modcallable *this = data;
1498 
1499 	if (!modcall_pass2(this->modulelist)) return -1;
1500 
1501 	return 0;
1502 }
1503 
1504 
1505 /*
1506  *	Load all of the virtual servers.
1507  */
virtual_servers_load(CONF_SECTION * config)1508 int virtual_servers_load(CONF_SECTION *config)
1509 {
1510 	CONF_SECTION *cs;
1511 	virtual_server_t *server;
1512 	static bool first_time = true;
1513 
1514 	DEBUG2("%s: #### Loading Virtual Servers ####", main_config.name);
1515 
1516 	/*
1517 	 *	If we have "server { ...}", then there SHOULD NOT be
1518 	 *	bare "authorize", etc. sections.  if there is no such
1519 	 *	server, then try to load the old-style sections first.
1520 	 *
1521 	 *	In either case, load the "default" virtual server first.
1522 	 *	this matches better with users expectations.
1523 	 */
1524 	cs = cf_section_find_name2(cf_subsection_find_next(config, NULL,
1525 							   "server"),
1526 				   "server", NULL);
1527 	if (cs) {
1528 		if (load_byserver(cs) < 0) {
1529 			return -1;
1530 		}
1531 	} else {
1532 		if (load_byserver(config) < 0) {
1533 			return -1;
1534 		}
1535 	}
1536 
1537 	/*
1538 	 *	Load all of the virtual servers.
1539 	 */
1540 	for (cs = cf_subsection_find_next(config, NULL, "server");
1541 	     cs != NULL;
1542 	     cs = cf_subsection_find_next(config, cs, "server")) {
1543 		char const *name2;
1544 
1545 		name2 = cf_section_name2(cs);
1546 		if (!name2) continue; /* handled above */
1547 
1548 		server = virtual_server_find(name2);
1549 		if (server &&
1550 		    (cf_top_section(server->cs) == config)) {
1551 			ERROR("Duplicate virtual server \"%s\" in file %s:%d and file %s:%d",
1552 			       server->name,
1553 			       cf_section_filename(server->cs),
1554 			       cf_section_lineno(server->cs),
1555 			       cf_section_filename(cs),
1556 			       cf_section_lineno(cs));
1557 			return -1;
1558 		}
1559 
1560 		if (load_byserver(cs) < 0) {
1561 			/*
1562 			 *	Once we successfully started once,
1563 			 *	continue loading the OTHER servers,
1564 			 *	even if one fails.
1565 			 */
1566 			if (!first_time) continue;
1567 			return -1;
1568 		}
1569 	}
1570 
1571 	/*
1572 	 *	Try to compile the "authorize", etc. sections which
1573 	 *	aren't in a virtual server.
1574 	 */
1575 	server = virtual_server_find(NULL);
1576 	if (server) {
1577 		int i;
1578 
1579 		for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) {
1580 			if (!modcall_pass2(server->mc[i])) return -1;
1581 		}
1582 
1583 		if (server->components &&
1584 		    (rbtree_walk(server->components, RBTREE_IN_ORDER,
1585 				 pass2_cb, NULL) != 0)) {
1586 			return -1;
1587 		}
1588 	}
1589 
1590 	/*
1591 	 *	Now that we've loaded everything, run pass 2 over the
1592 	 *	conditions and xlats.
1593 	 */
1594 	for (cs = cf_subsection_find_next(config, NULL, "server");
1595 	     cs != NULL;
1596 	     cs = cf_subsection_find_next(config, cs, "server")) {
1597 		int i;
1598 		char const *name2;
1599 
1600 		name2 = cf_section_name2(cs);
1601 
1602 		server = virtual_server_find(name2);
1603 		if (!server) continue;
1604 
1605 		for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) {
1606 			if (!modcall_pass2(server->mc[i])) return -1;
1607 		}
1608 
1609 		if (server->components &&
1610 		    (rbtree_walk(server->components, RBTREE_IN_ORDER,
1611 				 pass2_cb, NULL) != 0)) {
1612 			return -1;
1613 		}
1614 	}
1615 
1616 	/*
1617 	 *	If we succeed the first time around, remember that.
1618 	 */
1619 	first_time = false;
1620 
1621 	return 0;
1622 }
1623 
module_hup_module(CONF_SECTION * cs,module_instance_t * node,time_t when)1624 int module_hup_module(CONF_SECTION *cs, module_instance_t *node, time_t when)
1625 {
1626 	void *insthandle;
1627 	fr_module_hup_t *mh;
1628 
1629 	if (!node ||
1630 	    node->entry->module->bootstrap ||
1631 	    !node->entry->module->instantiate ||
1632 	    ((node->entry->module->type & RLM_TYPE_HUP_SAFE) == 0)) {
1633 		return 1;
1634 	}
1635 
1636 	/*
1637 	 *	Silently ignore multiple HUPs within a short time period.
1638 	 */
1639 	if ((node->last_hup + 2) >= when) return 1;
1640 	node->last_hup = when;
1641 
1642 	cf_log_module(cs, "Trying to reload module \"%s\"", node->name);
1643 
1644 	/*
1645 	 *	Parse the module configuration, and setup destructors so the
1646 	 *	module's detach method is called when it's instance data is
1647 	 *	about to be freed.
1648 	 */
1649 	if (module_conf_parse(node, &insthandle) < 0) {
1650 		cf_log_err_cs(cs, "HUP failed for module \"%s\" (parsing config failed). "
1651 			      "Using old configuration", node->name);
1652 
1653 		return 0;
1654 	}
1655 
1656 	if ((node->entry->module->instantiate)(cs, insthandle) < 0) {
1657 		cf_log_err_cs(cs, "HUP failed for module \"%s\".  Using old configuration.", node->name);
1658 		talloc_free(insthandle);
1659 
1660 		return 0;
1661 	}
1662 
1663 	INFO(" Module: Reloaded module \"%s\"", node->name);
1664 
1665 	module_instance_free_old(cs, node, when);
1666 
1667 	/*
1668 	 *	Save the old instance handle for later deletion.
1669 	 */
1670 	mh = talloc_zero(cs, fr_module_hup_t);
1671 	mh->mi = node;
1672 	mh->when = when;
1673 	mh->insthandle = node->insthandle;
1674 	mh->next = node->mh;
1675 	node->mh = mh;
1676 
1677 	/*
1678 	 *	Replace the instance handle while the module is running.
1679 	 */
1680 	node->insthandle = insthandle;
1681 
1682 	/*
1683 	 *	FIXME: Set a timeout to come back in 60s, so that
1684 	 *	we can pro-actively clean up the old instances.
1685 	 */
1686 
1687 	return 1;
1688 }
1689 
1690 
modules_hup(CONF_SECTION * modules)1691 int modules_hup(CONF_SECTION *modules)
1692 {
1693 	time_t when;
1694 	CONF_ITEM *ci;
1695 	CONF_SECTION *cs;
1696 	module_instance_t *node;
1697 
1698 	if (!modules) return 0;
1699 
1700 	when = time(NULL);
1701 
1702 	/*
1703 	 *	Loop over the modules
1704 	 */
1705 	for (ci=cf_item_find_next(modules, NULL);
1706 	     ci != NULL;
1707 	     ci=cf_item_find_next(modules, ci)) {
1708 		char const *instname;
1709 		module_instance_t myNode;
1710 
1711 		/*
1712 		 *	If it's not a section, ignore it.
1713 		 */
1714 		if (!cf_item_is_section(ci)) continue;
1715 
1716 		cs = cf_item_to_section(ci);
1717 		instname = cf_section_name2(cs);
1718 		if (!instname) instname = cf_section_name1(cs);
1719 
1720 		strlcpy(myNode.name, instname, sizeof(myNode.name));
1721 		node = rbtree_finddata(instance_tree, &myNode);
1722 
1723 		module_hup_module(cs, node, when);
1724 	}
1725 
1726 	return 1;
1727 }
1728 
1729 
define_type(CONF_SECTION * cs,DICT_ATTR const * da,char const * name)1730 static int define_type(CONF_SECTION *cs, DICT_ATTR const *da, char const *name)
1731 {
1732 	uint32_t value;
1733 	DICT_VALUE *dval;
1734 
1735 	/*
1736 	 *	Allow for conditionally loaded types
1737 	 */
1738 	if (*name == '-') name++;
1739 
1740 	/*
1741 	 *	If the value already exists, don't
1742 	 *	create it again.
1743 	 */
1744 	dval = dict_valbyname(da->attr, da->vendor, name);
1745 	if (dval) {
1746 		if (dval->value == 0) {
1747 			ERROR("The dictionaries must not define VALUE %s %s 0",
1748 			      da->name, name);
1749 			return 0;
1750 		}
1751 		return 1;
1752 	}
1753 
1754 	/*
1755 	 *	Create a new unique value with a
1756 	 *	meaningless number.  You can't look at
1757 	 *	it from outside of this code, so it
1758 	 *	doesn't matter.  The only requirement
1759 	 *	is that it's unique.
1760 	 */
1761 	do {
1762 		value = (fr_rand() & 0x00ffffff) + 1;
1763 	} while (dict_valbyattr(da->attr, da->vendor, value));
1764 
1765 	cf_log_module(cs, "Creating %s = %s", da->name, name);
1766 	if (dict_addvalue(name, da->name, value) < 0) {
1767 		ERROR("%s", fr_strerror());
1768 		return 0;
1769 	}
1770 
1771 	return 1;
1772 }
1773 
1774 /*
1775  *	Define Auth-Type, etc. in a server.
1776  */
server_define_types(CONF_SECTION * cs)1777 static bool server_define_types(CONF_SECTION *cs)
1778 {
1779 	rlm_components_t	comp;
1780 
1781 	/*
1782 	 *	Loop over all of the components
1783 	 */
1784 	for (comp = 0; comp < MOD_COUNT; ++comp) {
1785 		CONF_SECTION *subcs, *type_cs;
1786 		DICT_ATTR const *da;
1787 
1788 		subcs = cf_section_sub_find(cs,
1789 					    section_type_value[comp].section);
1790 		if (!subcs) continue;
1791 
1792 		if (cf_item_find_next(subcs, NULL) == NULL) continue;
1793 
1794 		/*
1795 		 *	Find the attribute used to store VALUEs for this section.
1796 		 */
1797 		da = dict_attrbyvalue(section_type_value[comp].attr, 0);
1798 		if (!da) {
1799 			cf_log_err_cs(subcs,
1800 				   "No such attribute %s",
1801 				   section_type_value[comp].typename);
1802 			return false;
1803 		}
1804 
1805 		/*
1806 		 *	Define dynamic types, so that others can reference
1807 		 *	them.
1808 		 *
1809 		 *	First, bare modules for 'authenticate'.
1810 		 *	Second, Auth-Type, etc.
1811 		 */
1812 		if (section_type_value[comp].attr == PW_AUTH_TYPE) {
1813 			CONF_ITEM *modref;
1814 
1815 			for (modref = cf_item_find_next(subcs, NULL);
1816 			     modref != NULL;
1817 			     modref = cf_item_find_next(subcs, modref)) {
1818 				CONF_PAIR *cp;
1819 
1820 				if (!cf_item_is_pair(modref)) continue;
1821 
1822 				cp = cf_item_to_pair(modref);
1823 				if (!define_type(cs, da, cf_pair_attr(cp))) {
1824 					return false;
1825 				}
1826 
1827 				/*
1828 				 *	Check for duplicates
1829 				 */
1830 				if (rad_debug_lvl) {
1831 					CONF_PAIR *cp2;
1832 					CONF_SECTION *cs2;
1833 
1834 					cp2 = cf_pair_find(subcs, cf_pair_attr(cp));
1835 					rad_assert(cp2 != NULL);
1836 					if (cp2 != cp) {
1837 						WARN("%s[%d]: Duplicate module '%s'",
1838 						     cf_pair_filename(cp2),
1839 						     cf_pair_lineno(cp2),
1840 						     cf_pair_attr(cp));
1841 					}
1842 
1843 					cs2 = cf_section_sub_find_name2(subcs, section_type_value[comp].typename, cf_pair_attr(cp));
1844 					if (cs2) {
1845 						WARN("%s[%d]: Duplicate Auth-Type '%s'",
1846 						     cf_section_filename(cs2),
1847 						     cf_section_lineno(cs2),
1848 						     cf_pair_attr(cp));
1849 					}
1850 				}
1851 
1852 			}
1853 		}
1854 
1855 		/*
1856 		 *	And loop over the type names
1857 		 */
1858 		for (type_cs = cf_subsection_find_next(subcs, NULL, section_type_value[comp].typename);
1859 		     type_cs != NULL;
1860 		     type_cs = cf_subsection_find_next(subcs, type_cs, section_type_value[comp].typename)) {
1861 			if (!define_type(cs, da, cf_section_name2(type_cs))) {
1862 				return false;
1863 			}
1864 
1865 			if (rad_debug_lvl) {
1866 				CONF_SECTION *cs2;
1867 
1868 				cs2 = cf_section_sub_find_name2(subcs, section_type_value[comp].typename, cf_section_name2(type_cs));
1869 				rad_assert(cs2 != NULL);
1870 				if (cs2 != type_cs) {
1871 					WARN("%s[%d]: Duplicate Auth-Type '%s'",
1872 					     cf_section_filename(cs2),
1873 					     cf_section_lineno(cs2),
1874 					     cf_section_name2(cs2));
1875 				}
1876 			}
1877 		}
1878 	} /* loop over components */
1879 
1880 	return true;
1881 }
1882 
1883 extern char const *unlang_keyword[];
1884 
is_reserved_word(const char * name)1885 static bool is_reserved_word(const char *name)
1886 {
1887 	int i;
1888 
1889 	if (!name || !*name) return false;
1890 
1891 	for (i = 1; unlang_keyword[i] != NULL; i++) {
1892 		if (strcmp(name, unlang_keyword[i]) == 0) return true;
1893 	}
1894 
1895 	return false;
1896 }
1897 
1898 
1899 /*
1900  *	Parse the module config sections, and load
1901  *	and call each module's init() function.
1902  */
modules_init(CONF_SECTION * config)1903 int modules_init(CONF_SECTION *config)
1904 {
1905 	CONF_ITEM	*ci, *next;
1906 	CONF_SECTION	*cs, *modules;
1907 
1908 	/*
1909 	 *	Set up the internal module struct.
1910 	 */
1911 	module_tree = rbtree_create(NULL, module_entry_cmp, NULL, 0);
1912 	if (!module_tree) {
1913 		ERROR("Failed to initialize modules\n");
1914 		return -1;
1915 	}
1916 
1917 	instance_tree = rbtree_create(NULL, module_instance_cmp,
1918 				      module_instance_free, 0);
1919 	if (!instance_tree) {
1920 		ERROR("Failed to initialize modules\n");
1921 		return -1;
1922 	}
1923 
1924 	memset(virtual_servers, 0, sizeof(virtual_servers));
1925 
1926 	/*
1927 	 *	Remember where the modules were stored.
1928 	 */
1929 	modules = cf_section_sub_find(config, "modules");
1930 	if (!modules) {
1931 		WARN("Cannot find a \"modules\" section in the configuration file!");
1932 	}
1933 
1934 	/*
1935 	 *	Load dictionaries.
1936 	 */
1937 	for (cs = cf_subsection_find_next(config, NULL, "server");
1938 	     cs != NULL;
1939 	     cs = cf_subsection_find_next(config, cs, "server")) {
1940 #if defined(WITH_DHCP) || defined(WITH_VMPS)
1941 		CONF_SECTION *subcs;
1942 		DICT_ATTR const *da;
1943 #endif
1944 
1945 #ifdef WITH_VMPS
1946 		/*
1947 		 *	Auto-load the VMPS/VQP dictionary.
1948 		 */
1949 		subcs = cf_section_sub_find(cs, "vmps");
1950 		if (subcs) {
1951 			da = dict_attrbyname("VQP-Packet-Type");
1952 			if (!da) {
1953 				if (dict_read(main_config.dictionary_dir, "dictionary.vqp") < 0) {
1954 					ERROR("Failed reading dictionary.vqp: %s",
1955 					      fr_strerror());
1956 					return -1;
1957 				}
1958 				cf_log_module(cs, "Loading dictionary.vqp");
1959 
1960 				da = dict_attrbyname("VQP-Packet-Type");
1961 				if (!da) {
1962 					ERROR("No VQP-Packet-Type in dictionary.vqp");
1963 					return -1;
1964 				}
1965 			}
1966 		}
1967 #endif
1968 
1969 #ifdef WITH_DHCP
1970 		/*
1971 		 *	Auto-load the DHCP dictionary.
1972 		 */
1973 		subcs = cf_subsection_find_next(cs, NULL, "dhcp");
1974 		if (subcs) {
1975 			da = dict_attrbyname("DHCP-Message-Type");
1976 			if (!da) {
1977 				cf_log_module(cs, "Loading dictionary.dhcp");
1978 				if (dict_read(main_config.dictionary_dir, "dictionary.dhcp") < 0) {
1979 					ERROR("Failed reading dictionary.dhcp: %s",
1980 					      fr_strerror());
1981 					return -1;
1982 				}
1983 
1984 				da = dict_attrbyname("DHCP-Message-Type");
1985 				if (!da) {
1986 					ERROR("No DHCP-Message-Type in dictionary.dhcp");
1987 					return -1;
1988 				}
1989 			}
1990 		}
1991 #endif
1992 		/*
1993 		 *	Else it's a RADIUS virtual server, and the
1994 		 *	dictionaries are already loaded.
1995 		 */
1996 
1997 		/*
1998 		 *	Root through each virtual server, defining
1999 		 *	Autz-Type and Auth-Type.  This is so that the
2000 		 *	modules can reference a particular type.
2001 		 */
2002 		if (!server_define_types(cs)) return -1;
2003 	}
2004 
2005 	DEBUG2("%s: #### Instantiating modules ####", main_config.name);
2006 
2007 	cf_log_info(config, " modules {");
2008 
2009 	/*
2010 	 *	Loop over module definitions, looking for duplicates.
2011 	 *
2012 	 *	This is O(N^2) in the number of modules, but most
2013 	 *	systems should have less than 100 modules.
2014 	 */
2015 	for (ci = cf_item_find_next(modules, NULL);
2016 	     ci != NULL;
2017 	     ci = next) {
2018 		char const *name1;
2019 		CONF_SECTION *subcs;
2020 		module_instance_t *node;
2021 
2022 		next = cf_item_find_next(modules, ci);
2023 
2024 		if (!cf_item_is_section(ci)) continue;
2025 
2026 		subcs = cf_item_to_section(ci);
2027 
2028 		node = module_bootstrap(subcs);
2029 		if (!node) return -1;
2030 
2031 		if (!next || !cf_item_is_section(next)) continue;
2032 
2033 		name1 = cf_section_name1(subcs);
2034 
2035 		if (is_reserved_word(name1)) {
2036 			cf_log_err_cs(subcs, "Module cannot be named for an 'unlang' keyword");
2037 			return -1;
2038 		}
2039 	}
2040 
2041 	/*
2042 	 *  Look for the 'instantiate' section, which tells us
2043 	 *  the instantiation order of the modules, and also allows
2044 	 *  us to load modules with no authorize/authenticate/etc.
2045 	 *  sections.
2046 	 */
2047 	cs = cf_section_sub_find(config, "instantiate");
2048 	if (cs) {
2049 		CONF_PAIR *cp;
2050 		module_instance_t *module;
2051 		char const *name;
2052 
2053 		cf_log_info(cs, "  instantiate {");
2054 
2055 		/*
2056 		 *  Loop over the items in the 'instantiate' section.
2057 		 */
2058 		for (ci=cf_item_find_next(cs, NULL);
2059 		     ci != NULL;
2060 		     ci=cf_item_find_next(cs, ci)) {
2061 			/*
2062 			 *	Skip sections and "other" stuff.
2063 			 *	Sections will be handled later, if
2064 			 *	they're referenced at all...
2065 			 */
2066 			if (cf_item_is_pair(ci)) {
2067 				cp = cf_item_to_pair(ci);
2068 				name = cf_pair_attr(cp);
2069 
2070 				module = module_instantiate(modules, name);
2071 				if (!module && (name[0] != '-')) {
2072 					return -1;
2073 				}
2074 			}
2075 
2076 			/*
2077 			 *	Can only be "redundant" or
2078 			 *	"load-balance" or
2079 			 *	"redundant-load-balance"
2080 			 */
2081 			if (cf_item_is_section(ci)) {
2082 				bool all_same = true;
2083 				module_t const *last = NULL;
2084 				CONF_SECTION *subcs;
2085 				CONF_ITEM *subci;
2086 
2087 				subcs = cf_item_to_section(ci);
2088 				name = cf_section_name1(subcs);
2089 
2090 				/*
2091 				 *	Groups, etc. must have a name.
2092 				 */
2093 				if (((strcmp(name, "group") == 0) ||
2094 				     (strcmp(name, "redundant") == 0) ||
2095 				     (strcmp(name, "redundant-load-balance") == 0) ||
2096 				     strcmp(name, "load-balance") == 0)) {
2097 					name = cf_section_name2(subcs);
2098 					if (!name) {
2099 						cf_log_err_cs(subcs, "Subsection must have a name");
2100 						return -1;
2101 					}
2102 
2103 					if (is_reserved_word(name)) {
2104 						cf_log_err_cs(subcs, "Instantiate sections cannot be named for an 'unlang' keyword");
2105 						return -1;
2106 					}
2107 				} else {
2108 					if (is_reserved_word(name)) {
2109 						cf_log_err_cs(subcs, "Instantiate sections cannot be named for an 'unlang' keyword");
2110 						return -1;
2111 					}
2112 				}
2113 
2114 				/*
2115 				 *	Ensure that the modules we reference here exist.
2116 				 */
2117 				for (subci=cf_item_find_next(subcs, NULL);
2118 				     subci != NULL;
2119 				     subci=cf_item_find_next(subcs, subci)) {
2120 					if (cf_item_is_pair(subci)) {
2121 						cp = cf_item_to_pair(subci);
2122 						if (cf_pair_value(cp)) {
2123 							cf_log_err(subci, "Cannot set return codes in a %s block",
2124 								   cf_section_name1(subcs));
2125 							return -1;
2126 						}
2127 
2128 						/*
2129 						 *	Allow "foo.authorize" in subsections.
2130 						 */
2131 						module = module_instantiate_method(modules, cf_pair_attr(cp), NULL);
2132 						if (!module) {
2133 							return -1;
2134 						}
2135 
2136 						if (all_same) {
2137 							if (!last) {
2138 								last = module->entry->module;
2139 							} else if (last != module->entry->module) {
2140 								last = NULL;
2141 								all_same = false;
2142 							}
2143 						}
2144 					} else {
2145 						all_same = false;
2146 					}
2147 
2148 					/*
2149 					 *	Don't check subsections for now.
2150 					 */
2151 				} /* loop over modules in a "redundant foo" section */
2152 
2153 				/*
2154 				 *	Register a redundant xlat
2155 				 */
2156 				if (all_same) {
2157 					if (!xlat_register_redundant(cf_item_to_section(ci))) {
2158 						WARN("%s[%d] Not registering expansions for %s",
2159 						     cf_section_filename(subcs), cf_section_lineno(subcs),
2160 						     cf_section_name2(subcs));
2161 					}
2162 				}
2163 			}  /* handle subsections */
2164 		} /* loop over the "instantiate" section */
2165 
2166 		cf_log_info(cs, "  }");
2167 	} /* if there's an 'instantiate' section. */
2168 
2169 	/*
2170 	 *	Now that we've loaded the explicitly ordered modules,
2171 	 *	load everything in the "modules" section.  This is
2172 	 *	because we've now split up the modules into
2173 	 *	mods-enabled.
2174 	 */
2175 	for (ci=cf_item_find_next(modules, NULL);
2176 	     ci != NULL;
2177 	     ci=next) {
2178 		char const *name;
2179 		module_instance_t *module;
2180 		CONF_SECTION *subcs;
2181 
2182 		next = cf_item_find_next(modules, ci);
2183 
2184 		if (!cf_item_is_section(ci)) continue;
2185 
2186 		subcs = cf_item_to_section(ci);
2187 		name = cf_section_name2(subcs);
2188 		if (!name) name = cf_section_name1(subcs);
2189 
2190 		module = module_instantiate(modules, name);
2191 		if (!module) return -1;
2192 	}
2193 	cf_log_info(config, " } # modules");
2194 
2195 	if (virtual_servers_load(config) < 0) return -1;
2196 
2197 	return 0;
2198 }
2199 
2200 /*
2201  *	Call all authorization modules until one returns
2202  *	somethings else than RLM_MODULE_OK
2203  */
process_authorize(int autz_type,REQUEST * request)2204 rlm_rcode_t process_authorize(int autz_type, REQUEST *request)
2205 {
2206 	return indexed_modcall(MOD_AUTHORIZE, autz_type, request);
2207 }
2208 
2209 /*
2210  *	Authenticate a user/password with various methods.
2211  */
process_authenticate(int auth_type,REQUEST * request)2212 rlm_rcode_t process_authenticate(int auth_type, REQUEST *request)
2213 {
2214 	return indexed_modcall(MOD_AUTHENTICATE, auth_type, request);
2215 }
2216 
2217 #ifdef WITH_ACCOUNTING
2218 /*
2219  *	Do pre-accounting for ALL configured sessions
2220  */
module_preacct(REQUEST * request)2221 rlm_rcode_t module_preacct(REQUEST *request)
2222 {
2223 	return indexed_modcall(MOD_PREACCT, 0, request);
2224 }
2225 
2226 /*
2227  *	Do accounting for ALL configured sessions
2228  */
process_accounting(int acct_type,REQUEST * request)2229 rlm_rcode_t process_accounting(int acct_type, REQUEST *request)
2230 {
2231 	return indexed_modcall(MOD_ACCOUNTING, acct_type, request);
2232 }
2233 #endif
2234 
2235 #ifdef WITH_SESSION_MGMT
2236 /*
2237  *	See if a user is already logged in.
2238  *
2239  *	Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
2240  */
process_checksimul(int sess_type,REQUEST * request,int maxsimul)2241 int process_checksimul(int sess_type, REQUEST *request, int maxsimul)
2242 {
2243 	rlm_rcode_t rcode;
2244 
2245 	if(!request->username)
2246 		return 0;
2247 
2248 	request->simul_count = 0;
2249 	request->simul_max = maxsimul;
2250 	request->simul_mpp = 1;
2251 
2252 	rcode = indexed_modcall(MOD_SESSION, sess_type, request);
2253 
2254 	if (rcode != RLM_MODULE_OK) {
2255 		/* FIXME: Good spot for a *rate-limited* warning to the log */
2256 		return 0;
2257 	}
2258 
2259 	return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
2260 }
2261 #endif
2262 
2263 #ifdef WITH_PROXY
2264 /*
2265  *	Do pre-proxying for ALL configured sessions
2266  */
process_pre_proxy(int type,REQUEST * request)2267 rlm_rcode_t process_pre_proxy(int type, REQUEST *request)
2268 {
2269 	return indexed_modcall(MOD_PRE_PROXY, type, request);
2270 }
2271 
2272 /*
2273  *	Do post-proxying for ALL configured sessions
2274  */
process_post_proxy(int type,REQUEST * request)2275 rlm_rcode_t process_post_proxy(int type, REQUEST *request)
2276 {
2277 	return indexed_modcall(MOD_POST_PROXY, type, request);
2278 }
2279 #endif
2280 
2281 /*
2282  *	Do post-authentication for ALL configured sessions
2283  */
process_post_auth(int postauth_type,REQUEST * request)2284 rlm_rcode_t process_post_auth(int postauth_type, REQUEST *request)
2285 {
2286 	return indexed_modcall(MOD_POST_AUTH, postauth_type, request);
2287 }
2288 
2289 #ifdef WITH_COA
process_recv_coa(int recv_coa_type,REQUEST * request)2290 rlm_rcode_t process_recv_coa(int recv_coa_type, REQUEST *request)
2291 {
2292 	return indexed_modcall(MOD_RECV_COA, recv_coa_type, request);
2293 }
2294 
process_send_coa(int send_coa_type,REQUEST * request)2295 rlm_rcode_t process_send_coa(int send_coa_type, REQUEST *request)
2296 {
2297 	return indexed_modcall(MOD_SEND_COA, send_coa_type, request);
2298 }
2299 #endif
2300