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