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