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