./scripts/min-includes +n <files listed here>
[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  The FreeRADIUS server project
21  * Copyright 2000  Alan DeKok <aland@ox.org>
22  * Copyright 2000  Alan Curry <pacman@world.std.com>
23  */
24
25 static const char rcsid[] = "$Id$";
26
27 #include <freeradius-devel/autoconf.h>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <freeradius-devel/radiusd.h>
34 #include <freeradius-devel/modpriv.h>
35 #include <freeradius-devel/modcall.h>
36 #include <freeradius-devel/rad_assert.h>
37
38 typedef struct indexed_modcallable {
39         int comp;
40         int idx;
41         modcallable *modulelist;
42 } indexed_modcallable;
43
44 /*
45  *      For each component, keep an ordered list of ones to call.
46  */
47 static lrad_hash_table_t *components;
48
49 static rbtree_t *module_tree = NULL;
50
51 typedef struct section_type_value_t {
52         const char      *section;
53         const char      *typename;
54         int             attr;
55 } section_type_value_t;
56
57
58 /*
59  *      Ordered by component
60  */
61 static const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
62         { "authenticate", "Auth-Type",       PW_AUTH_TYPE },
63         { "authorize",    "Autz-Type",       PW_AUTZ_TYPE },
64         { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },
65         { "accounting",   "Acct-Type",       PW_ACCT_TYPE },
66         { "session",      "Session-Type",    PW_SESSION_TYPE },
67         { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
68         { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
69         { "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE },
70 };
71
72 /*
73  *      Delete ASAP.
74  */
75 static const section_type_value_t old_section_type_value[] = {
76         { "authenticate", "authtype", PW_AUTH_TYPE },
77         { "authorize",    "autztype", PW_AUTZ_TYPE },
78         { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },/* unused */
79         { "accounting",   "acctype", PW_ACCT_TYPE },
80         { "session",      "sesstype", PW_SESSION_TYPE },
81         { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE }, /* unused */
82         { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE }, /* unused */
83         { "post-auth",    "post-authtype", PW_POST_AUTH_TYPE }
84 };
85
86
87 static void indexed_modcallable_free(void *data)
88 {
89         indexed_modcallable *c = data;
90
91         modcallable_free(&c->modulelist);
92         free(c);
93 }
94
95 static uint32_t indexed_modcallable_hash(const void *data)
96 {
97         uint32_t hash;
98         const indexed_modcallable *c = data;
99
100         hash = lrad_hash(&c->comp, sizeof(c->comp));
101         return lrad_hash_update(&c->idx, sizeof(c->idx), hash);
102 }
103
104 static int indexed_modcallable_cmp(const void *one, const void *two)
105 {
106         const indexed_modcallable *a = one;
107         const indexed_modcallable *b = two;
108
109         if (a->comp < b->comp) return -1;
110         if (a->comp >  b->comp) return +1;
111
112         return a->idx - b->idx;
113 }
114
115
116 /*
117  *      Free a module instance.
118  */
119 static void module_instance_free(void *data)
120 {
121         module_instance_t *this = data;
122
123         if (this->entry->module->detach)
124                 (this->entry->module->detach)(this->insthandle);
125 #ifdef HAVE_PTHREAD_H
126         if (this->mutex) {
127                 /*
128                  *      FIXME
129                  *      The mutex MIGHT be locked...
130                  *      we'll check for that later, I guess.
131                  */
132                 pthread_mutex_destroy(this->mutex);
133                 free(this->mutex);
134         }
135 #endif
136         free(this);
137 }
138
139
140 /*
141  *      Compare two module entries
142  */
143 static int module_entry_cmp(const void *one, const void *two)
144 {
145         const module_entry_t *a = one;
146         const module_entry_t *b = two;
147
148         return strcmp(a->name, b->name);
149 }
150
151 /*
152  *      Free a module entry.
153  */
154 static void module_entry_free(void *data)
155 {
156         module_entry_t *this = data;
157
158         lt_dlclose(this->handle);       /* ignore any errors */
159         free(this);
160 }
161
162
163 /*
164  *      Remove the module lists.
165  */
166 int detach_modules(void)
167 {
168         lrad_hash_table_free(components);
169
170         return 0;
171 }
172
173
174 /*
175  *      Find a module on disk or in memory, and link to it.
176  */
177 static module_entry_t *linkto_module(const char *module_name,
178                                      const char *cffilename, int cflineno)
179 {
180         module_entry_t myentry;
181         module_entry_t *node;
182         lt_dlhandle handle;
183         char module_struct[256];
184         char *p;
185         const void *module;
186
187         strNcpy(myentry.name, module_name, sizeof(myentry.name));
188         node = rbtree_finddata(module_tree, &myentry);
189         if (node) return node;
190
191         /*
192          *      Keep the handle around so we can dlclose() it.
193          */
194         handle = lt_dlopenext(module_name);
195         if (handle == NULL) {
196                 radlog(L_ERR|L_CONS, "%s[%d] Failed to link to module '%s':"
197                        " %s\n", cffilename, cflineno, module_name, lt_dlerror());
198                 return NULL;
199         }
200
201         /*
202          *      Link to the module's rlm_FOO{} module structure.
203          *
204          *      The module_name variable has the version number
205          *      embedded in it, and we don't want that here.
206          */
207         strcpy(module_struct, module_name);
208         p = strrchr(module_struct, '-');
209         if (p) *p = '\0';
210
211         DEBUG3("    (Loaded %s, checking if it's valid)", module_name);
212
213         /*
214          *      libltld MAY core here, if the handle it gives us contains
215          *      garbage data.
216          */
217         module = lt_dlsym(handle, module_struct);
218         if (!module) {
219                 radlog(L_ERR|L_CONS, "%s[%d] Failed linking to "
220                                 "%s structure in %s: %s\n",
221                                 cffilename, cflineno,
222                                 module_name, cffilename, lt_dlerror());
223                 lt_dlclose(handle);
224                 return NULL;
225         }
226         /*
227          *      Before doing anything else, check if it's sane.
228          */
229         if ((*(const uint32_t *) module) != RLM_MODULE_MAGIC_NUMBER) {
230                 lt_dlclose(handle);
231                 radlog(L_ERR|L_CONS, "%s[%d] Invalid version in module '%s'",
232                        cffilename, cflineno, module_name);
233                 return NULL;
234                 
235         }
236
237         /* make room for the module type */
238         node = rad_malloc(sizeof(*node));
239         memset(node, 0, sizeof(*node));
240         strNcpy(node->name, module_name, sizeof(node->name));
241         node->module = module;
242         node->handle = handle;
243
244         DEBUG("Module: Loaded %s ", node->module->name);
245
246         /*
247          *      Add the module as "rlm_foo-version" to the configuration
248          *      section.
249          */
250         if (!rbtree_insert(module_tree, node)) {
251                 radlog(L_ERR, "Failed to cache module %s", module_name);
252                 lt_dlclose(handle);
253                 free(node);
254                 return NULL;
255         }
256
257         return node;
258 }
259
260 /*
261  *      Find a module instance.
262  */
263 module_instance_t *find_module_instance(CONF_SECTION *modules,
264                                         const char *instname)
265 {
266         CONF_SECTION *cs;
267         const char *name1, *name2;
268         module_instance_t *node;
269         char module_name[256];
270
271         if (!modules) return NULL;
272
273         /*
274          *      Module instances are declared in the modules{} block
275          *      and referenced later by their name, which is the
276          *      name2 from the config section, or name1 if there was
277          *      no name2.
278          */
279         cs = cf_section_sub_find_name2(modules, NULL, instname);
280         if (cs == NULL) {
281                 radlog(L_ERR|L_CONS, "ERROR: Cannot find a configuration entry for module \"%s\".\n", instname);
282                 return NULL;
283         }
284
285         /*
286          *      If there's already a module instance, return it.
287          */
288         node = cf_data_find(cs, "instance");
289         if (node) return node;
290
291         name1 = cf_section_name1(cs);
292         name2 = cf_section_name2(cs);
293
294         /*
295          *      Found the configuration entry.
296          */
297         node = rad_malloc(sizeof(*node));
298         memset(node, 0, sizeof(*node));
299
300         node->insthandle = NULL;
301
302         /*
303          *      Names in the "modules" section aren't prefixed
304          *      with "rlm_", so we add it here.
305          */
306         snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
307
308         node->entry = linkto_module(module_name,
309                                     mainconfig.radiusd_conf,
310                                     cf_section_lineno(cs));
311         if (!node->entry) {
312                 free(node);
313                 /* linkto_module logs any errors */
314                 return NULL;
315         }
316
317         /*
318          *      Call the module's instantiation routine.
319          */
320         if ((node->entry->module->instantiate) &&
321             ((node->entry->module->instantiate)(cs, &node->insthandle) < 0)) {
322                 radlog(L_ERR|L_CONS,
323                                 "%s[%d]: %s: Module instantiation failed.\n",
324                        mainconfig.radiusd_conf, cf_section_lineno(cs),
325                        instname);
326                 free(node);
327                 return NULL;
328         }
329
330         /*
331          *      We're done.  Fill in the rest of the data structure,
332          *      and link it to the module instance list.
333          */
334         strNcpy(node->name, instname, sizeof(node->name));
335
336 #ifdef HAVE_PTHREAD_H
337         /*
338          *      If we're threaded, check if the module is thread-safe.
339          *
340          *      If it isn't, we create a mutex.
341          */
342         if ((node->entry->module->type & RLM_TYPE_THREAD_UNSAFE) != 0) {
343                 node->mutex = (pthread_mutex_t *) rad_malloc(sizeof(pthread_mutex_t));
344                 /*
345                  *      Initialize the mutex.
346                  */
347                 pthread_mutex_init(node->mutex, NULL);
348         } else {
349                 /*
350                  *      The module is thread-safe.  Don't give it a mutex.
351                  */
352                 node->mutex = NULL;
353         }
354
355 #endif
356         cf_data_add(cs, "instance", node, module_instance_free);
357
358         DEBUG("Module: Instantiated %s (%s) ", name1, node->name);
359
360         return node;
361 }
362
363 static indexed_modcallable *lookup_by_index(int comp, int idx)
364 {
365         indexed_modcallable myc;
366
367         myc.comp = comp;
368         myc.idx = idx;
369
370         return lrad_hash_table_finddata(components, &myc);
371 }
372
373 /*
374  *      Create a new sublist.
375  */
376 static indexed_modcallable *new_sublist(int comp, int idx)
377 {
378         indexed_modcallable *c;
379
380         c = lookup_by_index(comp, idx);
381
382         /* It is an error to try to create a sublist that already
383          * exists. It would almost certainly be caused by accidental
384          * duplication in the config file.
385          *
386          * index 0 is the exception, because it is used when we want
387          * to collect _all_ listed modules under a single index by
388          * default, which is currently the case in all components
389          * except authenticate. */
390         if (c) {
391                 if (idx == 0) {
392                         return c;
393                 }
394                 return NULL;
395         }
396
397         c = rad_malloc(sizeof(*c));
398         c->modulelist = NULL;
399         c->comp = comp;
400         c->idx = idx;
401
402         if (!lrad_hash_table_insert(components, c)) {
403                 free(c);
404                 return NULL;
405         }
406
407         return c;
408 }
409
410 static int indexed_modcall(int comp, int idx, REQUEST *request)
411 {
412         int rcode;
413         indexed_modcallable *this;
414
415         this = lookup_by_index(comp, idx);
416         if (!this) {
417                 if (idx != 0) DEBUG2("  ERROR: Unknown value specified for %s.  Cannot perform requested action.",
418                                      section_type_value[comp].typename);
419                 request->component = section_type_value[comp].typename;
420                 rcode = modcall(comp, NULL, request); /* does default action */
421         } else {
422                 DEBUG2("  Processing the %s section of %s",
423                        section_type_value[comp].section,
424                        mainconfig.radiusd_conf);
425                 request->component = section_type_value[comp].typename;
426                 rcode = modcall(comp, this->modulelist, request);
427         }
428         request->module = "<server-core>";
429         request->component = "<server-core>";
430         return rcode;
431 }
432
433 /*
434  *      Load a sub-module list, as found inside an Auth-Type foo {}
435  *      block
436  */
437 static int load_subcomponent_section(modcallable *parent,
438                                      CONF_SECTION *cs, int comp,
439                                      const char *filename)
440 {
441         indexed_modcallable *subcomp;
442         modcallable *ml;
443         DICT_VALUE *dval;
444         const char *name2 = cf_section_name2(cs);
445
446         rad_assert(comp >= RLM_COMPONENT_AUTH);
447         rad_assert(comp <= RLM_COMPONENT_COUNT);
448
449         /*
450          *      Sanity check.
451          */
452         if (!name2) {
453                 radlog(L_ERR|L_CONS,
454                        "%s[%d]: No name specified for %s block",
455                        filename, cf_section_lineno(cs),
456                        section_type_value[comp].typename);
457                 return 1;
458         }
459
460         /*
461          *      Compile the group.
462          */
463         ml = compile_modgroup(parent, comp, cs, filename);
464         if (!ml) {
465                 return 0;
466         }       
467
468         /*
469          *      We must assign a numeric index to this subcomponent.
470          *      It is generated and placed in the dictionary by
471          *      setup_modules(), when it loads the sections.  If it
472          *      isn't found, it's a serious error.
473          */
474         dval = dict_valbyname(section_type_value[comp].attr, name2);
475         if (!dval) {
476                 radlog(L_ERR|L_CONS,
477                        "%s[%d] %s %s Not previously configured",
478                        filename, cf_section_lineno(cs),
479                        section_type_value[comp].typename, name2);
480                 modcallable_free(&ml);
481                 return 0;
482         }
483
484         subcomp = new_sublist(comp, dval->value);
485         if (!subcomp) {
486                 radlog(L_ERR|L_CONS,
487                        "%s[%d] %s %s already configured - skipping",
488                        filename, cf_section_lineno(cs),
489                        section_type_value[comp].typename, name2);
490                 modcallable_free(&ml);
491                 return 1;
492         }
493
494         subcomp->modulelist = ml;
495         return 1;               /* OK */
496 }
497
498 static int load_component_section(modcallable *parent,
499                                   CONF_SECTION *cs, int comp,
500                                   const char *filename)
501 {
502         modcallable *this;
503         CONF_ITEM *modref;
504         int idx;
505         indexed_modcallable *subcomp;
506         const char *modname;
507         const char *visiblename;
508
509         /*
510          *      Loop over the entries in the named section.
511          */
512         for (modref = cf_item_find_next(cs, NULL);
513              modref != NULL;
514              modref = cf_item_find_next(cs, modref)) {
515                 CONF_PAIR *cp = NULL;
516                 CONF_SECTION *scs = NULL;
517
518                 /*
519                  *      Look for Auth-Type foo {}, which are special
520                  *      cases of named sections, and allowable ONLY
521                  *      at the top-level.
522                  *
523                  *      i.e. They're not allowed in a "group" or "redundant"
524                  *      subsection.
525                  */
526                 if (cf_item_is_section(modref)) {
527                         const char *sec_name;
528                         scs = cf_itemtosection(modref);
529
530                         sec_name = cf_section_name1(scs);
531
532                         if (strcmp(sec_name,
533                                    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
542                         /*
543                          *      Allow old names, too.
544                          */
545                         if (strcmp(sec_name,
546                                    old_section_type_value[comp].typename) == 0) {
547                                 if (!load_subcomponent_section(parent, scs,
548                                                                comp,
549                                                                filename)) {
550                                         return -1; /* FIXME: memleak? */
551                                 }
552                                 continue;
553                         }
554                         cp = NULL;
555                 } else if (cf_item_is_pair(modref)) {
556                         cp = cf_itemtopair(modref);
557                 } else {
558                         continue; /* ignore it */
559                 }
560
561                 /*
562                  *      Try to compile one entry.
563                  */
564                 this = compile_modsingle(parent, comp, modref, filename,
565                                          &modname);
566                 if (!this) {
567                         radlog(L_ERR|L_CONS,
568                                "%s[%d] Failed to parse %s section.\n",
569                                filename, cf_section_lineno(cs),
570                                cf_section_name1(cs));
571                         return -1;
572                 }
573
574                 if (comp == RLM_COMPONENT_AUTH) {
575                         DICT_VALUE *dval;
576                         const char *modrefname = NULL;
577
578                         if (cp) {
579                                 modrefname = cf_pair_attr(cp);
580                         } else {
581                                 modrefname = cf_section_name2(scs);
582                                 if (!modrefname) {
583                                         radlog(L_ERR|L_CONS,
584                                                "%s[%d] Failed to parse %s sub-section.\n",
585                                                filename, cf_section_lineno(scs),
586                                                cf_section_name1(scs));
587                                         return -1;
588                                 }
589                         }
590
591                         dval = dict_valbyname(PW_AUTH_TYPE, modrefname);
592                         if (!dval) {
593                                 /*
594                                  *      It's a section, but nothing we
595                                  *      recognize.  Die!
596                                  */
597                                 radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s sub-section.",
598                                        filename, cf_section_lineno(scs),
599                                        modrefname, section_type_value[comp].section);
600                                 return -1;
601                         }
602                         idx = dval->value;
603                 } else {
604                         /* See the comment in new_sublist() for explanation
605                          * of the special index 0 */
606                         idx = 0;
607                 }
608
609                 subcomp = new_sublist(comp, idx);
610                 if (subcomp == NULL) {
611                         radlog(L_INFO|L_CONS,
612                                         "%s %s %s already configured - skipping",
613                                         filename, section_type_value[comp].typename,
614                                         modname);
615                         modcallable_free(&this);
616                         continue;
617                 }
618
619                 /* If subcomp->modulelist is NULL, add_to_modcallable will
620                  * create it */
621                 visiblename = cf_section_name2(cs);
622                 if (visiblename == NULL)
623                         visiblename = cf_section_name1(cs);
624                 add_to_modcallable(&subcomp->modulelist, this,
625                                    comp, visiblename);
626         }
627
628         return 0;
629 }
630
631
632 /*
633  *      Parse the module config sections, and load
634  *      and call each module's init() function.
635  *
636  *      Libtool makes your life a LOT easier, especially with libltdl.
637  *      see: http://www.gnu.org/software/libtool/
638  */
639 int setup_modules(int reload)
640 {
641         int             comp;
642         CONF_SECTION    *cs, *modules;
643         int             do_component[RLM_COMPONENT_COUNT];
644         rad_listen_t    *listener;
645
646         /*
647          *      If necessary, initialize libltdl.
648          */
649         if (!reload) {
650                 /*
651                  *      Set the default list of preloaded symbols.
652                  *      This is used to initialize libltdl's list of
653                  *      preloaded modules.
654                  *
655                  *      i.e. Static modules.
656                  */
657                 LTDL_SET_PRELOADED_SYMBOLS();
658
659                 if (lt_dlinit() != 0) {
660                         radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
661                                         lt_dlerror());
662                         return -1;
663                 }
664
665                 /*
666                  *      Set the search path to ONLY our library directory.
667                  *      This prevents the modules from being found from
668                  *      any location on the disk.
669                  */
670                 lt_dlsetsearchpath(radlib_dir);
671
672                 DEBUG2("Module: Library search path is %s",
673                                 lt_dlgetsearchpath());
674
675                 /*
676                  *      Set up the internal module struct.
677                  */
678                 module_tree = rbtree_create(module_entry_cmp,
679                                             module_entry_free, 0);
680                 if (!module_tree) {
681                         radlog(L_ERR|L_CONS, "Failed to initialize modules\n");
682                         return -1;
683                 }
684         } else {
685                 lrad_hash_table_free(components);
686         }
687
688         components = lrad_hash_table_create(indexed_modcallable_hash,
689                                             indexed_modcallable_cmp,
690                                             indexed_modcallable_free);
691         if (!components) {
692                 radlog(L_ERR|L_CONS, "Failed to initialize components\n");
693                 return -1;
694         }
695
696         /*
697          *      Figure out which sections to load.
698          */
699         memset(do_component, 0, sizeof(do_component));
700         for (listener = mainconfig.listen;
701              listener != NULL;
702              listener = listener->next) {
703                 switch (listener->type) {
704                 case RAD_LISTEN_AUTH:
705                         do_component[RLM_COMPONENT_AUTZ] = 1;
706                         do_component[RLM_COMPONENT_AUTH] = 1;
707                         do_component[RLM_COMPONENT_POST_AUTH] = 1;
708                         do_component[RLM_COMPONENT_SESS] = 1;
709                         break;
710
711                 case RAD_LISTEN_DETAIL: /* just like acct */
712                 case RAD_LISTEN_ACCT:
713                         do_component[RLM_COMPONENT_PREACCT] = 1;
714                         do_component[RLM_COMPONENT_ACCT] = 1;
715                         break;
716
717                 case RAD_LISTEN_PROXY:
718                         do_component[RLM_COMPONENT_PRE_PROXY] = 1;
719                         do_component[RLM_COMPONENT_POST_PROXY] = 1;
720                         break;
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         /*
947          *      Older versions of the server would pass proxy requests
948          *      through the 'authorize' sections twice; once when the
949          *      packet was received from the NAS, and again after the
950          *      reply was received from the home server.  Now that we
951          *      have a 'post_proxy' section, the replies from the home
952          *      server should be sent through that, instead of through
953          *      the 'authorize' section again.
954          */
955         if (request->proxy != NULL) {
956                 DEBUG2(" authorize: Skipping authorize in post-proxy stage");
957                 return RLM_MODULE_NOOP;
958         }
959
960         return indexed_modcall(RLM_COMPONENT_AUTZ, autz_type, request);
961 }
962
963 /*
964  *      Authenticate a user/password with various methods.
965  */
966 int module_authenticate(int auth_type, REQUEST *request)
967 {
968         return indexed_modcall(RLM_COMPONENT_AUTH, auth_type, request);
969 }
970
971 /*
972  *      Do pre-accounting for ALL configured sessions
973  */
974 int module_preacct(REQUEST *request)
975 {
976         return indexed_modcall(RLM_COMPONENT_PREACCT, 0, request);
977 }
978
979 /*
980  *      Do accounting for ALL configured sessions
981  */
982 int module_accounting(int acct_type, REQUEST *request)
983 {
984         return indexed_modcall(RLM_COMPONENT_ACCT, acct_type, request);
985 }
986
987 /*
988  *      See if a user is already logged in.
989  *
990  *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
991  */
992 int module_checksimul(int sess_type, REQUEST *request, int maxsimul)
993 {
994         int rcode;
995
996         if(!request->username)
997                 return 0;
998
999         request->simul_count = 0;
1000         request->simul_max = maxsimul;
1001         request->simul_mpp = 1;
1002
1003         rcode = indexed_modcall(RLM_COMPONENT_SESS, sess_type, request);
1004
1005         if (rcode != RLM_MODULE_OK) {
1006                 /* FIXME: Good spot for a *rate-limited* warning to the log */
1007                 return 0;
1008         }
1009
1010         return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
1011 }
1012
1013 /*
1014  *      Do pre-proxying for ALL configured sessions
1015  */
1016 int module_pre_proxy(int type, REQUEST *request)
1017 {
1018         return indexed_modcall(RLM_COMPONENT_PRE_PROXY, type, request);
1019 }
1020
1021 /*
1022  *      Do post-proxying for ALL configured sessions
1023  */
1024 int module_post_proxy(int type, REQUEST *request)
1025 {
1026         return indexed_modcall(RLM_COMPONENT_POST_PROXY, type, request);
1027 }
1028
1029 /*
1030  *      Do post-authentication for ALL configured sessions
1031  */
1032 int module_post_auth(int postauth_type, REQUEST *request)
1033 {
1034         return indexed_modcall(RLM_COMPONENT_POST_AUTH, postauth_type, request);
1035 }
1036