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