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