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