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