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