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