Massively cleaned up #include's, so they're in a consistent
[freeradius.git] / src / main / modules.c
1 /*
2  * modules.c    Radius module support.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 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 #include <freeradius-devel/ident.h>
26 RCSID("$Id$")
27
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/modpriv.h>
30 #include <freeradius-devel/modcall.h>
31 #include <freeradius-devel/rad_assert.h>
32
33 typedef struct indexed_modcallable {
34         int comp;
35         int idx;
36         modcallable *modulelist;
37 } indexed_modcallable;
38
39 /*
40  *      For each component, keep an ordered list of ones to call.
41  */
42 static lrad_hash_table_t *components;
43
44 static rbtree_t *module_tree = NULL;
45
46 typedef struct section_type_value_t {
47         const char      *section;
48         const char      *typename;
49         int             attr;
50 } section_type_value_t;
51
52
53 /*
54  *      Ordered by component
55  */
56 static const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
57         { "authenticate", "Auth-Type",       PW_AUTH_TYPE },
58         { "authorize",    "Autz-Type",       PW_AUTZ_TYPE },
59         { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },
60         { "accounting",   "Acct-Type",       PW_ACCT_TYPE },
61         { "session",      "Session-Type",    PW_SESSION_TYPE },
62         { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
63         { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
64         { "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE },
65 };
66
67 /*
68  *      Delete ASAP.
69  */
70 static const section_type_value_t old_section_type_value[] = {
71         { "authenticate", "authtype", PW_AUTH_TYPE },
72         { "authorize",    "autztype", PW_AUTZ_TYPE },
73         { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },/* unused */
74         { "accounting",   "acctype", PW_ACCT_TYPE },
75         { "session",      "sesstype", PW_SESSION_TYPE },
76         { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE }, /* unused */
77         { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE }, /* unused */
78         { "post-auth",    "post-authtype", PW_POST_AUTH_TYPE }
79 };
80
81
82 static void indexed_modcallable_free(void *data)
83 {
84         indexed_modcallable *c = data;
85
86         modcallable_free(&c->modulelist);
87         free(c);
88 }
89
90 static uint32_t indexed_modcallable_hash(const void *data)
91 {
92         uint32_t hash;
93         const indexed_modcallable *c = data;
94
95         hash = lrad_hash(&c->comp, sizeof(c->comp));
96         return lrad_hash_update(&c->idx, sizeof(c->idx), hash);
97 }
98
99 static int indexed_modcallable_cmp(const void *one, const void *two)
100 {
101         const indexed_modcallable *a = one;
102         const indexed_modcallable *b = two;
103
104         if (a->comp < b->comp) return -1;
105         if (a->comp >  b->comp) return +1;
106
107         return a->idx - b->idx;
108 }
109
110
111 /*
112  *      Free a module instance.
113  */
114 static void module_instance_free(void *data)
115 {
116         module_instance_t *this = data;
117
118         if (this->entry->module->detach)
119                 (this->entry->module->detach)(this->insthandle);
120 #ifdef HAVE_PTHREAD_H
121         if (this->mutex) {
122                 /*
123                  *      FIXME
124                  *      The mutex MIGHT be locked...
125                  *      we'll check for that later, I guess.
126                  */
127                 pthread_mutex_destroy(this->mutex);
128                 free(this->mutex);
129         }
130 #endif
131         free(this);
132 }
133
134
135 /*
136  *      Compare two module entries
137  */
138 static int module_entry_cmp(const void *one, const void *two)
139 {
140         const module_entry_t *a = one;
141         const module_entry_t *b = two;
142
143         return strcmp(a->name, b->name);
144 }
145
146 /*
147  *      Free a module entry.
148  */
149 static void module_entry_free(void *data)
150 {
151         module_entry_t *this = data;
152
153         lt_dlclose(this->handle);       /* ignore any errors */
154         free(this);
155 }
156
157
158 /*
159  *      Remove the module lists.
160  */
161 int detach_modules(void)
162 {
163         lrad_hash_table_free(components);
164         rbtree_free(module_tree);
165
166         return 0;
167 }
168
169
170 /*
171  *      Find a module on disk or in memory, and link to it.
172  */
173 static module_entry_t *linkto_module(const char *module_name,
174                                      const char *cffilename, int cflineno)
175 {
176         module_entry_t myentry;
177         module_entry_t *node;
178         lt_dlhandle handle;
179         char module_struct[256];
180         char *p;
181         const void *module;
182
183         strlcpy(myentry.name, module_name, sizeof(myentry.name));
184         node = rbtree_finddata(module_tree, &myentry);
185         if (node) return node;
186
187         /*
188          *      Keep the handle around so we can dlclose() it.
189          */
190         handle = lt_dlopenext(module_name);
191         if (handle == NULL) {
192                 radlog(L_ERR|L_CONS, "%s[%d] Failed to link to module '%s':"
193                        " %s\n", cffilename, cflineno, module_name, lt_dlerror());
194                 return NULL;
195         }
196
197         /*
198          *      Link to the module's rlm_FOO{} module structure.
199          *
200          *      The module_name variable has the version number
201          *      embedded in it, and we don't want that here.
202          */
203         strcpy(module_struct, module_name);
204         p = strrchr(module_struct, '-');
205         if (p) *p = '\0';
206
207         DEBUG3("    (Loaded %s, checking if it's valid)", module_name);
208
209         /*
210          *      libltld MAY core here, if the handle it gives us contains
211          *      garbage data.
212          */
213         module = lt_dlsym(handle, module_struct);
214         if (!module) {
215                 radlog(L_ERR|L_CONS, "%s[%d] Failed linking to "
216                                 "%s structure in %s: %s\n",
217                                 cffilename, cflineno,
218                                 module_name, cffilename, lt_dlerror());
219                 lt_dlclose(handle);
220                 return NULL;
221         }
222         /*
223          *      Before doing anything else, check if it's sane.
224          */
225         if ((*(const uint32_t *) module) != RLM_MODULE_MAGIC_NUMBER) {
226                 lt_dlclose(handle);
227                 radlog(L_ERR|L_CONS, "%s[%d] Invalid version in module '%s'",
228                        cffilename, cflineno, module_name);
229                 return NULL;
230                 
231         }
232
233         /* make room for the module type */
234         node = rad_malloc(sizeof(*node));
235         memset(node, 0, sizeof(*node));
236         strlcpy(node->name, module_name, sizeof(node->name));
237         node->module = module;
238         node->handle = handle;
239
240         DEBUG("Module: Loaded %s ", node->module->name);
241
242         /*
243          *      Add the module as "rlm_foo-version" to the configuration
244          *      section.
245          */
246         if (!rbtree_insert(module_tree, node)) {
247                 radlog(L_ERR, "Failed to cache module %s", module_name);
248                 lt_dlclose(handle);
249                 free(node);
250                 return NULL;
251         }
252
253         return node;
254 }
255
256 /*
257  *      Find a module instance.
258  */
259 module_instance_t *find_module_instance(CONF_SECTION *modules,
260                                         const char *instname)
261 {
262         CONF_SECTION *cs;
263         const char *name1, *name2;
264         module_instance_t *node;
265         char module_name[256];
266
267         if (!modules) return NULL;
268
269         /*
270          *      Module instances are declared in the modules{} block
271          *      and referenced later by their name, which is the
272          *      name2 from the config section, or name1 if there was
273          *      no name2.
274          */
275         cs = cf_section_sub_find_name2(modules, NULL, instname);
276         if (cs == NULL) {
277                 radlog(L_ERR|L_CONS, "ERROR: Cannot find a configuration entry for module \"%s\".\n", instname);
278                 return NULL;
279         }
280
281         /*
282          *      If there's already a module instance, return it.
283          */
284         node = cf_data_find(cs, "instance");
285         if (node) return node;
286
287         name1 = cf_section_name1(cs);
288         name2 = cf_section_name2(cs);
289
290         /*
291          *      Found the configuration entry.
292          */
293         node = rad_malloc(sizeof(*node));
294         memset(node, 0, sizeof(*node));
295
296         node->insthandle = NULL;
297
298         /*
299          *      Names in the "modules" section aren't prefixed
300          *      with "rlm_", so we add it here.
301          */
302         snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
303
304         node->entry = linkto_module(module_name,
305                                     mainconfig.radiusd_conf,
306                                     cf_section_lineno(cs));
307         if (!node->entry) {
308                 free(node);
309                 /* linkto_module logs any errors */
310                 return NULL;
311         }
312
313         /*
314          *      Call the module's instantiation routine.
315          */
316         if ((node->entry->module->instantiate) &&
317             ((node->entry->module->instantiate)(cs, &node->insthandle) < 0)) {
318                 radlog(L_ERR|L_CONS,
319                                 "%s[%d]: %s: Module instantiation failed.\n",
320                        mainconfig.radiusd_conf, cf_section_lineno(cs),
321                        instname);
322                 free(node);
323                 return NULL;
324         }
325
326         /*
327          *      We're done.  Fill in the rest of the data structure,
328          *      and link it to the module instance list.
329          */
330         strlcpy(node->name, instname, sizeof(node->name));
331
332 #ifdef HAVE_PTHREAD_H
333         /*
334          *      If we're threaded, check if the module is thread-safe.
335          *
336          *      If it isn't, we create a mutex.
337          */
338         if ((node->entry->module->type & RLM_TYPE_THREAD_UNSAFE) != 0) {
339                 node->mutex = (pthread_mutex_t *) rad_malloc(sizeof(pthread_mutex_t));
340                 /*
341                  *      Initialize the mutex.
342                  */
343                 pthread_mutex_init(node->mutex, NULL);
344         } else {
345                 /*
346                  *      The module is thread-safe.  Don't give it a mutex.
347                  */
348                 node->mutex = NULL;
349         }
350
351 #endif
352         cf_data_add(cs, "instance", node, module_instance_free);
353
354         DEBUG("Module: Instantiated %s (%s) ", name1, node->name);
355
356         return node;
357 }
358
359 static indexed_modcallable *lookup_by_index(int comp, int idx)
360 {
361         indexed_modcallable myc;
362
363         myc.comp = comp;
364         myc.idx = idx;
365
366         return lrad_hash_table_finddata(components, &myc);
367 }
368
369 /*
370  *      Create a new sublist.
371  */
372 static indexed_modcallable *new_sublist(int comp, int idx)
373 {
374         indexed_modcallable *c;
375
376         c = lookup_by_index(comp, idx);
377
378         /* It is an error to try to create a sublist that already
379          * exists. It would almost certainly be caused by accidental
380          * duplication in the config file.
381          *
382          * index 0 is the exception, because it is used when we want
383          * to collect _all_ listed modules under a single index by
384          * default, which is currently the case in all components
385          * except authenticate. */
386         if (c) {
387                 if (idx == 0) {
388                         return c;
389                 }
390                 return NULL;
391         }
392
393         c = rad_malloc(sizeof(*c));
394         c->modulelist = NULL;
395         c->comp = comp;
396         c->idx = idx;
397
398         if (!lrad_hash_table_insert(components, c)) {
399                 free(c);
400                 return NULL;
401         }
402
403         return c;
404 }
405
406 static int indexed_modcall(int comp, int idx, REQUEST *request)
407 {
408         int rcode;
409         indexed_modcallable *this;
410
411         this = lookup_by_index(comp, idx);
412         if (!this) {
413                 if (idx != 0) DEBUG2("  ERROR: Unknown value specified for %s.  Cannot perform requested action.",
414                                      section_type_value[comp].typename);
415                 request->component = section_type_value[comp].typename;
416                 rcode = modcall(comp, NULL, request); /* does default action */
417         } else {
418                 DEBUG2("  Processing the %s section of %s",
419                        section_type_value[comp].section,
420                        mainconfig.radiusd_conf);
421                 request->component = section_type_value[comp].typename;
422                 rcode = modcall(comp, this->modulelist, request);
423         }
424         request->module = "<server-core>";
425         request->component = "<server-core>";
426         return rcode;
427 }
428
429 /*
430  *      Load a sub-module list, as found inside an Auth-Type foo {}
431  *      block
432  */
433 static int load_subcomponent_section(modcallable *parent,
434                                      CONF_SECTION *cs, int comp,
435                                      const char *filename)
436 {
437         indexed_modcallable *subcomp;
438         modcallable *ml;
439         DICT_VALUE *dval;
440         const char *name2 = cf_section_name2(cs);
441
442         rad_assert(comp >= RLM_COMPONENT_AUTH);
443         rad_assert(comp <= RLM_COMPONENT_COUNT);
444
445         /*
446          *      Sanity check.
447          */
448         if (!name2) {
449                 radlog(L_ERR|L_CONS,
450                        "%s[%d]: No name specified for %s block",
451                        filename, cf_section_lineno(cs),
452                        section_type_value[comp].typename);
453                 return 1;
454         }
455
456         /*
457          *      Compile the group.
458          */
459         ml = compile_modgroup(parent, comp, cs, filename);
460         if (!ml) {
461                 return 0;
462         }       
463
464         /*
465          *      We must assign a numeric index to this subcomponent.
466          *      It is generated and placed in the dictionary by
467          *      setup_modules(), when it loads the sections.  If it
468          *      isn't found, it's a serious error.
469          */
470         dval = dict_valbyname(section_type_value[comp].attr, name2);
471         if (!dval) {
472                 radlog(L_ERR|L_CONS,
473                        "%s[%d] %s %s Not previously configured",
474                        filename, cf_section_lineno(cs),
475                        section_type_value[comp].typename, name2);
476                 modcallable_free(&ml);
477                 return 0;
478         }
479
480         subcomp = new_sublist(comp, dval->value);
481         if (!subcomp) {
482                 radlog(L_ERR|L_CONS,
483                        "%s[%d] %s %s already configured - skipping",
484                        filename, cf_section_lineno(cs),
485                        section_type_value[comp].typename, name2);
486                 modcallable_free(&ml);
487                 return 1;
488         }
489
490         subcomp->modulelist = ml;
491         return 1;               /* OK */
492 }
493
494 static int load_component_section(modcallable *parent,
495                                   CONF_SECTION *cs, int comp,
496                                   const char *filename)
497 {
498         modcallable *this;
499         CONF_ITEM *modref;
500         int idx;
501         indexed_modcallable *subcomp;
502         const char *modname;
503         const char *visiblename;
504
505         /*
506          *      Loop over the entries in the named section.
507          */
508         for (modref = cf_item_find_next(cs, NULL);
509              modref != NULL;
510              modref = cf_item_find_next(cs, modref)) {
511                 CONF_PAIR *cp = NULL;
512                 CONF_SECTION *scs = NULL;
513
514                 /*
515                  *      Look for Auth-Type foo {}, which are special
516                  *      cases of named sections, and allowable ONLY
517                  *      at the top-level.
518                  *
519                  *      i.e. They're not allowed in a "group" or "redundant"
520                  *      subsection.
521                  */
522                 if (cf_item_is_section(modref)) {
523                         const char *sec_name;
524                         scs = cf_itemtosection(modref);
525
526                         sec_name = cf_section_name1(scs);
527
528                         if (strcmp(sec_name,
529                                    section_type_value[comp].typename) == 0) {
530                                 if (!load_subcomponent_section(parent, scs,
531                                                                comp,
532                                                                filename)) {
533                                         return -1; /* FIXME: memleak? */
534                                 }
535                                 continue;
536                         }
537
538                         /*
539                          *      Allow old names, too.
540                          */
541                         if (strcmp(sec_name,
542                                    old_section_type_value[comp].typename) == 0) {
543                                 if (!load_subcomponent_section(parent, scs,
544                                                                comp,
545                                                                filename)) {
546                                         return -1; /* FIXME: memleak? */
547                                 }
548                                 continue;
549                         }
550                         cp = NULL;
551                 } else if (cf_item_is_pair(modref)) {
552                         cp = cf_itemtopair(modref);
553                 } else {
554                         continue; /* ignore it */
555                 }
556
557                 /*
558                  *      Try to compile one entry.
559                  */
560                 this = compile_modsingle(parent, comp, modref, filename,
561                                          &modname);
562                 if (!this) {
563                         radlog(L_ERR|L_CONS,
564                                "%s[%d] Failed to parse %s section.\n",
565                                filename, cf_section_lineno(cs),
566                                cf_section_name1(cs));
567                         return -1;
568                 }
569
570                 if (comp == RLM_COMPONENT_AUTH) {
571                         DICT_VALUE *dval;
572                         const char *modrefname = NULL;
573                         int lineno = 0;
574
575                         if (cp) {
576                                 modrefname = cf_pair_attr(cp);
577                                 lineno = cf_pair_lineno(cp);
578                         } else {
579                                 modrefname = cf_section_name2(scs);
580                                 lineno = cf_section_lineno(scs);
581                                 if (!modrefname) {
582                                         radlog(L_ERR|L_CONS,
583                                                "%s[%d] Failed to parse %s sub-section.\n",
584                                                filename, lineno,
585                                                cf_section_name1(scs));
586                                         return -1;
587                                 }
588                         }
589
590                         dval = dict_valbyname(PW_AUTH_TYPE, modrefname);
591                         if (!dval) {
592                                 /*
593                                  *      It's a section, but nothing we
594                                  *      recognize.  Die!
595                                  */
596                                 radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s sub-section.",
597                                        filename, lineno,
598                                        modrefname, section_type_value[comp].section);
599                                 return -1;
600                         }
601                         idx = dval->value;
602                 } else {
603                         /* See the comment in new_sublist() for explanation
604                          * of the special index 0 */
605                         idx = 0;
606                 }
607
608                 subcomp = new_sublist(comp, idx);
609                 if (subcomp == NULL) {
610                         radlog(L_INFO|L_CONS,
611                                         "%s %s %s already configured - skipping",
612                                         filename, section_type_value[comp].typename,
613                                         modname);
614                         modcallable_free(&this);
615                         continue;
616                 }
617
618                 /* If subcomp->modulelist is NULL, add_to_modcallable will
619                  * create it */
620                 visiblename = cf_section_name2(cs);
621                 if (visiblename == NULL)
622                         visiblename = cf_section_name1(cs);
623                 add_to_modcallable(&subcomp->modulelist, this,
624                                    comp, visiblename);
625         }
626
627         return 0;
628 }
629
630
631 /*
632  *      Parse the module config sections, and load
633  *      and call each module's init() function.
634  *
635  *      Libtool makes your life a LOT easier, especially with libltdl.
636  *      see: http://www.gnu.org/software/libtool/
637  */
638 int setup_modules(int reload)
639 {
640         int             comp;
641         CONF_SECTION    *cs, *modules;
642         int             do_component[RLM_COMPONENT_COUNT];
643         rad_listen_t    *listener;
644
645         /*
646          *      If necessary, initialize libltdl.
647          */
648         if (!reload) {
649                 /*
650                  *      Set the default list of preloaded symbols.
651                  *      This is used to initialize libltdl's list of
652                  *      preloaded modules.
653                  *
654                  *      i.e. Static modules.
655                  */
656                 LTDL_SET_PRELOADED_SYMBOLS();
657
658                 if (lt_dlinit() != 0) {
659                         radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
660                                         lt_dlerror());
661                         return -1;
662                 }
663
664                 /*
665                  *      Set the search path to ONLY our library directory.
666                  *      This prevents the modules from being found from
667                  *      any location on the disk.
668                  */
669                 lt_dlsetsearchpath(radlib_dir);
670
671                 DEBUG2("Module: Library search path is %s",
672                                 lt_dlgetsearchpath());
673
674                 /*
675                  *      Set up the internal module struct.
676                  */
677                 module_tree = rbtree_create(module_entry_cmp,
678                                             module_entry_free, 0);
679                 if (!module_tree) {
680                         radlog(L_ERR|L_CONS, "Failed to initialize modules\n");
681                         return -1;
682                 }
683         } else {
684                 lrad_hash_table_free(components);
685         }
686
687         components = lrad_hash_table_create(indexed_modcallable_hash,
688                                             indexed_modcallable_cmp,
689                                             indexed_modcallable_free);
690         if (!components) {
691                 radlog(L_ERR|L_CONS, "Failed to initialize components\n");
692                 return -1;
693         }
694
695         /*
696          *      Figure out which sections to load.
697          */
698         memset(do_component, 0, sizeof(do_component));
699         for (listener = mainconfig.listen;
700              listener != NULL;
701              listener = listener->next) {
702                 switch (listener->type) {
703                 case RAD_LISTEN_AUTH:
704                         do_component[RLM_COMPONENT_AUTZ] = 1;
705                         do_component[RLM_COMPONENT_AUTH] = 1;
706                         do_component[RLM_COMPONENT_POST_AUTH] = 1;
707                         do_component[RLM_COMPONENT_SESS] = 1;
708                         break;
709
710                 case RAD_LISTEN_DETAIL: /* just like acct */
711                 case RAD_LISTEN_ACCT:
712                         do_component[RLM_COMPONENT_PREACCT] = 1;
713                         do_component[RLM_COMPONENT_ACCT] = 1;
714                         break;
715
716                 case RAD_LISTEN_PROXY:
717                         do_component[RLM_COMPONENT_PRE_PROXY] = 1;
718                         do_component[RLM_COMPONENT_POST_PROXY] = 1;
719                         break;
720
721
722                 default:
723                         rad_assert(0 == 1);
724                         break;
725                 }
726         }
727
728         for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
729                 /*
730                  *      Have the debugging messages all in one place.
731                  */
732                 if (!do_component[comp]) {
733                         DEBUG2("modules: Not loading %s{} section",
734                                section_type_value[comp].section);
735                 }
736         }
737
738         /*
739          *      Create any DICT_VALUE's for the types.  See
740          *      'doc/configurable_failover' for examples of 'authtype'
741          *      used to create new Auth-Type values.  In order to
742          *      let the user create new names, we've got to look for
743          *      those names, and create DICT_VALUE's for them.
744          */
745         for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
746                 int             value;
747                 const char      *name2;
748                 DICT_ATTR       *dattr;
749                 DICT_VALUE      *dval;
750                 CONF_SECTION    *sub, *next;
751                 CONF_PAIR       *cp;
752
753                 /*
754                  *      Not needed, don't load it.
755                  */
756                 if (!do_component[comp]) {
757                         continue;
758                 }
759                 cs = cf_section_find(section_type_value[comp].section);
760
761                 if (!cs) continue;
762
763                 sub = NULL;
764                 do {
765                         /*
766                          *      See if there's a sub-section by that
767                          *      name.
768                          */
769                         next = cf_subsection_find_next(cs, sub,
770                                                        section_type_value[comp].typename);
771
772                         /*
773                          *      Allow some old names, too.
774                          */
775                         if (!next && (comp <= 4)) {
776                                 next = cf_subsection_find_next(cs, sub,
777                                                                old_section_type_value[comp].typename);
778                         }
779                         sub = next;
780
781                         /*
782                          *      If so, look for it to define a new
783                          *      value.
784                          */
785                         name2 = cf_section_name2(sub);
786                         if (!name2) continue;
787
788
789                         /*
790                          *      If the value already exists, don't
791                          *      create it again.
792                          */
793                         dval = dict_valbyname(section_type_value[comp].attr,
794                                               name2);
795                         if (dval) continue;
796
797                         /*
798                          *      Find the attribute for the value.
799                          */
800                         dattr = dict_attrbyvalue(section_type_value[comp].attr);
801                         if (!dattr) {
802                                 radlog(L_ERR, "%s[%d]: No such attribute %s",
803                                        mainconfig.radiusd_conf,
804                                        cf_section_lineno(sub),
805                                        section_type_value[comp].typename);
806                                 continue;
807                         }
808
809                         /*
810                          *      Create a new unique value with a
811                          *      meaningless number.  You can't look at
812                          *      it from outside of this code, so it
813                          *      doesn't matter.  The only requirement
814                          *      is that it's unique.
815                          */
816                         do {
817                                 value = lrad_rand() & 0x00ffffff;
818                         } while (dict_valbyattr(dattr->attr, value));
819
820                         if (dict_addvalue(name2, dattr->name, value) < 0) {
821                                 radlog(L_ERR, "%s", librad_errstr);
822                                 return -1;
823                         }
824                 } while (sub != NULL);
825
826                 /*
827                  *      Loop over the non-sub-sections, too.
828                  */
829                 cp = NULL;
830                 do {
831                         /*
832                          *      See if there's a conf-pair by that
833                          *      name.
834                          */
835                         cp = cf_pair_find_next(cs, cp, NULL);
836                         if (!cp) break;
837
838
839                         /*
840                          *      If the value already exists, don't
841                          *      create it again.
842                          */
843                         name2 = cf_pair_attr(cp);
844                         dval = dict_valbyname(section_type_value[comp].attr,
845                                               name2);
846                         if (dval) continue;
847
848                         /*
849                          *      Find the attribute for the value.
850                          */
851                         dattr = dict_attrbyvalue(section_type_value[comp].attr);
852                         if (!dattr) {
853                                 radlog(L_ERR, "%s[%d]: No such attribute %s",
854                                        mainconfig.radiusd_conf,
855                                        cf_section_lineno(sub),
856                                        section_type_value[comp].typename);
857                                 continue;
858                         }
859
860                         /*
861                          *      Finally, create the new attribute.
862                          */
863                         do {
864                                 value = lrad_rand() & 0x00ffffff;
865                         } while (dict_valbyattr(dattr->attr, value));
866                         if (dict_addvalue(name2, dattr->name, value) < 0) {
867                                 radlog(L_ERR, "%s", librad_errstr);
868                                 return -1;
869                         }
870                 } while (cp != NULL);
871         } /* over the sections which can have redundent sub-sections */
872
873         /*
874          *      Remember where the modules were stored.
875          */
876         modules = cf_section_find("modules");
877         if (!modules) {
878                 radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!");
879                 return -1;
880         }
881
882         /*
883          *  Look for the 'instantiate' section, which tells us
884          *  the instantiation order of the modules, and also allows
885          *  us to load modules with no authorize/authenticate/etc.
886          *  sections.
887          */
888         cs = cf_section_find("instantiate");
889         if (cs != NULL) {
890                 CONF_ITEM *ci;
891                 CONF_PAIR *cp;
892                 module_instance_t *module;
893                 const char *name;
894
895                 /*
896                  *  Loop over the items in the 'instantiate' section.
897                  */
898                 for (ci=cf_item_find_next(cs, NULL);
899                      ci != NULL;
900                      ci=cf_item_find_next(cs, ci)) {
901
902                         /*
903                          *      Skip sections.  They'll be handled
904                          *      later, if they're referenced at all...
905                          */
906                         if (cf_item_is_section(ci)) {
907                                 continue;
908                         }
909
910                         cp = cf_itemtopair(ci);
911                         name = cf_pair_attr(cp);
912                         module = find_module_instance(modules, name);
913                         if (!module) {
914                                 return -1;
915                         }
916                 } /* loop over items in the subsection */
917         } /* if there's an 'instantiate' section. */
918
919         /*
920          *      Loop over all of the known components, finding their
921          *      configuration section, and loading it.
922          */
923         for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) {
924                 cs = cf_section_find(section_type_value[comp].section);
925                 if (cs == NULL)
926                         continue;
927
928                 if (!do_component[comp]) {
929                         continue;
930                 }
931
932                 if (load_component_section(NULL, cs, comp, mainconfig.radiusd_conf) < 0) {
933                         return -1;
934                 }
935         }
936
937         return 0;
938 }
939
940 /*
941  *      Call all authorization modules until one returns
942  *      somethings else than RLM_MODULE_OK
943  */
944 int module_authorize(int autz_type, REQUEST *request)
945 {
946         return indexed_modcall(RLM_COMPONENT_AUTZ, autz_type, request);
947 }
948
949 /*
950  *      Authenticate a user/password with various methods.
951  */
952 int module_authenticate(int auth_type, REQUEST *request)
953 {
954         return indexed_modcall(RLM_COMPONENT_AUTH, auth_type, request);
955 }
956
957 /*
958  *      Do pre-accounting for ALL configured sessions
959  */
960 int module_preacct(REQUEST *request)
961 {
962         return indexed_modcall(RLM_COMPONENT_PREACCT, 0, request);
963 }
964
965 /*
966  *      Do accounting for ALL configured sessions
967  */
968 int module_accounting(int acct_type, REQUEST *request)
969 {
970         return indexed_modcall(RLM_COMPONENT_ACCT, acct_type, request);
971 }
972
973 /*
974  *      See if a user is already logged in.
975  *
976  *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
977  */
978 int module_checksimul(int sess_type, REQUEST *request, int maxsimul)
979 {
980         int rcode;
981
982         if(!request->username)
983                 return 0;
984
985         request->simul_count = 0;
986         request->simul_max = maxsimul;
987         request->simul_mpp = 1;
988
989         rcode = indexed_modcall(RLM_COMPONENT_SESS, sess_type, request);
990
991         if (rcode != RLM_MODULE_OK) {
992                 /* FIXME: Good spot for a *rate-limited* warning to the log */
993                 return 0;
994         }
995
996         return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
997 }
998
999 /*
1000  *      Do pre-proxying for ALL configured sessions
1001  */
1002 int module_pre_proxy(int type, REQUEST *request)
1003 {
1004         return indexed_modcall(RLM_COMPONENT_PRE_PROXY, type, request);
1005 }
1006
1007 /*
1008  *      Do post-proxying for ALL configured sessions
1009  */
1010 int module_post_proxy(int type, REQUEST *request)
1011 {
1012         return indexed_modcall(RLM_COMPONENT_POST_PROXY, type, request);
1013 }
1014
1015 /*
1016  *      Do post-authentication for ALL configured sessions
1017  */
1018 int module_post_auth(int postauth_type, REQUEST *request)
1019 {
1020         return indexed_modcall(RLM_COMPONENT_POST_AUTH, postauth_type, request);
1021 }
1022