Pull fix from branch_1_1, so proxied EAP replies work
[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
579                         if (cp) {
580                                 modrefname = cf_pair_attr(cp);
581                         } else {
582                                 modrefname = cf_section_name2(scs);
583                                 if (!modrefname) {
584                                         radlog(L_ERR|L_CONS,
585                                                "%s[%d] Failed to parse %s sub-section.\n",
586                                                filename, cf_section_lineno(scs),
587                                                cf_section_name1(scs));
588                                         return -1;
589                                 }
590                         }
591
592                         dval = dict_valbyname(PW_AUTH_TYPE, modrefname);
593                         if (!dval) {
594                                 /*
595                                  *      It's a section, but nothing we
596                                  *      recognize.  Die!
597                                  */
598                                 radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s sub-section.",
599                                        filename, cf_section_lineno(scs),
600                                        modrefname, section_type_value[comp].section);
601                                 return -1;
602                         }
603                         idx = dval->value;
604                 } else {
605                         /* See the comment in new_sublist() for explanation
606                          * of the special index 0 */
607                         idx = 0;
608                 }
609
610                 subcomp = new_sublist(comp, idx);
611                 if (subcomp == NULL) {
612                         radlog(L_INFO|L_CONS,
613                                         "%s %s %s already configured - skipping",
614                                         filename, section_type_value[comp].typename,
615                                         modname);
616                         modcallable_free(&this);
617                         continue;
618                 }
619
620                 /* If subcomp->modulelist is NULL, add_to_modcallable will
621                  * create it */
622                 visiblename = cf_section_name2(cs);
623                 if (visiblename == NULL)
624                         visiblename = cf_section_name1(cs);
625                 add_to_modcallable(&subcomp->modulelist, this,
626                                    comp, visiblename);
627         }
628
629         return 0;
630 }
631
632
633 /*
634  *      Parse the module config sections, and load
635  *      and call each module's init() function.
636  *
637  *      Libtool makes your life a LOT easier, especially with libltdl.
638  *      see: http://www.gnu.org/software/libtool/
639  */
640 int setup_modules(int reload)
641 {
642         int             comp;
643         CONF_SECTION    *cs, *modules;
644         int             do_component[RLM_COMPONENT_COUNT];
645         rad_listen_t    *listener;
646
647         /*
648          *      If necessary, initialize libltdl.
649          */
650         if (!reload) {
651                 /*
652                  *      Set the default list of preloaded symbols.
653                  *      This is used to initialize libltdl's list of
654                  *      preloaded modules.
655                  *
656                  *      i.e. Static modules.
657                  */
658                 LTDL_SET_PRELOADED_SYMBOLS();
659
660                 if (lt_dlinit() != 0) {
661                         radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
662                                         lt_dlerror());
663                         return -1;
664                 }
665
666                 /*
667                  *      Set the search path to ONLY our library directory.
668                  *      This prevents the modules from being found from
669                  *      any location on the disk.
670                  */
671                 lt_dlsetsearchpath(radlib_dir);
672
673                 DEBUG2("Module: Library search path is %s",
674                                 lt_dlgetsearchpath());
675
676                 /*
677                  *      Set up the internal module struct.
678                  */
679                 module_tree = rbtree_create(module_entry_cmp,
680                                             module_entry_free, 0);
681                 if (!module_tree) {
682                         radlog(L_ERR|L_CONS, "Failed to initialize modules\n");
683                         return -1;
684                 }
685         } else {
686                 lrad_hash_table_free(components);
687         }
688
689         components = lrad_hash_table_create(indexed_modcallable_hash,
690                                             indexed_modcallable_cmp,
691                                             indexed_modcallable_free);
692         if (!components) {
693                 radlog(L_ERR|L_CONS, "Failed to initialize components\n");
694                 return -1;
695         }
696
697         /*
698          *      Figure out which sections to load.
699          */
700         memset(do_component, 0, sizeof(do_component));
701         for (listener = mainconfig.listen;
702              listener != NULL;
703              listener = listener->next) {
704                 switch (listener->type) {
705                 case RAD_LISTEN_AUTH:
706                         do_component[RLM_COMPONENT_AUTZ] = 1;
707                         do_component[RLM_COMPONENT_AUTH] = 1;
708                         do_component[RLM_COMPONENT_POST_AUTH] = 1;
709                         do_component[RLM_COMPONENT_SESS] = 1;
710                         break;
711
712                 case RAD_LISTEN_DETAIL: /* just like acct */
713                 case RAD_LISTEN_ACCT:
714                         do_component[RLM_COMPONENT_PREACCT] = 1;
715                         do_component[RLM_COMPONENT_ACCT] = 1;
716                         break;
717
718                 case RAD_LISTEN_PROXY:
719                         do_component[RLM_COMPONENT_PRE_PROXY] = 1;
720                         do_component[RLM_COMPONENT_POST_PROXY] = 1;
721                         break;
722
723                 default:
724                         rad_assert(0 == 1);
725                         break;
726                 }
727         }
728
729         for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
730                 /*
731                  *      Have the debugging messages all in one place.
732                  */
733                 if (!do_component[comp]) {
734                         DEBUG2("modules: Not loading %s{} section",
735                                section_type_value[comp].section);
736                 }
737         }
738
739         /*
740          *      Create any DICT_VALUE's for the types.  See
741          *      'doc/configurable_failover' for examples of 'authtype'
742          *      used to create new Auth-Type values.  In order to
743          *      let the user create new names, we've got to look for
744          *      those names, and create DICT_VALUE's for them.
745          */
746         for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
747                 int             value;
748                 const char      *name2;
749                 DICT_ATTR       *dattr;
750                 DICT_VALUE      *dval;
751                 CONF_SECTION    *sub, *next;
752                 CONF_PAIR       *cp;
753
754                 /*
755                  *      Not needed, don't load it.
756                  */
757                 if (!do_component[comp]) {
758                         continue;
759                 }
760                 cs = cf_section_find(section_type_value[comp].section);
761
762                 if (!cs) continue;
763
764                 sub = NULL;
765                 do {
766                         /*
767                          *      See if there's a sub-section by that
768                          *      name.
769                          */
770                         next = cf_subsection_find_next(cs, sub,
771                                                        section_type_value[comp].typename);
772
773                         /*
774                          *      Allow some old names, too.
775                          */
776                         if (!next && (comp <= 4)) {
777                                 next = cf_subsection_find_next(cs, sub,
778                                                                old_section_type_value[comp].typename);
779                         }
780                         sub = next;
781
782                         /*
783                          *      If so, look for it to define a new
784                          *      value.
785                          */
786                         name2 = cf_section_name2(sub);
787                         if (!name2) continue;
788
789
790                         /*
791                          *      If the value already exists, don't
792                          *      create it again.
793                          */
794                         dval = dict_valbyname(section_type_value[comp].attr,
795                                               name2);
796                         if (dval) continue;
797
798                         /*
799                          *      Find the attribute for the value.
800                          */
801                         dattr = dict_attrbyvalue(section_type_value[comp].attr);
802                         if (!dattr) {
803                                 radlog(L_ERR, "%s[%d]: No such attribute %s",
804                                        mainconfig.radiusd_conf,
805                                        cf_section_lineno(sub),
806                                        section_type_value[comp].typename);
807                                 continue;
808                         }
809
810                         /*
811                          *      Create a new unique value with a
812                          *      meaningless number.  You can't look at
813                          *      it from outside of this code, so it
814                          *      doesn't matter.  The only requirement
815                          *      is that it's unique.
816                          */
817                         do {
818                                 value = lrad_rand() & 0x00ffffff;
819                         } while (dict_valbyattr(dattr->attr, value));
820
821                         if (dict_addvalue(name2, dattr->name, value) < 0) {
822                                 radlog(L_ERR, "%s", librad_errstr);
823                                 return -1;
824                         }
825                 } while (sub != NULL);
826
827                 /*
828                  *      Loop over the non-sub-sections, too.
829                  */
830                 cp = NULL;
831                 do {
832                         /*
833                          *      See if there's a conf-pair by that
834                          *      name.
835                          */
836                         cp = cf_pair_find_next(cs, cp, NULL);
837                         if (!cp) break;
838
839
840                         /*
841                          *      If the value already exists, don't
842                          *      create it again.
843                          */
844                         name2 = cf_pair_attr(cp);
845                         dval = dict_valbyname(section_type_value[comp].attr,
846                                               name2);
847                         if (dval) continue;
848
849                         /*
850                          *      Find the attribute for the value.
851                          */
852                         dattr = dict_attrbyvalue(section_type_value[comp].attr);
853                         if (!dattr) {
854                                 radlog(L_ERR, "%s[%d]: No such attribute %s",
855                                        mainconfig.radiusd_conf,
856                                        cf_section_lineno(sub),
857                                        section_type_value[comp].typename);
858                                 continue;
859                         }
860
861                         /*
862                          *      Finally, create the new attribute.
863                          */
864                         do {
865                                 value = lrad_rand() & 0x00ffffff;
866                         } while (dict_valbyattr(dattr->attr, value));
867                         if (dict_addvalue(name2, dattr->name, value) < 0) {
868                                 radlog(L_ERR, "%s", librad_errstr);
869                                 return -1;
870                         }
871                 } while (cp != NULL);
872         } /* over the sections which can have redundent sub-sections */
873
874         /*
875          *      Remember where the modules were stored.
876          */
877         modules = cf_section_find("modules");
878         if (!modules) {
879                 radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!");
880                 return -1;
881         }
882
883         /*
884          *  Look for the 'instantiate' section, which tells us
885          *  the instantiation order of the modules, and also allows
886          *  us to load modules with no authorize/authenticate/etc.
887          *  sections.
888          */
889         cs = cf_section_find("instantiate");
890         if (cs != NULL) {
891                 CONF_ITEM *ci;
892                 CONF_PAIR *cp;
893                 module_instance_t *module;
894                 const char *name;
895
896                 /*
897                  *  Loop over the items in the 'instantiate' section.
898                  */
899                 for (ci=cf_item_find_next(cs, NULL);
900                      ci != NULL;
901                      ci=cf_item_find_next(cs, ci)) {
902
903                         /*
904                          *      Skip sections.  They'll be handled
905                          *      later, if they're referenced at all...
906                          */
907                         if (cf_item_is_section(ci)) {
908                                 continue;
909                         }
910
911                         cp = cf_itemtopair(ci);
912                         name = cf_pair_attr(cp);
913                         module = find_module_instance(modules, name);
914                         if (!module) {
915                                 return -1;
916                         }
917                 } /* loop over items in the subsection */
918         } /* if there's an 'instantiate' section. */
919
920         /*
921          *      Loop over all of the known components, finding their
922          *      configuration section, and loading it.
923          */
924         for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) {
925                 cs = cf_section_find(section_type_value[comp].section);
926                 if (cs == NULL)
927                         continue;
928
929                 if (!do_component[comp]) {
930                         continue;
931                 }
932
933                 if (load_component_section(NULL, cs, comp, mainconfig.radiusd_conf) < 0) {
934                         return -1;
935                 }
936         }
937
938         return 0;
939 }
940
941 /*
942  *      Call all authorization modules until one returns
943  *      somethings else than RLM_MODULE_OK
944  */
945 int module_authorize(int autz_type, REQUEST *request)
946 {
947         /*
948          *      Older versions of the server would pass proxy requests
949          *      through the 'authorize' sections twice; once when the
950          *      packet was received from the NAS, and again after the
951          *      reply was received from the home server.  Now that we
952          *      have a 'post_proxy' section, the replies from the home
953          *      server should be sent through that, instead of through
954          *      the 'authorize' section again.
955          */
956         if (request->proxy != NULL) {
957                 DEBUG2(" authorize: Skipping authorize in post-proxy stage");
958                 return RLM_MODULE_NOOP;
959         }
960
961         return indexed_modcall(RLM_COMPONENT_AUTZ, autz_type, request);
962 }
963
964 /*
965  *      Authenticate a user/password with various methods.
966  */
967 int module_authenticate(int auth_type, REQUEST *request)
968 {
969         return indexed_modcall(RLM_COMPONENT_AUTH, auth_type, request);
970 }
971
972 /*
973  *      Do pre-accounting for ALL configured sessions
974  */
975 int module_preacct(REQUEST *request)
976 {
977         return indexed_modcall(RLM_COMPONENT_PREACCT, 0, request);
978 }
979
980 /*
981  *      Do accounting for ALL configured sessions
982  */
983 int module_accounting(int acct_type, REQUEST *request)
984 {
985         return indexed_modcall(RLM_COMPONENT_ACCT, acct_type, request);
986 }
987
988 /*
989  *      See if a user is already logged in.
990  *
991  *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
992  */
993 int module_checksimul(int sess_type, REQUEST *request, int maxsimul)
994 {
995         int rcode;
996
997         if(!request->username)
998                 return 0;
999
1000         request->simul_count = 0;
1001         request->simul_max = maxsimul;
1002         request->simul_mpp = 1;
1003
1004         rcode = indexed_modcall(RLM_COMPONENT_SESS, sess_type, request);
1005
1006         if (rcode != RLM_MODULE_OK) {
1007                 /* FIXME: Good spot for a *rate-limited* warning to the log */
1008                 return 0;
1009         }
1010
1011         return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
1012 }
1013
1014 /*
1015  *      Do pre-proxying for ALL configured sessions
1016  */
1017 int module_pre_proxy(int type, REQUEST *request)
1018 {
1019         return indexed_modcall(RLM_COMPONENT_PRE_PROXY, type, request);
1020 }
1021
1022 /*
1023  *      Do post-proxying for ALL configured sessions
1024  */
1025 int module_post_proxy(int type, REQUEST *request)
1026 {
1027         return indexed_modcall(RLM_COMPONENT_POST_PROXY, type, request);
1028 }
1029
1030 /*
1031  *      Do post-authentication for ALL configured sessions
1032  */
1033 int module_post_auth(int postauth_type, REQUEST *request)
1034 {
1035         return indexed_modcall(RLM_COMPONENT_POST_AUTH, postauth_type, request);
1036 }
1037